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
类型,将字符串路径转换成文件系统。
// 所属文件: 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) } }
原文地址: https://shockerli.net/post/golang-pkg-http-file-server/

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
区块链开发公司介绍区块链如何保护隐私
区块链隐私保护技术成为关注热点。在区块链公有链中,每一个参与者都能够获得完整的数据备份,所有交易数据都是公开和透明的,这个区块链的优势特点,但另一方面,对于很多区块链应用方来说,这个特点又是致命的。 在区块链系统中,每一个参与者都能获得完整的数据备份,所有的交易数据公开透明、不可篡改。对无需隐私保护的数据而言,这是区块链无可比拟的优势。而对于需要加强保护的隐私数据来说,这又成了区块链足以致命的缺陷。 如何在区块链中保护数据隐私?是满足个人、企业、政府等对保护数据隐私要求,推动区块链技术规模化落地应用必须要解决的难题。 近两年来,随着区块链走入各行各业,用区块链实现隐私保护成为各类应用的重要卖点之一。然而,区块链一向以数据公开透明而闻名。乍听上去,这不仅和隐私保护毫无关系,甚至还南辕北辙。 在区块链公有链中,每一个参与者都能够获得完整的数据备份,所有交易数据都是公开和透明的,这个区块链的优势特点,但另一方面,对于很多区块链应用方来说,这个特点又是致命的。因为很多时候,不仅仅用户本身希望他的帐户隐私和交易信息被保护,就商业机构来说,很多帐户和交易信息更是这些机构的重要资产和商业机密,不希望...
- 下一篇
Leetcode打卡 | No.22 括号生成
No.22 括号生成 题目 : 给出 n 代表生成括号的对数,请你写出一个函数,使其能够生成所有可能的并且有效的括号组合。 例如,给出 n = 3,生成结果为: [ "((()))", "(()())", "()(())", "(())()", "()()()" ] 这一题和之前一题看起来类似 ,但难度却上升很多了 ,小伙伴们可以温故一下之前类似的题目 : Leetcode打卡 | No.20 有效的括号 两题差别有两个 ,一个是生成括号只包括小括号 ‘()’ ,另一个是逻辑相逆 ,这里是要生成有效的括号序列 。一个很关键的问题就出来了 ,什么样的序列有效呢 ?当然可以参考第 20 题 ,但是这里更简单只有一种小括号字符 。分析发现只要左右小括号数量相等 ,生成的括号序列就有效 。 这里提供两种思路 ,一个是暴力法 ,生成所有的括号序列 ,再判断是否有效 ;一个是递归生成有效的序列方法 。 思路一 :这里只有 ‘( ’ 和 ‘ )’ 两种字符可能 ,暴力生成所有字符串序列有 2的2n次方种可能 。根据自己的思维 ,小詹分成两个关键点讲解 ,一个是如何判断有效 ,一个是如何暴力生成所有字...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- SpringBoot2更换Tomcat为Jetty,小型站点的福音
- CentOS8安装MyCat,轻松搞定数据库的读写分离、垂直分库、水平分库
- CentOS6,CentOS7官方镜像安装Oracle11G
- Jdk安装(Linux,MacOS,Windows),包含三大操作系统的最全安装
- SpringBoot2整合MyBatis,连接MySql数据库做增删改查操作
- SpringBoot2全家桶,快速入门学习开发网站教程
- SpringBoot2编写第一个Controller,响应你的http请求并返回结果
- CentOS7安装Docker,走上虚拟化容器引擎之路
- CentOS8,CentOS7,CentOS6编译安装Redis5.0.7
- CentOS8编译安装MySQL8.0.19