Rack basics
Hello!
I am Enol Iglesias
You can find me at:
Rack, a modular Ruby webserver interface
Rack provides a minimal, modular, and adaptable interface for developing web applications in Ruby.
By wrapping HTTP requests and responses in the simplest way possible, it unifies and distills the API for web servers, web frameworks, and software in between (the so-called middleware) into a single method call.
What Rack does
Unicorn
Passenger
Puma
WEBrick
Rack
Rails
How it works
It must respond to call
The call method must accept a single argument
This argument is typically called env or environment.
The call method must return an array of three elements
That three elements, the response, are:
The environment object
The environment object is a Hash that contains info about the request. Some of that info are:
The response
Status
An HTTP status.
Headers
It must be a Hash (key-value pairs).
Body
The data returned by the server. It must respond to each, and yield string values.
Basic Rack app examples
Class based
require 'rack'
class Wadus
def call(env)
['200', {'X-Wadus' => 'Foo'}, ['Class based so simple rack app']]
end
end
Rack::Handler::WEBrick.run Wadus.new
Basic Rack app examples
Proc based
require 'rack'
app = -> (env) do
['200', {'X-Wadus' => 'foo'}, ['Proc based so simple rack app']]
end
Rack::Handler::WEBrick.run app
Basic Rack app examples
config.ru
run Proc.new { |env| [['200', {'X-Wadus' => 'foo'}, ['Bar']] }
This file, is a rack config file. It doesn’t need to require rack.
You can run this kind of applications with rackup
Rack middlewares
A middleware is a component (a single and simple rack application) between the client and the server, processing inbound requests and outbound responses.
Data flow
Basic Rack middleware
class Wadus� def initialize(app)� @app = app� end�� def call(env)� # Whatever you want to do before the rack middlewares stack execution� status, headers, body = @app.call(env)� # Whatever you want to do after the rack middlewares stack execution� [status, headers, body]� end�end
Putting all together
class LoggerMiddleware
def initialize(app)
@app = app
end
def call(env)
before = Time.now.to_f
status, headers, body = @app.call(env)
after = Time.now.to_f
puts "[LOGGER] Request time: #{after - before} sec."
[status, headers, body]
end
end
require './logger_middleware'��class Wadus� def call(env)� ['200', {'X-Wadus' => 'Foo'}, ['Class based so simple rack app']]� end�end��use LoggerMiddleware�run Wadus.new
Rails on Rack
Rails.application is the primary Rack application object of a Rails application.
Rails server does the basic job of creating a Rack::Server object and starting the webserver.
Rails middleware stack
(wait for it...)
Rails middleware stack list
Adding middleware to Rails stack
We can add a new middleware to the middleware stack of our Rails application configuring it in config/environments/* files:
Modifyng Rails middleware stack
We can modifyng the middleware stack in config/environments/* files:
Dummy example in Rails
class RequestTimeMiddleware� def initialize(app)� @app = app� end� def call(env)� before = Time.now.to_f� status, headers, body = @app.call env� time = "#{(Time.now.to_f - before).to_s} sec"� headers['X-Request-Time'] = time�� [status, headers, body]� end�end
�
config.middleware.insert_before "Rack::Sendfile", "RequestTimeMiddleware"
Stored in app/middleware/
Added in config/environments/*
Some ideas for middlewares
Thanks!
Any questions ?�
You can find me at:
Resources