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

2023-11-26

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

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

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

所以当网址是http://myserverurl/index.html or http://myserverurl/styles.css,它提供相应的文件。

但对于像这样的 URLhttp://myserverurl/myCustompage,它抛出404 if myCustompage不是构建文件夹中的文件。

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

它是一个单页 Web 应用程序,一旦提供 html 和 js,它将呈现适当的屏幕。但它需要index.html在没有文件的路线上提供服务。

如何才能做到这一点?


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

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

为了实现这一点,在我们的包装器中,我们创建了一个包装器http.ResponseWriter我们将其传递给返回的处理程序http.FileServer(),在这个包装器响应编写器中,我们可以检查状态代码,如果它是404,我们可以采取行动not将响应发送到客户端,但将重定向发送到/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.ico to index.html因为我没有favico.ico我的文件系统中的文件。如果您也没有,您可能希望将其添加为例外。

完整的示例可以在去游乐场。您无法在那里运行它,请将其保存到本地 Go 工作区并在本地运行。

另请检查此相关问题:http.FileServer 上记录 404

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

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