webmachine for Ruby 
webmachine-ruby is a port of Webmachine, which is written in Erlang. The goal of both projects is to expose interesting parts of the HTTP protocol to your application in a declarative way. This means that you are less concerned with handling requests directly and more with describing the behavior of the resources that make up your application. Webmachine is not a web framework per se, but more of a toolkit for building HTTP-friendly applications. For example, it does not provide a templating engine or a persistence layer; those choices are up to you.
A Note about Rack
Webmachine has a Rack adapter -- thanks to Jamis Buck -- but when using it, we recommend you ensure that NO middleware is used. The behaviors that are encapsulated in Webmachine could be broken by middlewares that sit above it, and there is no way to detect them at runtime. Caveat implementor. That said, Webmachine should behave properly when given a clear stack.
Getting Started
Webmachine is very young, but it's still easy to construct an application for it!
require 'webmachine'
# Require any of the files that contain your resources here
require 'my_resource'
# Create an application which encompasses routes and configruation
MyApp = Webmachine::Application.new do |app|
app.routes do
# Point all URIs at the MyResource class
add ['*'], MyResource
end
end
# Start the server, binds to port 8080 using WEBrick
MyApp.run
Your resource will look something like this:
class MyResource < Webmachine::Resource
def to_html
"<html><body>Hello, world!</body></html>"
end
end
Run the first file and your application is up. That's all there is to
it! If you want to customize your resource more, look at the available
callbacks in lib/webmachine/resource/callbacks.rb. For example, you
might want to enable "gzip" compression on your resource, for which
you can simply add an encodings_provided callback method:
class MyResource < Webmachine::Resource
def encodings_provided
{"gzip" => :encode_gzip, "identity" => :encode_identity}
end
def to_html
"<html><body>Hello, world!</body></html>"
end
end
There are many other HTTP features exposed to your resource through Webmachine::Resource::Callbacks. Give them a try!
Application/Configurator
There's a configurator that allows you to set the ip address and port
bindings as well as a different webserver adapter. You can also add
your routes in a block (as shown above). Both of these call return the
Webmachine::Application instance, so you could chain them if you
like. If you don't want to create your own separate application
object, Webmachine.application will return a global one.
require 'webmachine'
require 'my_resource'
Webmachine.application.routes do
add ['*'], MyResource
end
Webmachine.application.configure do |config|
config.ip = '127.0.0.1'
config.port = 3000
config.adapter = :Mongrel
end
# Start the server.
Webmachine.application.run
Webmachine includes adapters for Webrick, Mongrel, Reel, and Hatetepe. Additionally, the Rack adapter lets it run on any webserver that provides a Rack interface. It also lets it run on Shotgun (example).
Visual debugger
It can be hard to understand all of the decisions that Webmachine
makes when servicing a request to your resource, which is why we have
the "visual debugger". In development, you can turn on tracing of the
decision graph for a resource by implementing the #trace? callback
so that it returns true:
class MyTracedResource < Webmachine::Resource
def trace?
true
end
# The rest of your callbacks...
end
Then enable the visual debugger resource by adding a route to your configuration:
Webmachine.application.routes do
# This can be any path as long as it ends with '*'
add ['trace', '*'], Webmachine::Trace::TraceResource
# The rest of your routes...
end
Now when you visit your traced resource, a trace of the request
process will be recorded in memory. Open your browser to /trace to
list the recorded traces and inspect the result. The response from your
traced resource will also include the X-Webmachine-Trace-Id that you
can use to lookup the trace. It might look something like this:

Refer to examples/debugger.rb for an example of how to enable the debugger.
Features
- Handles the hard parts of content negotiation, conditional requests, and response codes for you.
- Most callbacks can interrupt the decision flow by returning an integer response code. You generally only want to do this when new information comes to light, requiring a modification of the response.
- Supports WEBrick and Mongrel (1.2pre+), and a Rack shim. Other host servers are being investigated.
- Streaming/chunked response bodies are permitted as Enumerables, Procs, or Fibers!
- Unlike the Erlang original, it does real Language negotiation.
- Includes the visual debugger so you can look through the decision graph to determine how your resources are behaving.
Caveats
- The Reel adapter might fail with a
SystemStackErroron MRI (< 2.0) due to its limited fiber stack size. The only known solution is to switch to JRuby, Rubinius or MRI 2.0.
Documentation & Finding Help
- API documentation
- Mailing list
- IRC channel #webmachine on freenode
Related libraries
- irwebmachine - IRB/Pry debugging of Webmachine applications
- webmachine-test - Helpers for testing Webmachine applications
- webmachine-linking - Helpers for linking between Resources, and Web Linking
- webmachine-sprockets - Integration with Sprockets assets packaging system
- webmachine-actionview - Integration of some Rails-style view conventions into Webmachine
LICENSE
webmachine-ruby is licensed under the Apache v2.0 license. See LICENSE for details.
Changelog
1.2.0
1.2.0 is a major feature release that adds the Events instrumentation framework, support for Websockets in Reel adapter and a bunch of bugfixes. Added Justin McPherson and Hendrik Beskow as contributors. Thank you for your contributions!
- Websockets support in Reel adapter.
- Added
Eventsframework implementing ActiveSupport::Notifications instrumentation API. - Linked mailing list and related library in README.
- Fixed operator precedence in
IOEncoder#each. - Fixed typo in Max-Age cookie attribute.
- Allowed attributes to be set in a
Cookie. - Fixed streaming in Rack adapter from Fiber that is expected to block
- Added a more comprehensive adapter test suite and fixed various bugs in the existing adapters.
- Webmachine::LazyRequestBody no longer double-buffers the request body and cannot be rewound.
1.1.0 January 12, 2013
1.1.0 is a major feature release that adds the Reel and Hatetepe adapters, support for "weak" entity tags, streaming IO response bodies, better error handling, a shortcut for spinning up specific resources, and a bunch of bugfixes. Added Tony Arcieri, Sebastian Edwards, Russell Garner, Justin McPherson, Paweł Pacana, and Nicholas Young as contributors. Thank you for your contributions!
- Added Reel adapter.
- The trace resource now opens static files in binary mode to ensure compatibility on Windows.
- The trace resource uses absolute URIs for its traces.
- Added Hatetepe adapter.
- Added direct weak entity tag support.
- Related libraries are linked from the README.
- Removed some circular requires.
- Fixed documentation for the
valid_content_headers?callback. - Fixed
Headersinitialization by downcasing incoming header names. - Added a
Headers#fetchmethod. - Conventionally "truthy" and "falsey" values (non-nil, non-false) can now be returned from callbacks that expect a boolean return value.
- Updated to the latest RSpec.
- Added support for IO response bodies (minimal).
- Moved streaming encoders to their own module for clarity.
- Added
Resource#runthat starts up a web server with default configuration options and the catch-all route to the resource. - The exception handling flow was improved, clarifying the
handle_exceptionandfinish_requestcallbacks. - Fix incompatibilities with Rack.
- The request URI will not be initialized with parts that are not present in the HTTP request.
- The tracing will now commit to storage after the response has been traced.
1.0.0 July 7, 2012
1.0.0 is a major feature release that finally includes the visual debugger, some nice cookie support, and some new extension points. Added Peter Johanson and Armin Joellenbeck as contributors. Thank you for your contributions!
- A cookie parsing and manipulation API was added.
- Conneg headers now accept any amount of whitespace around commas, including none.
Callbacks#handle_exceptionwas added so that resources can handle exceptions that they generate and produce more friendly responses.- Chunked and non-chunked response bodies in the Rack adapter were fixed.
- The WEBrick example was updated to use the new API.
Dispatcherwas refactored so that you can modify how resources are initialized before dispatching occurs.Routenow includes theTranslationmodule so that exception messages are properly rendered.- The visual debugger was added (more details in the README).
- The
Content-Lengthheader will always be set inside Webmachine and is no longer reliant on the adapter to set it.
0.4.2 March 22, 2012
0.4.2 is a bugfix release that corrects a few minor issues. Added Lars Gierth and Rob Gleeson as contributors. Thank you for your contributions!
- I always intended for Webmachine-Ruby to be Apache licensed, but now that is explicit.
- When the
#process_postcallback returns an invalid value, that will now beinspected in the raised exception's message. - Route bindings are now applied to the
Requestobject before theResourceclass is instantiated. This means you can inspect them inside the#initializemethod of your resource. - Some
NameErrorexceptions and scope problems in the Mongrel adapter were resolved. - URL-encoded
=characters in the query string decoded in the proper order.
0.4.1 February 8, 2012
0.4.1 is a bugfix release that corrects a few minor issues. Added Sam Goldman as a contributor. Thank you for your contributions!
- Updated README with
Webmachine::Applicationexamples. - The CGI env vars
CONTENT_LENGTHandCONTENT_TYPEare now being correctly converted into their Webmachine equivalents. - The request body given via the Rack and Mongrel adapters now
responds to
#to_sand#eachso it can be treated like aStringorEnumerablethat yields chunks.
0.4.0 February 5, 2012
0.4.0 includes some important refactorings, isolating the idea of global state into an Application object with its own Dispatcher and configuration, and making Adapters into real classes with a consistent interface. It also adds some query methods on the Request object for the HTTP method and scheme and Route guards (matching predicates). Added Michael Maltese, Emmanuel Gomez, and Bernerd Schaefer as committers. Thank you for your contributions!
- Fixed
Request#queryto handle nil values for the URI query accessor. Webmachine::Dispatcheris a real class rather than a module with state.Webmachine::Applicationis a class that includes its own dispatcher and configuration. The default instance is accessible viaWebmachine.application.Webmachine::Adapteris now the superclass of all implemented adapters so that they have a uniform interface.- The Mongrel spec is skipped on JRuby since version 1.2 (pre-release) doesn't work. Direct Mongrel support may be removed in a later release.
Webmachine::Dispatcher::Routenow accepts guards, which may be expressed as lambdas/procs or any object responding tocallpreceding theResourceclass in the route definition, or as a trailing block. All guards will be passed theRequestobject when matching the route and should return a truthy or falsey value (without side-effects).
0.3.0 November 9, 2011
0.3.0 introduces some new features, refactorings, and now has 100% documentation coverage! Among the new features are minimal Rack compatibility, streaming responses via Fibers and a friendlier route definition syntax. Added Jamis Buck as a committer. Thank you for your contributions!
- Chunked bodies are now wrapped in a way that works on webservers that don't automatically produce them.
- HTTP Basic Authentication is easy to add to resources, just include
Webmachine::Resource::Authentication. - Routes are a little less painful to add, you can now specify them
with
Webmachine.routeswhich will be evaled into theDispatcher. - The new default port is 8080.
- Rack is minimally supported as a host server. Don't put middleware above Webmachine!
- Fibers can be used as streamed response bodies.
Dispatcher#add_routewill now return the addedRouteinstance.- The header-conversion code for CGI-style servers has been extracted
into
Webmachine::Headers. Route#path_specis now public so that applications can inspect existing routes, perhaps for URL generation.Request#querynow usesCGI.unescapeso '+' characters are correctly parsed.- YARD documentation has 100% coverage.
0.2.0 September 11, 2011
0.2.0 includes an adapter for Mongrel and a central place for configuration as well as numerous bugfixes. Added Ian Plosker and Bernd Ahlers as committers. Thank you for your contributions!
- Acceptable media types are matched less strictly, which has implications on both responses and PUT requests. See the discussion on the commit.
- Resources now receive a callback after the language has been negotiated, so they can decide what to do with it.
- Added
Webmachine::Configurationso we can more easily support more than one host server/adapter. - Added Mongrel adapter, supporting 1.2pre+.
- Media type headers are more lax about whitespace following semicolons.
- Fix some problems with callable response bodies.
- Make sure String response bodies get a Content-Length header added and streaming responses get chunked encoding.
- Numerous refactorings, including extracting
MediaTypeinto its own top-level class.
0.1.0 August 25, 2011
This is the initial release. Most things work, but only WEBrick is supported.