-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Description
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:
def call(env)
req = Rack::Request.new(env)
# do stuff with req
@app.call(req.env)
endI 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:
- Make a middleware that casts the env hash to a request object, then passes the request object to the next middleware
- Make the request object quack enough like a hash that existing legacy middleware can use the request object as if it was the env hash
Step 1 could be as simple as this:
class CastsToRequest
def initialize(app)
@app = app
end
def call(env); @app.call(Rack::Request.new(env)); end
endIf 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 as Rack::Request).