Middleware with named arguments not initialized properly – wrong number of arguments
ahx opened this issue · comments
Andreas Haller commented
When trying to use
a middleware that uses named arguments like this:
class TellQuotaMiddleware
def initialize(app, quota:)
@app = app
@quota = quota
end
def call(env)
status, headers, body = @app.call(env)
headers["X-API-Rate-Limit-Quota"] = @quota
[status, headers, body]
end
end
It fails with
ArgumentError:
wrong number of arguments (given 2, expected 1; required keyword: quota)
See #34 for a failing test.
Andreas Haller commented
I don't know if it is allowed to use named arguments as options for rack middlewares, but I did not find anything that says the opposite. So I think it's allowed.
Luca Guidi commented
@ahx This is a Rack limitation. Rack::Builder#use
doesn't support keyword arguments (API docs).
Indeed, if you look at the stack trace, the error is happening in the Rack codebase:
Failures:
1) Hanami::API Rack middleware with complex app uses Rack middleware
Failure/Error:
def initialize(app, quota:)
@app = app
@quota = quota
end
ArgumentError:
wrong number of arguments (given 2, expected 1; required keyword: quota)
# ./spec/integration/hanami/api/middleware_spec.rb:66:in `initialize'
# /Users/jodosha/.gem/ruby/3.1.0/gems/rack-2.2.3/lib/rack/builder.rb:158:in `new'
# /Users/jodosha/.gem/ruby/3.1.0/gems/rack-2.2.3/lib/rack/builder.rb:158:in `block in use'
# /Users/jodosha/.gem/ruby/3.1.0/gems/rack-2.2.3/lib/rack/builder.rb:235:in `block in to_app'
# /Users/jodosha/.gem/ruby/3.1.0/gems/rack-2.2.3/lib/rack/builder.rb:235:in `each'
# /Users/jodosha/.gem/ruby/3.1.0/gems/rack-2.2.3/lib/rack/builder.rb:235:in `inject'
# /Users/jodosha/.gem/ruby/3.1.0/gems/rack-2.2.3/lib/rack/builder.rb:235:in `to_app'
# ./lib/hanami/api/middleware/app.rb:27:in `block in initialize'
# ./lib/hanami/api/middleware/app.rb:18:in `each'
# ./lib/hanami/api/middleware/app.rb:18:in `initialize'
# ./lib/hanami/api/middleware.rb:47:in `new'
# ./lib/hanami/api/middleware.rb:47:in `finalize'
# ./lib/hanami/api/router.rb:40:in `to_rack_app'
# ./lib/hanami/api/dsl.rb:105:in `freeze'
# ./lib/hanami/api/dsl.rb:99:in `initialize'
# ./spec/integration/hanami/api/middleware_spec.rb:243:in `new'
# ./spec/integration/hanami/api/middleware_spec.rb:243:in `block (4 levels) in <top (required)>'
# ./spec/integration/hanami/api/middleware_spec.rb:5:in `block (3 levels) in <top (required)>'
# ./spec/integration/hanami/api/middleware_spec.rb:247:in `block (4 levels) in <top (required)>'
The correct syntax would be
class TellQuotaMiddleware
def initialize(app, quota)
@app = app
@quota = quota
end
end
use TellQuotaMiddleware, 100
Andreas Haller commented
Thanks for looking into this, @jodosha .