Imagine you want to add a new middleware for your application that does a simple thing: verify a token sent in the header by the client code. If this token matches our secret token, allow the request to proceed. Otherwise, immediately return an error without passing the request to the application.
To accomplish this, let's introduce a custom middleware, which is just a Ruby class with the interface we saw in the introduction. As mentioned above, it will have a call
method that takes the incoming request and returns an array containing the HTTP status, headers, and the response body.
# lib/middleware/verify_token.rb
module Middleware
class VerifyToken
def initialize(app)
@app = app
end
def call(env)
request = ActionDispatch::Request.new(env)
if request.headers['token'] != 'my-secret-token'
return [200, {}, ['invalid or missing token']]
end
@app.call(env)
end
end
end
As you can see, in the call
method, we'll first verify the token and return an error if it doesn't match our secret token. If it matches, we send the normal response.
Where do you put middleware in your Rails app?
Middleware can't be in
app
because they can't be reloaded. They should be inlib
. - Rafael Franca
Let's create a new folder called middleware
in the lib
folder and add VerifyToken
middleware in it.
We're not done yet, we need to tell Rails to insert this middleware in the middleware stack. Let's do this using the config.middleware
object.
Rails Middleware API
Rails provides a simple configuration interface config.middleware
for adding, removing, and modifying the middleware stack.
The object returned by config.middleware
method is an instance of Rails::Configuration::MiddlewareStackProxy
class. As the name suggests, it's a proxy for the Rails middleware stack that lets you configure the middleware for your application.
You can either use config.middleware
in the application.rb
file or one of the environment-specific configuration files under the environments/<env>.rb
file.
To add a new middleware, use the config.middleware.use
method, passing the name of the Ruby class that acts as middleware. Rails will insert this middleware at the end of the existing middleware stack, meaning it will get executed in the end, just before your application is called.
# config/application.rb
require_relative "../lib/middleware/verify_token"
module Blog
class Application < Rails::Application
config.middleware.use Middleware::VerifyToken
end
end
That's it! We've successfully added a middleware to verify an incoming request.
Instead of putting your middleware in the end, if you wish to insert it before or after another middleware, you can do so using the insert_before
or insert_after
method.
config.middleware.insert_before ActionDispatch::Callbacks, VerifyToken
This will insert the VerifyToken
callback before the ActionDispatch::Callbacks
middleware runs.