Middleware and Rack
The Rack stack.
Middleware and Rack is a free Ruby Academy lesson on CoddyKit. This is lesson 4 of 4. Any 3 lessons of this learning path are free to read in full — after that, CoddyKit PRO unlocks every lesson, plus hands-on practice with a built-in code editor and a 24/7 AI tutor. It is part of the Ruby Academy learning path, and your progress syncs across the web and the CoddyKit app. The Ruby Academy course includes 4 lessons in total.
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
Learn Ruby with an AI tutor — free
Write and run real code in your browser, get instant help from a 24/7 AI tutor, and pick up where you left off on the web or in the app.
- Courses
- 29
- Lessons
- 109
Frequently Asked Questions
Is the “Middleware and Rack” lesson free?
Yes — any 3 lessons of the Ruby Academy learning path, including “Middleware and Rack”, are free to read in full here on the web. After that, CoddyKit PRO unlocks every lesson, plus interactive practice with a built-in code editor and a 24/7 AI tutor. The Ruby Academy course includes 4 lessons in total.
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, so you can start here or from the beginning and move at your own pace. This is lesson 4 of 4.
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