fs: Add redirects

This commit is contained in:
Adnan Maolood 2021-02-17 01:38:18 -05:00
parent 995769556c
commit 8eccefb8c9

45
fs.go
View File

@ -32,7 +32,7 @@ type fileServer struct {
} }
func (fs fileServer) ServeGemini(w ResponseWriter, r *Request) { func (fs fileServer) ServeGemini(w ResponseWriter, r *Request) {
ServeFile(w, fs, path.Clean(r.URL.Path)) serveFile(w, r, fs, path.Clean(r.URL.Path), true)
} }
// ServeFile responds to the request with the contents of the named file // ServeFile responds to the request with the contents of the named file
@ -42,7 +42,19 @@ func (fs fileServer) ServeGemini(w ResponseWriter, r *Request) {
// relative to the current directory and may ascend to parent directories. If // relative to the current directory and may ascend to parent directories. If
// the provided name is constructed from user input, it should be sanitized // the provided name is constructed from user input, it should be sanitized
// before calling ServeFile. // before calling ServeFile.
func ServeFile(w ResponseWriter, fsys fs.FS, name string) { func ServeFile(w ResponseWriter, r *Request, fsys fs.FS, name string) {
serveFile(w, r, fsys, name, false)
}
func serveFile(w ResponseWriter, r *Request, fsys fs.FS, name string, redirect bool) {
const indexPage = "/index.gmi"
// Redirect .../index.gmi to .../
if strings.HasSuffix(r.URL.Path, indexPage) {
w.Header(StatusPermanentRedirect, "./")
return
}
if name == "/" { if name == "/" {
name = "." name = "."
} else { } else {
@ -62,9 +74,34 @@ func ServeFile(w ResponseWriter, fsys fs.FS, name string) {
return return
} }
// Redirect to canonical path
if redirect {
url := r.URL.Path
if stat.IsDir() { if stat.IsDir() {
// Try opening index file // Add trailing slash
index, err := fsys.Open(path.Join(name, "index.gmi")) if url[len(url)-1] != '/' {
w.Header(StatusPermanentRedirect, path.Base(url)+"/")
return
}
} else {
// Remove trailing slash
if name[len(name)-1] == '/' {
w.Header(StatusPermanentRedirect, "../"+path.Base(url))
return
}
}
}
if stat.IsDir() {
// Redirect if the directory name doesn't end in a slash
url := r.URL.Path
if url[len(url)-1] != '/' {
w.Header(StatusRedirect, path.Base(url)+"/")
return
}
// Use contents of index.gmi if present
index, err := fsys.Open(path.Join(name, indexPage))
if err == nil { if err == nil {
defer index.Close() defer index.Close()
istat, err := index.Stat() istat, err := index.Stat()