Using Rack

Developer at work.
gilaxia/Getty Images

In the previous article, you learned what Rack is. Now, it’s time to start using Rack and serve up some pages.

Hello World

First, let’s start with a “Hello world” application. This application will, no matter what type of request it’s given, return ​with a status code of 200 (which is HTTP-speak for “OK”) and the string ”Hello world” as the body.

Before examining the following code, consider again the requirements that any Rack application must meet.

A Rack application is any Ruby object that responds to the call method, takes a single hash parameter and returns an array containing the response status code, HTTP response headers and the response body as an array of strings.
class HelloWorld
  def call(env)
    return [200, {}, ["Hello world!"]]

As you can see, an object of the type HelloWorld will meet all of these requirements. It does so in a very minimal and not terribly useful way, but it does meet all of the requirements.


That’s pretty simple, now let’s plug it into WEBrick (the HTTP server that comes with Ruby). To do this, we use the method, pass it an instance of HelloWorld and the port to run on. A WEBrick server will now be running, and Rack will be passing requests between the HTTP server and your application.

Note, this isn’t an ideal way to launch things with Rack. It's only shown here to get something running before diving into another feature of Rack called "Rackup," which is shown below.

Using Rack::Handler in this way has a few problems. First, it’s not very configurable. Everything is hard-coded into the script. Second, as you’ll notice if you run the following script, you can’t kill the program. It won’t respond to Ctrl-C. If you run this command, simply close the terminal window and open a new one.

#!/usr/bin/env ruby
require 'rack'

class HelloWorld
  def call(env)
    return [200, {}, ["Hello world!"]]
  :Port => 9000



While this is quite easy to do, it isn’t how Rack is normally used. Rack is normally used with a tool called rackup. Rackup does more or less what was in the bottom section of the code above, but in a more usable way. Rackup is run from the command-line, and is given a .ru “Rackup file.” This is just a Ruby script that, among other things, feeds an application to Rackup.

A very basic Rackup file for the above would look something like this.

class HelloWorld
  def call(env)
    return [
      {'Content-Type' => 'text/html'},
      ["Hello world!"]


First, we had to make one tiny change to the HelloWorld class. Rackup is running a middleware app called Rack::Lint that sanity-checks responses. All HTTP responses should have a Content-Type header, so that was added. Then, the last line just creates an instance of the app and passes it to the run method. Ideally, your application shouldn’t be written entirely within the Rackup file, this file should require your application into it and create an instance of it that way.

The Rackup file is just “glue,” no real application code should be there.

If you run the command rackup, it’ll start a server on port 9292. This is the default Rackup port.

Rackup has some more useful features. First, things like the port can be changed on the command line, or in a special line in the script. On the command-line, simply pass in a -p port parameter. For example: rackup -p 1337 From the script itself, if the first line starts with #\, then it’s parsed just like the command line. So you can define options here as well. If you wanted to run on port 1337, the first line of the Rackup file could read #\ -p 1337.