I'm writing a rack middleware component for a rails app that will need to conditionally set cookies. I am currently trying to figure out to set cookies. From googling around it seems like this should work:
class RackApp
def initialize(app)
@app = app
end
def call(env)
@status, @headers, @response = @app.call(env)
@response.set_cookie("foo", {:value => "bar", :path => "/", :expires => Time.now+24*60*60})
[@status, @headers, @response]
end
end
which doesn't give errors, but doesn't set a cookie either. What am I doing wrong?
You can also use the Rack::Utils
library to set and delete headers without creating a Rack::Response object.
class RackApp
def initialize(app)
@app = app
end
def call(env)
status, headers, body = @app.call(env)
Rack::Utils.set_cookie_header!(headers, "foo", {:value => "bar", :path => "/"})
[status, headers, body]
end
end
If you want to use the Response class, you need to instantiate it from the results of calling the middleware layer further down the stack. Also, you don't need instance variables for a middleware like this and probably don't want to use them that way(@status,etc would stay around in the middleware instance after the request is served)
class RackApp
def initialize(app)
@app = app
end
def call(env)
status, headers, body = @app.call(env)
# confusingly, response takes its args in a different order
# than rack requires them to be passed on
# I know it's because most likely you'll modify the body,
# and the defaults are fine for the others. But, it still bothers me.
response = Rack::Response.new body, status, headers
response.set_cookie("foo", {:value => "bar", :path => "/", :expires => Time.now+24*60*60})
response.finish # finish writes out the response in the expected format.
end
end
If you know what you are doing you could directly modify the cookie header, if you don't want to instantiate a new object.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With