---
title: "What is Rack? A Ruby on Rails Webserver Interface"
description: "What is Rack application? What is middleware? How to use Rack in Ruby on Rails and webservers? Learn about Ruby Rack, middleware in detail."
author: "Krupa Suthar"
category: "Engineering"
published: "2019-06-04"
reading_time: "4 min read"
canonical: "https://www.solutelabs.com/blog/what-is-rack-a-ruby-on-rails-webserver-interface"
---

# What is Rack? A Ruby on Rails Webserver Interface

As a Ruby on Rails developer at SoluteLabs, when I came across Rack application in one of our projects it encouraged me to dig deeper into insides of Rack and helped me to find the answers of below questions,

1. What is the Rack application?
2. What is Rack middleware?
3. Where it is used?

## What is Rack?

As per [**Rack**](http://rack.github.io/), *it provides a minimal interface between web servers that support Ruby and Ruby frameworks.*

In simple terms, Rack sits between the ruby based application and web server helping them to interact with each other.

## Creating Rack application

Rack application is nothing but the object that responds to the **call** method.

```
class Hello
  def call(env)
    [200, {"Content-Type" => "text/html"}, ["Hello there!"]]
  end
end

run Hello.new
```

To run our newly created application invoke ***rackup config.ru*** command. Now go to http://localhost:9292/ and our application will be available there.

When we hit the above URL, in server **run** command will be invoked and it will call method ***call*** on Hello.new object.

If you look at the call method, it accepts the environment hash which contains information about the incoming HTTP request and the environment in which application is running as an argument and returns an array of exactly three values: The status, headers, and body.

**Now let’s take look at few of Rack’s terms:**

***run***

It takes Ruby object which responds to method **call** as an argument and runs **call** method on it.

***map***

It takes a string as a parameter and maps incoming requests against it and if it matches it will run the block assign to handle that.

***Use***

It includes the middleware in rack application.

## What is Rack Middleware?

**Middleware**

You can refer rack middleware as a small component that assists with the execution of a task. For example, You can think of different middleware doing different processes like logging, caching.

It can modify or halt requests before they reach the final middleware(The object which we assigned to run method).

**Middleware Stack**

When you include more than one middleware, it is called middleware stack. Its implementation is similar to [pipeline design pattern](https://www.cise.ufl.edu/research/ParallelPatterns/PatternLanguage/AlgorithmStructure/Pipeline.htm) for a web server that uses Rack. It means every incoming request passes through each middleware in the same order as they are defined.

**Built-in middlewares**

There are many already built-in [middleware components in rack](https://github.com/rack/rack/wiki/List-of-Middleware) available to use in your Rack application.

## Creating custom Middleware and using it in Rack Application

Let’s create our own custom middleware ***Cookie*** which will add cookies to response.

```
class Cookie
  def initialize(app, expiry)
    @app = app
    @expiry = expiry
  end

  def call(env)
    status, headers, body = @app.call(env)
    headers = headers.dup
    opts = {
        expires: Time.now + @expiry,
        value: 'value',
        path: '/',
    }
    Rack::Utils.set_cookie_header!(headers, "mycookie", opts)
    [ status, headers, body ]
  end
end
```

First, starting from constructor you may have noticed the ***app*** parameter in it. The **app** is next application middleware and every middleware constructor must have to include it.

This middleware calls ***@app.call(call)*** first which will call the next middleware in the stack(In our case it is **Hello**) and return its response. After that Cookie middleware will add cookies to respond and return the response back to the application.

```
require './cookie'
class Hello
  def call(env)
    [200, {"Content-Type" => "text/html"}, ["Hello there!"]]
  end
end

use Cookie, 24 * 60 * 60 # one day

run Hello.new
```

As explained above ***use*** command is used for adding middleware in the stack, we can use Cookies middleware in our Rack application as above.

## Rails and Rack

If rails project directory if you run **rake middleware** it will give the list of middlewares being used in rails as below,

```
use Rack::Sendfile
use ActionDispatch::Static
use ActionDispatch::Executor
use ActiveSupport::Cache::Strategy::LocalCache::Middleware
use Rack::Runtime
use Rack::MethodOverride
use ActionDispatch::RequestId
use ActionDispatch::RemoteIp
use Sprockets::Rails::QuietAssets
use Rails::Rack::Logger
use ActionDispatch::ShowExceptions
use WebConsole::Middleware
use ActionDispatch::DebugExceptions
use ActionDispatch::Reloader
use ActionDispatch::Callbacks
use ActiveRecord::Migration::CheckPending
use ActionDispatch::Cookies
use ActionDispatch::Session::CookieStore
use ActionDispatch::Flash
use ActionDispatch::ContentSecurityPolicy::Middleware
use Rack::Head
use Rack::ConditionalGet
use Rack::ETag
use Rack::TempfileReaper
run RailsRakeDemoApp::Application.routes
```

Every incoming request to your app will pass through this stack from up to bottom and finally giving its control to routes which dispatch request to the controller, controller process it and returns the response. This response will again pass through this middleware stack from bottom to up.

***But how these middlewares are being invoked and where they are defined?***

Every Ruby on Rails project have a config.ru file in its root directory and it has following content,

```
# This file is used by Rack-based servers to start the application.

require_relative 'config/environment'

run Rails.application
```

This file loads config/environment files and invokes **Rails.application** which will call Application defined in **application.rb.**

```
require_relative 'boot'

require 'rails/all'

# Require the gems listed in Gemfile, including any gems
# you've limited to :test, :development, or :production.
Bundler.require(*Rails.groups)

module DemoApp
  class Application < Rails::Application
    # Initialize configuration defaults for originally generated Rails version.
    config.load_defaults 5.2

    # Settings in config/environments/* take precedence over those specified here.
    # Application configuration can go into files in config/initializers
    # -- all .rb files in that directory are automatically loaded after loading
    # the framework and any gems in your application.
  end
end
```

Now let’s look at what does **application.rb** have,

Here ***Application*** is inherited from [***Rails::Application***](https://github.com/rails/rails/blob/main/railties/lib/rails/application.rb) which is inherited from [**Engine**](https://github.com/rails/rails/blob/main/railties/lib/rails/engine.rb). This Engine is a Rack application that has a ***call*** method defined in it which is being invoked when ***config.ru*** calls ***Rails.application.*** This is how Ruby on Rails application uses Rack.

***Rails::Application*** class loads **DefaultMiddlewareStack** which have the same middleware stack defined in it which we went through earlier.

## How can I use it?

Rails allow you to [***configure middleware stack***](https://guides.rubyonrails.org/rails_on_rack.html#configuring-middleware-stack) for adding your custom middleware to stack, deleting middleware from the stack and, changing the position of any middleware from the stack.
