Understand "hit for pass" cache objects

Justin Pasher justinp at newmediagateway.com
Mon Feb 15 23:42:51 CET 2010


Laurence Rowe wrote:
>> In my situation, I think I could avoid this problem altogether if I
>> could make Varnish store a DIFFERENT set of headers in the cache object
>> than the headers return to the client. For example, if I receive a
>> response with a Set-Cookie header, I would remove the Set-Cookie header
>> from the soon-to-be-cached object (so it wouldn't serve that header up
>> for everyone), but LEAVE the Set-Cookie header for the individual that
>> made the original request. This would allow the page to cache normally
>> even if the only requests going to that page result in a Set-Cookie
>> header. However, from what I've been able to see, there is no way to do
>> this.
>>     
>
> Why not cache the object with the Set-Cookie header in vcl_fetch, then
> in vcl_deliver remove the header for users without your cookie,
> something like:
>
>
>     if (req.http.cookie ~ "(^|; )my_cookie=") {
>         remove obj.http.Set-Cookie;
>     }
>   

Hmm.. That's an interesting idea, but I see two potential problems. The 
main one is that "req" is not available in vcl_deliver() (neither is 
"obj", but "resp" would be what I want to change anyway). The other 
problem I see is that if an object is cached with the Set-Cookie header, 
then someone who has NOT been to the site before hits that same URL, it 
will pull from the cache, notice that they don't have the "my_cookie" 
set yet, and ignore the remove line, thus passing the original 
Set-Cookie header, which would actually be someone else's cookie (the 
value of the cookie identifies their session ID). If I really could get 
the desired behavior, then I do understand that subsequent visits to the 
same page by other people would be served from cache and thus not 
receive a Set-Cookie header in their response (which is fine). That's 
the trade-off for allowing a page to be cached.

> You can achieve this using a Vary, I use something similar for serving
> cached pages to anonymous users but personalised dynamic pages to
> logged in users):
>
> In vcl_recv:
>
>     if (req.http.cookie ~ "(^|; )mycookie=") {
>         set req.http.X-My-Cookie = "true";
>     }
>
> in vcl_fetch:
>
>     set obj.http.Vary = "X-My-Cookie";
>     if (req.http.X-My-Cookie) {
>         pass;
>     }
>   

If I understand correctly, this would still cause a "hit for pass" cache 
object to be created, since the final action is "pass". I've figured out 
the way to avoid the "hit for pass" cache object is to "set obj.ttl = 
0s", but that only half solves my problem. If 1000 people visiting a 
particular page are doing so for the first time (thus they do not have a 
session cookie), it will never end of storing a cached version of the 
page because it will hit a "pass" action, then not store an object in cache.


-- 
Justin Pasher



More information about the varnish-misc mailing list