The
http.FileServer
method belongs to the standard library
net/http
and returns an HTTP processor that uses the FileSystem interface root to provide file access services. A static file server can be implemented conveniently.
http.ListenAndServe(":8080", http.FileServer(http.Dir("/files/path")))
Access http://127.0.0.1:8080
, you can see similar Nginx in the autoindex
directory browsing function.
SOURCE parsing
Let's start by dissecting the only line of code above and see how it's done. The source code in the English note is also more detailed, can refer to.
We look at it, http.Dir()
look at http.FileServer()
it, listen to the http.ListenAndServe()
TCP port and provide the routing service, not here.
http. Dir ()
From the following source code we can see that the type Dir string
implementation type FileSystem interface
of the interface function Open
, the http.Dir("/")
actual return is the http.Dir
type, the string path into the file system.
// 所属文件: src/net/http/fs.go, 26-87行type Dir stringfunc (d Dir) Open(name string) (File, error) { // ...}type FileSystem interface { Open(name string) (File, error)}
http. Fileserver ()
http.FileServer()
method returns an fileHandler
instance, and the fileHandler
struct implements the Handler
method of the interface ServeHTTP()
. ServeHTTP
the core in the method is the serveFile()
method.
// 所属文件: 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()
method to determine if the access path is a directory, the directory content is listed, if the file is used to output the contents of the serveContent()
file. The serveContent()
method is a way to read the contents of the file and output it, and no more code is posted here.
// 所属文件: 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)}
Supports subdirectory paths
http.StripPrefix()
The method mates http.Handle()
or http.HandleFunc()
can implement a file service that is prefixed by the lead.
package mainimport ( "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) }}
Original address: Https://shockerli.net/post/go
...