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 的接口函数 Openhttp.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/

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. windows 10 安装可视化mycat

    前提: 1.安装配置好JDK环境 2.安装配置好mysql 3.安装配置好Navicat 一.下载mycat git:https://github.com/MyCATApache/Mycat-down ...

  2. Object constructor

    1. Object is an instance of Function.2. Object does not have a property called constructor so when w ...

  3. mysql的like子句

    直接上例子 查询字段以 php 开头的信息. SELECT * FROM position WHERE name LIKE 'php%'; 查询字段包含 php 的信息. SELECT * FROM ...

  4. 为什么重写equals一定要重写hashCode?

    大家都知道,equals和hashcode是java.lang.Object类的两个重要的方法,在实际应用中常常需要重写这两个方法,但至于为什么重写这两个方法很多人都搞不明白,以下是我的一些个人理解. ...

  5. 汇总java生态圈常用技术框架、开源中间件,系统架构及经典案例等

    转自:http://www.51testing.com/html/83/n-3718883.html 有人认为编程是一门技术活,要有一定的天赋,非天资聪慧者不能及也.非也,这是近几年,对于技术这碗饭有 ...

  6. springboot的拦截器Interceptor的性质

    Interceptor在springboot2.x版本的快速入门 实现HandlerInterceptor的接口,并重载它的三个方法:preHandle.postHandle.afterComplet ...

  7. uintAPi 之Renderer.material

    Renderer.material public Material material; Returns the first instantiated Material assigned to the ...

  8. Openvswitch手册(4): Mirror

    这一节我们来分析Mirror Mirror就是配置一个bridge,将某些包发给指定的mirrored ports 对于包的选择: select_all,所有的包 select_dst_port se ...

  9. 图片处理类 类库--C#

    调用如下: Bitmap bitmap = new Bitmap("C:\\Users\\Thinkpad\\Desktop\\aa.jpg"); Bitmap[] bit = n ...

  10. python爬虫学习之日志记录模块

    这次的代码就是一个日志记录模块,代码很容易懂,注释很详细,也不需要安装什么库.提供的功能是日志可以显示在屏幕上并且保存在日志文件中.调用的方式也很简单,测试代码里面有. 源代码: #encoding= ...