使用golang的http.FileServer()时,目录列出了错误的链接

3
我将使用Go语言中的http.FileServer来提供某个目录下的静态文件。
以下是我使用mux作为路由器进行映射的方法:
r.PathPrefix("/download").Handler(http.StripPrefix("/download", http.FileServer(http.Dir(dirPath)))).Methods("GET")

其中dirPath是我文件系统中一个目录的绝对路径。

现在,当使用localhost:8080/download请求目录列表时,似乎能够正常工作,因为它返回了这样一个页面。

<pre>
<a href="a.xml">a.xml</a>
<a href="b.xml">b.zip</a>
</pre>

很不幸,链接已损坏,因为我期望它们被映射到例如localhost:8080/download/a.xml,但文件服务器将它们映射到localhost:8080/a.xml

我该如何使我的目录列表中的链接保留/download路径前缀?

1个回答

6
问题在于您使用的处理程序模式:"/download"
它存在两个问题:
  1. 生成的URL是错误的,因为由http.FileServer()函数生成的处理程序会生成相对于传递给http.FileServer()的根文件夹的文件和子文件夹的URL;如果您的页面可在路径/download下使用,则类似于href="a.xml"的相对URL将被解析为/a.xml,而不是/download/a.xml

  2. 即使URL正确,文件也无法服务,因为请求不会路由到您的处理程序(文件服务器处理程序)。您必须添加一个斜杠,因为"/download"仅匹配此单个路径,而不是所有以其开头的路径。添加一个斜杠:"/download/",它将匹配根子树/download/*

因此解决方案是:
r.PathPrefix("/download/").Handler(
    http.StripPrefix("/download", http.FileServer(http.Dir(dirPath))),
).Methods("GET")

这在http.ServeMux中有记录:

模式命名了固定的根路径,如 "/favicon.ico",或者以根路径为前缀的子树,如 "/images/"(注意末尾的斜杠)。

请注意,即使我们现在使用了注册路径"/download/",用户在浏览器中输入时也不需要添加末尾的斜杠,因为服务器会自动将其重定向到以斜杠结尾的路径。这也在http.ServeMux中有记录:

如果已经注册了子树并且接收到的请求命名了子树根而没有其末尾的斜杠,ServeMux会将该请求重定向到该子树根(添加末尾的斜杠)。可以通过单独注册没有末尾斜杠的路径来覆盖此行为。例如,注册"/images/"会导致ServeMux将对“/images”的请求重定向到“/images/”,除非已单独注册“/images”。

阅读相关问题:Go web server is automatically redirecting POST requests

这里是一个仅使用标准库的简单文件服务器应用:

http.Handle("/dl/",
    http.StripPrefix("/dl", http.FileServer(http.Dir("/home/bob/Downloads"))),
)
panic(http.ListenAndServe("localhost:8080", nil))

你说得对。调用者必须在URL中输入尾部斜杠吗:localhost:8080/download/? - Andrea Castello
@AndreaCastello 不需要,因为服务器会发送重定向指令,浏览器会自动跟随。请参考修改后的答案。你可以自己试一下。 - icza
@AndreaCastello 请查看修订后的答案,已添加关于错误URL的解释。 - icza

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