Bug: Rack inserts "Set cookie" on 304 Not Modified request

392 views
Skip to first unread message

Jan M.

unread,
Jun 15, 2010, 6:01:32 AM6/15/10
to Rack Development

The rack session logic always adds a "Set cookie" header to each
response, even when the cookie has not changed. This is a little bit
wasteful but if the response happens to be a "304 - Not Modified" then
this is actually problematic in one particular edge case: Internet
Explorer 7 will destroy the cookie if there is a combination of a "Set
cookie" header on a 304 response inside an Iframe. This happens even
if the cookie previously existed, thus destroying the session and
typically logging the user out.

This bug is hard to identify since it requires a combination of IE7,
an Iframe and a 304 request, but a search on the Rails forums on
"iframe logout" turns up quite a few people who ran into it. The
reason that IE7 does this is that it requires a so called P3P header
for it to accept cookies inside an Iframe and Apache will correctly
filter P3P headers from the response since those are not allowed on
304 responses according to W3C specs. Whether the Set-Cookie header is
allowed on a 304 is debatable, but Apache doesn't filter those leading
IE7 to believe there is a problem.

So it's a combination of 3 bugs: Rack should not add a cookie on a
304, Apache should filter all headers or none, but not half, and IE7
should not destroy a cookie that already existed (fixed in IE8 by the
way).

A solution is to add a middleware layer in rails that simply does:

def call(env)
response = @app.call(env)
response[1].delete('Set-Cookie') if response[0] == 304
response
end

One option is to add similar logic to Rack, but in my opinion it would
be more elegant if Rack would simply not add a cookie when the cookie
has not changed.
Credit to Robert Vogel for figuring most of this out.

Gaius

unread,
Jun 15, 2010, 8:10:58 AM6/15/10
to Rack Development
+100,000,000,000 to Jan for such a thorough and well-written bug
report!

But I'm not sure about a +1 for the actual change. If you look at the
HTTP spec (http://www.w3.org/Protocols/rfc2616/rfc2616-
sec10.html#sec10.3.5), 304 responses can't have entity headers, but as
Ryan Eberhard points out (https://issues.apache.org/bugzilla/
show_bug.cgi?id=18388), "Set-Cookie" can reasonably be described as a
response header rather than an entity header.

Jan M.

unread,
Jun 15, 2010, 7:37:06 PM6/15/10
to Rack Development
Yes, valid point, there was a similar discussion on the Apache mailing
list; It's debatable whether this is actually a "bug" in Rack since
both Apache and IIS allow cookies on 304 headers (ISS even incorrectly
allows P3P headers, but that does help avoid the IE7 problem).

Nevertheless, there is still a case to be made for this change as a
feature request:
- It saves about 50 bytes on most requests
- It avoids the IE7/Iframe/304 problem described above

With the countless Rack instances out there saving 50 bytes for
quazillion request every day requests you could even make a case that
this saves energy :-)
-j

Jan M.

unread,
Jun 15, 2010, 7:43:08 PM6/15/10
to Rack Development
Just to clarify my previous post: Those saved bytes would only happen
if the feature request would be to only add a cookie if it has
actually changed. Compared to the solution to simply remove the cookie
on a 304 it avoids the discussion whether cookies are allowed on a 304
but still fixes the IE7 issue.
Reply all
Reply to author
Forward
0 new messages