rubyrack

can we have rack middleware after main?


I am trying to understand how order in middleware of rack work. I have this middleware

class Middleware1
  def initialize(app)
    @app = app
  end

  def call(env)
    puts "Middleware 1 start"
    status, headers, body = response = @app.call(env)
    puts "Middleware 1 to return"
    response
  end
end

and i am calling it after my main application

require_relative "lib/middleware1"

class MyApp
  def call(env)
    puts "main calling"
    [200, {}, ["Hello World"]]
  end
end

run MyApp.new
use Middleware1

I thought after main returns, the Middleware1 will not get executed. But the output show Middleware get called first. here is the log

Middleware 1 start
main calling
Middleware 1 to return

How come Middleware1 get called first? is there any specific reason for it? thanks


Solution

  • A middleware is a layer that lives between the application and the client.

    The communication flow between a client, an application and its middleware, is the following:

        ┌────────────┐      ┌────────────┐      ┌─────────────┐
        │            ├──1──▶│            ├──2──▶│             │
        │   Client   │      │ Middleware │      │ Application │
        │            │◀──4──┤            │◀──3──┤             │
        └────────────┘      └────────────┘      └─────────────┘
    
    1. A client sends a request to the middleware.
    2. The middleware might run code, for example, logging or changing the request and then forwards a request to the application.
    3. The application returns its response to the middleware.
    4. The middleware grabs that response, might again run additional code to change the response, and then sends it to the client.

    That means the middleware is actually a wrapper around the application, and it runs before the application but also after the application.

    It has full access to read and/or manipulate the incoming and forwarded request, and the response returned by the application and the response actually returned to the client.