1

I'm trying to use Rack Middleware to set a cookie and send a response with the cookie in effect in the same request-response cycle.

Here is the context: I'm working on a website with two modes: a US mode and a UK mode (different logos, navigation bars, styles, etc). When a UK visitor hits the page for the first time, I want to set a 'uk mode' cookie on his browser but also render the UK version of the page. Here is my code so far:

 # middleware/geo_filter_middleware.rb

 def initialize(app)
   @app = app
 end

 def call(env)
   status, headers, body = @app.call(env)
   response = Rack::Response.new(body, status, headers)
   if from_uk?(env)
      response.set_cookie('country', 'UK')
   end
   response.to_a
 end

When a UK visitor hits the page for the first time, it sets the 'uk mode' in their cookie but it still renders the default US version of the page. It's only after the second request when the cookie would come into effect and the UK visitor sees the UK mode.

Does anyone have any idea to simultaneously set the cookie and return a response with the cookie in effect in one request-response cycle?

User314159
  • 7,733
  • 9
  • 39
  • 63

1 Answers1

3

you need to setup your middleware in your application.rb

config.middleware.insert_before "ActionDispatch::Cookies", "GeoFilterMiddleware"

and in your middleware do something like this:

  def call(env)
    status, headers, body = @app.call(env)
    if from_uk?(env)
      Rack::Utils.set_cookie_header!(headers, 'country', { :value => 'UK', :path => '/'})
    end
    [status, headers, body]
  end
Zen
  • 382
  • 3
  • 9
  • Hey, this looks promising. Thanks for answering! – User314159 Jul 09 '13 at 17:06
  • This does look promising, but it doesn't work. It has the same effect as the existing code in the question - the cookie is set, but not for the same request. Anything that works would have to modify the env BEFORE doing @app.call(env) – joshua.paling Sep 14 '15 at 12:32