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
}