Boris Guéry
Boris Guéry

Reputation: 47604

Why the beresp.ttl is set to 0 when a Cookie is added to the request in Varnish?

Ok, so I'm trying to make Varnish works properly and I've a weird behavior I can't explain (may be due by a lack of understanding).

Here is what I'm trying to do:

GET http://scm.dev:6081/articles
If-None-Match: "50a0794aaca51fce202e86da428b7dca9b4bbff93"

And I get:

HTTP/1.1 200 OK
Age: 3                                    // Correctly using a cached result
Content-Length: 3878
Content-Type: application/json
Date: Fri, 14 Dec 2012 10:59:34 GMT
Via: 1.1 varnish
X-Cacheable: YES                          // It is correct
Cache-Control: max-age=10, public, s-maxage=20
Etag: "50a0794aca51fce202e86da428b7dca9b4bbff93"
Vary: Accept,Accept-Encoding

Now, if I add a Cookie to my request:

GET http://scm.dev:6081/articles
If-None-Match: "50a0794aaca51fce202e86da428b7dca9b4bbff93"
Cookie: foo=bar

I get a non cached response and a non cacheable warning:

HTTP/1.1 200 OK
Age: 0                                    // Always set to 0
Content-Length: 3878
Content-Type: application/json
Date: Fri, 14 Dec 2012 10:59:34 GMT
Via: 1.1 varnish
X-Cacheable: NO:Not Cacheable             // It is not correct
Cache-Control: max-age=10, public, s-maxage=20
Etag: "50a0794aca51fce202e86da428b7dca9b4bbff93"
Vary: Accept,Accept-Encoding

If you check the later vcl configuration, the X-Cacheable: NO:Not Cacheable header is set if the beresp.ttl is less than or equal to 0.

Why?

I also assume that a Request with a Cookie which returns a Cache-Control: public should be cached as far as the backend assume the responsibility to correctly set the public parameter when it should be.

I would have assumed that the X-Cacheable: NO:Got Session would have been set when making a Request with a Cookie, but it even does not go further.

The command line to start varnish daemon:

/usr/sbin/varnishd -P /var/run/varnishd.pid -a :6081 -T 192.168.1.100:6082 -f /etc/varnish/custom.vcl -S /etc/varnish/secret -s malloc,256m

Here is my custom.vcl

backend scm {
.host = "scm.dev";
.port = "80";
}

sub vcl_recv {
    set req.http.Surrogate-Capability = "abc=ESI/1.0";
}

sub vcl_fetch {
    if (beresp.http.Surrogate-Control ~ "ESI/1.0") {
        unset beresp.http.Surrogate-Control;
        set beresp.do_esi = true;
    }

    # Varnish determined the object was not cacheable
    if (beresp.ttl <= 0s) {
        set beresp.http.X-Cacheable = "NO:Not Cacheable";

    # You don't wish to cache content for logged in users
    } elsif (req.http.Cookie ~ "(foo)") {
        set beresp.http.X-Cacheable = "NO:Got Session";

        return(hit_for_pass);
    # You are respecting the Cache-Control=private header from the backend
    } elsif (beresp.http.Cache-Control ~ "private") {
        set beresp.http.X-Cacheable = "NO:Cache-Control=private";

        return(hit_for_pass);
    # Varnish determined the object was cacheable
    } else {
        set beresp.http.X-Cacheable = "YES";
    }

    return(deliver);
}

sub vcl_hit {
    if (req.request == "PURGE") {
        set obj.ttl = 0s;
        error 200 "Purged";
    }
}

sub vcl_miss {
    if (req.request == "PURGE") {
        error 404 "Not purged";
    }
}

Upvotes: 0

Views: 4529

Answers (1)

Ketola
Ketola

Reputation: 2767

Varnish will not, by design, fetch any requests from cache if cookies are present. Usually cookies are an indication that the response will be unique to the specific user.

You can either unset req.http.Cookie; in vcl_recv() entirely, if you do not care about the cookies, or if you want to keep specific cookies do

if(req.http.Cookie) {
  if (req.http.Cookie !~ "(important_cookie|php_session)" ) {
    remove req.http.Cookie;
  }
}

Upvotes: 1

Related Questions