Skip to content

Instantly share code, notes, and snippets.

@Integralist
Last active October 28, 2021 18:09
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save Integralist/56cf991ae97551583d5a2f0d69f37788 to your computer and use it in GitHub Desktop.
Save Integralist/56cf991ae97551583d5a2f0d69f37788 to your computer and use it in GitHub Desktop.
[Fastly's Custom VCL] #fastly #cdn #varnish #vcl
#--FASTLY DELIVER BEGIN
# record the journey of the object, expose it only if req.http.Fastly-Debug.
if (req.http.Fastly-Debug || req.http.Fastly-FF) {
set resp.http.Fastly-Debug-Path = "(D " server.identity " " now.sec ") "
if(resp.http.Fastly-Debug-Path, resp.http.Fastly-Debug-Path, "");
set resp.http.Fastly-Debug-TTL = if(obj.hits > 0, "(H ", "(M ")
server.identity
if(req.http.Fastly-Tmp-Obj-TTL && req.http.Fastly-Tmp-Obj-Grace, " " req.http.Fastly-Tmp-Obj-TTL " " req.http.Fastly-Tmp-Obj-Grace " ", " - - ")
if(resp.http.Age, resp.http.Age, "-")
") "
if(resp.http.Fastly-Debug-TTL, resp.http.Fastly-Debug-TTL, "");
set resp.http.Fastly-Debug-Digest = digest.hash_sha256(req.digest);
} else {
unset resp.http.Fastly-Debug-Path;
unset resp.http.Fastly-Debug-TTL;
}
# add or append X-Served-By/X-Cache(-Hits)
{
if(!resp.http.X-Served-By) {
set resp.http.X-Served-By = server.identity;
} else {
set resp.http.X-Served-By = resp.http.X-Served-By ", " server.identity;
}
set resp.http.X-Cache = if(resp.http.X-Cache, resp.http.X-Cache ", ","") if(fastly_info.state ~ "HIT($|-)", "HIT", "MISS");
if(!resp.http.X-Cache-Hits) {
set resp.http.X-Cache-Hits = obj.hits;
} else {
set resp.http.X-Cache-Hits = resp.http.X-Cache-Hits ", " obj.hits;
}
}
if (req.http.X-Timer) {
set resp.http.X-Timer = req.http.X-Timer ",VE" time.elapsed.msec;
}
# VARY FIXUP
{
# remove before sending to client
set resp.http.Vary = regsub(resp.http.Vary, "Fastly-Vary-String, ", "");
if (resp.http.Vary ~ "^\s*$") {
unset resp.http.Vary;
}
}
unset resp.http.X-Varnish;
# Pop the surrogate headers into the request object so we can reference them later
set req.http.Surrogate-Key = resp.http.Surrogate-Key;
set req.http.Surrogate-Control = resp.http.Surrogate-Control;
# If we are not forwarding or debugging unset the surrogate headers so they are not present in the response
if (!req.http.Fastly-FF && !req.http.Fastly-Debug) {
unset resp.http.Surrogate-Key;
unset resp.http.Surrogate-Control;
}
if(resp.status == 550) {
return(deliver);
}
#default response conditions
#--FASTLY DELIVER END
#--FASTLY ERROR BEGIN
if (obj.status == 801) {
set obj.status = 301;
set obj.response = "Moved Permanently";
set obj.http.Location = "https://" req.http.host req.url;
synthetic {""};
return (deliver);
}
if (req.http.Fastly-Restart-On-Error) {
if (obj.status == 503 && req.restarts == 0) {
restart;
}
}
{
if (obj.status == 550) {
return(deliver);
}
}
#--FASTLY ERROR END
#--FASTLY FETCH BEGIN
# record which cache ran vcl_fetch for this object and when
set beresp.http.Fastly-Debug-Path = "(F " server.identity " " now.sec ") " if(beresp.http.Fastly-Debug-Path, beresp.http.Fastly-Debug-Path, "");
# generic mechanism to vary on something
if (req.http.Fastly-Vary-String) {
if (beresp.http.Vary) {
set beresp.http.Vary = "Fastly-Vary-String, " beresp.http.Vary;
} else {
set beresp.http.Vary = "Fastly-Vary-String, ";
}
}
# priority: 0
# Gzip basic GZIP rules
if ((beresp.status == 200 || beresp.status == 404) && (beresp.http.content-type ~ "^(text\/html|application\/x\-javascript|text\/css|application\/javascript|text\/javascript|application\/json|application\/vnd\.ms\-fontobject|application\/x\-font\-opentype|application\/x\-font\-truetype|application\/x\-font\-ttf|application\/xml|font\/eot|font\/opentype|font\/otf|image\/svg\+xml|image\/vnd\.microsoft\.icon|text\/plain|text\/xml)\s*($|;)" || req.url ~ "\.(css|js|html|eot|ico|otf|ttf|json)($|\?)" ) ) {
# always set vary to make sure uncompressed versions dont always win
if (!beresp.http.Vary ~ "Accept-Encoding") {
if (beresp.http.Vary) {
set beresp.http.Vary = beresp.http.Vary ", Accept-Encoding";
} else {
set beresp.http.Vary = "Accept-Encoding";
}
}
if (req.http.Accept-Encoding == "gzip") {
set beresp.gzip = true;
}
}
#--FASTLY FETCH END
#--FASTLY HASH BEGIN
# support purge all
set req.hash += "#####GENERATION#####";
#--FASTLY HASH END
#--FASTLY HIT BEGIN
# we cannot reach obj.ttl and obj.grace in deliver, save them when we can in vcl_hit
set req.http.Fastly-Tmp-Obj-TTL = obj.ttl;
set req.http.Fastly-Tmp-Obj-Grace = obj.grace;
{
set req.http.Fastly-Cachetype = "HIT";
}
#--FASTLY HIT END
#--FASTLY MISS BEGIN
# this is not a hit after all, clean up these set in vcl_hit
unset req.http.Fastly-Tmp-Obj-TTL;
unset req.http.Fastly-Tmp-Obj-Grace;
{
if (req.http.Fastly-Check-SHA1) {
error 550 "Doesnt exist";
}
#--FASTLY BEREQ BEGIN
{
if (req.http.Fastly-Original-Cookie) {
set bereq.http.Cookie = req.http.Fastly-Original-Cookie;
}
if (req.http.Fastly-Original-URL) {
set bereq.url = req.http.Fastly-Original-URL;
}
{
if (req.http.Fastly-FF) {
set bereq.http.Fastly-Client = "1";
}
}
{
# do not send this to the backend
unset bereq.http.Fastly-Original-Cookie;
unset bereq.http.Fastly-Original-URL;
unset bereq.http.Fastly-Vary-String;
unset bereq.http.X-Varnish-Client;
}
if (req.http.Fastly-Temp-XFF) {
if (req.http.Fastly-Temp-XFF == "") {
unset bereq.http.X-Forwarded-For;
} else {
set bereq.http.X-Forwarded-For = req.http.Fastly-Temp-XFF;
}
# unset bereq.http.Fastly-Temp-XFF;
}
}
#--FASTLY BEREQ END
#;
set req.http.Fastly-Cachetype = "MISS";
}
#--FASTLY MISS END
#--FASTLY PASS BEGIN
{
#--FASTLY BEREQ BEGIN
{
if (req.http.Fastly-Original-Cookie) {
set bereq.http.Cookie = req.http.Fastly-Original-Cookie;
}
if (req.http.Fastly-Original-URL) {
set bereq.url = req.http.Fastly-Original-URL;
}
{
if (req.http.Fastly-FF) {
set bereq.http.Fastly-Client = "1";
}
}
{
# do not send this to the backend
unset bereq.http.Fastly-Original-Cookie;
unset bereq.http.Fastly-Original-URL;
unset bereq.http.Fastly-Vary-String;
unset bereq.http.X-Varnish-Client;
}
if (req.http.Fastly-Temp-XFF) {
if (req.http.Fastly-Temp-XFF == "") {
unset bereq.http.X-Forwarded-For;
} else {
set bereq.http.X-Forwarded-For = req.http.Fastly-Temp-XFF;
}
# unset bereq.http.Fastly-Temp-XFF;
}
}
#--FASTLY BEREQ END
#;
set req.http.Fastly-Cachetype = "PASS";
}
#--FASTLY PASS END
#--FASTLY PIPE BEGIN
{
#--FASTLY BEREQ BEGIN
{
if (req.http.Fastly-Original-Cookie) {
set bereq.http.Cookie = req.http.Fastly-Original-Cookie;
}
if (req.http.Fastly-Original-URL) {
set bereq.url = req.http.Fastly-Original-URL;
}
{
if (req.http.Fastly-FF) {
set bereq.http.Fastly-Client = "1";
}
}
{
# do not send this to the backend
unset bereq.http.Fastly-Original-Cookie;
unset bereq.http.Fastly-Original-URL;
unset bereq.http.Fastly-Vary-String;
unset bereq.http.X-Varnish-Client;
}
if (req.http.Fastly-Temp-XFF) {
if (req.http.Fastly-Temp-XFF == "") {
unset bereq.http.X-Forwarded-For;
} else {
set bereq.http.X-Forwarded-For = req.http.Fastly-Temp-XFF;
}
# unset bereq.http.Fastly-Temp-XFF;
}
}
#--FASTLY BEREQ END
#;
set req.http.Fastly-Cachetype = "PIPE";
set bereq.http.connection = "close";
}
#--FASTLY PIPE END
#--FASTLY RECV BEGIN
if (req.restarts == 0) {
if (!req.http.X-Timer) {
set req.http.X-Timer = "S" time.start.sec "." time.start.usec_frac;
}
set req.http.X-Timer = req.http.X-Timer ",VS0";
}
set req.backend = autodirector_;
# default conditions
set req.backend = autodirector_;
# end default conditions
#--FASTLY RECV END
@sjparkinson
Copy link

Might be worth including the normalisation of Accept-Encoding Fastly does. Either it's Accept-Encoding: gzip or there is no header.

It's not done in the default VCL or mentioned in the boilerplate, or viewable in the generated VCL, but does happen.

@thieryl
Copy link

thieryl commented Mar 21, 2019

Can we have a snippet for http auth for certain keywords to be used with magento mostly

@Integralist
Copy link
Author

From Fastly...

It looks like we set the value of req.http.Fastly-Temp-XFF always but X-Forwarded-For is conditionally set, so we may just store the client IP in req.http.Fastly-Temp-XFF and leave X-Forwarded-For unmodified in some circumstances.

The following is custom fastly code not included above and shows how the logic relates to X-Forwarded-For...

if (...) {
    if (req.http.X-Forwarded-For) {
        set req.http.Fastly-Temp-XFF = req.http.X-Forwarded-For ", " client.ip;
    } else {
        set req.http.Fastly-Temp-XFF = client.ip;
    }
} else {
    set req.http.Fastly-Temp-XFF = req.http.X-Forwarded-For;
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment