Context
Varnish is conservative in when it comes to caching and assumes that the use of cookies implies a level of personalization of the response.
Caching a personalized response could result in privacy or security issues. It could also result in inconsistent output.
Imagine caching a page that has a shopping cart. Caching the whole page would result in everyone having the same shopping cart value.
Here's the built-in VCL behavior for Varnish for cookies:
- When Varnish sees a
Cookie
header in the request, it will not serve the object from the cache because it assumes the content is personalized.
See https://www.varnish-software.com/developers/tutorials/varnish-builtin-vcl/#authorization-headers-and-cookies-are-not-cacheable
- When Varnish sees a
Set-Cookie
header in the response, it will not store the object in the cache because setting a cookie is a state change that also implies personalization.
See https://www.varnish-software.com/developers/tutorials/varnish-builtin-vcl/#dont-cache-responses-with-set-cookie-headers
Stripping cookies
Once a cookie is set through the Set-Cookie
response header, it will be passed as a Cookie
request header for every subsequent request, even for pages that don't really need these cookies.
That's why it's important to determine which pages require cookies and which don't. It's equally important identify tracking cookies, because they are processed by the client in Javascript and not on the server.
Here's a VCL example where we strip off all cookies, except the ones we need on the server:
vcl 4.1;
sub vcl_recv {
if (req.http.Cookie) {
set req.http.Cookie = ";" + req.http.Cookie;
set req.http.Cookie = regsuball(req.http.Cookie, "; +", ";");
set req.http.Cookie = regsuball(req.http.Cookie, ";(PHPSESSID)=", "; \1=");
set req.http.Cookie = regsuball(req.http.Cookie, ";[^ ][^;]*", "");
set req.http.Cookie = regsuball(req.http.Cookie, "^[; ]+|[; ]+$", "");
}
if (req.http.cookie ~ "^\s*$") {
unset req.http.cookie;
}
}
In this case only the PHPSESSID
cookie is kept, because it is required to keep track of logins. If after the replace logic this cookie is still there, Varnish will not serve the response from cache. If this cookie was not set, but there were a bunch of tracking cookies, all cookies are removed and the page can be served from the cache.
Removing cookies for certain pages
While the previous example featured stripping off select cookies and only keeping the PHPSESSID
cookie, you could still end up on pages that don't actually need that session cookie.
Here's a VCL example that where cookies are stripped off entirely, except on pages that actually need a specific cookie, like the admin pages and shopping cart page:
vcl 4.1;
sub vcl_recv {
if(req.url ~ "^/admin" || req.url == "/cart") {
return(pass);
}
unset req.http.Cookie;
}
Removing Set-Cookie headers
As shown on https://www.varnish-software.com/developers/tutorials/varnish-builtin-vcl/#dont-cache-responses-with-set-cookie-headers, the built-in VCL will not store an object in the cache if a Set-Cookie
header is used, because it implies a state change.
However, this doesn't mean that page will never end up in the cache: the next backend response will probably not contain the Set-Cookie
header because the cookie is already set. In that case the next response without the Set-Cookie
header may end up in the cache.
However, if you're certain you don't need to set a cookie for certain pages, you can also decide to strip off the Set-Cookie
header.
The following example prevents a backend from setting a cookie for static content:
vcl 4.1;
sub vcl_backend_response {
if (bereq.url ~ "^[^?]*\.(7z|avi|bmp|bz2|css|csv|doc|docx|eot|flac|flv|gif|gz|ico|jpeg|jpg|js|less|mka|mkv|mov|mp3|mp4|mpeg|mpg|odt|ogg|ogm|opus|otf|pdf|png|ppt|pptx|rar|rtf|svg|svgz|swf|tar|tbz|tgz|ttf|txt|txz|wav|webm|webp|woff|woff2|xls|xlsx|xml|xz|zip)(\?.*)?$") {
unset beresp.http.Set-Cookie;
}
}
Re-attaching cookies
While it is possible to store the cookie value in a header, then strip off the cookies in VCL to serve if from cache, to finally re-attach for backend requests, it doesn't really make much sense.
Why would you send cookies for a backend request if the cacheable response doesn't need a cookie to create its output?
If a backend requests needs the cookie value to compose the output, it probably means that response won't be cacheable, so you might as well bypass the cache altogether for that request.
Next steps
Because your question wasn't very specific, I also had to give you a very general response.
If my response that fully answer your question, I invite you to specify more details about your use case and in return I'll give you a more detailed response.