为什么我需要使用http.StripPrefix来访问我的静态文件?

53

main.go

package main

import (
    "net/http"
)

func main() {
    http.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.Dir("static"))))
    http.ListenAndServe(":8080", nil)
}

目录结构:

%GOPATH%/src/project_name/main.go
%GOPATH%/src/project_name/static/..files and folders ..

即使阅读了文档,我仍然很难理解在这里 http.StripPrefix 到底做了什么。

1) 如果我删除 http.StripPrefix,为什么我无法访问 localhost:8080/static

2) 如果我删除该函数,哪个URL将映射到 /static 文件夹?


你尝试过使用 http.Handle("/static/", http.FileServer(http.Dir("/"))) 吗? - Muktadir
http.Handle("/static/", http.FileServer(http.Dir(""))) 运行正常。 - Sunny
4个回答

67

http.StripPrefix()将请求的处理转发到您指定的函数,但在此之前它会通过删除指定的前缀来修改请求URL。

例如,在您的情况下,如果浏览器(或HTTP客户端)请求资源:

/static/example.txt

StripPrefix将会剪切掉/static/,并将修改后的请求转发给http.FileServer()返回的处理程序,以便其能够看到所请求的资源是什么。

/example.txt
http.FileServer()返回的Handler将会在指定的文件夹(或者更确切地说是FileSystem)中寻找和提供一个文件的内容,并且这个文件名是相对于函数参数指定的根目录"static"的路径。由于"example.txt"static文件夹下,你需要指定一个相对路径以获取正确的文件路径。

另一个例子可以在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",我们希望服务器发送文件 "/tmp/example.txt"

为了实现这一点,我们必须从 URL 中去除 "/tmpfiles",剩下的部分将是相对于根文件夹 "/tmp" 的相对路径,如果我们连接起来,则为:

/tmp/example.txt

8
阅读此内容的任何人,请确保在“/tmpfiles/”中有尾部斜杠,否则您将会遇到麻烦。 - daino3
3
为了澄清和传播正确的常识,Handle 中的 /tmpfile/ 很重要,但在 StripPrefix 中不是必须的。比如说 http.Handle("/tmpfiles/", http.StripPrefix("/tmpfiles", http.FileServer(http.Dir("/tmp")))) 也可以正常工作。 - Amazingandyyy

17

假设

我有一个文件。

/home/go/src/js/kor.js

然后,告诉fileserve服务本地目录。

fs := http.FileServer(http.Dir("/home/go/src/js"))

示例1 - 根URL到Filerserver根目录

现在,文件服务器将"/"请求视为"/home/go/src/js"+"/"

http.Handle("/", fs)

是的,http://localhost/kor.js 的请求告诉文件服务器,在

kor.js中查找

"/home/go/src/js" +  "/"  + "kor.js".

我们得到了kor.js文件。

示例2 - 自定义URL到文件服务器根目录

但是,如果我们添加额外的请求名称。

http.Handle("/static/", fs)

现在文件服务器将"/static/"请求视为"/home/go/src/js"+"/static/"

是的,http://localhost/static/kor.js请求告诉文件服务器,在

"/home/go/src/js" +  "/static/"  + "kor.js".

我们遇到了404错误。

示例3-使用自定义URL访问Fileserver根目录

所以,在Fileserver接收请求之前,我们使用http.StripPrefix("/tmpfiles/", ...对请求URL进行了修改。

stripPrefix之后,Fileserver将采用/而不是/static/

"/home/go/src/js" +  "/"  + "kor.js".

得到了 kor.js


2

我会逐一回答这两个问题。

问题1的答案1: 如果你的代码像下面这样编写:

http.Handle("/static/", http.FileServer(http.Dir("static"))

您的根目录是%GOPATH%/src/project_name/static/。当您访问localhost:8080/static时,URL /static将被转发到由http.FileServer()返回的处理程序。然而,在根文件夹中没有名为static的目录或文件。
回答2的问题2:通常情况下,如果您删除http.StripPrefix(),则无法访问/static文件夹。但是,如果您有一个名为static的目录或文件,您可以使用URLlocalhost:8080:/static访问它(确切地说不是您想要的根目录)。
顺便说一下,如果您的URL不以/static开头,因为http.ServeMux不会重定向您的请求,所以您无法访问任何内容。

0
对于遇到子目录问题的人,你需要添加一个".",因为它似乎只将路径视为相对路径,如果它是二进制根目录中的文件夹。
例如
s.router.PathPrefix("/logos/").Handler(
        http.StripPrefix("/logos/", http.FileServer(http.Dir("./uploads/logos/"))))

请注意在“/uploads”之前的“.”

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接