HTTP 静态文件处理程序不断显示目录列表
HTTP Static file handler keeps showing the directory list
当我实现静态服务器处理程序时,如果我访问根路径,它将显示整个目录,如下所示:
我的代码是:
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))
}
幸运与否,http.FileServer
的默认行为是如果路径表示没有 index.html
文件的目录,将提供目录列表。而且它没有提供一种简单的方法来关闭它。但是...
http.FileServer
在 虚拟 文件系统上运行,由 http.FileSystem
接口描述。
这个接口只有一个方法,它告诉我们如何打开一个文件,并获取它的 http.File
"view":
type FileSystem interface {
Open(name string) (File, error)
}
如果你想禁用目录列表,你所要做的就是提供你自己的http.FileSystem
实现,当一个目录被定位时,你只需报告/return一个错误。仅此而已。
当然你不必一个人做这一切。您可以创建自己的 FileSystem
,它使用/利用 http.Dir
,这是使用本机文件系统的默认实现(仅限于特定的目录树)。
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
}
使用上面的自定义实现:
handler := http.FileServer(myfs{http.Dir(*directory)})
http.Handle(
"/statics/",
http.StripPrefix(strings.TrimRight("/statics/", "/"), handler),
)
仅此而已。尝试浏览 http://locahost:3000/statics/
将导致默认响应:
404 page not found
备注:
上面的实现第二次 Dir.Open()
调用 return 一个错误,它总是相同的。对于 "speed things up",我们可以存储此响应并重新使用它:
var notFoundFile, notFoundErr = http.Dir("dummy").Open("does-not-exist")
当我们在 myfs.Open()
方法中检测到目录时:
if fi.IsDir() {
// Return a response that "belogns" to opening a non-existing folder:
return notFoundFile, notFoundErr
}
当我实现静态服务器处理程序时,如果我访问根路径,它将显示整个目录,如下所示:
我的代码是:
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))
}
幸运与否,http.FileServer
的默认行为是如果路径表示没有 index.html
文件的目录,将提供目录列表。而且它没有提供一种简单的方法来关闭它。但是...
http.FileServer
在 虚拟 文件系统上运行,由 http.FileSystem
接口描述。
这个接口只有一个方法,它告诉我们如何打开一个文件,并获取它的 http.File
"view":
type FileSystem interface {
Open(name string) (File, error)
}
如果你想禁用目录列表,你所要做的就是提供你自己的http.FileSystem
实现,当一个目录被定位时,你只需报告/return一个错误。仅此而已。
当然你不必一个人做这一切。您可以创建自己的 FileSystem
,它使用/利用 http.Dir
,这是使用本机文件系统的默认实现(仅限于特定的目录树)。
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
}
使用上面的自定义实现:
handler := http.FileServer(myfs{http.Dir(*directory)})
http.Handle(
"/statics/",
http.StripPrefix(strings.TrimRight("/statics/", "/"), handler),
)
仅此而已。尝试浏览 http://locahost:3000/statics/
将导致默认响应:
404 page not found
备注:
上面的实现第二次 Dir.Open()
调用 return 一个错误,它总是相同的。对于 "speed things up",我们可以存储此响应并重新使用它:
var notFoundFile, notFoundErr = http.Dir("dummy").Open("does-not-exist")
当我们在 myfs.Open()
方法中检测到目录时:
if fi.IsDir() {
// Return a response that "belogns" to opening a non-existing folder:
return notFoundFile, notFoundErr
}