Rails 2's CookieStore produces invalid cookie data, causing tests to break

Posted . Visible to the public.

Note that this seems to affect only recent Rails 2 versions.

You will not encounter this until you are writing to the cookie more than once, but when doing so, integration tests (Cucumber) may break for you with this error:

You have a nil object when you didn't expect it!
You might have expected an instance of ActiveRecord::Base.
The error occurred while evaluating nil.[] (NoMethodError)

Background

The regular/short cucumber backtrace is not of any help but looking at the full trace reveals that ActionPack's action_controller/integration.rb is breaking while doing this:

cookies = @headers['Set-Cookie']
cookies = cookies.to_s.split("\n") unless cookies.is_a?(Array)
cookies.each do |cookie|
  name, value = cookie.match(/^([^=]*)=([^;]*);/)[1,2]
  @cookies[name] = value
end

This won't work when you there are empty lines in a cookie -- which is exactly what happened for me. That is how my cookie looked when debugging:

(rdb:1) puts headers['Set-Cookie']
remember_token=abcdef123456; path=/; expires=Mon, 31-Dec-2029 23:03:29 GMT

foo=23; path=/; expires=Thu, 30-Jan-2020 23:03:29 GMT

bar=42; path=/; expires=Thu, 30-Jan-2020 23:03:30 GMT
_some_session=foobarbaz; path=/; expires=Thu, 31-Dec-2020 23:03:30 GMT; HttpOnly

Solution

This seems to be a bug in Rails, the CookieStore (for sessions) or Rack::Utils.set_cookie_header -- I did not bother looking closer.

My problems went away when introducing an initializer that cleans up line breaks:

module ActionController
  module Session
    CookieStore.class_eval do

      def call_with_line_break_fix(*args)
        status, headers, body = call_without_line_break_fix(*args)
        headers['Set-Cookie'].gsub! "\n\n", "\n" if headers['Set-Cookie'].present?
        [ status, headers, body ]
      end

      alias_method_chain :call, :line_break_fix

    end
  end
end

Put that into a file like config/intializers/cookie_store_with_line_break_fix.rb and you are good to go.

If you don't feel like monkey-patching, you could also write a Rack middleware Show archive.org snapshot that tidys up your cookie data. I prefer doing API-stable patches, if possible.

Arne Hartherz
Last edit
License
Source code in this card is licensed under the MIT License.
Posted by Arne Hartherz to makandra dev (2012-06-26 10:21)