Reputation: 189
I'm building a small website in Go and having issues with the custom 404 page. Here's my current router code:
r := mux.NewRouter()
// Page routing
r.HandleFunc("/", homeHandler).Methods("GET")
r.HandleFunc("/example1", exampleOneHandler).Methods("GET")
r.HandleFunc("/example2", exampleTwoHandler).Methods("GET", "POST")
// Other paths for static assets omitted
// Psuedo-root directory for icon files, etc.
r.PathPrefix("/").Handler(http.FileServer(http.Dir("public")))
// 404 Page
r.NotFoundHandler = http.HandlerFunc(notFoundHandler)
log.Fatal(http.ListenAndServe(":1234", r))
So without the PathPrefix definition on line 11, the notFoundHandler is hit as expected and returns the custom 404 HTML.
However, now I've added that path definition to cater for the root directory standards, things like favicon.ico, robots.txt, app icons, etc. and that works as intended. However as a side effect, anything that doesn't match /example1 or /example2, let's say /example3, will go and look for an file called "example3" in the psuedo-root directory via http.FileServer. After it doesn't find it, FileServer writes directly to the http.ResponseWriter with "404 not found", completely bypassing mux's NotFoundHandler.
The only feasible solution I can see is adding an explicit route for every file, but that seems like quite a brutal solution. Is there a more elegant way of solving this problem that I'm missing?
Upvotes: 1
Views: 782
Reputation: 417622
The notFoundHandler
is activated for paths for which there is no registered handler. And since you registered a handler (the file server) to path "/"
, that will always match all requests, so the not found handler will not be called anymore.
To circumvent this, easiest is to manually register all files that must be at the root (there aren't many of these, or at least there shouldn't be). If you have bunch of other, non-standard static files, publish them under a path like /static/
, so unregistered path such as /example3
will trigger the not-found handler.
Another solution could be to leave your file server at path "/"
, but wrap it, and if it would return a 404
status code, call your own notFoundHandler
to serve the custom error page. This is more complex compared to my previous suggestion, so I'd still go with that one.
Upvotes: 2