【问题标题】:In Rails, can middleware execute after each request?在 Rails 中,中间件可以在每次请求后执行吗?
【发布时间】:2021-09-10 15:50:16
【问题描述】:

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

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

但是,期望中间件在每个请求之后运行是否合理?

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

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

【问题讨论】:

  • 我认为Guide 提供了一个相当全面的默认中间件,它如何工作、何时触发以及如何添加额外的中间件
  • 是的,中间件同时处理请求和响应

标签: ruby-on-rails middleware


【解决方案1】:

在 Rails 中,中间件排列在一个堆栈中(您可以认为这个堆栈是一个管道),请求和响应向两个相反的方向扔堆栈。

rails 中间件堆栈

$ rails middleware

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

为了将堆栈中的这些中间件链接在一起,较高的中间件会递归调用较低的中间件,让我们看一些代码来了解它是如何工作的,假设我们有 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

而最底层的中间件是 Rails 应用,所以调用栈看起来像一条链

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

因此您可以通过在此链中添加/插入_之前(之后)/删除节点来更改应用行为(或您的应用处理请求/响应的方式),非常灵活!!!

【讨论】:

  • 好的,感谢您的回复!
猜你喜欢
  • 2021-06-15
  • 1970-01-01
  • 2021-06-10
  • 2021-06-01
  • 1970-01-01
  • 2016-01-05
  • 2012-04-13
  • 1970-01-01
  • 2013-04-08
相关资源
最近更新 更多