Yet Another Http Request Router

Stop me. I’ve just written another http request router for Go, adding to the ever growing list in the world. But there was a reason…

Previously I’ve used either net/http or, when parameterised routes were required, gorilla/mux. This worked fine and still does. But I disliked the way gorilla/mux defined routes, it seemed cumbersome, probably since it allows you to do some pretty complicated things. I wanted the simplicity of http.Handle("/some", someHandler) but with parameters.

So I started looking at others. One stood out above the others: julienschmidt/httprouter. If you look at the benchmarks it is incredible. But this did a little too much, all handlers were registered with the route and method. I’ve been writing apps in a style where a handler defines all of the methods within itself, so I only want to be registering with a route.

I began by cloning the repo and ripping out the method related stuff. This took it down to registering everything to a single tree, based on route, just like ServeMux. All was good.

But then I ran into a small problem: I wanted to register the following url structure,

/
/:name
/:name/edit
/:name/delete
/-/create
/-/sign-in
/-/sign-out

The problem is that httprouter doesn’t allow registering overlapping routes like this, I would have to change /:name to /something/:name so the /:name/... and /-/... prefixes didn’t overlap (sim. for the others). This wasn’t ideal, why should I have to change the urls?

So I thought I’d just make a quick change to the route registration to fix these cases, I started reading the implementation. It uses a radix tree which is nice and space efficient, but I had no idea where/if I could make the changes.

Instead I gave up and wrote a new, simpler, tree. The new version makes no attempt to reuse common path segments but instead splits a path on each /, building a new node for each segment. This is slightly less space efficient but made it easy to allow overlapping url structures: we simply try to find an exact match first, failing that we match the parameter.

So that is why hawx/route exists. Yet another http request router.