在https://www.alexedwards.net/blog/serving-static-sites-with-go处,有一个静态文件服务器示例,用于在单个目录中提供网站:static
。
File: app.go
...
func main() {
fs := http.FileServer(http.Dir("static"))
http.Handle("/static/", http.StripPrefix("/static/", fs))
log.Println("Listening...")
http.ListenAndServe(":3000", nil)
}
但是,我发现我可以通过以下方式得到相同的结果。
func main() {
fs := http.FileServer(http.Dir(".")) // root at the root directory.
http.Handle("/static/", fs) //leave off the StripPrefix call.
log.Println("Listening...")
http.ListenAndServe(":3000", nil)
}
这样做是否有任何(性能或安全性)缺点?我可以看到,如果我在文件系统上的文件位置与它们所服务的URL不匹配,我必须使用StripPrefix
,但在这种情况下,似乎调用{{1没必要。
编辑:我忘了提及,但我自己也对此进行过调查。在性能方面,它似乎不是一个问题,因为调用StripPrefix
实际上并没有将文件加载到内存中;它只是存储了地址。在安全方面,这似乎完全相同:我尝试使用类似下面的内容进行目录遍历攻击。
FileServer
但是我对这两个版本都得到了301响应,这让我感到很惊讶。
答案 0 :(得分:1)
使用http.ServeMux
处理程序
http.ServeMux
将在匹配路径
https://github.com/golang/go/blob/master/src/net/http/server.go#L2305
func (mux *ServeMux) Handler(r *Request) (h Handler, pattern string) {
// snip
path := cleanPath(r.URL.Path)
//snip
}
cleanPath函数返回p的规范路径,消除。和..元素。
https://github.com/golang/go/blob/master/src/net/http/server.go#L2174-L2193
// cleanPath returns the canonical path for p, eliminating . and .. elements.
func cleanPath(p string) string {
if p == "" {
return "/"
}
if p[0] != '/' {
p = "/" + p
}
np := path.Clean(p)
// path.Clean removes trailing slash except for root;
// put the trailing slash back if necessary.
if p[len(p)-1] == '/' && np != "/" {
// Fast path for common case of p being the string we want:
if len(p) == len(np)+1 && strings.HasPrefix(p, np) {
np = p
} else {
np += "/"
}
}
return np
}