Notes on the httprouter Golang library

For most simple to moderately complex web servers in Golang, I have always preferred to use the standard net/http library, laboring through the parsing of RequestPaths and query parameters when necessary.

But when the boilerplate code for request parsing starts obscuring the business logic, I tend to look out at other libraries. I however have always hesitated using too heavy a framework to keep dependencies simple.

For HTTP routing, for example, I have found httprouter to satisfy most of the gaps in the standard library that I have frequently faced, and at the same time the library is totally dep free!

Here are some really quick notes about using the library, mostly for my own reference. 😄

CONTENTS:

Overview

This is a very minimalistic http router library which addresses the most frequently felt gaps in the standard library:

  1. http method specific handlers.
  2. Named parameters in the path.

The feature set is deliberately kept simple, and for users who want more, the author encourages them to use one of the many other libraries that have popped up wrapping this routing library.

Example Usage

Notes:

  1. A route registration call specifies the HTTP method - router.GET().

  2. The Index() and Hello handlers are not stdlib compatible and have an extra library specific parameter.

  3. The Hello() handler uses a named parameter retrieved inside the handler using the new third parameter in the handler.

  4. Calls to /hello/xxx/yyy will not be matched to /hello/:name - the routing is explicit.

  5. You cannot add a static route overlapping the named parameter. e.g. You cannot now have a route for /hello/somewhere. That second path component is already taken by the route for /hello/:name.

  6. As shown in the Welcome() handler, you can use a wildcard named parameter (e.g. *where here) at the end of a routing pattern using a * prefix to slurp up everything to the right of the URI. You can use a named parameter as many times as you want as well, but the wildcard one has to be at the end of the pattern - see (C).

    $ curl -s localhost:8888/welcome/sandip/to/wonderland/for/ever
    Welcome, sandip to to/wonderland/for/ever!
    
  7. You can use a standard http handler too - see Salut(). To reach for the named parameters, you need to use httprouter.ParamsFromContext() helper function to retrieve the usual third parameter in the custom handlers, the Params from the request context - see (A).

    However, note that the routing function is now a non-standard router.HandlerFunc() which expects the HTTP method name as the first parameter - see (B).

  8. You can provide an endpoint for static file serving using ServeFiles() - see (D).

    !!Note!! however that directory index display is enabled, so an empty file name can display directory contents.

    $ curl -s 127.0.0.1:8888/files/
    <pre>
    <a href="go.mod">go.mod</a>
    <a href="go.sum">go.sum</a>
    <a href="simple.go">simple.go</a>
    </pre>
    

Additional features

The router has some optional fields for provide default handling of specific exceptions:

  1. router.Notfound can be set to handle requests to paths which are not matched by any routing patterns.
  2. Setting router.HandleMethodNotAllowed to true allows you to set a handler in router.MethodNotAllowed to handle situations when a request has been sent to a router pattern which exists but with a different http verb. e.g. Only a GET route exists but a POST verb was used in the request.
  3. You can recover from panics in your server handlers by setting router.PanicHandler to an appropriate handler which can send a suitable 5xx error.
  4. You can set CORS headers by setting router.GlobalOPTIONS to a suitable handler. The Godoc provides a code sample.

Credit: “Blue Gopher” icon by Ashley McNamara


techgolang
Automating MySQL GTID Migration With Ansible Using Podman as a Docker Desktop alternative using Vagrant