Affichage d’une page d’erreur 404 personnalisée avec un package http standard

En supposant que nous avons:

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

L’utilisateur voit une “page 404 non trouvée” quand il tente une URL incorrecte. Comment puis-je retourner une page personnalisée pour cette affaire?

Mise à jour concernant Gorilla / mux

La réponse acceptée est correcte pour ceux qui utilisent le package net / http pur.

Si vous utilisez gorilla / mux, vous devriez utiliser quelque chose comme ceci:

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

Et implémentez func notFound(w http.ResponseWriter, r *http.Request) comme vous voulez.

Je le fais habituellement:

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

Ici, j’ai simplifié le code pour afficher uniquement le 404 personnalisé, mais je fais plus avec cette configuration: je gère toutes les erreurs HTTP avec errorHandler , dans lequel je me connecte des informations utiles et errorHandler courrier électronique.

Vous devez juste créer votre propre gestionnaire notFound et l’enregistrer avec HandleFunc pour le chemin que vous ne gérez pas.

Si vous souhaitez avoir le plus grand contrôle sur votre logique de routage, vous devrez utiliser un type de serveur personnalisé et un gestionnaire personnalisé.

Cela vous permet d’implémenter une logique de routage plus complexe que celle que HandleFunc vous permettra de faire.

Voici l’approche que je choisis. Il est basé sur un extrait de code que je ne peux pas reconnaître depuis que j’ai perdu le signet du navigateur.

Exemple de code: (je l’ai mis dans mon paquet principal)

 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, hR) { 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.SsortingpPrefix("/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); } } 

Veuillez personnaliser le func fire404 pour sortir votre propre version du message pour l’erreur 404.

Si vous utilisez Gorilla Mux, vous pouvez remplacer la fonction principale ci-dessous:

 func main(){ handler_statics := http.SsortingpPrefix("/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)); } 

S’il vous plaît veuillez corriger le code si c’est faux, puisque je ne suis qu’un débutant à Go. Merci.

Un fil ancien, mais je viens de faire quelque chose pour intercepter http.ResponseWriter , pourrait être pertinent ici.

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

Peut-être que je me trompe, mais je viens de vérifier les sources: http://golang.org/src/pkg/net/http/server.go

Il semble que spécifier une fonction NotFound () personnalisée soit difficilement possible: NotFoundHandler () renvoie une fonction codée en dur appelée NotFound ().

Vous devriez probablement soumettre un problème à ce sujet.

En guise de solution de contournement, vous pouvez utiliser votre gestionnaire “/”, qui est une solution de secours si aucun autre gestionnaire n’a été trouvé (car c’est le plus court). Donc, check is page existe dans ce gestionnaire et renvoie une erreur 404 personnalisée.