2. 2 / 11
What is rack?
Rack is a webserver interface. It means Rack is an editable list of
components that every request goes through in order to build the
response(HTML page).
4. 4 / 11
When we start (rails s), a web server is launched and receives request
from browser. The web server then submit that request to Rack, which
then processes the request and builds the response that the web server
will send back to the client(browser).
When we create a new rails project, it comes with 23 rack middlewares.
To view - run command (rake middleware) at the root of the rails project.
5. 5 / 11
How to use Rack
To create a middleware, you need an object that responds to (call(env))
function and returns an array that will then be sent to the browser. The
array exactly consists of three things -
1. Status code(200, 302, 404, ...)
2. A hash containing the header.
3. The body(Needs to be enumerable via # each)
6. 6 / 11
Creating a rack middleware
To create your own rack you need to follow these steps:
create a folder in app/ named middleware
create a file called my_middleware.rb and fill it up with these lines of code.
In your application.rb add
class MyMiddleware
def initialize(app)
end
def call(env)
[200, {"Content-Type" => "text/html"}, ["Hello Rack!"]]
end
end
Now start the server and run application in the browser.
You always get the welcome message - "Hello Rack!" whatever
path you hit in the bowser.
config.middleware.insert_before Rack::Sendfile, 'MyMiddleware'
7. 7 / 11
Because Rails builds the middleware list through
ActionDispatch::MiddlewareStack. By doing so, it adds another rule
to the middleware: MiddlewareStack and initializes every middleware by
passing an argument app to the object.
The (env) variable is the current environment built for that request. Its
the glue between middlewares, the only varaible that will be persisted. If
you set something in there, other middlewares will be able to access it,
even the controller.
The app parameter during the initialization is actually the next
middleware in the chain. By not calling (@app.call(env)), rack was
stopped at the very first middleware and returned our value.
8. 8 / 11
Now change your MyMiddleware class by this code.
class MyMiddleware
def initialize(app)
end
@app = app #Store the app to call it down the stack end
def call(env)
# Initialize stuff before entering 'rails'
# Retrieve a connection form a pool (Redis, Memcache, etc.)
# Authentication/authorization/tenancy setup needs to be done before
# Remember, you can set stuff in env and then access it in your controller.
# The response has the same structure as before:
# [200, {"Content-Type" => "text/html"}, ["Hello Rack!"]]
# The header is now fully populated and instead of the "Hello Rack!",
# the body is a full HTML page.
# @app.call will call ActionDispatch::Static which, in turn,
will call ActiveSupport::CacheStrategy which will
# call Rack::Runtime and so on up to your controller/view.
response = @app.call(env)
end
end
9. 9 / 11
And your application starts behaving normally.
Lets better understand the situation with AUTHENTICATION AND
AUTHORIZATION
Now change your middleware code by this:
class MyMiddleware
def initialize(app)
@app = app #the next middleware to be called
@fallback = RestrictedController
end
def call(env)
result = catch(:restricted) do
@app.call(env)
end
if result.nil?
@fallback.call(env)
else
result
end
end
end
10. 10 / 11
Add this method on application controller
class ApplicationController < ActionController::Base
protect_from_forgery with: :exception
def restrict!
throw :restricted
end
end
Add a controller - (restricted_controller)
class RestrictedController < ActionController::Base
def self.call(env)
action(:respond).call(env)
end
def respond
flash.alert = "Couldn't access the resource"
redirect_to root_url
end
end
The middleware calls the class method RestrictedController.call.
In any of your controller, if you call restrict!, it will throw an error that will
becaught(:restricted) by your rack application. When the error is raised,
the fallback application will be called.
11. 11 / 11
Thank you !!
Ashish Garg
Sonu Kumar
Aakanksha Bhardwaj