Cookies being sent back with a cached response

Cosimo Streppone cosimo at streppone.it
Mon Oct 5 16:20:45 CEST 2009


Hi everyone,

thanks for Varnish!
I've been trying to understand how to control it (2.0.4)
during these last few weeks. :)

It seems I'm experiencing an issue with unexpected content being
delivered to clients. Full story:

I tried to configure varnish to accept only one kind of request for now,
where the URL matches "/avatar/12345" where 12345 is the userid.
That's a static picture. Actually is a redirect (301) that points to
a static picture, so I'm caching the redirect response from the backend.
So far, so good.

Our frontend apaches only send Varnish this type of request, nothing else.
In no whatsoever way these requests can issue cookies (Set-Cookie header),
but we've had reports of users getting other people's pictures, but
how can that be since URLs are clearly user-based?

So, say:

     /avatar/12345 is avatar of user whose id is 12345

and it can be requested by anyone without being logged-in.
Sometimes it seems like varnish serves the wrong content (?).

Then looking at varnishlog output, and grepping for "Cookie",
I saw this (unrelated?):

  90 TxHeader     b Cookie: session=bf6ac86feaed6b23bef66a8f44097eac42cf24  
...

How can this ever happen?
The backends that serve the request never output cookies, and even if they
did, it would be "Set-Cookie:" anyway... I'm confused.

I also wrote a perl test script that runs against a Varnish
instance and reports results back, with expected cookies
or cache hit/miss, and that runs and passes all tests.
It's only when I put it on production load that this
seems to happen...

The following is the VCL I'm using.

I tried to add some "debug" information in the headers.
I'm pretty sure there's something awfully broken,
but I have no idea of what it is :)

   # Add a special header to mark objects as hit/miss
   sub vcl_deliver {
     if (obj.hits > 0) {
       set resp.http.X-Varnish-Status = "hit";
     } else {
       set resp.http.X-Varnish-Status = "miss";
     }
   }

   sub vcl_recv {
     set req.backend = mybackends;
     if (req.request != "GET") {
         pass;
     }
     if (req.url ~ "^/avatar/.+$") {
         unset req.http.Cookie;
         unset req.http.Authorization;
         lookup;
     }
     pass;
   }

   sub vcl_fetch {
     set obj.http.X-Varnish-URL = req.url;

     if (!obj.cacheable) {
       set obj.http.X-Varnish-Cacheable = "no, not cacheable";
       pass;
     }

     if (req.http.Cache-Control ~ "no-cache") {
       set obj.http.X-Varnish-Cacheable = "no, cache-control=no-cache";
       purge_url(req.url);
       pass;
     }

     if (req.http.Cache-Control ~ "private") {
       set obj.http.X-Varnish-Cacheable = "no, cache-control=private";
       pass;
     }

     if (obj.http.Set-Cookie) {
       set obj.http.X-Varnish-Cacheable = "no, sets a cookie";
       pass;
     }

     if (req.request != "GET") {
       set obj.http.X-Varnish-Cacheable = "no, !GET";
       pass;
     }

     if (req.url ~ "^/avatar/.+$") {
         #//// XXX This shouldn't be necessary?
         unset obj.http.Set-Cookie;
         set obj.http.X-Varnish-Cacheable = "yes, allowed by URL";
         set obj.ttl = 1h;
         deliver;
     }

     # Check for cookie only after always-cache URLs
     if (req.http.Cookie ~ "session") {
         set obj.http.X-Varnish-Cacheable = "no, session cookie";
         pass;
     }

     set obj.http.X-Varnish-Cacheable = "no, URL didn't match";
     pass;
   }

Thank you for reading through this, I would
appreciate any help from you or hints on how to further
debug this.

-- 
Cosimo



More information about the varnish-misc mailing list