Showing custom 404 error page with standard http package

问题描述 投票:0回答:8

我们拥有:

http.HandleFunc("/smth", smthPage)
http.HandleFunc("/", homePage)

用户在尝试错误的URL时会看到一个普通的“未找到404页”。如何返回该情况的自定义页面?

关于大猩猩/mux

的update 对于使用纯NET/HTTP软件包的人来说是可以的答案。

如果您使用大猩猩/Mux,则应使用类似的东西:

func main() { r := mux.NewRouter() r.NotFoundHandler = http.HandlerFunc(notFound) }

并根据需要实现
func notFound(w http.ResponseWriter, r *http.Request)

我通常这样做:

package main import ( "fmt" "net/http" ) func main() { http.HandleFunc("/", homeHandler) http.HandleFunc("/smth/", smthHandler) http.ListenAndServe(":12345", nil) } func homeHandler(w http.ResponseWriter, r *http.Request) { if r.URL.Path != "/" { errorHandler(w, r, http.StatusNotFound) return } fmt.Fprint(w, "welcome home") } func smthHandler(w http.ResponseWriter, r *http.Request) { if r.URL.Path != "/smth/" { errorHandler(w, r, http.StatusNotFound) return } fmt.Fprint(w, "welcome smth") } func errorHandler(w http.ResponseWriter, r *http.Request, status int) { w.WriteHeader(status) if status == http.StatusNotFound { fmt.Fprint(w, "custom 404") } }
go
8个回答
91
投票
这里我简化了代码仅显示自定义404,但是我实际上在此设置中做了更多:我处理所有HTTP错误,其中我会记录有用的信息并将电子邮件发送给我自己。

我选择的方法是遵循的方法。它是基于代码段,因为我丢失了浏览器书签,因此我无法承认。
样本代码:(我将其放在我的主包中)

errorHandler

求职自定义

type hijack404 struct { http.ResponseWriter R *http.Request Handle404 func (w http.ResponseWriter, r *http.Request) bool } func (h *hijack404) WriteHeader(code int) { if 404 == code && h.Handle404(h.ResponseWriter, h.R) { panic(h) } h.ResponseWriter.WriteHeader(code) } func Handle404(handler http.Handler, handle404 func (w http.ResponseWriter, r *http.Request) bool) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request){ hijack := &hijack404{ ResponseWriter:w, R: r, Handle404: handle404 } defer func() { if p:=recover(); p!=nil { if p==hijack { return } panic(p) } }() handler.ServeHTTP(hijack, r) }) } func fire404(res http.ResponseWriter, req *http.Request) bool{ fmt.Fprintf(res, "File not found. Please check to see if your URL is correct."); return true; } func main(){ handler_statics := http.StripPrefix("/static/", http.FileServer(http.Dir("/Path_To_My_Static_Files"))); var v_blessed_handler_statics http.Handler = Handle404(handler_statics, fire404); http.Handle("/static/", v_blessed_handler_statics); // add other handlers using http.Handle() as necessary if err := http.ListenAndServe(":8080", nil); err != nil{ log.Fatal("ListenAndServe: ", err); } }

8
投票
如果您碰巧使用大猩猩Mux,则可能希望用以下方式替换主要功能:

func fire404

如果我只是一个新手,请谨校正代码。谢谢

我认为干净的方式是:

func main(){
    handler_statics := http.StripPrefix("/static/", http.FileServer(http.Dir("/Path_To_My_Static_Files")));

    var v_blessed_handler_statics http.Handler = Handle404(handler_statics, fire404);

    r := mux.NewRouter();
    r.PathPrefix("/static/").Handler(v_blessed_handler_statics);

    // add other handlers with r.HandleFunc() if necessary...

    http.Handle("/", r);

    log.Fatal(http.ListenAndServe(":8080", nil));
}

如果地址不是 /calulator或 /历史记录,则它可以处理NotFoundHandler函数。

随机线程,但我只是做了一些要拦截的线程,在这里可能很重要。

func main() { http.HandleFunc("/calculator", calculatorHandler) http.HandleFunc("/history", historyHandler) http.HandleFunc("/", notFoundHandler) log.Fatal(http.ListenAndServe(":80", nil)) }


5
投票
Maybe我错了,但我只是检查了来源:

http://golang.org/src/pkg/net/http/server.go

IT似乎几乎不可能指定Custo notfound()函数:notfoundhandler()返回一个名为notfound()的硬编码函数。

可能,您应该在此提交一个问题。

为了解决方法,您可以使用“/”处理程序,如果找不到其他处理程序(因为它是最短的),这将是后备。因此,该处理程序中存在检查页面并返回自定义404错误。

3
投票

您只需要创建自己的未发现处理程序,然后用thangefunc注册它,以确保您不处理的路径。

如果您需要对路由逻辑的最大控制权,则需要使用自定义服务器和自己的自定义处理程序类型。

Http://golang.org/pkg/net/http/#handler

2
投票

Http://golang.org/pkg/net/http/#server

这使您可以实现比HandleFunc允许您这样做的更复杂的路由逻辑。

您可以定义

http.ResponseWriter


2
投票

简而言之,只需检查R.URL.Path是否匹配您期望找到的URL,例如通过循环浏览一系列页面即可。 Requiring an exact URL match, you avoid the catchall problem pointed out by @RomaH

现在我在一个称为drawpage的函数中执行此操作:
  • package main //GAE POC originally inspired by https://thornelabs.net/2017/03/08/use-google-app-engine-and-golang-to-host-a-static-website-with-same-domain-redirects.html import ( "net/http" ) func init() { http.HandleFunc("/", handler) } // HeaderWriter is a wrapper around http.ResponseWriter which manipulates headers/content based on upstream response type HeaderWriter struct { original http.ResponseWriter done bool } func (hw *HeaderWriter) Header() http.Header { return hw.original.Header() } func (hw *HeaderWriter) Write(b []byte) (int, error) { if hw.done { //Silently let caller think they are succeeding in sending their boring 404... return len(b), nil } return hw.original.Write(b) } func (hw *HeaderWriter) WriteHeader(s int) { if hw.done { //Hmm... I don't think this is needed... return } if s < 400 { //Set CC header when status is < 400... //TODO: Use diff header if static extensions hw.original.Header().Set("Cache-Control", "max-age=60, s-maxage=2592000, public") } hw.original.WriteHeader(s) if s == 404 { hw.done = true hw.original.Write([]byte("This be custom 404...")) } } func handler(w http.ResponseWriter, r *http.Request) { urls := map[string]string{ "/example-post-1.html": "https://example.com/post/example-post-1.html", "/example-post-2.html": "https://example.com/post/example-post-2.html", "/example-post-3.html": "https://example.com/post/example-post-3.html", } w.Header().Set("Strict-Transport-Security", "max-age=15768000") //TODO: Put own logic if value, ok := urls[r.URL.Path]; ok { http.Redirect(&HeaderWriter{original: w}, r, value, 301) } else { http.ServeFile(&HeaderWriter{original: w}, r, "static/"+r.URL.Path) } } last部分取自 @许晨峰
  • 在此处添加一个更新的答案,因为我相信GO已在提出这个问题以来已经在标准库中实现了一些新功能。 现在您可以简单地做到这一点:
  • http.HandleFunc("/", func(writer http.ResponseWriter, request *http.Request) { if request.URL.Path != "/" { writer.WriteHeader(404) writer.Write([]byte(`not found, da xiong dei !!!`)) return } })

您可以简单地使用以下内容:

0
投票
is404 := true // assume the worst // start loop through a data structure of all my pages if (r.URL.Path == data.Options[i].URL) { is404 = false } // end loop if is404 { // failed our test w.WriteHeader(404) w.Write([]byte(`404 not found`)) return } // draw the page we found

如果您需要获得标准,只需写:
http.HandleFunc("/smth", smthPage)
http.HandleFunc("/{$}", homePage)  // {$} represents the end of the URL
http.HandleFunc("/", custom404Page)

你会得到:

0
投票
func Handle404(w http.ResponseWriter, r *http.Request) { fmt.Fprint(w, "404 error\n") } func main(){ http.HandleFunc("/", routes.Handle404) }

最新问题
© www.soinside.com 2019 - 2025. All rights reserved.