= Usher
Tree-based router library. Useful for (specifically) for Rails and Rack, but probably generally useful for anyone interested in doing routing. Based on Ilya Grigorik suggestion, turns out looking up in a hash and following a tree is faster than Krauter's massive regex approach.
== Features
* Understands single and path-globbing variables
* Arbitrary HTTP header requirements
* No optimization phase, so routes are always alterable after the fact
* Understands Proc and Regex transformations, validations
* Really, really fast
* Relatively light and happy code-base, should be easy and fun to alter
* Interface and implementation are separate, encouraging cross-pollination
== Route format
From the rdoc:
Creates a route from +path+ and +options+
=== +path+
A path consists a mix of dynamic and static parts delimited by /
==== Dynamic
Dynamic parts are prefixed with either :, *. :variable matches only one part of the path, whereas *variable can match one or
more parts.
Example:
/path/:variable/path would match
* /path/test/path
* /path/something_else/path
* /path/one_more/path
In the above examples, 'test', 'something_else' and 'one_more' respectively would be bound to the key :variable.
However, /path/test/one_more/path would not be matched.
Example:
/path/*variable/path would match
* /path/one/two/three/path
* /path/four/five/path
In the above examples, ['one', 'two', 'three'] and ['four', 'five'] respectively would be bound to the key :variable.
==== Static
Static parts of literal character sequences. For instance, /path/something.html would match only the same path.
==== Optional sections
Sections of a route can be marked as optional by surrounding it with brackets. For instance, in the above static example, /path/something(.html) would match both /path/something and /path/something.html.
==== One and only one sections
Sections of a route can be marked as "one and only one" by surrounding it with brackets and separating parts of the route with pipes. For instance, the path, /path/something(.xml|.html) would only match /path/something.xml and /path/something.html.
=== +options+
* +transformers+ - Transforms a variable before it gets to the requirements. Takes either a +proc+ or a +symbol+. If its a +symbol+, calls the method on the incoming parameter. If its a +proc+, its called with the variable.
* +requirements+ - After transformation, tests the condition using ===. If it returns false, it raises an Usher::ValidationException
* +conditions+ - Accepts any of the following :protocol, :domain, :port, :query_string, :remote_ip, :user_agent, :referer and :method. This can be either a string or a regular expression.
* Any other key is interpreted as a requirement for the variable of its name.
== Rails
script/plugin install git://github.com/joshbuddy/usher.git
== Rack
=== rackup.ru
require 'usher'
app = proc do |env|
body = "Hi there #{env['usher.params'][:name]}"
[
200, # Status code
{ # Response headers
'Content-Type' => 'text/plain',
'Content-Length' => body.size.to_s,
},
[body] # Response body
]
end
routes = Usher::Interface.for(:rack)
routes.add('/hello/:name').to(app)
run routes
------------
>> curl http://127.0.0.1:3000/hello/samueltanders
<< Hi there samueltanders
== DONE
* add support for () optional parts
* Add support for arbitrary HTTP header checks
* Emit exceptions inline with relevant interfaces
* More RDoc! (optionally cowbell)
== TODO
* Make it integrate with merb
* Make it integrate with rails3
* Create decent DSL for use with rack
(Let me show you to your request)