Library for creating ReSTful web services

The latest “stable” documentation can be found here:


Confronted with the task of implementing a ReSTful web service in Ruby, I checked out a number of existing libraries and frameworks, including Ruby-on-Rails, and then decided to brew my own, the reason being that I couldn’t find a library or framework with all of the following properties:

Hello World!

Here’s a working example of a simple ReSTful server:

# Load core functionality:
require 'rackful'

# Load extra middlewares: ({Rackful::MethodOverride}, {Rackful::HeaderSpoofing})
require 'rackful/middleware'

require 'digest/md5'

# The class of the object we're going to serve:
class Root < Rackful::Resource
  attr_reader :to_rackful
  def initialize
    super( 'http://localhost:9292/hallo_wereld' )
    @to_rackful = {
      :a => 'Hello',
      :b =>,
      :c => URI('') }
  def do_PUT request, response
    @to_rackful = self.parser(request).parse
  def get_etag
    '"' + + '"'
  add_serializer Rackful::Serializer::XHTML, 1.0
  add_serializer Rackful::Serializer::JSON, 0.5
  add_parser Rackful::Parser::XHTML
  add_parser Rackful::Parser::JSON
$root_resource = nil

use Rack::Reloader
use Rackful::MethodOverride
use Rackful::HeaderSpoofing

run { |uri|
  $root_resource ||=

This file is included in the distribution as example/ If you go to the example directory and run rackup, you should see something like this:

$> rackup
[2012-07-10 11:45:32] INFO  WEBrick 1.3.1
[2012-07-10 11:45:32] INFO  ruby 1.9.2 (2011-12-27) [java]
[2012-07-10 11:45:32] INFO  WEBrick::HTTPServer#start: pid=5994 port=9292

Go with your browser to http://localhost:9292/ and be greeted.

In this example, we implement GET and PUT requests for the resource at “/”. but we get a few things for free:

Free OPTIONS response:


Host: localhost:9292


HTTP/1.1 204 No Content
Date: Tue, 10 Jul 2012 10:22:52 GMT

As you can see, the server accurately reports all available methods for the resource. Notice the availability of the HEAD method; if you implement the GET method, you’ll get HEAD for free. It’s still a good idea to explicitly implement your own HEAD request handler, especially for expensive resources, when responding to a HEAD request should be much more efficient than generating a full GET response, and strip off the response body.

Free conditional request handling:

Let’s first get the current state of the resource, with this request:

GET / HTTP/1.1
Host: localhost:9292


HTTP/1.1 200 OK
Content-Type: text/plain
Content-Length: 12
ETag: "86fb269d190d2c85f6e0468ceca42a20"
Date: Tue, 10 Jul 2012 10:34:36 GMT

Hello world!

Now, we’d like to change the state of the resource, but only if it’s still in the state we last saw, to avoid the “lost update problem”. To do that, we produce an If-Match: header, with the entity tag of our last version:

PUT / HTTP/1.1
Host: localhost:9292
Content-Type: text/plain
Content-Length: 31
If-Match: "86fb269d190d2c85f6e0468ceca42a20"

All your base are belong to us.


HTTP/1.1 204 No Content
ETag: "920c1e9267f923c62b55a471c1d8a528"
Date: Tue, 10 Jul 2012 10:58:57 GMT

The response contains an ETag: header, with the new entity tag of this resource. When we replay this request, we get the following response:

HTTP/1.1 412 Precondition Failed
Content-Type: text/html; charset="UTF-8"
Date: Tue, 10 Jul 2012 11:06:54 GMT

<h1>HTTP/1.1 412 Precondition Failed</h1>
<p>If-Match: "86fb269d190d2c85f6e0468ceca42a20"</p>

The server returns with status 412 Precondition Failed. In the HTML response body, the server kindly points out exactly which precondition.

Further reading


Some conventions used throughout the code and documentation:


Copyright ©2011-2014 Pieter van Beek

Licensed under the Apache License 2.0. You should have received a copy of the license as part of this distribution.