当前位置: 移动技术网 > IT编程>脚本编程>Go语言 > 解析Go 标准库 http.FileServer 实现静态文件服务

解析Go 标准库 http.FileServer 实现静态文件服务

2018年09月23日  | 移动技术网IT编程  | 我要评论

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 实现静态文件服务,希望对大家有所帮助

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网