gpt4 book ai didi

go - 使用 Gorilla Mux 和标准 http.FileServer 的自定义 404

转载 作者:IT王子 更新时间:2023-10-29 00:54:24 26 4
gpt4 key购买 nike

我有以下代码,一切正常。

var view404 = template.Must(template.ParseFiles("views/404.html"))

func NotFound(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(404)
err := view404.Execute(w, nil)
check(err)
}

func main() {
router := mux.NewRouter()
router.StrictSlash(true)
router.NotFoundHandler = http.HandlerFunc(NotFound)
router.Handle("/", IndexHandler).Methods("GET")
router.PathPrefix("/public/").Handler(http.StripPrefix("/public/", http.FileServer(http.Dir("public"))))
http.Handle("/", router)
http.ListenAndServe(":8000", nil)
}

对像 /cannot/find 这样的路由的请求显示了我的自定义 404 模板。我的 /public/ 目录中的所有静态文件也都得到了正确的服务。

我在处理不存在的静态文件和为它们显示自定义 NotFound 处理程序时遇到问题。对 /public/cannot/find 的请求调用标准的 http.NotFoundHandler,它回复

404 page not found

如何为普通路由和静态文件设置相同的自定义 NotFoundHandler?


更新

我最终通过包装 http.ServeFile 实现了我自己的 FileHandler,正如@Dewy Broto 所建议的。

type FileHandler struct {
Path string
}

func (f FileHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
prefix := "public"
http.ServeFile(w, r, path.Join(prefix, f.Path))
}

// ...

router.Handle("/css/styles.css", FileHandler{"/css/styles.css"}).Methods("GET")

现在我的 NotFound 处理程序捕获所有丢失的路由,甚至丢失的文件。

最佳答案

文件服务器正在生成 404 响应。 FileServer 处理 mux 传递给它的所有请求,包括丢失文件的请求。有几种方法可以使用自定义 404 页面提供静态文件:

  • 使用 ServeContent 编写您自己的文件处理程序.该处理程序可以以您想要的任何方式生成错误响应。如果您不生成索引页面,代码量并不多。
  • 包装 FileServer处理程序与另一个 Hook ResponseWriter 的处理程序传递给 FileHandler。当 WriteHeader(404) 时,钩子(Hook)会写一个不同的主体被称为。
  • 向 mux 注册每个静态资源,以便 mux 中的 catchall 处理未发现的错误。这种方法需要一个围绕 ServeFile 的简单包装器.

这是第二种方法中描述的包装器的草图:

type hookedResponseWriter struct {
http.ResponseWriter
ignore bool
}

func (hrw *hookedResponseWriter) WriteHeader(status int) {
hrw.ResponseWriter.WriteHeader(status)
if status == 404 {
hrw.ignore = true
// Write custom error here to hrw.ResponseWriter
}
}

func (hrw *hookedResponseWriter) Write(p []byte) (int, error) {
if hrw.ignore {
return len(p), nil
}
return hrw.ResponseWriter.Write(p)
}

type NotFoundHook struct {
h http.Handler
}

func (nfh NotFoundHook) ServeHTTP(w http.ResponseWriter, r *http.Request) {
nfh.h.ServeHTTP(&hookedResponseWriter{ResponseWriter: w}, r)
}

通过包装文件服务器来使用钩子(Hook):

 router.PathPrefix("/public/").Handler(NotFoundHook{http.StripPrefix("/public/", http.FileServer(http.Dir("public")))})

这个简单 Hook 的一个警告是它阻止了服务器中从文件复制到套接字的优化。

关于go - 使用 Gorilla Mux 和标准 http.FileServer 的自定义 404,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26141953/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com