Rack RESTful Dispatcher
George Malamidis, January 29th, 2008
Quoting the authors, Rack provides a minimal, modular and adaptable interface for developing web applications in Ruby. By wrapping HTTP requests and responses in the simplest way possible, it unifies and distills the API for web servers, web frameworks, and software in between (the so-called middleware) into a single method call
.
To test the theory in practice, I put together a superficial interface for writing RESTful HTTP services by implementing any of the DELETE, GET, POST, PUT, etc HTTP verbs in Ruby classes.
require "rubygems"
require "rack"
module RestfulDispatcher
def call(env)
request = Rack::Request.new(env)
dispatcher = dispatcher_class.new(request)
body = dispatcher.send(request.request_method.downcase)
[200, {'Content-Type' => dispatcher.content_type}, body]
end
def dispatcher_class
@dispatcher ||= Class.new(self.class) do
attr_accessor :content_type
def initialize(request)
@request, @content_type = request, 'text/xml'
end
end
end
module SingletonMethods
def start(handler, host, port)
handler.run Rack::Lint.new(self.new), :Host => host, :Port => port
end
end
def self.included(receiver)
receiver.extend SingletonMethods
end
end
Let’s examine the example one method at a time.
All Rack applications must implement one method – call – which accepts one argument, the environment, which encapsulates data relevant to the HTTP roundtrip. The call method must return an array of 3 items: a greater than 100 integer representation of the response status, a hash holding name/value pairs representing the response’s header entries and an array of strings – the body of the response.
In the case of the RestfulDispatcher module, call first wraps env in Rack::Request, a convenient and stateless interface to the Rack environment. We then create a new instance of a dispatcher class passing it the Rack Request. We will revisit this in more detail when talking about the dispatcher_class method. Instantiating a new dispatcher to handle the request should keep things thread safe. We then call a method on the dispatcher instance corresponding to the HTTP verb included in the request. This call should return the response body. Finally, adhering to the Rack standard, we return an array containing the response status code, headers and body.
dispatcher_class creates a new class by subclassing the service we will be defining and giving it a constructor that accepts a request object. We also expose the content_type field, in case we want to override it anywhere in our service’s implementation.
Finally, we provide a start singleton method which we can call to start the service.
Mixing the RestfulDispatcher module in a class will effectively enable the class to act as a standalone RESTful service. All we need to do is implement instance methods that correspond to the HTTP verbs we want the service to respond to.
class FooService
include RestfulDispatcher
def get
"<test>#{@request.GET['key']}</test>"
end
end
require "thin"
FooService.start Rack::Handler::Thin, '127.0.0.1', 2323
Rack::Request#GET conveniently returns the data received in the request query string (e.g http://127.0.0.1/?key=hello) as a hash.
Thanks to Rack’s modular nature, switching from Thin to Mongrel is as easy as replacing the last two lines of the code above with:
require "mongrel" FooService.start Rack::Handler::Mongrel, '127.0.0.1', 2323

January 29th, 2008 at 2:33 pm
This looks a lot like the a naive version of Mojasef Java framework which I have been using successfully for several years now.
I’m surprised at the choice of an array of strings for the body type, though. I wonder how that is supposed to handle non-textual responses, such as serving an image, for example.
January 29th, 2008 at 2:41 pm
http://rack.rubyforge.org/doc/classes/Rack/File.html
January 30th, 2008 at 12:21 am
[...] Rack RESTful Dispatcher (tags: ruby rest web programming web2.0) [...]
January 30th, 2008 at 10:12 am
Rack RESTful Dispatcher…
[...]Example of using Rack to create standalone RESTFul services in Ruby.[...]…
January 30th, 2008 at 10:26 am
[...] Nutrun » Blog Archive » Rack RESTful Dispatcher (tags: ruby rack programming) [...]
January 31st, 2008 at 5:14 am
[...] Nutrun » Blog Archive » Rack RESTful Dispatcher [...]
January 31st, 2008 at 8:03 am
Frank: It doesn’t really matter. Ruby just treats strings as series of 8 bit bytes, so you can store an image in a string, or whatever. Piping it out via HTTP via a string will work fine. For example, if you made it use image/gif for the content type, you could easily just send File.read(‘whatever.gif’) straight back and it’d work.