Creating an HTTP 404 handler for Go net/http
servers
I've recently been writing some HTTP servers using Go's net/http
package, and found that trying to add a 404 handler - by default - wasn't super straightforward.
As per the net/http
documentation:
Note that since a pattern ending in a slash names a rooted subtree, the pattern "/" matches all paths not matched by other registered patterns, not just the URL with Path == "/".
This means that if we register a handler for /
, we can then check the incoming path of the request and see if it's not the root path.
This would allow us to write the following code:
package main
import (
"fmt"
"html"
"log"
"net/http"
)
func main() {
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
if r.URL.Path != "/" {
w.WriteHeader(http.StatusNotFound)
fmt.Fprintf(w, "Error: handler for %s not found", html.EscapeString(r.URL.Path))
return
}
fmt.Fprintln(w, "Welcome to / handler")
})
http.HandleFunc("/health", func(w http.ResponseWriter, r *http.Request) {
})
log.Fatal(http.ListenAndServe(":8080", nil))
}
Which then handles requests like so:
% curl localhost:8080/
Welcome to / handler
% curl localhost:8080/ -i
HTTP/1.1 200 OK
Date: Thu, 11 May 2023 20:40:44 GMT
Content-Length: 21
Content-Type: text/plain; charset=utf-8
Welcome to / handler
% curl localhost:8080/not/there/ -i
HTTP/1.1 404 Not Found
Date: Thu, 11 May 2023 20:40:52 GMT
Content-Length: 40
Content-Type: text/plain; charset=utf-8
Error: handler for /not/there/ not found%
% curl localhost:8080/health -i
HTTP/1.1 200 OK
Date: Thu, 11 May 2023 20:40:55 GMT
Content-Length: 0