New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Pass a request object to middleware rather than a hash #1879
Comments
As I mentioned in #1878 (comment), I'm against this proposal. Completely breaking backwards compatibility at this stage in rack's lifecycle makes is a very bad trade off, IMO. If given a choice between a request object and an h2 style |
@jeremyevans what part of this proposal are you against? The contract with the webserver doesn't change, it just lets downstream rack applications avoid allocating more request objects (should they want to opt-in, and they must opt-in by having the |
@tenderlove I don't think it's a good idea to change the object passed to middleware/applications. Part of your comment makes this appear to be opt-in, which is not nearly as bad as having it on by default, but I still don't think it's a good idea. You would have to complicate all middleware that ship with rack to deal with both Additionally, If the goal is to avoid allocations, my recommendation would be to add the following to current middleware that ship with Rack: # change
request = Rack::Request.new(env)
# to:
request = env['rack.request'] ||= Rack::Request.new(env) What are your thoughts on that approach? |
Sorry I don't follow this. A middleware would have to say "I only work when
We've tried this exact approach in Rails before and ended up removing it. Though I have to admit I don't remember why. Regardless, I would prefer not to litter every middleware with a lazy allocator and I would also prefer not to rely on the good graces of all previous middleware to pass the same |
I guess you are working under the assumption that you can get a request object that operates enough like an Unless you are able to make this transparent, so that a request object can be used anywhere an env hash is currently used, I think this will place a burden on the ecosystem. It either increases complexity for all middleware/applications to support both, or it bifurcates the ecosystem and middleware/applications support one and not the other. Additionally, is it really opt-in if webservers are allowed to use a request object instead of an |
If the issue is middleware that ship with Rack, as an alternative to this, I volunteer to modify all middleware that ship with rack to not rely on Rack::Request. |
Been slowly catching up to the several threads about the topic, and it seems that there are two valid perspectives: on one side, the protocol needs to evolve, while on the other, breaking code relying on the current contract is unacceptable. So why not just create a new entrypoint, and thereby, a new protocol, that could reuse most of the existing boilerplace? I'd propose smth like this: def call_req(request)
# do stuff with req
# get a response object
response = @app.call_req(request)
return response
end This could provide new ground for speccing smth which the current The class NewMiddleware
def call_req(req)
@app.call_req(req)
end
end
class OldMiddleware
def call(env)
@app.call(env)
end
end
class DualMiddleware
def call_req(req)
@app.call_req(req)
end
def call(env)
@app.call(env)
end
end The class NewMiddleware
# rack would inject: attr_reader :request_class
def call_req(req)
@app.call_req(req)
end
# rack would inject
def call(env)
call_req(@request_class.from_env(env))
end
class OldMiddleware
def call(env)
@app.call(env)
end
# rack would inject
def call_req(request)
rack_array = call(request.to_env)
request.make_response(rack_array)
end
end If we skip bikeshedding on the names above, the benefit would be that old middlewares would play well with new middlewares and vice-versa, in any order, with negligible impact (1 extra method call in the stack). Middlewares could be adapted for both versions. Frameworks could provide entrypoints for both versions and adapt accordingly. Application servers would be in charge with passing down request and response interfaces complying with the new protocol. I also agree with @jeremyevans that (I've tried, and ultimately gave up on, years ago, to build an alternative to rack). |
…test-sprint Add rack-session gem when testing rack-attack
One problem I see in many middleware is that they "cast" the env hash to a Rack request object, do some manipulations, then pass then cast it back to a hash and pass it on.
For example:
I would really like it if we could stop allocating request objects all the time, but since every middleware is passed a hash it's something that happens quite frequently.
I would like to do 2 things:
Step 1 could be as simple as this:
If some middleware want to take advantage of this "pre allocated" request object, then they would require that
CastsToRequest
is in the middleware stack above them. Those middleware would no longer have to cast back and forth between hash and request object.If the
Rack::Request
object quacks enough like a hash, then users could add legacy middleware without changing anything, though they could be upgraded to take advantage of the request object.I think this idea could work because it should be OK for any middleware to say "yes I work with any Rack compatible web server, but I must be run after the
CastsToRequest
middleware. I think this would also unlock the ability for web servers to start passing their own request objects to middleware (as long as they quack the same asRack::Request
).The text was updated successfully, but these errors were encountered: