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

简介:

http.FileServer 方法属于标准库 net/http,返回一个使用 FileSystem 接口 root 提供文件访问服务的 HTTP 处理器。可以方便的实现静态文件服务器。
http.ListenAndServe(":8080", http.FileServer(http.Dir("/files/path")))
访问 http://127.0.0.1:8080,即可看到类似 Nginx 中 autoindex 目录浏览功能。

源码解析
我们现在开始将上述的那仅有的一行代码进行剖析,看看到底是如何实现的。源码中英文注释也比较详细,可以参考。

我们先看 http.Dir(),再看 http.FileServer(),而 http.ListenAndServe() 监听 TCP 端口并提供路由服务,此处不赘述。

http.Dir()
从以下源码我们可以看出,type Dir string 实现了 type FileSystem interface 的接口函数 Open,http.Dir("/") 实际返回的是 http.Dir 类型,将字符串路径转换成文件系统。

1// 所属文件: src/net/http/fs.go, 26-87行type Dir stringfunc (d Dir) Open(name string) (File, error) {    // ...}type FileSystem interface {
2    Open(name string) (File, error)
3}
http.FileServer()

http.FileServer() 方法返回的是 fileHandler 实例,而 fileHandler 结构体实现了 Handler 接口的方法ServeHTTP()。ServeHTTP 方法内的核心是 serveFile() 方法。

1// 所属文件: src/net/http/fs.go, 690-716行type fileHandler struct {
 2    root FileSystem
 3}func FileServer(root FileSystem) Handler {    return &fileHandler{root}
 4}func (f *fileHandler) ServeHTTP(w ResponseWriter, r *Request) {
 5    upath := r.URL.Path    if !strings.HasPrefix(upath, "/") {
 6        upath = "/" + upath
 7        r.URL.Path = upath
 8    }
 9    serveFile(w, r, f.root, path.Clean(upath), true)
10}
1// 所属文件: src/net/http/server.go, 82行type Handler interface {
2    ServeHTTP(ResponseWriter, *Request)
3}

serveFile() 方法判断,如果访问路径是目录,则列出目录内容,如果是文件则使用 serveContent() 方法输出文件内容。serveContent() 方法则是个读取文件内容并输出的方法,此处不再贴代码。

1// 所属文件: src/net/http/fs.go, 540行// name is '/'-separated, not filepath.Separator.func serveFile(w ResponseWriter, r *Request, fs FileSystem, name string, redirect bool) {    // 中间代码已省略
 2
 3    if d.IsDir() {        if checkIfModifiedSince(r, d.ModTime()) == condFalse {
 4            writeNotModified(w)            return
 5        }
 6        w.Header().Set("Last-Modified", d.ModTime().UTC().Format(TimeFormat))
 7        dirList(w, r, f)        return
 8    }    // serveContent will check modification time
 9    sizeFunc := func() (int64, error) { return d.Size(), nil }
10    serveContent(w, r, d.Name(), d.ModTime(), sizeFunc, f)
11}

支持子目录路径
http.StripPrefix() 方法配合 http.Handle() 或 http.HandleFunc() 可以实现带路由前缀的文件服务。

1package mainimport (    "net/http"
 2    "fmt")func main() {
 3
 4    http.Handle("/tmpfiles/", http.StripPrefix("/tmpfiles/", http.FileServer(http.Dir("/tmp"))))
 5
 6    err := http.ListenAndServe(":8080", nil)    if err != nil {
 7        fmt.Println(err)
 8    }
 9
10}

原文发布时间为:2018-08-21
本文作者:舆图易稿
本文来自云栖社区合作伙伴“Golang语言社区”,了解相关信息可以关注“Golang语言社区”。

相关文章
|
2月前
|
Shell Go API
Go语言grequests库并发请求的实战案例
Go语言grequests库并发请求的实战案例
|
8天前
|
Go UED
Go Web服务中如何优雅平滑重启?
在生产环境中,服务升级时如何确保不中断当前请求并应用新代码是一个挑战。本文介绍了如何使用 Go 语言的 `endless` 包实现服务的优雅重启,确保在不停止服务的情况下完成无缝升级。通过示例代码和测试步骤,详细展示了 `endless` 包的工作原理和实际应用。
24 3
|
16天前
|
网络协议 安全 Go
Go语言进行网络编程可以通过**使用TCP/IP协议栈、并发模型、HTTP协议等**方式
【10月更文挑战第28天】Go语言进行网络编程可以通过**使用TCP/IP协议栈、并发模型、HTTP协议等**方式
44 13
|
9天前
|
JSON Go UED
Go Web服务中如何优雅关机?
在构建 Web 服务时,优雅关机是一个关键的技术点,它确保服务关闭时所有正在处理的请求都能顺利完成。本文通过一个简单的 Go 语言示例,展示了如何使用 Gin 框架实现优雅关机。通过捕获系统信号和使用 `http.Server` 的 `Shutdown` 方法,我们可以在服务关闭前等待所有请求处理完毕,从而提升用户体验,避免数据丢失或不一致。
14 1
|
15天前
|
存储 Cloud Native Shell
go库介绍:Golang中的Viper库
Viper 是 Golang 中的一个强大配置管理库,支持环境变量、命令行参数、远程配置等多种配置来源。本文详细介绍了 Viper 的核心特点、应用场景及使用方法,并通过示例展示了其强大功能。无论是简单的 CLI 工具还是复杂的分布式系统,Viper 都能提供优雅的配置管理方案。
|
17天前
|
JSON 安全 网络协议
go语言使用内置函数和标准库
【10月更文挑战第18天】
13 3
|
19天前
|
JSON 监控 安全
go语言选择合适的工具和库
【10月更文挑战第17天】
11 2
|
24天前
|
前端开发 JavaScript 中间件
前端全栈之路Deno篇(四):Deno2.0如何快速创建http一个 restfulapi/静态文件托管应用及oak框架介绍
Deno 是由 Node.js 创始人 Ryan Dahl 开发的新一代 JavaScript 和 TypeScript 运行时,旨在解决 Node.js 的设计缺陷,具备更强的安全性和内置的 TypeScript 支持。本文介绍了如何使用 Deno 内置的 `Deno.serve` 快速创建 HTTP 服务,并详细讲解了 Oak 框架的安装和使用方法,包括中间件、路由和静态文件服务等功能。Deno 和 Oak 的结合使得创建 RESTful API 变得高效且简便,非常适合快速开发和部署现代 Web 应用程序。
|
1月前
|
关系型数据库 MySQL 数据库
vertx 的http服务表单提交与mysql验证
本文介绍了如何使用Vert.x处理HTTP服务中的表单提交,并通过集成MySQL数据库进行验证,包括项目依赖配置、表单HTML代码和完整的Vert.x服务代码。
19 2
|
1月前
|
JSON 网络协议 网络安全
详解新一代 HTTP 请求库:httpx
详解新一代 HTTP 请求库:httpx
53 1