Golang实现静态服务器详解
来源:互联网 发布:2016全国人口流动数据 编辑:程序博客网 时间:2024/05/22 18:50
Golang实现静态服务器详解
Go的http库已经做了很好的底层封装,所以用该库可以用很简单的几十行代码编写一个http静态服务器。下面我们就具体分析一下http库对静态服务器的具体实现。
package mainimport ("net/http")func StaticServer(w http.ResponseWriter, r *http.Request) {http.StripPrefix("/", http.FileServer(http.Dir("./static/"))).ServeHTTP(w, r)}func main() {http.HandleFunc("/", StaticServer)http.ListenAndServe(":8080", nil)}以上代码,在本地8080端口上打开一个http服务,可以访问当前目录下的static文件夹下的内容。具体实现都封装在http库里面了,好在go语言的库都是提供源代码的,我们可以一窥其全貌。
http服务实现部分我将会用另外一篇文章做说明,这里只讲http静态文件部分,即 以下这句代码的实现细节:
http.StripPrefix("/", http.FileServer(http.Dir("./static/"))).ServeHTTP(w, r)
首先 http.Dir("./static/") 这个结构体在“\Go\src\net\http\fs.go” 文件中实现,代码如下:
// A Dir implements FileSystem using the native file system restricted to a// specific directory tree.//// While the FileSystem.Open method takes '/'-separated paths, a Dir's string// value is a filename on the native file system, not a URL, so it is separated// by filepath.Separator, which isn't necessarily '/'.//// An empty Dir is treated as ".".type Dir stringfunc (d Dir) Open(name string) (File, error) {if filepath.Separator != '/' && strings.IndexRune(name, filepath.Separator) >= 0 ||strings.Contains(name, "\x00") {return nil, errors.New("http: invalid character in file path")}dir := string(d)if dir == "" {dir = "."}f, err := os.Open(filepath.Join(dir, filepath.FromSlash(path.Clean("/"+name))))if err != nil {return nil, err}return f, nil}该结构体实现了一个叫做FileSystem 的接口,代码如下:
// A FileSystem implements access to a collection of named files.// The elements in a file path are separated by slash ('/', U+002F)// characters, regardless of host operating system convention.type FileSystem interface {Open(name string) (File, error)}
http.FileServer<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);"> 函数接受一个 <span style="color: rgb(0, 0, 128); background-color: rgb(240, 240, 240);">FileSystem</span> 接口,返回一个</span><span style="font-family: Arial, Helvetica, sans-serif; color: rgb(0, 0, 128);">fileHandler</span><span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);"> 结构体,</span><span style="font-family: Arial, Helvetica, sans-serif; color: rgb(0, 0, 128);">fileHandler</span><span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);"> 实现了http.</span><span style="font-family: Arial, Helvetica, sans-serif; color: rgb(0, 0, 128);">Handler</span><span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);"> 接口 ,具体代码如下: </span>
// FileServer returns a handler that serves HTTP requests// with the contents of the file system rooted at root.//// To use the operating system's file system implementation,// use http.Dir://// http.Handle("/", http.FileServer(http.Dir("/tmp")))//// As a special case, the returned file server redirects any request// ending in "/index.html" to the same path, without the final// "index.html".func FileServer(root FileSystem) Handler {return &fileHandler{root}}
type fileHandler struct {root FileSystem}func (f *fileHandler) ServeHTTP(w ResponseWriter, r *Request) {upath := r.URL.Pathif !strings.HasPrefix(upath, "/") {upath = "/" + upathr.URL.Path = upath}serveFile(w, r, f.root, path.Clean(upath), true)}
// A Handler responds to an HTTP request.//// ServeHTTP should write reply headers and data to the ResponseWriter// and then return. Returning signals that the request is finished; it// is not valid to use the ResponseWriter or read from the// Request.Body after or concurrently with the completion of the// ServeHTTP call.//// Depending on the HTTP client software, HTTP protocol version, and// any intermediaries between the client and the Go server, it may not// be possible to read from the Request.Body after writing to the// ResponseWriter. Cautious handlers should read the Request.Body// first, and then reply.//// If ServeHTTP panics, the server (the caller of ServeHTTP) assumes// that the effect of the panic was isolated to the active request.// It recovers the panic, logs a stack trace to the server error log,// and hangs up the connection.type Handler interface {ServeHTTP(ResponseWriter, *Request)}
最后,http.StripPrefix 函数在“\Go\src\net\http\server.go” 中实现,它接受一个string和一个http.Handler 接口同时返回一个http.Handler 接口,代码如下:
// StripPrefix returns a handler that serves HTTP requests// by removing the given prefix from the request URL's Path// and invoking the handler h. StripPrefix handles a// request for a path that doesn't begin with prefix by// replying with an HTTP 404 not found error.func StripPrefix(prefix string, h Handler) Handler {if prefix == "" {return h}return HandlerFunc(func(w ResponseWriter, r *Request) {if p := strings.TrimPrefix(r.URL.Path, prefix); len(p) < len(r.URL.Path) {r.URL.Path = ph.ServeHTTP(w, r)} else {NotFound(w, r)}})}
// The HandlerFunc type is an adapter to allow the use of// ordinary functions as HTTP handlers. If f is a function// with the appropriate signature, HandlerFunc(f) is a// Handler that calls f.type HandlerFunc func(ResponseWriter, *Request)// ServeHTTP calls f(w, r).func (f HandlerFunc) ServeHTTP(w ResponseWriter, r *Request) {f(w, r)}这里值得注意的是,HandlerFunc 是一个类似C++的仿函数(或者叫函数对象,即实现了函数调符的类对象) 的东西,当HandlerFunc 类型的结构体(其本身是一个函数,可以把同类型的函数强制转换为该结构体) 调用ServeHTTP(w,r) 的时候,就会调用该函数本身,是一个很精妙的实现。
接下来的实现有点繁琐,限于个人水平,不能用文字简单的表达清楚,所以制作了一个xls文件,大家可以下载来看看,连接如下:
Go静态HTTP服务器.xlsx
0 0
- Golang实现静态服务器详解
- golang实现http静态资源服务器
- golang实现图片缩放服务器
- 服务器开发利器golang context用法详解
- Golang搭建静态服务器- 两行代码搞定
- Node实现静态服务器
- golang 建立web服务器 http包源码详解
- Nginx实现静态资源服务器
- Node实现静态服务器2
- nginx实现静态资源服务器
- Go实战--golang实现MP4视频文件服务器(nareix/joy4)
- 静态资源web服务器配置详解
- Nginx作为静态web服务器详解
- Golang 基础 HTTP服务器
- golang websocket 服务器
- 游戏服务器框架 golang
- Golang游戏服务器
- Golang实战【web服务器】
- linux cd 一些用法
- poj 2299 线段树
- 用Maven创建第一个web项目
- IT职业技能图谱:IT工程师学习路线
- 无GPU,ubuntu14.04安装caffe及解决问题
- Golang实现静态服务器详解
- Freemaker 模板生成html文件带barcode4j条形码并转PDF
- 九个uname命令获取Linux系统详情的实例
- Java 使用 Redis
- 关于解决多台服务器间的文件实时同步问题
- HTTP的通信的 发送请求、接收响应 包含哪些内容?OC中是怎样实现的?
- 关于linux下时间延迟函数精度问题
- Cocoa pods最快最新的安装方法
- Activity中的四种启动模式