显示带有标准http包的自定义404错误页面

sha*_*hin 63 go

假设我们有:

http.HandleFunc("/smth", smthPage)
http.HandleFunc("/", homePage)
Run Code Online (Sandbox Code Playgroud)

用户在尝试错误的网址时会看到一个简单的"找不到404页面".如何为该案例返回自定义页面?

有关大猩猩/多路复用的更新

对于使用纯net/http包的人来说,接受的答案是可以接受的.

如果你使用gorilla/mux,你应该使用这样的东西:

func main() {
    r := mux.NewRouter()
    r.NotFoundHandler = http.HandlerFunc(notFound)
}
Run Code Online (Sandbox Code Playgroud)

func notFound(w http.ResponseWriter, r *http.Request)并按您的意愿实施.

Mos*_*afa 61

我经常这样做:

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")
    }
}
Run Code Online (Sandbox Code Playgroud)

在这里,我简化了代码以仅显示自定义404,但实际上我使用此设置做了更多:我处理所有HTTP错误errorHandler,其中我记录了有用的信息并向我自己发送电子邮件.

  • 至少从Go 1.7开始,这个答案仍然是正确的,但是"模式"/"匹配所有与其他注册模式不匹配的路径".只有homeHandler或"/"才需要在此示例中对errorHandler进行条件检查. (5认同)
  • @RomaH除非你想匹配`/ smth /`但不匹配`/ smth/foo`,在这种情况下它会属于smthHandler而不会引发错误. (2认同)

zel*_*lda 5

以下是我选择的方法。它基于一个代码片段,由于我丢失了浏览器书签,因此我无法确认。

示例代码:(我将其放在主程序包中)

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

请自定义,func fire404以输出您自己的错误消息版本404。

如果您碰巧正在使用Gorilla Mux,则不妨将主要功能替换为以下内容:

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));
}
Run Code Online (Sandbox Code Playgroud)

如果我输入的是错误的代码,请改正该代码,因为我只是新手。谢谢。