10 ms·
Mux – A lightweight, fast HTTP request router for Go
- SEJeff 10y agoDoes it use a trie? If not, it probably should. Here's a wonderful talk on using that datastructure (with go) for the gov uk url router: https://gdstechnology.blog.gov.uk/2013/12/05/building-a-new-router-for-gov-uk/ https://gdstechnology.blog.gov.uk/2013/12/05/building-a-new-... The Vulcan proxy from Mailgun does the same thing: http://vulcand.github.io/proxy.html#route http://vulcand.github.io/proxy.html#route It looks like it doesn't, so existing open source golang url routers will perform much better, contrary to this post. The one in vuland is interesting in that it supports both regex AND tries, so you get the best of both. Additionally, httprouter (golang) uses a trie and is fast as hell: https://github.com/julienschmidt/httprouter https://github.com/julienschmidt/httprouter Edit: Adding another one (thanks buro9!) that is used in production by CloudFlare: https://github.com/pressly/chi https://github.com/pressly/chi
- dvdhnt 10y agoThese links are pretty cool. Are there any tutorials or walkthroughs you would recommend? Like, Go has always interested me but I have no idea where to start to get an experience like say ExpressJS or even where to find templating or rendering. Any suggestions are appreciated!
- cloverich 10y agoWhen I was learning Go, Negroni was where I left off and felt like what you may be looking for as a next step: https://github.com/urfave/negroni https://github.com/urfave/negroni (I"m sure someone more experienced can provide more context or other / better links -- thought this would be a better answer than none until then)
- navd 10y agoWith go there is really less emphasis on taking advantage of a web framework like expressjs (look at go alternatives like gin) and building server functionality from the std library (since everything you need is there). I wrote a small helper library to help with template rendering if you're interested in looking at the source to see how you can take advantage of the std library for templating: https://github.com/dannav/migo https://github.com/dannav/migo
- thewhitetulip 10y agohttps://github.com/thewhitetulip/web-dev-golang-anti-textbook/ https://github.com/thewhitetulip/web-dev-golang-anti-textboo... I have written a very basic introduction to writing webapps in Go without using a framework, as others have rightly pointed out, we really do not need to use a framework in Go for writing webapps, and Go is a great language. If you don't like mine, https://github.com/astaxie/build-web-application-with-golang/tree/master/en https://github.com/astaxie/build-web-application-with-golang... is a nice start for new comers.
- creshal 10y agohttprouter is really awesome. I switched to it when Go's built-in router would cause panics during msan stress testing (back in Go 1.6), and really performs well.
- alex_dev 10y agoLooks like it uses regexp... There isn't any benchmark code as one would expect when making a claim that it's "fast".
- laumars 10y agoRegexp definitely isn't something you'd want to be using if you're primary goal is speed. When running tight loops in string parsing I've found using string splitting and then cycling through the range of indices in a slice was several times faster than Regexp matching. Obviously performance difference will vary depending on the expression and application but that was enough to convince me to think twice about future usage of Regex - as to whether the problem needed Regex or if I was just using them lazily. The latter being a practice I'd slipped into after years of Perl hacking.
- jules 10y agoThat depends entirely on the regex implementation. If the implementation uses a DFA to match multiple regexes simultaneously then the performance will be as good as a trie because a DFA is more or less a trie.
- vanderZwan 10y ago> That depends entirely on the regex implementation True, and anyone who knows that Russ Cox is a core member of the Go team will have a hard time suppressing a smirk when reading this :) https://swtch.com/~rsc/regexp/ https://swtch.com/~rsc/regexp/
- laumars 10y agoTrue. I was talking specifically about the same Regexp package as the one used in the topic project though. I assumed that would have been obvious given the context however I apologise for not stating that in my comment and shall amend it appropriately. [edit: i can't add an amendment to my previous post now]
- mypalmike 10y ago
- alistproducer2 10y agoInterestingly enough, I used a trie (without knowing that's what it was called) when building the router for my Frontend framework. https://github.com/ShamariFeaster/Templar/blob/master/core/Route.js https://github.com/ShamariFeaster/Templar/blob/master/core/R...
- zbobet2012 10y agoTrie's are my favorite data structure. The implementation in the Linux kernel is a lock free RCU structure (http://lxr.free-electrons.com/source/lib/radix-tree.c http://lxr.free-electrons.com/source/lib/radix-tree.c). It is used for the page cache among other things.
- sorokod 10y agoWhy is a trie obviously better then a hash map?
- teraflop 10y agoA hash map doesn't solve the same problem. Given a collection of routes, you need to find the longest one which is a prefix of the given URL.
- jeremiep 10y agoThey allow you to match the URL in a series of steps. Where each step can be static (ie "/foo") or dynamic (ie /images/). You can then easily add features to this structure, like route middlewares at every level in the tree; just apply them while doing the routing. This also allows you to match route variants easily, ie "foo" and "foo/" are the same, so are "/" and "/index.html". In the same way you can extract query parameters for middleware/handler use.
- mstade 10y agoAlso, tries means it's trivial to do detect routing ambiguities, so your routing table doesn't necessarily have to be built up front, or in any particular order. This is particularly powerful when you're developing an application with a team distributed both over space and time.
- SEJeff 10y agoFixed lookup time. A trie (aka radix tree) 3 levels deep with 1 million entries has the same lookup time as a 3 level deep trie with 5 entries.
- gkop 10y agoI don't usually say this but - isn't this a poor choice of name? Gorilla framework's Mux [0] has been around awhile and is quite popular for routing in Go. [0] https://github.com/gorilla/mux https://github.com/gorilla/mux
- insertnickname 10y agoThat's why we have namespaces. There's gorilla/mux and now there's donutloop/mux.
- Lewisham 10y agoThis. It's actually more idiomatic to use the same name, then you can often just sub out one library for another without any hassle.
- deleted 10y ago[deleted]
- 1_2__3 10y agoWhat? No! There's no indication at all these two libraries are compatible - why would you want two completely disparate projects to give some indication they support the same interface?
- Lewisham 10y agoBecause many of the base infrastructure libraries are compatible as long as they used interfaces (grumble grumble os.File). I would be very surprised if this doesn't implement net/http/ServeHTTP
- TheDong 10y agoIt doesn't matter what it's named though, you can always alias the import. If it was "github.com/foo/poppycock" I could just write import mux "github.com/foo/poppycock" and use it as mux. Import name similarity is a terrible argument for picking a name.
- nouney 10y agoFrom the README: "mux is a lightweight fast HTTP request router [...] It also scales better." Where can I find the benchmarks?
- buro9 10y agoMy favourite current HTTP request router is https://github.com/pressly/chi https://github.com/pressly/chi The list of those using it in production includes: - Pressly - Cloudflare - Heroku - 99designs - Origami - IT Jobs Watch - CrowdRiff At Cloudflare it's our default router for internal APIs, which are all written in Go. (and yes it uses a trie)
- daenney 10y agoDo you know how it stacks up to httprouter for example? We can run benchmarks all day but it would be cool if you happened to have some real production statistics, by any change?
- buro9 10y agoThey're in the same ballpark, choosing one over the other was preference. The benchmarks skew slightly in favour of httprouter, but only because pressly/chi embraces use of req.Context and this does a few ops. If you add req.Context use to httprouter they're basically the same. If you're doing work with Context, you aren't going to be able to measure a difference that you'll care about. If you're just serving static files, perhaps you'll care.
- mmgutz 10y agohttprouter is unforgiving with routes. IIRC, having both of these routes are not allowed /users/:id /users/create Seems like a common use case.
- peterkieltyka 10y agoInteresting.. and btw, pressly/chi supports those routes easily, among many other combinations. Chi was designed to be very composeable with middlewares, subrouters and handlers. The idea is to consider the request passing through a "flow" of layers, handling and building the response along the way. This makes it easier to reason and organize each piece separately and then connect it all together.
- bmurphy1976 10y ago
- jstimpfle 10y agoWhat's the use case for all these routing libraries? Why not write a few lines of procedural code? It's a natural encoding of the routes "trie". @methods('POST') def set_int(request): x = pop_int_component(request) no_more_components(request) do_set_the_int(x) return Ok def myapp(request): x = pop_id_component(request) if x == 'set_int': return set_int(request) else: return NotFound No type system hacks, extremely modular and simple to understand. Exceptions can replace basically all the boilerplate. The only drawback being there's no URL generation, but it's not like most sites have so many URLs that writing this by hand (directly in HTML templates or as "inverse functions") would be unmaintainable.
- tscs37 10y agoIt's not a python router though, it's for go. In this case, I don't see any typesystem hacks either, it uses the standard library types and as it looks, can just hook up to net/http/ServeFunc typed functions, which are basically what you'll use anyway if you use the standard library. I don't quite understand what your irk is with this particular library (excepts that it's not the net/http default mux)
- peclink 10y agoAll these routing libraries are just wrong level of abstraction. In HTTP you have resources, and resources are not flat, they are hierarchical. And hierarchy of resources defines some connection between then, and some common properties (data, access level etc). So any resource can respond to some HTTP method or can delegate to another, nested resource (if any) for any method. So (in PHP, from our still proprietary framework): // Index resource, just routing, no HTTP method handling. class IndexResource extends Resource { public function __construct(Application $app) { // ... } // Route nested resources for any request public function any(Request $request) { // Static path: $this->path( CollectionResource::Path, new CollectionResource($this) ); } } class CollectionResource extends Resource { const Path = 'items'; // Parent resource type constraint, you can access // parent data using IndexResource API: public function __construct(IndexResource $parent) { //... } // Route nested resources for any HTTP method: public function any(Request $request) { // Regexp pattern for URI segment: $this->match(ItemResource::Pattern, new ItemResource($this)); } // Or handle GET public function GET(Request $request) { // ... } // Or POST maybe public function POST(Request $request) { // ... } } class ItemResource extends Resource { const Pattern = '(\d+)'; public function __construct(CollectionResource $parent) { // ... } public function any(Request $request, $prefix, $id) { $this->item = Item::find($id); } public function GET(Request $request) { return JSON::string($this->item); } } It's not about routers + controllers etc, it's just resources + delegation to nested resources: - recursive routes are trivial, so no problems with CMS-like applications; - looks good with type systems; - no long routing tables (in fact, no routing tables at all), so true modular apps; - you can use anything (e.g. database) for resources lookup, good for CMSes again; - it's absolutely RESTful. Yes, automatic URI building is not so easy, but it's kinda possible, in some semi-automatic way. I wonder why frameworks built this way are so uncommon (ours were inspired by Bullet BTW).
- alexellisuk 10y ago+1 for the confusion with Gorilla's mux library. Have you benchmarked this against Gorilla's lib to show why we would want to use this (relatively unproven) library instead?
- alexellisuk 10y ago+1 for the confusion with Gorilla's mux library. Have you benchmarked this against Gorilla's lib to show why we would want to use this (relatively unproven) library instead?
- 1_2__3 10y agoIf you're not going to explain in your readme or docs why anyone should use this over the Gorilla library you're kind of wasting everyone's time. Gorilla/Mux is very widely used and well-supported.
- stcredzero 10y agoIt also scales better. In what sense? Can it support many, many more routes? Or does it scale better in the sense that it causes zero or near zero GC pressure? Better than what?
- pbreit 10y agoWhy does routing get so complicated? I use Web2py which doesn't even have a router and it's so much easier. Are regxes, variables, http methods all that necessary in the router? Just pass the info to a controller.
- hackerboos 10y agoIf you don't need a router for web2py it's because WSGI is doing all the hard work for you. https://en.wikipedia.org/wiki/Web_Server_Gateway_Interface https://en.wikipedia.org/wiki/Web_Server_Gateway_Interface
- jratkevic 10y agoTop notch engineers behind this one!!
- psiclops 10y agoParts of the readme are copied from [0] julienschmidt/httprouter... "In contrast to the default mux of Go's net/http package, this router supports variables in the routing pattern and matches against the request method. It also scales better." [0] https://github.com/julienschmidt/httprouter https://github.com/julienschmidt/httprouter