I have no need for this feature and am only asking out of curiosity.
I'm aware that middlewares run before to each request.
Is it, however, reasonable to expect middleware to run after each request?
If that's the case, how can we go about doing it?
If not, how does the logger middleware report the response to the request?
CodePudding user response:
in Rails, middlewares are arranged in a stack (you could consider this stack is a pipeline), the request and the response go throw the stack in 2 opposite directions.
rails middleware stack
$ rails middleware
request # ... ^
| use Rack::ETag |
| use Rack::TempfileReaper |
| use Warden::Manager |
| run Bookstore::Application.routes response
V
In order to those middlewares in stack link together, the higher middlewares will call recursive the lower middlewares, let see some code to understand how it works, suppose we have 2 middlewares m1 and m2 in which m1 is arranged right above m2 in the stack, then the flow the request and the response go throw m1, m2 as below (steps in order [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
And the lowest middleware is Rails app, so the call stack look like a chain
call( ... call( ... call( ... rails_app.call() ))..)
so you could change app behavior (or how your app handle request/response) by adding/inserting_before(after)/removing nodes in this chain, very flexible !!!