Live data from Hacker News

Mux – A lightweight, fast HTTP request router for Go

github.com

51–60 of 80 posts

Re: Mux – A lightweight, fast HTTP request router for Go

#51
post #37

Earlier quoted context omitted.

Why is a trie obviously better then a hash map?

They 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…

Also, 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.

Re: Mux – A lightweight, fast HTTP request router for Go

#52

What'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 mo…

All 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).

Re: Mux – A lightweight, fast HTTP request router for Go

#53
post #48
post #42

Earlier quoted context omitted.

Regexes are the problem, because they're simply the wrong tool for the job.

> Regexes are the problem, because they're simply the wrong tool for the job. 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".

Wouldn't it make more sense to use something faster and simpler for most routing, and then an optional argument for regular expressions? Lots of web frameworks use that approach.

Re: Mux – A lightweight, fast HTTP request router for Go

#54
post #45
post #16

Earlier quoted context omitted.

Do 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?

httprouter is unforgiving with routes. IIRC, having both of these routes are not allowed /users/:id /users/create Seems like a common use case.

Interesting.. 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.

Re: Mux – A lightweight, fast HTTP request router for Go

#56
post #44
post #28

Earlier quoted context omitted.

Regexp 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…

That 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.

> 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/

Re: Mux – A lightweight, fast HTTP request router for Go

#57
post #41
post #40

Earlier quoted context omitted.

Fixed 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.

Isn't the same thing true for a 3 level deep hashmap of hashmaps?

See a much better answer than mine: https://news.ycombinator.com/item?id=13108781

Re: Mux – A lightweight, fast HTTP request router for Go

#58
post #44
post #28

Earlier quoted context omitted.

Regexp 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…

That 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.

True. 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]

Re: Mux – A lightweight, fast HTTP request router for Go

#59
post #52

What'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 mo…

All 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 fr…

> In HTTP you have resources, and resources are not flat, they are hierarchical.

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:

http://stapler.kohsuke.org/what-is.html

Re: Mux – A lightweight, fast HTTP request router for Go

#60
post #29

Earlier quoted context omitted.

Looks like it uses regexp... There isn't any benchmark code as one would expect when making a claim that it's "fast".

Go regexps are slow ( https://goo.gl/r0K2xw ), the problem is not regexps but Go's implementation of regexps. So let's not blame regexps when regexps aren't the problem. Because by that logic, people shouldn't use the sort package as well ...

You're making a distinction where one doesn't need to be made. It doesn't matter if regexp is generally slow or if it's Go implementation specifically - if you're using Go and wanting something where performance is your primary goal then you're generally best to avoid using regexp.
Post reply on HN