Cookie problem with proxy cache

I had a problem with the proxy cache. I have a login page that sets a
cookie and
returns “Vary: cookie”. For some reason, nginx seems to think the page
can be
cached and thus strips the Set-Cookie header. So I can’t login. :slight_smile:

I’ve fixed the problem by adding a proxy_pass_header Set-Cookie. But I
guess the
root of the problem is that nginx thinks it can cache the page in spite
of the
“Vary: cookie” header. Isn’t this a bug?

For the record, Varnish doesn’t cache Vary: cookie pages.

I have the following cache settings, copied from an example in the
English
documentation:

proxy_cache defaultzone;
proxy_cache_valid 200 302 2m;
proxy_cache_valid 301 1h;
proxy_cache_valid any 30s;

The login page comes from a web framework (Django admin) which makes
plenty use
of the Vary: cookie header.

Ole

Ole Laursen wrote:

I’ve fixed the problem by adding a proxy_pass_header Set-Cookie. But I
guess the
root of the problem is that nginx thinks it can cache the page in spite
of the
“Vary: cookie” header. Isn’t this a bug?

I’m wondering too how to use proxy_cache correctly. I’ve added
“proxy_set_header Cookie $http_cookie;” and I have also made sure that
$http_cookie is part of the proxy_cache_key, or nginx would return
cached pages (meant for a specific user who had previously logged in)
for any request.

I guess that I’d like NOT to cache any responses whose request included
a Cookie: header, but proxy_cache cannot work in a conditional section,
and I guess that there’s a good reason for that.

I’d truly appreciate guidance on this subject.

Thanks!

2009/11/17 Emanuele P. [email protected]:

$http_cookie is part of the proxy_cache_key, or nginx would return
cached pages (meant for a specific user who had previously logged in)
for any request.

I guess that I’d like NOT to cache any responses whose request included
a Cookie: header, but proxy_cache cannot work in a conditional section,
and I guess that there’s a good reason for that.

I’d truly appreciate guidance on this subject.

Cookies are a way to generate dynamic pages in function of user action.
Cache does take into account users, it does not know them.
Both are incompatible (in most cases).

Example:

The first time you’re visiting a website, you arrive without any
cookies (you’re anonymous). It says it has never seen you before.
In addition to the response, the webserver send you back a cookie
saying (“today at 7:04”).

The second time you’re visiting this website, you’re sending the
cookie and it says it saw you “today at 7:04”.
In addition to the response, the webserver send you an update of the
cookie saying (“today at 7:05”)

But if in front of the webserver you’re using cache, the first time
it’ll fetch the page saying you’re anonymous. The second time, it will
send you the page from cache saying you’re anonymous even if it’s
false.

You can imagine how it can be with multiple users at the same time.

Cache mechanisms ignore cookies (an incoming cookie is not sent to the
backend server and a cookie from a backend user is not sent back to
the final user) because it doesn’t know how to deal with them.

Even if it can deal with them (page A with cookie A is cached as file
C1 and page A with cookie B is cached as file C2). In this case cache
is totally useless because each couple PAGE/COOKIE is unique and there
is almost nothing to gain here.

Hope this helps.

++ jerome

This would be true except that a lot of times cookies are set
automatically even for guest users, as a session cookie. Oftentimes,
this session cookie will not change what you’re seeing at the site.

And then, of course, cookies will be sent even when trying to access
things like images, css, js files, which will not be changing
regardless of the cookie sent. So vary-cookie makes sense to me. I
guess if I were caching software, I would just decide not to cache
anything when it said vary-cookie, and would then ignore the cookies
otherwise, and cache anyway, even if there were cookies. That seems to
make the most sense to me.

2009/11/17 Jérôme Loyet [email protected]:

I agree. Full vary support for cookies seems like a waste, the
overhead in caching items that will never be requested again outweighs
the benefits. But, caching without regard to cookies, except when a
cookie vary header is there, and then not caching at all, that seems
efficient and useful.

Gabriel R. <gabe@…> writes:

And then, of course, cookies will be sent even when trying to access
things like images, css, js files, which will not be changing
regardless of the cookie sent. So vary-cookie makes sense to me. I
guess if I were caching software, I would just decide not to cache
anything when it said vary-cookie, and would then ignore the cookies
otherwise, and cache anyway, even if there were cookies. That seems to
make the most sense to me.

Yes, exactly. The backend signals that a page depends on a cookie by
sending a
Vary: cookie header. Nginx shouldn’t cache and send such a page to
everyone.

Here’s the code in Varnish that handles the Vary header:

http://varnish.projects.linpro.no/browser/trunk/varnish-cache/bin/varnishd/cache_vary.c

I think it constructs a regexp used when looking for a matching object.
So my
assertion about Varnish was wrong, it actually caches the page, but it
only
returns it to a client with the same cookie. Full vary supports looks
like it’s
some work:

http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.44

But I’d be happy with just support for Vary: cookie that simply bypasses
the
cache. I had a brief look at the nginx code, but I’m not sure where one
would do
the change?

Ole