= 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. As well, variables can have a regex matcher. Example: /product/{:id,\d+} would match * /product/123 * /product/4521 But not * /product/AE-35 As well, the same logic applies for * variables as well, where only parts matchable by the supplied regex will actually be bound to the variable Variables can also have a greedy regex matcher. These matchers ignore all delimiters, and continue matching for as long as much as their regex allows. Example: /product/{!id,hello/world|hello} would match * /product/hello/world * /product/hello ==== Static Static parts of literal character sequences. For instance, /path/something.html would match only the same path. As well, static parts can have a regex pattern in them as well, such as /path/something.{html|xml} which would match only /path/something.html and /path/something.xml ==== 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. Generally its more efficent to use one and only sections over using regex. === +options+ * +requirements+ - After transformation, tests the condition using ===. If it returns false, it raises an Usher::ValidationException * +conditions+ - Accepts any of the +request_methods+ specificied in the construction of Usher. 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 === config.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) do add('/hello/:name').to(app) end 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)