Yet Another Http Request Router
Joshua HawxwellStop 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.