Middleware and Rack
The Rack stack.
Middleware and Rack is a free Ruby Academy lesson on CoddyKit — lesson 4 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the Ruby Academy learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.
What Is Rack?
Rack is the minimal interface between Ruby web servers and frameworks. Sinatra, Rails, and others all run on Rack.
- Standardizes how requests and responses flow
- Enables reusable middleware
- A Rack app is anything that responds to
call(env)
app = lambda do |env|
[200, { 'Content-Type' => 'text/plain' }, ['Hello Rack']]
end
puts app.call({}).inspectThe Rack Contract
A Rack app's call must return a three element array:
- Status integer (e.g. 200)
- Headers hash
- Body that responds to
each(usually an array of strings)
status, headers, body = 200, { 'Content-Type' => 'text/html' }, ['<h1>Hi</h1>']
puts status
puts headers.inspect
body.each { |chunk| puts chunk }The env Hash
The env argument is a hash describing the request.
REQUEST_METHODlike GET or POSTPATH_INFOthe requested pathQUERY_STRINGraw query parameters
env = { 'REQUEST_METHOD' => 'GET', 'PATH_INFO' => '/home' }
puts "#{env['REQUEST_METHOD']} #{env['PATH_INFO']}"What Is Middleware?
Middleware wraps an app to add behavior before or after the request reaches it.
- Logging, authentication, compression
- Each middleware also responds to
call(env) - It calls the next app in the chain
class Logger
def initialize(app)
@app = app
end
def call(env)
puts "Request: #{env['PATH_INFO']}"
@app.call(env)
end
endBuilding a Middleware Class
Middleware stores the wrapped app and delegates to it in call.
- Constructor receives the inner app
callcan modify env, then forward- It can also alter the response on the way back
class UpcaseBody
def initialize(app)
@app = app
end
def call(env)
status, headers, body = @app.call(env)
new_body = body.map(&:upcase)
[status, headers, new_body]
end
end
puts 'Middleware defined'The Middleware Stack
Middleware forms a stack. The request flows down to the app, the response flows back up.
- Outer middleware runs first on the way in
- Outer middleware runs last on the way out
inner = lambda { |env| [200, {}, ['core']] }
class Wrap
def initialize(app); @app = app; end
def call(env)
s, h, b = @app.call(env)
[s, h, b.map { |x| "[#{x}]" }]
end
end
puts Wrap.new(inner).call({}).last.inspectUsing Middleware in Sinatra
Add middleware to a Sinatra app with use.
use Rack::Logger- Order of
usecalls defines the stack order
require 'sinatra'
use Rack::Logger
get '/' do
'Logged request'
endconfig.ru and rackup
A config.ru file boots a Rack app with rackup or Puma.
runsets the final appuseadds middleware before it
# config.ru
require './app'
use Rack::CommonLogger
run Sinatra::ApplicationCommon Built-in Middleware
Rack ships with useful middleware.
Rack::CommonLoggerrequest logsRack::Deflatergzip compressionRack::Staticserve filesRack::Session::Cookiesessions
# In config.ru
# use Rack::Deflater
# use Rack::Static, urls: ['/assets'], root: 'public'
puts 'See comments for usage'Modifying the Response
Middleware often adds response headers after the inner app runs.
- Capture the response triple
- Mutate headers, then return it
class AddHeader
def initialize(app); @app = app; end
def call(env)
status, headers, body = @app.call(env)
headers['X-Powered-By'] = 'Ruby'
[status, headers, body]
end
end
app = AddHeader.new(lambda { |e| [200, {}, ['ok']] })
puts app.call({})[1].inspectShort Circuiting Requests
Middleware can halt a request without calling the inner app.
- Useful for auth gates or rate limits
- Return a response triple directly
class Auth
def initialize(app); @app = app; end
def call(env)
return [401, {}, ['Unauthorized']] unless env['token']
@app.call(env)
end
end
app = Auth.new(lambda { |e| [200, {}, ['ok']] })
puts app.call({})[0]Quick Check
Verify your Rack understanding.
Recap
You learned the Rack stack:
- Rack is the common interface beneath Ruby web frameworks
- A Rack app responds to
call(env)and returns[status, headers, body] - Middleware wraps an app to add cross cutting behavior
- Use
usein Sinatra orconfig.ruto compose the stack - Middleware can modify responses or short circuit requests
Frequently asked questions
Is the “Middleware and Rack” lesson free?
Yes — the full text of “Middleware and Rack” is free to read here on the web, and the Ruby Academy course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the Ruby Academy course, upgrade to CoddyKit PRO.
What will I learn in “Middleware and Rack”?
The Rack stack. You practise Ruby Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.
Do I need any experience to start Ruby Academy?
No prior experience is required. Ruby Academy on CoddyKit is structured for beginners through advanced learners; this is — lesson 4 of 4, so you can start here or from the beginning and move at your own pace.
How long does the “Middleware and Rack” lesson take?
Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.
Can I write and run code in this Ruby Academy lesson?
Yes. Every Ruby Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.
All lessons in this course
- Sinatra Basics
- Routes and Params
- JSON APIs
- Middleware and Rack