Middleware is very useful for writing logic that is not specific to your web application, such as authenticating the request, logging, or error handling. It focuses on doing one thing and doing it well.
Middleware sits between the user and the application code. When an HTTP request comes in, the middleware can intercept, examine, and modify it. Similarly, it can examine and modify the HTTP response before forwarding it to the user.
Middleware provides a convenient mechanism for inspecting and filtering HTTP requests entering your application. For example, Rails includes the Rack::MethodOverride
middleware that inspects and overrides the HTTP verb of the incoming request.
Using middleware simplifies your application code, and it can only focus on the logic related to the application.
Authentication is another good use case for middleware. If the user is not authenticated, the middleware will redirect the user to your application's login screen. However, if the user is authenticated, the middleware will allow the request to proceed further into the application.
You can write middleware to perform a variety of tasks besides authentication. For example, as we'll see later, a logging middleware logs all incoming requests to your application.
There are several middleware (is 'middlewares' a word?) included in the Rails framework. You can see a list of all middleware by running the bin/rails middleware
command. The Rails guides also provide a brief description of what each middleware does.
Middleware can perform tasks before or after passing the request deeper into the application. For example, the following middleware performs some task both before and after the request is handled by the application:
module Middleware
class DoSomething
def initialize(app)
@app = app
end
def call(env)
# perform something before passing the request to the application
process_request(env)
response = @app.call(env)
# perform something after receiving the response from the application.
# It should also return the response.
process_response(response)
end
end
end
No matter where a middleware performs its action, it still has to return a valid Rack-compatible response to the next middleware in the pipeline, or the web server.
In the next section, we'll learn how you can create your own middleware.