Varnish expires header configuration

Sujith picture Sujith · Mar 14, 2014 · Viewed 7.1k times · Source

Please help me in adding expires header in varnish configuration. max_age is already defined in vcl_fetch and need to add expires header according to the max_age.

Answer

Ketola picture Ketola · Mar 14, 2014

Usually you do not need to set Expires header in addition to Cache-Control. The Expires header tells the cache (be it a proxy server or a browser cache) to cache the file until Expires time is reached. If both Cache-Control and Expires are defined, Cache-Control takes precedence.

Consider the following response header:

HTTP/1.1 200 OK
Content-Type: image/jpeg
Date: Fri, 14 Mar 2014 08:34:00 GMT
Expires: Fri, 14 Mar 2014 08:35:00 GMT
Cache-Control: public, max-age=600

According to Expires header the content should be refreshed after one minute, but since max-age is set to 600 seconds, the image stays cached until 08:44:00 GMT.

If you wish to expire content at a specific time, you should drop the Cache-Control header and only use Expires.

Mark Nottingham has written a very good tutorial on caching. It's definitely worth reading when considering your cache strategy.

If you wish to set Expires header based on Cache-Control: max-age, you need to use inline-C in your VCL. The following is copied from https://www.varnish-cache.org/trac/wiki/VCLExampleSetExpires in case the page is removed in the future.

Add the following prototypes:

C{
        #include <string.h>
        #include <stdlib.h>

        void TIM_format(double t, char *p);
        double TIM_real(void);
}C

And the following piece of inline-C to the vcl_deliver function:

C{
        char *cache = VRT_GetHdr(sp, HDR_RESP, "\016cache-control:");
        char date[40];
        int max_age = -1;
        int want_equals = 0;
        if(cache) {
                while(*cache != '\0') {
                        if (want_equals && *cache == '=') {
                                cache++;
                                max_age = strtoul(cache, 0, 0);
                                break;
                        }

                        if (*cache == 'm' && !memcmp(cache, "max-age", 7)) {
                                cache += 7;
                                want_equals = 1;
                                continue;
                        }
                        cache++;
                }
                if (max_age != -1) {
                        TIM_format(TIM_real() + max_age, date);
                        VRT_SetHdr(sp, HDR_RESP, "\010Expires:", date, vrt_magic_string_end);
                }
        }
}C