Golang。要使用什么? http.ServeFile(..)或http.FileServer(..)? [英] Golang. What to use? http.ServeFile(..) or http.FileServer(..)?
问题描述
我有点困惑。很多例子显示了两者的用法: http.ServeFile(..)
和 http.FileServer(..)
,但似乎他们有非常密切的功能。另外我还没有找到有关如何设置自定义NotFound处理程序的信息。
//这可以从路径
中去除/ static /片段fs:= http.FileServer(http .dir(static))
http.Handle(/ static /,http.StripPrefix(/ static /,fs))
//这也可以,但/ static2 /片段仍然存在,需要手动分条
http.HandleFunc(/ static2 /,func(w http.ResponseWriter,r * http.Request){
http.ServeFile(w ,r,r.URL.Path [1:])
})
http.ListenAndServe(:8080,nil)
我尝试读取源代码,并且它们都使用 serveFile(ResponseWriter,* Request,FileSystem,string,bool)
底层函数。然而 http.FileServer
返回 fileHandler
以及它自己的 ServeHTTP()
方法并在提供文件之前做一些准备工作(例如path.Clean())。
那么为什么需要这种分离呢?哪种方法更好用?我怎样才能设置自定义NotFound处理程序,例如当找不到请求的文件时? 主要区别在于 http.FileServer
有效地将HTTP前缀与文件系统几乎进行1:1映射。用简单的英语,它提供了一个完整的目录路径。和其所有的孩子。
假设您有一个名为 / home / bob / static
的目录,并且您有此设置:
fs:= http.FileServer(http.Dir(/ home / bob / static))
http.Handle(/ static /,http.StripPrefix(/ static,fs))
你的服务器会收到例如 )
相比之下, ServeFile
是一个较低级别的帮助程序,可用于实现与FileServer类似的功能,或者可能实现自己的路径,以及任何数量的事情。它只需获取指定的本地文件并通过HTTP连接发送它。本身,它不会提供一个完整的目录前缀(除非你编写了一个类似于FileServer的查找处理程序)
注意天真地建立一个文件系统是一个潜在的危险的事情(有可能的方式来打破根源树),因此我建议,除非你真的知道你在做什么,可以使用 http.FileServer
和 http.Dir
,因为它们包含检查以确保人们无法摆脱FS ServeFile
不会。
附录
您的第二个问题,您如何进行自定义不幸的是,NotFound处理程序不容易回答。因为这是从内部函数 serveFile
调用的,因此您没有超级简单的地方可以打开它。可能有一些偷偷摸摸的事情,例如拦截你自己的 ResponseWriter
来拦截404响应代码,但我会将这个练习留给你。
I'm a little bit confused. Much of examples shows usage of both: http.ServeFile(..)
and http.FileServer(..)
, but seems they have very close functionality. Also I have found no information about how to set custom NotFound handler.
// This works and strip "/static/" fragment from path
fs := http.FileServer(http.Dir("static"))
http.Handle("/static/", http.StripPrefix("/static/", fs))
// This works too, but "/static2/" fragment remains and need to be striped manually
http.HandleFunc("/static2/", func(w http.ResponseWriter, r *http.Request) {
http.ServeFile(w, r, r.URL.Path[1:])
})
http.ListenAndServe(":8080", nil)
I've tried to read source code and both of them use serveFile(ResponseWriter, *Request, FileSystem, string, bool)
underlying function. However http.FileServer
return fileHandler
with its own ServeHTTP()
method and make some preparation work before serving file (eg path.Clean()).
So why need this separation? Which method better to use? And how can I set custom NotFound handler, for example when requested file not found?
The main difference is that http.FileServer
does effectively almost 1:1 mapping of an HTTP prefix with a filesystem. In plain english, it serves up an entire directory path. and all its children.
Say you had a directory called /home/bob/static
and you had this setup:
fs := http.FileServer(http.Dir("/home/bob/static"))
http.Handle("/static/", http.StripPrefix("/static", fs))
Your server would take requests for e.g. /static/foo/bar
and serve whatever is at /home/bob/static/foo/bar
(or 404)
In contrast, the ServeFile
is a lower level helper that can be used to implement something similar to FileServer, or implement your own path munging potentially, and any number of things. It simply takes the named local file and sends it over the HTTP connection. By itself, it won't serve a whole directory prefix (unless you wrote a handler that did some lookup similar to FileServer)
NOTE Serving up a filesystem naively is a potentially dangerous thing (there are potentially ways to break out of the rooted tree) hence I recommend that unless you really know what you're doing, use http.FileServer
and http.Dir
as they include checks to make sure people can't break out of the FS, which ServeFile
doesn't.
Addendum
Your secondary question, how do you do a custom NotFound handler, unfortunately, is not easily answered. Because this is called from internal function serveFile
as you noticed, there's no super easy place to break into that. There are potentially some sneaky things like intercepting the response with your own ResponseWriter
which intercepts the 404 response code, but I'll leave that exercise to you.
这篇关于Golang。要使用什么? http.ServeFile(..)或http.FileServer(..)?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!