如何自定义处理在使用go静态文件服务器时找不到的文件



所以我使用go服务器来提供单页web应用程序。

这适用于为根路由上的所有资产提供服务。所有的CSS和HTML都是正确的。

fs := http.FileServer(http.Dir("build"))
http.Handle("/", fs)

因此,当URL是http://myserverurl/index.htmlhttp://myserverurl/styles.css时,它为相应的文件提供服务。

但是对于像http://myserverurl/myCustompage这样的URL,如果myCustompage不是构建文件夹中的文件,它就会抛出404

如何使不存在文件的所有路由都为index.html服务?

它是一个单页web应用程序,一旦提供了html和js,它就会呈现相应的屏幕。但它需要index.html在没有文件的路由上提供服务。

如何做到这一点?

http.FileServer()返回的处理程序不支持自定义,不支持提供自定义的404页面或操作。

我们可以做的是包装http.FileServer()返回的处理程序,当然,在我们的处理程序中,我们可以做任何我们想做的事情。在我们的包装器处理程序中,我们将调用文件服务器处理程序,如果这将发送一个404未找到响应,我们不会将其发送到客户端,而是用重定向响应替换它。

为了实现这一点,在我们的包装器中,我们创建了一个包装器http.ResponseWriter,我们将把它传递给http.FileServer()返回的处理程序,在这个包装器响应编写器中我们可以检查状态代码,如果它是404,我们可以采取而不是向客户端发送响应,而是向/index.html发送重定向。

这是这个包装器http.ResponseWriter的一个例子:

type NotFoundRedirectRespWr struct {
http.ResponseWriter // We embed http.ResponseWriter
status              int
}
func (w *NotFoundRedirectRespWr) WriteHeader(status int) {
w.status = status // Store the status for our own use
if status != http.StatusNotFound {
w.ResponseWriter.WriteHeader(status)
}
}
func (w *NotFoundRedirectRespWr) Write(p []byte) (int, error) {
if w.status != http.StatusNotFound {
return w.ResponseWriter.Write(p)
}
return len(p), nil // Lie that we successfully written it
}

并且包装http.FileServer()返回的处理程序可能如下所示:

func wrapHandler(h http.Handler) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
nfrw := &NotFoundRedirectRespWr{ResponseWriter: w}
h.ServeHTTP(nfrw, r)
if nfrw.status == 404 {
log.Printf("Redirecting %s to index.html.", r.RequestURI)
http.Redirect(w, r, "/index.html", http.StatusFound)
}
}
}

请注意,我使用了http.StatusFound重定向状态代码,而不是http.StatusMovedPermanently,因为后者可能会被浏览器缓存,因此如果稍后创建具有该名称的文件,浏览器不会请求它,而是立即显示index.html

现在使用main()函数:

func main() {
fs := wrapHandler(http.FileServer(http.Dir(".")))
http.HandleFunc("/", fs)
panic(http.ListenAndServe(":8080", nil))
}

试图查询一个不存在的文件,我们会在日志中看到:

2017/11/14 14:10:21 Redirecting /a.txt3 to /index.html.
2017/11/14 14:10:21 Redirecting /favicon.ico to /index.html.

请注意,我们的自定义处理程序(行为良好)还将请求重定向到/favico.icoindex.html,因为我的文件系统中没有favico.ico文件。如果你也没有,你可能想把它作为一个例外来添加。

完整的示例可在Go Playground上找到。您不能在那里运行它,请将它保存到本地Go工作区并在本地运行。

还要查看这个相关的问题:在http上记录404。FileServer

相关内容

  • 没有找到相关文章

最新更新