๐Ÿง…

Rack & Middleware

HTTP processing layer underneath Rails

Rack is the standard interface between Ruby web servers (Puma, Unicorn) and web frameworks (Rails, Sinatra). The spec is very simple: a call(env) method returns a [status, headers, body] array.

Rails itself is a Rack app. When a request arrives, it passes through multiple Middleware layers before reaching the Rails router.

Key Middleware (check with rake middleware):

  • ActionDispatch::SSL โ€” Force HTTPS

  • ActionDispatch::Cookies โ€” Cookie handling

  • ActionDispatch::Session โ€” Session management

  • ActionDispatch::Flash โ€” Flash messages

  • Rack::MethodOverride โ€” PUT/PATCH/DELETE method support

  • ActionDispatch::RequestId โ€” Request tracking ID

You can write custom Middleware to handle request logging, authentication, CORS, etc. independently from the Rails app.

Architecture Diagram

How requests pass through the Middleware stack (onion model):
๐ŸŒ HTTP Request
Rack::SSL Force HTTPS
ActionDispatch::Cookies Cookie handling
ActionDispatch::Session Session management
ActionDispatch::Flash Flash messages
Rack::MethodOverride PUT/PATCH/DELETE support
ActionDispatch::RequestId Request tracking ID
Rails Router โ†’ Controller#Action
Response also passes through Middleware in reverse order
Key point: Requests/responses <strong>pass through Middleware layers sequentially</strong> โ€” each layer processes independently

Key Points

1

HTTP request arrives at web server (Puma)

2

Passed to Middleware stack via Rack interface

3

Each Middleware processes/modifies request in order (onion model)

4

Reaches Rails Router โ†’ Controller#Action executes

5

Response passes through Middleware stack in reverse

6

Final response [status, headers, body] returned to browser

Pros

  • Separation of concerns โ€” add features without touching Rails code
  • Compatible across Ruby web frameworks (Rails, Sinatra, etc.)
  • Easy to test (independent units)
  • Request/response pipeline customization

Cons

  • Middleware order matters โ€” wrong order breaks things
  • Hard to find which middleware causes issues during debugging
  • Too many middlewares degrade performance
  • Added abstraction layers increase complexity

Use Cases

Custom authentication middleware API request logging CORS handling Rate Limiting