Reputation: 302
When I implement a static server handler, if I access to root path, it will show the whole directory, like this:
My code is:
package main
import (
"flag"
"log"
"net/http"
"strings"
)
func main() {
port := flag.String("p", "3000", "port to serve on")
directory := flag.String("d", ".", "the directory of static file to host")
flag.Parse()
http.Handle("/statics/", http.StripPrefix(strings.TrimRight("/statics/", "/"), http.FileServer(http.Dir(*directory))))
log.Printf("Serving %s on HTTP port: %s\n", *directory, *port)
log.Fatal(http.ListenAndServe(":"+*port, nil))
}
go to : http://locahost:3000/statics/
Upvotes: 5
Views: 2342
Reputation: 417947
Fortunately or not, the default behavior of http.FileServer
is that if the path denotes a directory without an index.html
file, a directory listing will be served. And it does not provide a simple way to turn that off. But...
http.FileServer
operates on a virtual filesystem described by the http.FileSystem
interface.
This interface has a single method which tells how to open a file, and obtain an http.File
"view" of it:
type FileSystem interface {
Open(name string) (File, error)
}
If you want to disable directory listing, all you have to do is provide your own implementation of http.FileSystem
which when a directory is targeted, you simply report / return an error. That's all it takes.
Of course you don't have to do this all by yourself. You may create your own FileSystem
which uses / utilizes http.Dir
, which is the default implementation that uses the native file system (restricted to a specific directory tree).
type myfs struct {
http.Dir
}
func (m myfs) Open(name string) (result http.File, err error) {
f, err := m.Dir.Open(name)
if err != nil {
return
}
fi, err := f.Stat()
if err != nil {
return
}
if fi.IsDir() {
// Return a response that would have been if directory would not exist:
return m.Dir.Open("does-not-exist")
}
return f, nil
}
Using the above custom implementation:
handler := http.FileServer(myfs{http.Dir(*directory)})
http.Handle(
"/statics/",
http.StripPrefix(strings.TrimRight("/statics/", "/"), handler),
)
And that's all. Attempting to browse http://locahost:3000/statics/
will result in the default response:
404 page not found
Notes:
The above implementation does a second Dir.Open()
call to return an error, which is always the same. To "speed things up", we can store this response and just reuse it:
var notFoundFile, notFoundErr = http.Dir("dummy").Open("does-not-exist")
And when we detect a directory in our myfs.Open()
method:
if fi.IsDir() {
// Return a response that "belogns" to opening a non-existing folder:
return notFoundFile, notFoundErr
}
Upvotes: 9