http://qs321.pair.com?node_id=717029

(A little meditation from my blog.)

The most fun for me when building a new web framework is always the dispatcher design.
Thats one of the main reasons why Mojo is completely dispatcher agnostic.

Now you might be asking "WTF is a dispatcher?".
It is the part of your framework that maps incoming requests to the actual code that builds the response for it.

A very naive way of doing this would be a simple list of paths with classes and methods mapped to them.
/foo/bar/index -> Foo::index() /test123.html -> Bar::default() /cookies/list/fresh -> Cookies::list()
Every web framework out there has their own way of doing this, they all have advantages and disadvantages.

Catalyst 5 - Perl
Lets start with my good old Catalyst 5.
Meta data is kept close to the code which makes initial development easier, but for debugging you depend very much on good log output.
Changing paths later on can be painful, and using attributes is also very tricky because the Perl api for them sucks, it can look quite good though if used right.
# /foo/bar/index package Foo::Bar; sub index : Relative { ... } # /test123.html package Foo::Bar; sub test : Path('/test123.html') { ... } # /cookies/list/fresh package Cookies; sub list : Relative Args(1) { ... }
Servlets 3.0 - Java
Servlets 3.0 will do something similar with annotations. (I'm not going to give you full examples here because...well...it's Java and ugly as hell)
@Servlet(urlMappings={"/foo", "/bar"}) public class ControllerWithAnnotations { @GET public void handleGet(HttpServletRequest req, HttpServletResponse +res) { ... } }
Jifty - Perl
For quite some time i was a big fan of declarative dispatchers like the Jifty one.

Meta data and code are once again close together, but you have to use a full blown domain specific language.
You can't use basic Perl features like inheritance and need to reinvent a lot.
The flow is easier to follow than in Catalyst though without using log output.
# /foo/bar/index on 'foo/bar/index' => do { ... } # /test123.index on 'test123.html' => do { ... } # /cookies/list/fresh on '/cookies/list/*' => do { ... }
Catalyst 4 - Perl
Fun fact, we nearly built a declarative dispatcher for Catalyst 4, a long time before it was cool. :)
__PACKAGE__->action('/foo/bar/index' => sub { ... });
Ruby on Rails - Ruby
Ruby on Rails originally started using a static "/controller/action/args" mapping with Apache's mod_rewrite in front of it.
To get rid of the Apache dependency they've invented one of the imo coolest dispatcher concepts out there called Routes.

Routes separate meta data and code completely, so you can use all the basic language features in your code.
For easy initial development you start with a simple default route like ":controller/:action/:id" and later move on to more complicated url mappings.
# /foo/bar/index map.connect 'foo/bar/index', :controller => "foo", :action => "index" # /test123.html map.connect 'test123.html', :controller => "foo", :action => "test" # /cookies/list/fresh map.connect ':controller/:action/:quality', :controller => "cookies", +:action => "list", :quality => "fresh", :requirements => { :quality => /\w+/ }
Most interesting for me is the ability to reverse the route and generate urls from the pattern.
<%= link_to "Fresh Cookies", :controller => "cookies", :action => "lis +t", :quality => "fresh" %>
Merb - Ruby
Merb uses an alternative Routes implementation, with a lot of cool new ideas.
# /foo/bar/index r.match("/foo/bar/index").to(:controller => "foo", :action => "index") # /test123.html r.match("/test123.html").to(:controller => "foo", :action => "test") # /cookies/list/fresh r.match(%r[^/cookies/list/(\w+)$]).to(:controller => "cookies", :actio +n => "list", :quality => 'path[1]')
Django - Python
The prize for the ugliest dispatcher goes to Python's Django, which uses plain old regex for everything.
urlpatterns = patterns('', (r'^foo/bar/index$', 'foo.views.index'), (r'^test123\.html$', 'foo.views.test'), (r'^cookies/list/(\w+)$', 'cookies.views.list'), )
Mojolicious - Perl
For Mojolicious i'll be using a Perl-ish Routes implementation with some Catalyst goodness added.
More about that in my next article. ;)
# /foo/bar/index $r->route('/foo/bar/index')->to(controller => 'foo', action => 'index' +); # /test123.html $r->route('/test123.html')->to(controller => 'foo', action => 'test'); # /cookies/list/fresh $r->route('/:controller/:action/:quality', quality => qr/\w+/) ->to(controller => 'cookies', action => 'list', quality => 'fresh'); $c->url_for(controller => 'cookies', action => 'list', quality => 'fre +sh');
Note that this was just a very basic overview, all frameworks have much more features than i've shown here.
But i hope it will help all you future framework developers, building dispatchers is fun, get Mojo and start today!