Parse Go standard library ES1en.FileServer to implement static file service
- 2020-06-15 09:15:51
- OfStack
The http. FileServer method belongs to the standard library net/http and returns an HTTP processor that provides file access services using the FileSystem interface root. Static file server can be easily implemented.
http.ListenAndServe(":8080", http.FileServer(http.Dir("/files/path")))
Visit http://127.0.0.1:8080 to see autoindex directory browsing similar to Nginx.
The source code parsing
Let's now go through the 1 line above and see how it works. Source in English and Chinese annotations are more detailed, you can refer to.
Let's look at http. Dir(), then http. FileServer(), and
http.ListenAndServe()
Listens on TCP port and provides routing services, which will not be described here.
http.Dir()
From the following source code we can see that type Dir string implements type FileSystem interface's interface function Open, http.Dir ("/") actually returns the http.Dir type to convert the string path to the file system.
// Belongs to the file : src/net/http/fs.go, 26-87 line
type Dir string
func (d Dir) Open(name string) (File, error) {
// ...
}
type FileSystem interface {
Open(name string) (File, error)
}
http.FileServer()
http.FileServer() Method returns fileHandler Instance, fileHandler The structure is implemented Handler Methods of interfaces ServeHTTP() . ServeHTTP The core of the method is serveFile() Methods.
// Belongs to the file : src/net/http/fs.go, 690-716 line
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)
}
// Belongs to the file : src/net/http/server.go, 82 line
type Handler interface {
ServeHTTP(ResponseWriter, *Request)
}
serveFile()
Method to list the contents of a directory if the access path is a directory, or a file
serveContent()
Method outputs the file contents.
serveContent()
Method is a method that reads the contents of the file and outputs it. No more code is posted here.
// Belongs to the file : src/net/http/fs.go, 540 line
// name is '/'-separated, not filepath.Separator.
func serveFile(w ResponseWriter, r *Request, fs FileSystem, name string, redirect bool) {
// The intermediate code has been omitted
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)
}
Subdirectory paths are supported
http.StripPrefix()
Methods with
http.Handle()
or
http.HandleFunc()
You can implement a routing file service with a prefix.
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)
}
}
conclusion