Program Tip

표준 http 패키지로 사용자 지정 404 오류 페이지 표시

programtip 2020. 12. 5. 10:29
반응형

표준 http 패키지로 사용자 지정 404 오류 페이지 표시


우리가 가지고 있다고 가정하면 :

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

사용자가 잘못된 URL을 입력하면 일반 "404 페이지를 찾을 수 없음"이 표시됩니다. 해당 사례에 대한 사용자 지정 페이지를 반환하려면 어떻게합니까?

Gorilla / Mux 관련 업데이트

순수한 net / http 패키지를 사용하는 사람들에게 허용되는 대답은 괜찮습니다.

gorilla / 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")
    }
}

여기에서는 사용자 지정 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);
    }
}

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));
}

나는 단지 Go를 처음 사용하기 때문에 코드가 틀리면 친절하게 수정하십시오. 감사.


자신 만의 notFound 핸들러를 만들고 처리하지 않는 경로에 대해 HandleFunc에 등록하기 만하면됩니다.

라우팅 논리를 최대한 제어하려면 사용자 지정 서버와 사용자 지정 처리기 유형을 사용해야합니다.

이를 통해 HandleFunc가 허용하는 것보다 더 복잡한 라우팅 로직을 구현할 수 있습니다.


고대의 실이지만, 방금 차단할 무언가를 만들었습니다 http.ResponseWriter. 여기에 관련이있을 수 있습니다.

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)
    }
}

Maybe I'm wrong, but I just checked the sources: http://golang.org/src/pkg/net/http/server.go

It seems like specifying custom NotFound() function is hardly possible: NotFoundHandler() returns a hardcoded function called NotFound().

Probably, you should submit an issue on this.

As a workaround, you can use your "/" handler, which is a fallback if no other handlers were found (as it is the shortest one). So, check is page exists in that handler and return a custom 404 error.


you can define

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
    }
})

when access not found resource, it will execute to http.HandleFunc("/", xxx)

참고URL : https://stackoverflow.com/questions/9996767/showing-custom-404-error-page-with-standard-http-package

반응형