Ped*_*ius 3 ruby rack middleware express
我真的很想知道这些东西是如何工作的,特别是在技术方面.目前,我正在更深入地研究ruby并尝试仅将其用于机架,以便了解基于机架的框架如何工作.
此时,机架中间件让我发疯.为什么?虽然中间件非常简单,但我对它有点困惑@app.call(env)
.为清楚起见,请考虑以下代码:
class MyCustomMiddleware
def initialize(app)
@app = app
end
def call(env)
@app.call(env) if env['REQUEST_METHOD'] != 'POST'
body = env['rack.input'].clone
body = JSON.parse(body.gets || {}, symbolize_names: true)
body[:some_message] = "Peace, Love and Hope"
env.update('rack.input', StringIO.new(JSON.dump(body)))
@app.call(env)
env
end
Run Code Online (Sandbox Code Playgroud)
我想做的就是更改请求体,如果(并且仅当)请求方法是POST
.如果请求方法是除"POST"之外的任何其他类型,我想将请求传递给下一个中间件(它在Rack中以这种方式工作,对吧?).问题是,无论请求方法是否存在,所有代码都在执行POST
.
也许这可能是对机架中间件的误解,因为我习惯了Express.js
.在Express
,您有一堆请求通过的中间件,并且每个中间件调用该next()
方法以"释放"请求.我认为这@app.call(env)
将类似于Express
' next()
方法...但看起来不是,因为当我调用它并且所有代码都被执行时请求没有被释放.
有人可以解释一下这个方法到底做了什么,并指出我的错误在哪里?
@app.call
不会终止处理程序的执行 - 它只是调用链中的下一个中间件.预计每个中间件将调用链中的下一个并返回其返回值,或者通过返回数组来终止链[status_code, body, headers]
.期望每个中间件[status_code, body, headers]
通过将该值从其#call
方法中返回来传递备份链的数组.回想一下,在Ruby中,每个方法的最后一个语句的返回值被隐式返回给它的调用者.
如上所述,您将调用堆栈中剩余的中间件,然后丢弃其结果,然后继续使用您的处理程序,运行代码,再次调用剩余的中间件堆栈,最后将结果返回上游.
return
如果你想摆脱处理程序,只需要明确:
def call(env)
return @app.call(env) if env['REQUEST_METHOD'] != 'POST'
body = env['rack.input'].clone
body = JSON.parse(body.gets || {}, symbolize_names: true)
body[:some_message] = "Peace, Love and Hope"
env.update('rack.input', StringIO.new(JSON.dump(body)))
@app.call(env)
end
Run Code Online (Sandbox Code Playgroud)
可能更清楚的是有条件地运行mutators,然后总是@app.call
终止处理程序:
def call(env)
mutate!(env) if env['REQUEST_METHOD'] == "POST"
@app.call(env)
end
def mutate!(env)
body = env['rack.input'].clone
body = JSON.parse(body.gets || {}, symbolize_names: true)
body[:some_message] = "Peace, Love and Hope"
env.update('rack.input', StringIO.new(JSON.dump(body)))
end
Run Code Online (Sandbox Code Playgroud)
由于这@app.call
是#call
此处的最后一个语句,因此其返回值将返回给中间件的调用者.