Sinatra-ish routing logic for Strelka::Apps
This plugin adds the ability to declare hooks for requests based on their attributes. The default router (Strelka::Router::Default) uses only the HTTP verb and the path, but you can also define your own router class if you want to include other attributes.
You declare a hook using the HTTP verb, followed by the path, followed by a Hash of options and a block that will be called when a matching request is handled.
When two or more hooks match the same request, the most-specific match wins. The mongrel2 route part of the path is stripped before comparing.
The hooks are given a Strelka::Request object, and are expected to return either a Strelka::Response or something that can be made into one.
class HelloWorld < Strelka::App plugins :routing # match any GET request get do |req| res = req.response res.puts 'Hello, World!' return res end # match any GET request whose path starts with '/goodbye' get '/goodbye' do |req| res = req.response res.puts "Goodbye, cruel World!" return res end # match any GET request whose path ends with '.pdf' get /\.pdf$/ do |req| res = req.response res.body = generate_pdf() return res end end # class HelloWorld
The algorithm used to map requests to routes are defined by an object that
implements the Strategy pattern. These routing strategies are pluggable, so
if Mongrel2's the “longest-match wins” routing isn't to your taste,
you can specify a different one using the router
declaration.
Strelka comes with one alternative
“exclusive” router that implements a more restrictive mapping:
class ExclusiveHelloWorld < Strelka::App plugins :routing router :exclusive # match a GET request for the exact route only get do |req| res = req.response res.puts 'Hello, World!' return res end # only match a GET request for '/goodbye' get '/goodbye' do |req| res = req.response res.puts "Goodbye, cruel World!" return res end # Every other request responds with a 404 end # class ExclusiveHelloWorld
See the Strelka::Router for information on how to define your own routing strategies.
The App's router object
Create a new router object for each class with Routing.
# File lib/strelka/app/routing.rb, line 279
def initialize( * )
super
@router ||= Strelka::Router.create( self.class.routerclass, self.class.routes )
end
Dispatch the request using the Router.
# File lib/strelka/app/routing.rb, line 290
def handle_request( request, &block )
self.log.debug "[:routing] Routing request using %p" % [ self.router.class ]
if route = self.router.route_request( request )
# Track which route was chosen for later plugins
request.notes[:routing][:route] = route
# Bind the action of the route and call it
return super { route[:action].bind( self ).call( request, &block ) }
else
finish_with HTTP::NOT_FOUND, "The requested resource was not found on this server."
end
self.log.debug "[:routing] Done with routing."
end