Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

httprouter configuring NotFound

I'm using httprouter for an API and I'm trying to work out how to handle 404s. It does say in the docs that 404's can be handled manually but I don't really have an idea how to write my own custom handler.

I've tried the following after my other routes...

router.NotFound(pageNotFound)

But I get the error not enough arguments in call to router.NotFound.

If anyone could point me in the right direction it would be great.

like image 265
tommyd456 Avatar asked Dec 24 '22 18:12

tommyd456


1 Answers

The type httprouter.Router is a struct which has a field:

NotFound http.Handler

So type of NotFound is http.Handler, an interface type which has a single method:

ServeHTTP(ResponseWriter, *Request)

If you want your own custom "Not Found" handler, you have to set a value that implements this interface.

The easiest way is to define a function with signature:

func(http.ResponseWriter, *http.Request)

And use the http.HandlerFunc() helper function to "convert" it to a value that implements the http.Handler interface, whose ServeHTTP() method simply calls the function with the above signature.

For example:

func MyNotFound(w http.ResponseWriter, r *http.Request) {
    w.Header().Set("Content-Type", "text/plain; charset=utf-8")
    w.WriteHeader(http.StatusNotFound) // StatusNotFound = 404
    w.Write([]byte("My own Not Found handler."))
    w.Write([]byte(" The page you requested could not be found."))
}

var router *httprouter.Router = ... // Your router value
router.NotFound = http.HandlerFunc(MyNotFound)

This NotFound handler will be invoked by the httprouter package. If you would want to call it manually from one of your other handlers, you would have to pass a ResponseWriter and a *Request to it, something like this:

func ResourceHandler(w http.ResponseWriter, r *http.Request) {
    exists := ... // Find out if requested resource is valid and available
    if !exists {
        MyNotFound(w, r) // Pass ResponseWriter and Request
        // Or via the Router:
        // router.NotFound(w, r)
        return
    }

    // Resource exists, serve it
    // ...
}
like image 86
icza Avatar answered Dec 27 '22 21:12

icza