Rackless Ruby Servers: Why not?
An exploration of the interaction between four different Ruby web servers and their respective Rack handlers
The idea is to use these servers to GET
a Hello, World!
at /
, both on and off Rack. The goal is to make it clearer why Rack was created in the first place, and why to this day it’s still so relevant.
Getting Ready
The examples to come will help to illustrate the role that Rack, specially the Rack::Handler
, plays on being that minimal interface between Ruby web servers and Ruby web frameworks, as stated by Rack documentation.
To run each one of the examples in this article:
$ ruby server.rb
To verify that example works as expected:
$ curl localhost:3000
Which should output a simple:
> Hello, World!
Webrick
Off Rack
Since Webrick comes with Ruby, one can directly require, mount and run the server, without needing to install any third party libraries:
On Rack
On Rack, using its famous minimal interface, the same behaviour could be achieved with:
Mongrel
Off Rack
Mongrel, Thin and Puma will require a gem installation. For sake of simplicity, in this article each gem will be installed using an embedded Gemfile definition. So the Mongrel example would look like this:
On Rack
On Rack it will be necessary to use a specific rack
version, since Mongrel support was removed on one of Rack's last releases, but otherwise the interface remains the same:
Thin
Thin and Puma examples are going to be a bit closer to the Rack specification even for a simpleHello, World!
, which was actually a bit surprising to be honest.
That is because, different from the previously shown Webrick and Mongrel, they both expect an object with a Rack app interface, even when directly launched without their respective Rack handlers.
Off Rack
Thin is definitely the one that requires the least amount of code to launch the simple Hello, World!
output. This how one can achieve it:
On Rack
On Rack, the interface remains the same from the previous examples:
Puma
Off Rack
This is how a Hello, World!
with Puma could be achieved:
On Rack
In Puma case, the rack
gem doesn't come with the Rack::Handler::Puma
class, as one would expect, since puma comes with its own rack handler.
And as expected, once again, the interface remains the same:
That’s it! Have anything to say? Leave a comment, I’d love to hear about it. Learned something new? Share this article and spread the word!