Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Showing custom 404 error page with standard http package

Tags:

go

Assuming that we have:

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

User sees a plain "404 page not found" when they try a wrong URL. How can I return a custom page for that case?

Update concerning gorilla/mux

Accepted answer is ok for those using pure net/http package.

If you use gorilla/mux you should use something like this:

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

And implement func notFound(w http.ResponseWriter, r *http.Request) as you want.

like image 932
shalakhin Avatar asked Apr 03 '12 15:04

shalakhin


2 Answers

I usually do this:

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

Here I've simplified the code to only show custom 404, but I actually do more with this setup: I handle all the HTTP errors with errorHandler, in which I log useful information and send email to myself.

like image 85
Mostafa Avatar answered Sep 19 '22 21:09

Mostafa


Following is the approach I choose. It is based on a code snippet which I cannot acknowledge since I lost the browser bookmark.

Sample code : (I put it in my main package)

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

Please customize the func fire404 to output your own version of message for error 404.

If you happen to be using Gorilla Mux, you may wish to replace the main function with below :

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

Please kindly correct the code if it is wrong, since I am only a newbie to Go. Thanks.

like image 24
zelda Avatar answered Sep 19 '22 21:09

zelda