Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Integralist/979098ebd90a0820456c246c4224f770 to your computer and use it in GitHub Desktop.
Save Integralist/979098ebd90a0820456c246c4224f770 to your computer and use it in GitHub Desktop.
[Fastly VCL Boilerplate for handling mutliple subdomains] #fastly #vcl #boilerplate
######################################################################################
#
# detailed blog post on fastly's implementation details:
# http://www.integralist.co.uk/posts/fastly-varnish/
#
# fastly custom vcl boilerplate:
# https://docs.fastly.com/vcl/custom-vcl/creating-custom-vcl/#fastlys-vcl-boilerplate
#
# vcl_recv
# vcl_error
# vcl_hash
# vcl_pass
# vcl_miss
# vcl_hit
# vcl_fetch
# vcl_deliver
#
######################################################################################
table deny_list {
"/bad-thing-1": "true",
"/bad-thing-2": "true",
}
sub set_backend {
set req.backend = F_httpbin;
if (req.http.Host == "example-stage.acme.com/") {
set req.backend = F_httpbin_stage;
}
}
sub vcl_recv {
#FASTLY recv
call set_backend;
# configure purges to require api authentication:
# https://docs.fastly.com/en/guides/authenticating-api-purge-requests
#
if (req.method == "FASTLYPURGE") {
set req.http.Fastly-Purge-Requires-Auth = "1";
}
# force HTTP to HTTPS
#
# related: req.http.Fastly-SSL
# https://docs.fastly.com/en/guides/tls-termination
#
if (req.protocol != "https") {
error 601 "Force SSL";
}
# fastly 'tables' are different to 'edge dictionaries':
# https://docs.fastly.com/en/guides/about-edge-dictionaries
#
if (table.lookup(deny_list, req.url.path)) {
error 600 "Not found";
}
# don't bother doing a cache lookup for a request type that isn't cacheable
if (req.method !~ "(GET|HEAD|FASTLYPURGE)") {
return(pass);
}
if (req.restarts == 0) {
# nagios/monitoring cache bypass
#
if (req.url ~ "123") {
set req.http.X-Monitoring = "true";
return(pass);
}
}
return(lookup);
}
sub vcl_error {
#FASTLY error
# fastly synthetic error responses:
# https://docs.fastly.com/en/guides/creating-error-pages-with-custom-responses
#
if (obj.status == 600) {
set obj.status = 404;
synthetic {"
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Error</title>
</head>
<body>
<h1>404 Not Found (varnish)</h1>
</body>
</html>
"};
return(deliver);
}
# fastly HTTP to HTTPS 301 redirect:
# https://docs.fastly.com/en/guides/generating-http-redirects-at-the-edge
#
# example:
# curl -sD - http://example.acme.com/
# curl -H Fastly-Debug:1 -sLD - -o /dev/null http://example.acme.com/?cachebust=$(uuidgen)
#
if (obj.status == 601 && obj.response == "Force SSL") {
set obj.status = 301;
set obj.response = "Moved Permanently";
set obj.http.Location = "https://" req.http.host req.url;
synthetic {""};
return (deliver);
}
}
sub vcl_hash {
#FASTLY hash
set req.hash += req.url;
set req.hash += req.http.host;
# call debug_info_hash;
return(hash);
}
sub vcl_pass {
#FASTLY pass
}
sub vcl_miss {
#FASTLY miss
return(fetch);
}
sub vcl_hit {
#FASTLY hit
}
sub vcl_fetch {
#FASTLY fetch
# fastly caching directive:
# https://docs.fastly.com/en/guides/cache-control-tutorial
#
# example:
# define stale behaviour if none provided by origin
#
if (beresp.http.Surrogate-Control !~ "(stale-while-revalidate|stale-if-error)") {
set beresp.stale_if_error = 31536000s; // 1 year
set beresp.stale_while_revalidate = 60s; // 1 minute
}
# fastly stale-if-error:
# https://docs.fastly.com/en/guides/serving-stale-content
#
if (beresp.status >= 500 && beresp.status < 600) {
if (stale.exists) {
return(deliver_stale);
}
}
# hit-for-pass:
# https://www.integralist.co.uk/posts/fastly-varnish/#hit-for-pass
#
if (beresp.http.Cache-Control ~ "private") {
return(pass);
}
# ensure we set our own default cache TTL if no caching directives found
if (beresp.cacheable && !beresp.http.Surrogate-Control:max-age && !beresp.http.Cache-Control:max-age) {
set beresp.ttl = 1h; # 1 hour
}
return(deliver);
}
sub vcl_deliver {
#FASTLY deliver
# fastly internal state information:
# https://docs.fastly.com/en/guides/useful-variables-to-log
#
set resp.http.Fastly-State = fastly_info.state;
if (req.http.X-Monitoring == "true") {
set resp.http.X-Monitoring = req.http.X-Monitoring;
}
return(deliver);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment