解析Go 标准库 http.FileServer 实现静态文件服务
http.fileserver 方法属于标准库 net/http,返回一个使用 filesystem 接口 root 提供文件访问服务的 http 处理器。可以方便的实现静态文件服务器。
http.listenandserve(":8080", http.fileserver(http.dir("/files/path")))
访问 ,即可看到类似 nginx 中 autoindex 目录浏览功能。
源码解析
我们现在开始将上述的那仅有的一行代码进行剖析,看看到底是如何实现的。源码中英文注释也比较详细,可以参考。
我们先看 http.dir(),再看 http.fileserver(),而 http.listenandserve()
监听 tcp 端口并提供路由服务,此处不赘述。
http.dir()
从以下源码我们可以看出,type dir string 实现了 type filesystem interface 的接口函数 open,http.dir("/") 实际返回的是 http.dir 类型,将字符串路径转换成文件系统。
// 所属文件: src/net/http/fs.go, 26-87行 type dir string func (d dir) open(name string) (file, error) { // ... } type filesystem interface { open(name string) (file, error) } http.fileserver() http.fileserver() 方法返回的是 filehandler 实例,而 filehandler 结构体实现了 handler 接口的方法 servehttp()。servehttp 方法内的核心是 servefile() 方法。 // 所属文件: src/net/http/fs.go, 690-716行 type filehandler struct { root filesystem } func fileserver(root filesystem) handler { return &filehandler{root} } func (f *filehandler) servehttp(w responsewriter, r *request) { upath := r.url.path if !strings.hasprefix(upath, "/") { upath = "/" + upath r.url.path = upath } servefile(w, r, f.root, path.clean(upath), true) } // 所属文件: src/net/http/server.go, 82行 type handler interface { servehttp(responsewriter, *request) }
servefile()
方法判断,如果访问路径是目录,则列出目录内容,如果是文件则使用 servecontent()
方法输出文件内容。servecontent()
方法则是个读取文件内容并输出的方法,此处不再贴代码。
// 所属文件: src/net/http/fs.go, 540行 // name is '/'-separated, not filepath.separator. func servefile(w responsewriter, r *request, fs filesystem, name string, redirect bool) { // 中间代码已省略 if d.isdir() { if checkifmodifiedsince(r, d.modtime()) == condfalse { writenotmodified(w) return } w.header().set("last-modified", d.modtime().utc().format(timeformat)) dirlist(w, r, f) return } // servecontent will check modification time sizefunc := func() (int64, error) { return d.size(), nil } servecontent(w, r, d.name(), d.modtime(), sizefunc, f) }
支持子目录路径
http.stripprefix()
方法配合 http.handle()
或 http.handlefunc()
可以实现带路由前缀的文件服务。
package main import ( "net/http" "fmt" ) func main() { http.handle("/tmpfiles/", http.stripprefix("/tmpfiles/", http.fileserver(http.dir("/tmp")))) err := http.listenandserve(":8080", nil) if err != nil { fmt.println(err) } }
总结
以上所述是小编给大家介绍的解析go 标准库 http.fileserver 实现静态文件服务,希望对大家有所帮助
上一篇: 办公室里女同事多是一种什么体验
下一篇: Go 并发实现协程同步的多种解决方法