http.FileServer 方法属于标准库 net/http,返回一个使用 FileSystem 接口 root 提供文件访问服务的 HTTP 处理器。可以方便的实现静态文件服务器。

  1. 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 的接口函数 Openhttp.Dir("/") 实际返回的是 http.Dir 类型,将字符串路径转换成文件系统。

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

http.FileServer()

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

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

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

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

支持子目录路径

http.StripPrefix() 方法配合 http.Handle()http.HandleFunc() 可以实现带路由前缀的文件服务。

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

原文地址: https://shockerli.net/post/golang-pkg-http-file-server/

Go 标准库 http.FileServer 实现静态文件服务的更多相关文章

  1. nodejs anywhere 搭建本地静态文件服务

    一.背景 工作中有时候往往会遇到下述场景:例如需要将新打好的安装包等文件临时性的给到同事,可能还需要给到多个同事.这时,我们往往有如下几种方案: 1,一般都会有公司内部的文件系统,上传文件后将对应的地 ...

  2. Nginx配置静态文件服务从入门到精通

    作者:三十三重天 博客:http://www.zhouhuibo.club 通过学习和分享的过程,将自己工作中的问题和技术总结输出,希望菜鸟和老鸟都能通过自己的文章收获新的知识,并付诸实施. 引言 使 ...

  3. gin中提供静态文件服务

    package main import ( "github.com/gin-gonic/gin" "net/http" ) func main() { // 静 ...

  4. Nginx 静态文件服务

    Nginx 静态文件服务 我们先来看看最简单的本地静态文件服务配置示例: server { listen 80; server_name www.test.com; charset utf-8; ro ...

  5. 【玩转Golang】beego下实现martini中的透明式静态文件服务(static folder)效果。

    出于效率等原因,最近将web框架由martini切换为了beego,其他地方都很平顺,只是两个框架的handler签名不一致,需要修改,所以耗时较长,这是预计到的.但是有一个地方没有预计到,也耗费了较 ...

  6. Django -> debug模式下的静态文件服务(/media/)

    正式公布django项目的时候,假设存在静态文件(通常会统一放在名称为media或static的文件夹下),则须要建立url到文件系统的映射,比如.使用nginx的时候我们须要进行这种配置. # Dj ...

  7. Python 标准库 —— zipfile(读取 zip 文件)

    Python模块学习:zipfile zip文件操作 Python 学习入门(16)-- zipfile 0. 解压 with zipfile.ZipFile('../data/jaychou_lyr ...

  8. Go Web 编程之 静态文件

    概述 在 Web 开发中,需要处理很多静态资源文件,如 css/js 和图片文件等.本文将介绍在 Go 语言中如何处理文件请求. 接下来,我们将介绍两种处理文件请求的方式:原始方式和http.File ...

  9. ASP.NET Core 中文文档 第三章 原理(3)静态文件处理

    原文:Working with Static Files 作者:Rick Anderson 翻译:刘怡(AlexLEWIS) 校对:谢炀(kiler398).许登洋(Seay).孟帅洋(书缘) 静态文 ...

随机推荐

  1. MySQL中 DECIMAL FLOAT DOUBLE的区别

    第一篇文章: MySQL中Decimal类型和Float Double等区别 MySQL中存在float,double等非标准数据类型,也有decimal这种标准数据类型. 其区别在于,float,d ...

  2. 将Paul替换成Ringo

    <!DOCTYPE html><html><head lang="en">  <meta charset="UTF-8" ...

  3. STM32-跑马灯实验

    实验环境: STM32开发板 Keil uVision4 FlyMcu.exe 一. 建立文件夹 1.建立跟文件夹"BASE"(名称任意),再在其下建立四个子文件夹 2. 在&qu ...

  4. android-mediaplayer播放

    优先参考 待补充.android 8.0

  5. 基础项目构建,引入web模块,完成一个简单的RESTful API 转载来自翟永超

    简介 在您第一次接触和学习Spring框架的时候,是否因为其繁杂的配置而退却了?在你第n次使用Spring框架的时候,是否觉得一堆反复粘贴的配置有一些厌烦?那么您就不妨来试试使用Spring Boot ...

  6. 没有job offer,拿加拿大工签PGWP回国如何续签加拿大小签?

     很多同学因为在加拿大毕业后申请了三年的工作签证PGWP之后匆匆回国,没有来得及续签小签,但是回国一段时间之后又想要回加拿大,想要用自己的三年工签来续自己的小签.拿了加拿大PGWP没有job offe ...

  7. 了解AOP

    Spring AOP的实现是基于JAVA的代理机制, 从JDK1.3开始就支持代理功能, 但是性能成为一个很大问题, 为了解决JDK代理性能问题, 出现了CGLIB代理机制.它可以生成字节码, 所以它 ...

  8. 133. leetcode-Clone Graph

    拷贝图,可以一边遍历一边拷贝 DFS class Solution { public: Node* cloneGraph(Node* node) { unordered_map<int, Nod ...

  9. 《响应式Web设计实践》学习笔记

    原书: 响应式Web设计实践 目录: 第2章 流动布局 1. 布局选项 2. 字体大小 3. 网格布局 4. 混合固定宽度和流动宽度 第3章 媒介查询 1. 视口 2. 媒介查询结构 3. 内嵌样式与 ...

  10. WordPress图片或文字添加水印插件:Easy Watermark

    Easy Watermark可以在上传到WordPress媒体库时自动为图像添加水印.您也可以手动为现有图像添加水印(一次全部或每个图像).水印可以是图像,文本或两者. 插件功能 图像水印可以是jpg ...