Skip to content

Instantly share code, notes, and snippets.

@daniel-nelson
Created February 7, 2013 18:30
Show Gist options
  • Save daniel-nelson/4733045 to your computer and use it in GitHub Desktop.
Save daniel-nelson/4733045 to your computer and use it in GitHub Desktop.
backend example {
.host = "<%=http_endpoint%>";
.port = "<%=http_port%>";
}
backend s3 {
.host = "assets.example.me";
.port = "80";
}
backend s3staging {
.host = "stagingassets.example.me";
.port = "80";
}
sub vcl_deliver {
# This just inserts a diagnostic header to let us know if the content
# was served via a cache hit, or whether it was a miss.
if (obj.hits > 0) {
set resp.http.X-Cache = "HIT";
} else {
set resp.http.X-Cache = "MISS";
}
}
sub vcl_recv {
# if request is a purge then allow it through without doing redirects or ssl checks (it's purpose is clear)
if (req.request == "PURGE") {
if (!req.http.X-Purge-Token ~ "xxxxxxxxxxxxxxx") {
error 405 "Not allowed.";
}
return(lookup);
}
# if it matches our domains and is not secure then redirect
if ( (req.http.host ~ "^(www\.)?example\.me\.?" || req.http.host ~ "^(www\.)?examplestaging\.com\.?")
&& req.http.X-Forwarded-Proto !~ "(?i)https"
&& req.url !~ "/(images|assets|javascripts|stylesheets|themes|vendor)") {
# If we are insecure and also have the www. then strip that as well (avoiding double redirect below)
# This is done here instead of below to improve user experience.
# If this wasn't here, it would redirect with www then hit a second redirect
set req.http.host = regsub(req.http.host, "^www\.", "");
set req.http.host = regsub(req.http.host, "\.$", "");
set req.http.x-Redir-Url = "https://" + req.http.host + req.url;
error 750 req.http.x-Redir-Url; # throw exception which is caught in vcl_error and turned into redirect
}
# If we are correctly using https but we have the www. or we have a trailing period, strip it off
if ( req.http.host ~ "^www\.example\.me" || req.http.host ~ "^www\.examplestaging\.com" || req.http.host ~ "example\.me\.$" || req.http.host ~ "examplestaging\.com\.$") {
set req.http.host = regsub(req.http.host, "^www\.", "");
set req.http.host = regsub(req.http.host, "\.$", "");
set req.http.x-Redir-Url = "https://" + req.http.host + req.url;
error 750 req.http.x-Redir-Url; # throw exception which is caught in vcl_error and turned into redirect
}
# pass asset data on to s3. append gz to appropriate content so that we store gz content in cache.
# varnish will decompress it if the browser doesn't support it.
if ( req.http.host ~ "^s3assets.example.me$") {
set req.url = regsub(req.url, "(css|js)$", "\1.gz");
set req.http.host = "assets.example.me";
set req.backend = s3;
} else if (req.http.host ~ "^s3assets.examplestaging.com$") {
set req.url = regsub(req.url, "(css|js)$", "\1.gz");
set req.http.host = "stagingassets.example.me";
set req.backend = s3staging;
} else {
set req.backend = example;
}
if (req.request != "GET") {
return(pass);
}
# force to a single encoding type so that order in list doesn't break our caches
# disable ie6 from receiving compression, even if it says it supports it. ie6 has many bugs around this
if (req.http.Accept-Encoding) {
if (req.http.User-Agent ~ "MSIE 6") {
unset req.http.Accept-Encoding;
} elsif (req.http.Accept-Encoding ~ "gzip") {
set req.http.Accept-Encoding = "gzip";
} elsif (req.http.Accept-Encoding ~ "deflate") {
set req.http.Accept-Encoding = "deflate";
} else {
unset req.http.Accept-Encoding;
}
}
return(lookup);
}
sub vcl_hit {
if (req.request == "PURGE") {
purge; # Varnish 3.0.x
error 200 "Purged.";
}
}
sub vcl_miss {
if (req.request == "PURGE") {
error 200 "Not in cache.";
}
}
sub vcl_fetch {
if (beresp.http.Server ~ "AmazonS3") {
# if it is coming from amazon then it would have the header Server: AmazonS3
# we don't want to cache this as it is going to be cached by cloudfront
# remove cookies from all publicly cacheable resources
remove beresp.http.Set-Cookie;
# save the decision that this request can not be cached by creating a hit_for_pass object
# http://stackoverflow.com/questions/12691489/varnish-hit-for-pass-means
return(hit_for_pass);
} else if (beresp.http.Cache-Control ~ "public") {
# remove cookies from all publicly cacheable resources
remove beresp.http.Set-Cookie;
if (beresp.http.X-Public-ExampleDoc ~ "true") {
remove beresp.http.X-Public-ExampleDoc;
# this is a publicly published doc. set cache-control in such a way as to force
# browser to check with Varnish to see whether the doc has been modified (which
# happens when changes or published or the doc is no longer publicly published
# at this url) on all subsequent requests
set beresp.http.Cache-Control = "public, max-age=0, must-revalidate";
}
return(deliver);
}
# do NOT cache this. the previous conditional already checked the cache control header for 'public',
# so this document does not include a public cache control
# save the decision that this request can not be cached by creating a hit_for_pass object
# http://stackoverflow.com/questions/12691489/varnish-hit-for-pass-means
return(hit_for_pass);
}
sub vcl_error {
if (obj.status == 200) {
# purge errors with 200
return (deliver);
}
if (obj.status == 750) {
#catch errors to handle redirect scenarios. used for redirecting to ssl
set obj.http.Location = obj.response;
set obj.status = 302;
return (deliver);
}
return (deliver);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment