Mux – A lightweight, fast HTTP request router for Go
github.com
github.com
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
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
Edit: Adding another one (thanks buro9!) that is used in production by CloudFlare:
Any suggestions are appreciated!
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... is a nice start for new comers.
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 :)
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]
That said, most regex performance problems are PEBKAC. Writing a fast regex is hard and requires a pretty thorough understanding of parser theory. And many who use regexes don't understand that it's critical to precompile them for performance. You don't get a fast parser when you rebuild the DFA each time you use it.
*edit: a word
for what job? Extracting route variables from paths ?they are the right tool for the job, only in the Go community they are deemed "wrong tool for the job". Your statement embodies everything that is wrong with the Go community. Instead of finding a solution to a problem you guys spend your time shifting the blame on "bad practices".
Avoiding regexp doesn't fix Go's implementation of regexp. Making them faster does. Your argument is preposterous. If the Go team really cared about performances it would fix its regexp implementation.
I'm not missing the point of the discussion. Using regex is not the wrong tool for the job. You deemed it the wrong tool for the job. And deeming it the wrong tool for the job doesn't fix Go regex being slower than in other languages. The 2 issues are not separate .People like you talk about performances as a goal while dismissing obviously performance issues in the standard library as "wrong tool for the job".
You're not going to convince anybody with this kind of argument, aside from gophers who already think like you do. I'm not one of them.
I often have taught the same lesson to my junior colleagues who use regex in Python or C++ code where splitting the string would be simpler, more maintainable, and faster.
Because a few people on HN is the consensus ? give me a break. You have your opinion, I've got mine, whatever you think you are you're in no way an authority on the matter. There are many ways to implement an http router, there are also many ways to implement regular expressions. A bad implementation isn't saved by deeming the use of regexp "wrong tool for the job".
> A regex, while perfectly good for certain types of pattern matching makes no sense here.
What make no sense is your petty comment.
> Forget your pointless anti-go bias
Pointing out facts is "anti-go bias". OK , how about you stopping drinking the "pro-go koolaid" ?
Are you resorting to insults now ? or is the typical hate and mean spirit of the Go community ? a router isn't a hammer. And I could care less about your opinion.
https://github.com/ShamariFeaster/Templar/blob/master/core/R...
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.
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.
Historically gophers haven't minded the occasional namespace collision: https://github.com/golang/go/issues/9
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)
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.
/users/:id
/users/create
Seems like a common use case.Where can I find the benchmarks?
"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."
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?
@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.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)
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).
That isn't really true. There is nothing about HTTP, or even REST, that requires resources to be hierarchical. That said, it is quite common, and helpful for human beings, if they are hierarchical, so ...
> I wonder why frameworks built this way are so uncommon
Good question! The only one that springs to mind is Stapler:
There are nested routes in Express and some Golang libraries (see gongular near on HN), but they are not resource oriented. And yes, there are resources in Rails, but it's sooo complex and heavy.
I suppose that is also a benefit (maybe some resource can divert to another resource under heavy load/when its DB is unavailable). But quite frequently I want to answer this question with just the source code.
Exactly. And that is also a benefit if routes are fetched dynamically from database, e.g. for content application, so your database is really content repository without too many levels of abstraction.
As for source code, it's kinda silly to split your app to fixed «controllers» and «models», you should split it functionally for simple reuse. Most modern PHP frameworks are so unflexible that way (laravel is just terrible IMO).