在Rails中,中间件可以在每次请求后执行吗?

In Rails, can middleware execute after each request?

我不需要这个功能,只是出于好奇才问的。

我知道中间件 运行 在每个请求之前。

但是,期望中间件在每次请求后 运行 合理吗?

如果是这样的话,我们该怎么做呢?

如果不是,记录器中间件如何报告对请求的响应?

在Rails中,中间件被安排在一个堆栈中(你可以认为这个堆栈是一个管道),请求和响应从两个相反的方向抛出堆栈。

rails 中间件栈

$ rails middleware

request  # ...                                ^
  |      use Rack::ETag                       | 
  |      use Rack::TempfileReaper             |
  |      use Warden::Manager                  | 
  |      run Bookstore::Application.routes   response 
  V

为了把堆栈中的那些中间件link放在一起,高层中间件会递归调用底层中间件,让我们看一些代码来理解它是如何工作的,假设我们有2个中间件m1和m2,其中m1被安排在堆栈中 m2 的正上方,然后请求和响应的流程将抛出 m1,m2,如下所示(步骤 [1],[2],...):

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

 def call(env) # [1] higher middleware call
   # [2] before call recursive
   # you could get request
   request = ActionDispatch::Request.new env
   # log request , or something else ...
 
   status, headers, body = \ # [9] get response from M2
       @app.call(env) # [3] call recursive M2
   
   # log response, or do something else ...
   [status, headers, body] # [10] return response to higher middleware
 end  
end

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

 def call(env) # [4] M1 call
   # [5] before call recursive lower middleware
   # same as above 

   status, headers, body = \ # [7] get response from lower middlewares
       @app.call(env) # [6] call recursive lower middleware
   
   # log response, or do something else ...
   [status, headers, body] # [8] return response to M1 above
 end 
end

最底层的中间件是Railsapp,所以调用栈看起来像一个链

call( ... call( ... call( ... rails_app.call() ))..)

因此您可以通过 adding/inserting_before(之后)/删除此链中的节点来更改应用程序行为(或您的应用程序如何处理 request/response),非常灵活!!!