我不需要这个功能,只是出于好奇。
我知道中间件在每个请求之前运行。
然而,期望中间件在每个请求之后运行是合理的吗?如果是这样的话,我们该怎么做呢?
如果没有,日志中间件如何报告对请求的响应?
在Rails中,中间件被安排在一个堆栈中(你可以认为这个堆栈是一个管道),请求和响应将堆栈扔向两个相反的方向。
rails中间件栈
$ rails middleware
request # ... ^
| use Rack::ETag |
| use Rack::TempfileReaper |
| use Warden::Manager |
| run Bookstore::Application.routes response
V
为了将堆栈中的中间件链接在一起,较高的中间件将递归地调用较低的中间件,让我们看一些代码来理解它是如何工作的,假设我们有两个中间件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 app,所以调用栈看起来像一个链
call( ... call( ... call( ... rails_app.call() ))..)
所以你可以改变应用程序的行为(或你的应用程序如何处理请求/响应)通过添加/inserting_before(after)/删除节点在这个链,非常灵活!!