http.StripPrefix在File Server中的用途
一. 保持代码的整洁和进行合理的分流
http.StripPrefix函数的作用之一,就是在将请求定向到你通过参数指定的请求处理处之前,将特定的prefix从URL中过滤出去。下面是一个浏览器或HTTP客户端请求资源的例子:
/static/example.txt
StripPrefix 函数将会过滤掉/static/,并将修改过的请求定向到http.FileServer所返回的Handler中去,因此请求的资源将会是:
/example.txt
http.FileServer 返回的Handler将会进行查找,并将与文件夹或文件系统有关的内容以参数的形式返回给你(在这里你将"static"作为静态文件的根目录)。因为你的"example.txt"文件在静态目录中,你必须定义一个相对路径去获得正确的文件路径。
二. 根据需要定制访问路径
下面这个例子可以在http包的文档中找到:
// To serve a directory on disk (/tmp) under an alternate URL
// path (/tmpfiles/), use StripPrefix to modify the request
// URL's path before the FileServer sees it:
http.Handle("/tmpfiles/",
http.StripPrefix("/tmpfiles/", http.FileServer(http.Dir("/tmp"))))
FileServer 已经明确静态文件的根目录在"/tmp",但是我们希望URL以"/tmpfiles/“开头。如果有人请求”/tempfiles/example.txt",我们希望服务器能将文件发送给他。为了达到这个目的,我们必须从URL中过滤掉"/tmpfiles", 而剩下的路径是相对于根目录"/tmp"的相对路径。如果我们按照如上做法,将会得到如下结果:
/tmp/example.txt
http.FileServer通常要跟http.StripPrefix结合使用
用go写一个文件服务器很简单:
http.handle(“/”, http.FileServer(http.Dir(“doc”))
http.ListenAndServe(":8888”, nil)
打开localhost:8888,就能看到doc目录下的所有文件。
但如果,你想用localhost:8888/doc来显示进入文件目录,则需要
http.Handle(“/doc", http.StripPrefix(“/doc", http.FileServer(http.Dir(“doc"))))
http.StripPrefix用于过滤request,参数里的handler的request过滤掉特定的前序,只有这样,才能正确显示文件目录。
注意:需要/doc/这样设置前缀,否则,能看到目录,没办法下载。
Golang1.8标准库http.Fileserver跟http.ServerFile小例子
package main
import (
"fmt"
"net/http"
"os"
"path"
"strings"
)
var staticfs = http.FileServer(http.Dir("D:\\code\\20160902\\src\\"))
func main() {
//浏览器打开的时候显示的就是D:\\code\\20160902\\src\\client目录下的内容"
http.Handle("/client/", http.FileServer(http.Dir("D:\\code\\20160902\\src\\")))
http.HandleFunc("/static/", static)
http.HandleFunc("/js/", js)
http.HandleFunc("/", route)
http.ListenAndServe(":1789", nil)
}
func route(w http.ResponseWriter, r *http.Request) {
fmt.Println(r.URL)
fmt.Fprintln(w, "welcome")
r.Body.Close()
}
//这里可以自行定义安全策略
func static(w http.ResponseWriter, r *http.Request) {
fmt.Printf("访问静态文件:%s\n", r.URL.Path)
old := r.URL.Path
r.URL.Path = strings.Replace(old, "/static", "/client", 1)
staticfs.ServeHTTP(w, r)
}
//设置单文件访问,不能访问目录
func js(w http.ResponseWriter, r *http.Request) {
fmt.Printf("不能访问目录:%s\n", r.URL.Path)
old := r.URL.Path
name := path.Clean("D:/code/20160902/src" + strings.Replace(old, "/js", "/client", 1))
info, err := os.Lstat(name)
if err == nil {
if !info.IsDir() {
http.ServeFile(w, r, name)
} else {
http.NotFound(w, r)
}
} else {
http.NotFound(w, r)
}
}
文件下载
package main
import (
"net/http"
"path/filepath"
)
func main() {
http.HandleFunc("/download", download)
http.ListenAndServe(":8080", nil)
}
func download(w http.ResponseWriter, r *http.Request) {
file := r.FormValue("file")
path := filepath.Join(`c:\share`, file)
http.ServeFile(w, r, path)
}
代码
http.Handle("/js/", http.StripPrefix("/js/", http.FileServer(http.Dir("js"))))
http.ListenAndServe("8080", nil)
http.StripPrefix用于过滤request,参数里的handler的request过滤掉特定的前序,只有这样,才能正确显示文件目录。
看一下我的路径 以及下面存放的文件
结果如下: