Don't allow clients to force a pass

Don't allow clients to force a pass

    # Fixup for Varnish ESI not dealing with https:// absolute URLs well
    if (req.is_esi_subreq && req.url ~ "/https://([^/]+)(/.*)$") {
        set req.http.Host = re.group.1;
        set req.url = re.group.2;
    }

    # Rewrite /static/versionxxxxx URLs. Avoids us having to rewrite on nginx layer
    if (req.url ~ "^/static/version(\d*/)?(.*)$") {
       set req.url = "/static/" + re.group.2 + "?" + re.group.1;
    }

    # User's Cookie may contain some Magento Vary items we should vary on
    if (req.http.cookie:X-Magento-Vary ) {
        set req.http.X-Magento-Vary = req.http.cookie:X-Magento-Vary;
    } else {
        unset req.http.X-Magento-Vary;
    }

    # auth for purging
    if (req.request == "FASTLYPURGE") {
      # extract token signature and expiration
      if (!req.http.X-Purge-Token ~ "^([^_]+)_(.*)" ) {
        error 403;
      }

      declare local var.X-Exp STRING;
      declare local var.X-Sig STRING;
      /* extract token expiration and signature */
      set var.X-Exp = re.group.1;
      set var.X-Sig = re.group.2;

      /* validate signature */
      if (var.X-Sig == regsub(digest.hmac_sha1(req.service_id, req.url.path var.X-Exp), "^0x", "")) {
        /* check that expiration time has not elapsed */
        if (time.is_after(now, std.integer2time(std.atoi(var.X-Exp)))) {
          error 410;
        }

      } else {
        error 403;
      }
    }

    # set HTTPS header for offloaded TLS
    if (req.http.Fastly-SSL) {
        set req.http.Https = "on";
    }

    if (req.http.Fastly-FF) {
        # disable ESI processing on Origin Shield
        set req.esi = false;
        # Needed for proper handling of stale while revalidated when shielding is involved
        set req.max_stale_while_revalidate = 0s;
    }

    # geoip lookup
    if (req.url ~ "fastlyCdn/geoip/getaction/") {
        # check if GeoIP has been already processed by client. this normally happens before essential cookies are set.
        if (req.http.cookie:X-Magento-Vary || req.http.cookie:form_key) {
            error 200 "";
        } else {
            # append parameter with country code only if it doesn't exist already
            if ( req.url.qs !~ "country_code=" ) {
                set req.url = req.url "?country_code=" if ( req.http.geo_override, req.http.geo_override, client.geo.country_code);
            }
        }
    } else {
        # Per suggestions in https://github.com/sdinteractive/SomethingDigital_PageCacheParams
        # we'll strip out query parameters used in Google AdWords, Mailchimp tracking
        set req.http.Magento-Original-URL = req.url;
        set req.url = querystring.regfilter(req.url, "^(utm_.*|gclid|gdftrk|_ga|mc_.*)");
    }

    # Don't allow clients to force a pass
    if (req.restarts == 0) {
        unset req.http.x-pass;
    }

    # Pass on checkout URLs. Because it's a snippet we want to execute this after backend selection so we handle it
    # in the request condition
    if (req.url ~ "/(catalogsearch|checkout)") {
        set req.http.x-pass = "1";
    # Pass all admin actions
    } else if ( req.url ~ "^/(index\.php/)?admin(_.*)?/" ) {
        set req.http.x-pass = "1";
    } else {
        # Sort the query arguments to increase cache hit ratio with query arguments that
        # may be out od order
        set req.url = boltsort.sort(req.url);
    }

    # static files are always cacheable. remove SSL flag and cookie
    if (req.url ~ "^/(pub/)?(media|static)/.*") {
        unset req.http.Https;
        unset req.http.Cookie;
    }

    # Fixup for Varnish ESI not dealing with https:// absolute URLs well
    if (req.is_esi_subreq && req.url ~ "/https://([^/]+)(/.*)$") {
        set req.http.Host = re.group.1;
        set req.url = re.group.2;
    }

    # Rewrite /static/versionxxxxx URLs. Avoids us having to rewrite on nginx layer
    if (req.url ~ "^/static/version(\d*/)?(.*)$") {
       set req.url = "/static/" + re.group.2 + "?" + re.group.1;
    }

    # User's Cookie may contain some Magento Vary items we should vary on
    if (req.http.cookie:X-Magento-Vary ) {
        set req.http.X-Magento-Vary = req.http.cookie:X-Magento-Vary;
    } else {
        unset req.http.X-Magento-Vary;
    }

    # auth for purging
    if (req.request == "FASTLYPURGE") {
      # extract token signature and expiration
      if (!req.http.X-Purge-Token ~ "^([^_]+)_(.*)" ) {
        error 403;
      }

      declare local var.X-Exp STRING;
      declare local var.X-Sig STRING;
      /* extract token expiration and signature */
      set var.X-Exp = re.group.1;
      set var.X-Sig = re.group.2;

      /* validate signature */
      if (var.X-Sig == regsub(digest.hmac_sha1(req.service_id, req.url.path var.X-Exp), "^0x", "")) {
        /* check that expiration time has not elapsed */
        if (time.is_after(now, std.integer2time(std.atoi(var.X-Exp)))) {
          error 410;
        }

      } else {
        error 403;
      }
    }

    # set HTTPS header for offloaded TLS
    if (req.http.Fastly-SSL) {
        set req.http.Https = "on";
    }

    if (req.http.Fastly-FF) {
        # disable ESI processing on Origin Shield
        set req.esi = false;
        # Needed for proper handling of stale while revalidated when shielding is involved
        set req.max_stale_while_revalidate = 0s;
    }

    # geoip lookup
    if (req.url ~ "fastlyCdn/geoip/getaction/") {
        # check if GeoIP has been already processed by client. this normally happens before essential cookies are set.
        if (req.http.cookie:X-Magento-Vary || req.http.cookie:form_key) {
            error 200 "";
        } else {
            # append parameter with country code only if it doesn't exist already
            if ( req.url.qs !~ "country_code=" ) {
                set req.url = req.url "?country_code=" if ( req.http.geo_override, req.http.geo_override, client.geo.country_code);
            }
        }
    } else {
        # Per suggestions in https://github.com/sdinteractive/SomethingDigital_PageCacheParams
        # we'll strip out query parameters used in Google AdWords, Mailchimp tracking
        set req.http.Magento-Original-URL = req.url;
        set req.url = querystring.regfilter(req.url, "^(utm_.*|gclid|gdftrk|_ga|mc_.*)");
    }

    # Pass on checkout URLs. Because it's a snippet we want to execute this after backend selection so we handle it
    # in the request condition
    if (req.url ~ "/(catalogsearch|checkout)") {
        set req.http.x-pass = "1";
    # Pass all admin actions
    } else if ( req.url ~ "^/(index\.php/)?admin(_.*)?/" ) {
        set req.http.x-pass = "1";
    } else {
        # Sort the query arguments to increase cache hit ratio with query arguments that
        # may be out od order
        set req.url = boltsort.sort(req.url);
    }

    # static files are always cacheable. remove SSL flag and cookie
    if (req.url ~ "^/(pub/)?(media|static)/.*") {
        unset req.http.Https;
        unset req.http.Cookie;
    }


Add Fastly-Page-Cacheable headers to expose whether  a specific page is cacheable regardless of cache control headers

    if (resp.status >= 500 && resp.status < 600) {
        /* restart if the stale object is available */
        if (stale.exists) {
            restart;
        }
    }

    # Send no cache headers to end users for non-static content. Also make sure
    # we only set this on the edge nodes and not on shields
    if (req.url !~ "^/(pub/)?(media|static)/.*" && !req.http.Fastly-FF ) {
        set resp.http.Pragma = "no-cache";
        set resp.http.Cache-Control = "no-store, no-cache, must-revalidate, max-age=0";
    }

    # Remove X-Magento-Vary and HTTPs Vary served to the user
    if ( !req.http.Fastly-FF ) {
        set resp.http.Vary = regsub(resp.http.Vary, "X-Magento-Vary,Https", "Cookie");
    }

    # Add an easy way to see whether custom Fastly VCL has been uploaded
    if ( req.http.Fastly-Debug ) {
        set resp.http.Fastly-Magento-VCL-Uploaded = "1.2.24";
    } else {
        remove resp.http.Fastly-Module-Enabled;
        remove resp.http.fastly-page-cacheable;
    }
    # debug info
    if (resp.http.X-Magento-Debug) {
        if (obj.hits > 0) {
            set resp.http.X-Magento-Cache-Debug = "HIT";
            set resp.http.X-Magento-Cache-Hits = obj.hits;
        } else {
            set resp.http.X-Magento-Cache-Debug = "MISS";
        }
    } else {
        # remove Varnish/proxy header
        remove resp.http.Age;
        remove resp.http.X-Magento-Debug;
        remove resp.http.X-Magento-Tags;
        remove resp.http.X-Magento-Cache-Control;
        remove resp.http.X-Powered-By;
        remove resp.http.Server;
        remove resp.http.X-Varnish;
        remove resp.http.Via;
        remove resp.http.X-Purge-URL;
        remove resp.http.X-Purge-Host;
    }

    if (resp.status >= 500 && resp.status < 600) {
        /* restart if the stale object is available */
        if (stale.exists) {
            restart;
        }
    }

    # Send no cache headers to end users for non-static content. Also make sure
    # we only set this on the edge nodes and not on shields
    if (req.url !~ "^/(pub/)?(media|static)/.*" && !req.http.Fastly-FF ) {
        set resp.http.Pragma = "no-cache";
        set resp.http.Cache-Control = "no-store, no-cache, must-revalidate, max-age=0";
    }

    # Remove X-Magento-Vary and HTTPs Vary served to the user
    if ( !req.http.Fastly-FF ) {
        set resp.http.Vary = regsub(resp.http.Vary, "X-Magento-Vary,Https", "Cookie");
    }

    # Add an easy way to see whether custom Fastly VCL has been uploaded
    if ( req.http.Fastly-Debug ) {
        set resp.http.Fastly-Magento-VCL-Uploaded = "1.2.24";
    } else {
        remove resp.http.Fastly-Module-Enabled;
    }
    # debug info
    if (resp.http.X-Magento-Debug) {
        if (obj.hits > 0) {
            set resp.http.X-Magento-Cache-Debug = "HIT";
            set resp.http.X-Magento-Cache-Hits = obj.hits;
        } else {
            set resp.http.X-Magento-Cache-Debug = "MISS";
        }
    } else {
        # remove Varnish/proxy header
        remove resp.http.Age;
        remove resp.http.X-Magento-Debug;
        remove resp.http.X-Magento-Tags;
        remove resp.http.X-Magento-Cache-Control;
        remove resp.http.X-Powered-By;
        remove resp.http.Server;
        remove resp.http.X-Varnish;
        remove resp.http.Via;
        remove resp.http.X-Purge-URL;
        remove resp.http.X-Purge-Host;
    }


Updated backend.vcl to include better documentation and valid VCL syntax.

{#
Default VCL for web configs.

Expected Result:
    backend web1 {
        .host = "10.0.0.1"
        .port = "80"
    }
    backend web2 {
        .host = "10.0.0.1"
        .port = "80"
    }
    ...

Available Variables:
    (array) resources containing one or more (Resource) resource.
    Resource class and it's descendants will always implement __str__ to make it easier to use here.
#}

{% for ipresource in resources %}
    backend web{{ loop.index0 }} {
            .host = "{{ ipresource }}";
            .port = "80";
    }
{% endfor %}

{% for ip in resources %}
    web loop.index0 {
        host:{{ ip }}
    }
{% endfor %}


Update advanced_mobile recipe's varnish cache config

/*
 * Default Cache.vcl
 *
 * By default, any responses with Cache-Control set correctly are cached.
 *
 * If you don't want to cache anything, you need to update vcl_fetch and
 * comment out some lines so return(pass) is always called.
 *
 * If you do want to cache with more granularity, read up on Varnish
 * configurations and modify this file CAREFULLY.
 */

sub vcl_fetch {
  /*
   * Default Varnish logic EXCEPT:
   *   (1) Responses with a set-cookie header can still make their way
   *       into the cache. But I remove the set-cookie header in those instances.
   *   (2) Instead of using 'beresp.cacheable' to determine cacheability,
   *       I am checking for Cache-Control public
   */

  // Copy the X-Mob-Type type from the request header into the response header
  set beresp.http.X-Mob-Type = req.http.X-Mob-Type;

   // This caches any response w max-age in the Cache-Control header
   // for the duration specified in the header. We expect assets to have these headers set.
   // Comment out the 4 lines below if you don't want to cache anything
   if (beresp.http.Cache-Control ~ "(public|max\-age)") {
    remove beresp.http.Set-Cookie;
    return (deliver);
  }

  return (pass);
}

sub vcl_recv {
  set req.backend = application_director;

  /*
   * Default Varnish Caching logic with four exceptions:
   * (1) requests with cookies are cacheable
   * (2) X-Forwarded-For is only set when the client ip is not 127.0.0.1
   * (3) X-Moov-Secure requests are not cacheable
   * (4) Set the QA backend server to <customer>_appv01 which has a fixed IP
   * (5) Set the X-Mob-Type header based on user agent
   * (6) requests for assets are cacheable
   */

  // Cache all assets
  if (req.url ~ "\.(png|gif|jpeg|jpg|ico|swf|css|js)(\?[a-z0-9%&]+)?$") {
    unset req.http.Cookie;
  }
  if (req.http.Content-Type ~ "png|gif|jpeg|jpg|ico|swf|css|javascript") {
    unset req.http.Cookie;
  }

  // Set the X-Mob-Type based on the user agent
  set req.http.X-Mob-Type = "1";

  // Use the following lines to vary the cache for any user agents that will be
  // served different content; here's an example for blackberry
  /*
  if (req.http.User-Agent ~ "BlackBerry[0-9]{4}\/(4\.6|4\.7|4\.8|5\.)") {
    set req.http.X-Mob-Type = "2";
  }
  */

  if (req.http.host ~ "^mstage") {
    set req.backend = {{#GOPERIOD#ProjectName}}_appv01;
    set req.http.X-QA = "true";
  }

  if (client.ip != "127.0.0.1") {
    if (req.http.x-forwarded-for) {
      set req.http.X-Forwarded-For =
        req.http.X-Forwarded-For ", " client.ip;
    } else {
      set req.http.X-Forwarded-For = client.ip;
    }
  }

  if (req.request != "GET" &&
      req.request != "HEAD" &&
      req.request != "PUT" &&
      req.request != "POST" &&
      req.request != "TRACE" &&
      req.request != "OPTIONS" &&
      req.request != "DELETE") {
    /* Non-RFC2616 or CONNECT which is weird. */
    return (pipe);
  }

  if (req.request != "GET" && req.request != "HEAD") {
    /* We only deal with GET and HEAD by default */
    return (pass);
  }

  if (req.http.x-moov-secure) {
    /* This request originated as an HTTPS request: not cacheable */
    return (pass);
  }
  if (req.http.Authorization) {
    /* Not cacheable by default */
    return (pass);
  }

  return (lookup);
}

sub vcl_hash {
  /*
   * Start default.vcl
   * Copied from default config so we can use the default hash and add the
   * X-Mob-Type to it.
   */
  set req.hash += req.url;
  if (req.http.host) {
    set req.hash += req.http.host;
  } else {
    set req.hash += server.ip;
  }
  /*
   * End default.vcl
   */

  // Add the X-Mob-Type to the hash value
  set req.hash += req.http.X-Mob-Type;

  // Return the custom hash value to Varnish
  return (hash);
}

/*
 * Error page to be presented should there be a problem in the cache
 */
sub vcl_error {
  set obj.http.Content-Type = "text/html; charset=utf-8";
  synthetic{"
  <!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Transitional//EN' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd'>

  <title>Something went wrong</title>

Looks like something went wrong here!

We're currently experiencing a technical issue. Please try to refresh the page or visit us on our <a href='www.{{#GOPERIOD#Domain}}' desktop site. We apologize for the inconvenience.

  "};
  return (deliver);
}

/*
 * Default Cache.vcl
 *
 * If you don't want to cache anything, you are all set.
 * If you do want to cache some things, you will have to modify this file.
 * As a starting point you can simply remove the first 'return (pass);' line from
 * 'vcl_fetch'. This will enable some reasonable caching rules.
 */
sub vcl_fetch {
  /*
   * Default Varnish logic EXCEPT:
   *   (1) Responses with a set-cookie header can still make their way
   *       into the cache. But I remove the set-cookie header in those instances.
   *   (2) Instead of using 'beresp.cacheable' to determine cacheability,
   *       I am checking for Cache-Control public
   */

  // Copy the X-Mob-Type type from the request header into the response header
  set beresp.http.X-Mob-Type = req.http.X-Mob-Type;

  if (beresp.http.Cache-Control ~ "public") {
    remove beresp.http.Set-Cookie;
    return (deliver);
  }

  return (pass);
}

sub vcl_recv {
  set req.backend = application_director;

  /*
   * Default Varnish Caching logic with four exceptions:
   * (1) requests with cookies are cacheable
   * (2) X-Forwarded-For is only set when the client ip is not 127.0.0.1
   * (3) X-Moov-Secure requests are not cacheable
   * (4) Set the QA backend server to <customer>_appv01 which has a fixed IP
   * (5) Set the X-Mob-Type header based on user agent
   * (6) requests for assets are cacheable
   */

  // Cache all assets
  if (req.url ~ "\.(png|gif|jpeg|jpg|ico|swf|css|js)(\?[a-z0-9%&]+)?$") {
    unset req.http.Cookie;
  }
  if (req.http.Content-Type ~ "png|gif|jpeg|jpg|ico|swf|css|javascript") {
    unset req.http.Cookie;
  }

  // Set the X-Mob-Type based on the user agent
  set req.http.X-Mob-Type = "1";

  // Use the following lines to vary the cache for any user agents that will be
  // served different content; here's an example for blackberry
  /*
  if (req.http.User-Agent ~ "BlackBerry[0-9]{4}\/(4\.6|4\.7|4\.8|5\.)") {
    set req.http.X-Mob-Type = "2";
  }
  */

  if (req.http.host ~ "^mstage") {
    set req.backend = {{#GOPERIOD#ProjectName}}_appv01;
    set req.http.X-QA = "true";
  }

  if (client.ip != "127.0.0.1") {
    if (req.http.x-forwarded-for) {
      set req.http.X-Forwarded-For =
        req.http.X-Forwarded-For ", " client.ip;
    } else {
      set req.http.X-Forwarded-For = client.ip;
    }
  }

  if (req.request != "GET" &&
      req.request != "HEAD" &&
      req.request != "PUT" &&
      req.request != "POST" &&
      req.request != "TRACE" &&
      req.request != "OPTIONS" &&
      req.request != "DELETE") {
    /* Non-RFC2616 or CONNECT which is weird. */
    return (pipe);
  }

  if (req.request != "GET" && req.request != "HEAD") {
    /* We only deal with GET and HEAD by default */
    return (pass);
  }

  if (req.http.x-moov-secure) {
    /* This request originated as an HTTPS request: not cacheable */
    return (pass);
  }
  if (req.http.Authorization) {
    /* Not cacheable by default */
    return (pass);
  }

  return (lookup);
}

sub vcl_hash {
  /*
   * Start default.vcl
   * Copied from default config so we can use the default hash and add the
   * X-Mob-Type to it.
   */
  set req.hash += req.url;
  if (req.http.host) {
    set req.hash += req.http.host;
  } else {
    set req.hash += server.ip;
  }
  /*
   * End default.vcl
   */

  // Add the X-Mob-Type to the hash value
  set req.hash += req.http.X-Mob-Type;

  // Return the custom hash value to Varnish
  return (hash);
}

/*
 * Error page to be presented should there be a problem in the cache
 */
sub vcl_error {
  set obj.http.Content-Type = "text/html; charset=utf-8";
  synthetic{"
  <!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Transitional//EN' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd'>

  <title>Something went wrong</title>

Looks like something went wrong here!

We're currently experiencing a technical issue. Please try to refresh the page or visit us on our <a href='www.{{#GOPERIOD#Domain}}' desktop site. We apologize for the inconvenience.

  "};
  return (deliver);
}


Perform legacy redirect at Fastly.

Perform legacy redirect at Fastly.

sub vcl_recv {
#FASTLY recv

	if (req.request != "HEAD" && req.request != "GET" && req.request != "FASTLYPURGE") {
	  return(pass);
	}

	# Redirect legacy service users to legacy service
	set req.http.X-Referer-Host = regsub(req.http.Referer, "^https?\:\/\/([^\/]+)(\/.*)?$", "\1");
	if (req.url == "/normalize.js" ||
		req.url == "/normalize.css" ||
		req.url == "/normalise.js" ||
		req.url == "/normalise.css" ||
		req.http.X-Referer-Host == "www.manrepeller.com" ||
		req.http.X-Referer-Host == "www.mulesoft.com" ||
		req.http.X-Referer-Host == "iluoghidelcuore.it" ||
		req.http.X-Referer-Host == "it.donga.com" ||
		req.http.X-Referer-Host == "www.watchguard.com" ||
		req.http.X-Referer-Host == "www.mulesoft.org" ||
		req.http.X-Referer-Host == "asmwall.com" ||
		req.http.X-Referer-Host == "www.jcsu.edu" ||
		req.http.X-Referer-Host == "adscendmedia.com" ||
		req.http.X-Referer-Host == "game.donga.com" ||
		req.http.X-Referer-Host == "framkino.no" ||
		req.http.X-Referer-Host == "www.accesswireless.com" ||
		req.http.X-Referer-Host == "represent.com" ||
		req.http.X-Referer-Host == "www.designergreek.com" ||
		req.http.X-Referer-Host == "www.plumbingoverstock.com" ||
		req.http.X-Referer-Host == "servicos.searh.rn.gov.br" ||
		req.http.X-Referer-Host == "www.jane-usa.com" ||
		req.http.X-Referer-Host == "www.juntaempresa.com.br" ||
		req.http.X-Referer-Host == "watchguard.com" ||
		req.http.X-Referer-Host == "www.logianalytics.com" ||
		req.http.X-Referer-Host == "www.thebathpoint.com" ||
		req.http.X-Referer-Host == "blogs.mulesoft.org" ||
		req.http.X-Referer-Host == "www.purecanadiangaming.com" ||
		req.http.X-Referer-Host == "play.egzaminatorius.lt" ||
		req.http.X-Referer-Host == "internetacademi.com" ||
		req.http.X-Referer-Host == "www.skyhighnetworks.com" ||
		req.http.X-Referer-Host == "interactive.guim.co.uk" ||
		req.http.X-Referer-Host == "www.soloio.com" ||
		req.http.X-Referer-Host == "desenvolvimentoparaweb.com" ||
		req.http.X-Referer-Host == "daily-fantasy.trunk.development.manhattan.gq1.yahoo.com" ||
		req.http.X-Referer-Host == "blog.damyller.com.br" ||
		req.http.X-Referer-Host == "doggiebag.no" ||
		req.http.X-Referer-Host == "www.beverlydiamonds.com" ||
		req.http.X-Referer-Host == "www.rogerscup.com" ||
		req.http.X-Referer-Host == "blog.hudy.cz" ||
		req.http.X-Referer-Host == "techhamlet.com" ||
		req.http.X-Referer-Host == "www.flirtfachmann.de" ||
		req.http.X-Referer-Host == "alpacacomics.com" ||
		req.http.X-Referer-Host == "areariservata.fondoprevidenzafinanze.it" ||
		req.http.X-Referer-Host == "www.framkino.no" ||
		req.http.X-Referer-Host == "www.nationalsecurities.com" ||
		req.http.X-Referer-Host == "www.tenniscanada.com" ||
		req.http.X-Referer-Host == "libek.org.rs" ||
		req.http.X-Referer-Host == "learn.logianalytics.com" ||
		req.http.X-Referer-Host == "www.impartner.lt" ||
		req.http.X-Referer-Host == "chameleon.biworldwide.com" ||
		req.http.X-Referer-Host == "www.pujckapowebu.cz" ||
		req.http.X-Referer-Host == "www.dlcnetwork.com" ||
		req.http.X-Referer-Host == "www.forbes.com" ||
		req.http.X-Referer-Host == "blog.skyhighnetworks.com" ||
		req.http.X-Referer-Host == "rflx.bjornborg.com" ||
		req.http.X-Referer-Host == "www.coach-outlet-store.com" ||
		req.http.X-Referer-Host == "gist.io" ||
		req.http.X-Referer-Host == "www.suicideispreventable.org" ||
		req.http.X-Referer-Host == "www.rangemastertacticalgear.com" ||
		req.http.X-Referer-Host == "www.hcpozicka.sk" ||
		req.http.X-Referer-Host == "www.airsoftmegastore.com" ||
		req.http.X-Referer-Host == "colortile.github.io" ||
		req.http.X-Referer-Host == "brasstacksmadras.com" ||
		req.http.X-Referer-Host == "hotelcasadomingo.com.mx" ||
		req.http.X-Referer-Host == "client.local" ||
		req.http.X-Referer-Host == "www.worcesterpromotions.co.uk" ||
		req.http.X-Referer-Host == "www.asmwall.com" ||
		req.http.X-Referer-Host == "training.mulesoft.com" ||
		req.http.X-Referer-Host == "localhost" ||
		req.http.X-Referer-Host == "exhilarateme.com" ||
		req.http.X-Referer-Host == "www.kommentatorskampen.viasatsport.se" ||
		req.http.X-Referer-Host == "www.golfgearselect.com" ||
		req.http.X-Referer-Host == "www.hcpujcka.cz" ||
		req.http.X-Referer-Host == "www.industriallawsociety.org.uk" ||
		req.http.X-Referer-Host == "www.locawebcorp.com.br" ||
		req.http.X-Referer-Host == "giffffr.giphy.com" ||
		req.http.X-Referer-Host == "mccall.co.uk" ||
		req.http.X-Referer-Host == "kommentatorskampen.viasatsport.se" ||
		req.http.X-Referer-Host == "bpharm.localhost" ||
		req.http.X-Referer-Host == "miraclebodyandpaint.com" ||
		req.http.X-Referer-Host == "www.tymprozdravi.cz" ||
		req.http.X-Referer-Host == "delicius.it" ||
		req.http.X-Referer-Host == "www.bluehighwaygames.com" ||
		req.http.X-Referer-Host == "tales-of-pikohan.de" ||
		req.http.X-Referer-Host == "demo.restoreadytest.com" ||
		req.http.X-Referer-Host == "mark.stratmann.me" ||
		req.http.X-Referer-Host == "apixtechnology.com" ||
		req.http.X-Referer-Host == "www.telefonickapozicka.sk" ||
		req.http.X-Referer-Host == "www.telefonnipujcka.cz" ||
		req.http.X-Referer-Host == "www.iteo.no" ||
		req.http.X-Referer-Host == "www.diktate.info" ||
		req.http.X-Referer-Host == "bpharm.192.168.56.102.xip.io" ||
		req.http.X-Referer-Host == "www.artisanprecast.com" ||
		req.http.X-Referer-Host == "tcisolutions.com" ||
		req.http.X-Referer-Host == "icelebrate.icehotel.com" ||
		req.http.X-Referer-Host == "www.thirtysevenwest.com" ||
		req.http.X-Referer-Host == "www.asgllc.com" ||
		req.http.X-Referer-Host == "www.mailinbox.net" ||
		req.http.X-Referer-Host == "rustyfelty.com" ||
		req.http.X-Referer-Host == "pulse.p2c.com" ||
		req.http.X-Referer-Host == "www.framkino.com" ||
		req.http.X-Referer-Host == "armourselfstorage.com" ||
		req.http.X-Referer-Host == "www.dezrezblog.com" ||
		req.http.X-Referer-Host == "goodpeople.com" ||
		req.http.X-Referer-Host == "survey-project.localhost" ||
		req.http.X-Referer-Host == "www.eden-houlgate.com" ||
		req.http.X-Referer-Host == "www.patiovirtual.com.br" ||
		req.http.X-Referer-Host == "stats.egzaminatorius.lt" ||
		req.http.X-Referer-Host == "www.movieville.org" ||
		req.http.X-Referer-Host == "secure.watchguard.com" ||
		req.http.X-Referer-Host == "nationalsecurities.com" ||
		req.http.X-Referer-Host == "timepad.localhost" ||
		req.http.X-Referer-Host == "www.snaponindustrial.eu" ||
		req.http.X-Referer-Host == "www.fangear.com" ||
		req.http.X-Referer-Host == "www.scribbleshop.com" ||
		req.http.X-Referer-Host == "forums.mulesoft.org" ||
		req.http.X-Referer-Host == "dataentries.in" ||
		req.http.X-Referer-Host == "maki.alconost.com" ||
		req.http.X-Referer-Host == "dixso.github.io" ||
		req.http.X-Referer-Host == "citaprevia.volkswagen.es" ||
		req.http.X-Referer-Host == "movieville.org" ||
		req.http.X-Referer-Host == "www.seoestudios.com" ||
		req.http.X-Referer-Host == "tickets.campo.nu" ||
		req.http.X-Referer-Host == "perriehale.toucan" ||
		req.http.X-Referer-Host == "online.printstation.cz" ||
		req.http.X-Referer-Host == "www.le-bistrot-basque.com" ||
		req.http.X-Referer-Host == "www.thaiartofmassage.com" ||
		req.http.X-Referer-Host == "www.seevolution.com" ||
		req.http.X-Referer-Host == "janeusa.david" ||
		req.http.X-Referer-Host == "www.goodpeople.com" ||
		req.http.X-Referer-Host == "feeds.feedburner.com" ||
		req.http.X-Referer-Host == "www.millwardesque.com" ||
		req.http.X-Referer-Host == "cci.smartucs.a" ||
		req.http.X-Referer-Host == "forum.tales-of-pikohan.de" ||
		req.http.X-Referer-Host == "small.mu" ||
		req.http.X-Referer-Host == "crisp.toucan" ||
		req.http.X-Referer-Host == "www.fosterdenovo.local" ||
		req.http.X-Referer-Host == "dev1776.nationalsecurities.com" ||
		req.http.X-Referer-Host == "byose.net" ||
		req.http.X-Referer-Host == "www.eurodiary.ie" ||
		req.http.X-Referer-Host == "lemouvementassociatif.org" ||
		req.http.X-Referer-Host == "www.ey.com" ||
		req.http.X-Referer-Host == "cuterunslive.com" ||
		req.http.X-Referer-Host == "taxes-in-serbia.localhost" ||
		req.http.X-Referer-Host == "blog.odynia.org" ||
		req.http.X-Referer-Host == "solarenaymar.com.ar" ||
		req.http.X-Referer-Host == "www.aispaitalia.it" ||
		req.http.X-Referer-Host == "www.startupsaturday.it" ||
		req.http.X-Referer-Host == "support.watchguard.com" ||
		req.http.X-Referer-Host == "dax.absolnet.se" ||
		req.http.X-Referer-Host == "www.creativeinnovation.net.au" ||
		req.http.X-Referer-Host == "dev.raird.no" ||
		req.http.X-Referer-Host == "lesjeteursdencre.fr" ||
		req.http.X-Referer-Host == "itnotes.pl" ||
		req.http.X-Referer-Host == "www.thesocietyinternational.com" ||
		req.http.X-Referer-Host == "terminalfx.com" ||
		req.http.X-Referer-Host == "draft.sx" ||
		req.http.X-Referer-Host == "atelier-florent.fr" ||
		req.http.X-Referer-Host == "www.buona-tavola-ristorante.fr" ||
		req.http.X-Referer-Host == "www.terminalfx.com" ||
		req.http.X-Referer-Host == "www.taxattorney.com" ||
		req.http.X-Referer-Host == "proenter.dev" ||
		req.http.X-Referer-Host == "bodelo-advocaten.be" ||
		req.http.X-Referer-Host == "www.football1asia.com" ||
		req.http.X-Referer-Host == "rets.ly" ||
		req.http.X-Referer-Host == "erriol.com" ||
		req.http.X-Referer-Host == "shssandiego.com" ||
		req.http.X-Referer-Host == "notecrow.appspot.com" ||
		req.http.X-Referer-Host == "framkino.com" ||
		req.http.X-Referer-Host == "sexsite.daan" ||
		req.http.X-Referer-Host == "sro.dk" ||
		req.http.X-Referer-Host == "www.coloft.com" ||
		req.http.X-Referer-Host == "taxiplus.vsystem.hu" ||
		req.http.X-Referer-Host == "stage.mulesoft.com" ||
		req.http.X-Referer-Host == "local.dev.ugameplan.com" ||
		req.http.X-Referer-Host == "posh-nosh.com" ||
		req.http.X-Referer-Host == "phongthuyshop.vn" ||
		req.http.X-Referer-Host == "local.mansionhouse.co.uk" ||
		req.http.X-Referer-Host == "www.compareaccounting.com" ||
		req.http.X-Referer-Host == "news.coinometrics.com" ||
		req.http.X-Referer-Host == "prod-yann.mailinbox.net" ||
		req.http.X-Referer-Host == "rachelree.se" ||
		req.http.X-Referer-Host == "dev1.accesswireless.usdigitalpartners.net" ||
		req.http.X-Referer-Host == "www.ewirisk.com" ||
		req.http.X-Referer-Host == "snapchan.com" ||
		req.http.X-Referer-Host == "www.trikatasieraakademija.lv" ||
		req.http.X-Referer-Host == "www.fosteringadoptionswindon.org.uk" ||
		req.http.X-Referer-Host == "patiovirtual.com.br" ||
		req.http.X-Referer-Host == "www.libmanpro.com" ||
		req.http.X-Referer-Host == "www.diktate.dev" ||
		req.http.X-Referer-Host == "idisco.pianetaitalia.intra" ||
		req.http.X-Referer-Host == "strudelfolhadinho.com.br" ||
		req.http.X-Referer-Host == "www.cunesoft.com" ||
		req.http.X-Referer-Host == "www.shropshirefoundation.org" ||
		req.http.X-Referer-Host == "speakingofbeauty.tv" ||
		req.http.X-Referer-Host == "www.sbs.com.au" ||
		req.http.X-Referer-Host == "bosch.pikmahosting.de" ||
		req.http.X-Referer-Host == "janeusa.lol" ||
		req.http.X-Referer-Host == "eso.toucan" ||
		req.http.X-Referer-Host == "www.lamedicis.com" ||
		req.http.X-Referer-Host == "cereseurope.com" ||
		req.http.X-Referer-Host == "www.pizza-moltobene.fr" ||
		req.http.X-Referer-Host == "www.kaptiva.com.br" ||
		req.http.X-Referer-Host == "flixified.com" ||
		req.http.X-Referer-Host == "www.12roundsboxing.co.uk" ||
		req.http.X-Referer-Host == "www.tensionautomation.com" ||
		req.http.X-Referer-Host == "www.copyprint.nl" ||
		req.http.X-Referer-Host == "unisol" ||
		req.http.X-Referer-Host == "timepad.ews.co.rs" ||
		req.http.X-Referer-Host == "dev.rets.ly" ||
		req.http.X-Referer-Host == "www.vrhabilis.com" ||
		req.http.X-Referer-Host == "trondheggelund.no" ||
		req.http.X-Referer-Host == "www.ferienwohnungen-lebenswert.de" ||
		req.http.X-Referer-Host == "blog.mainline.com" ||
		req.http.X-Referer-Host == "arcstonepartners.com" ||
		req.http.X-Referer-Host == "dev-mj" ||
		req.http.X-Referer-Host == "www.crisp-cpd.com" ||
		req.http.X-Referer-Host == "purecanadiangaming.com" ||
		req.http.X-Referer-Host == "mainline.com" ||
		req.http.X-Referer-Host == "idx.dev.rets.ly" ||
		req.http.X-Referer-Host == "eneco.flicker.visualwind.com" ||
		req.http.X-Referer-Host == "mi.etoilemedia.it" ||
		req.http.X-Referer-Host == "www.atmosphericwatergenerator.net" ||
		req.http.X-Referer-Host == "www.gasnaturalenergyclass.com" ||
		req.http.X-Referer-Host == "salesmarketing.championpetfoods.com" ||
		req.http.X-Referer-Host == "www.watchgaurd.com" ||
		req.http.X-Referer-Host == "vm-sqlext-svil" ||
		req.http.X-Referer-Host == "dev.accesswireless.usdigitalpartners.net" ||
		req.http.X-Referer-Host == "kommentatorskampen.ohmytest.se" ||
		req.http.X-Referer-Host == "m.euvivoesporte.com.br" ||
		req.http.X-Referer-Host == "blog.dasroot.net" ||
		req.http.X-Referer-Host == "bugsdashboard.com" ||
		req.http.X-Referer-Host == "www.eurodiary.co.uk" ||
		req.http.X-Referer-Host == "seecanadabetter-app.appspot.com" ||
		req.http.X-Referer-Host == "www.bobbychanblog.com" ||
		req.http.X-Referer-Host == "www.mybenefitsatwork.co.uk" ||
		req.http.X-Referer-Host == "www.fotolotos.lt" ||
		req.http.X-Referer-Host == "robferguson.org" ||
		req.http.X-Referer-Host == "staging.motherapp.com" ||
		req.http.X-Referer-Host == "www.undergroundminingequipmentcompaniescalgaryquotes.com" ||
		req.http.X-Referer-Host == "idisco.pianetaitalia.com" ||
		req.http.X-Referer-Host == "cliocalman.com" ||
		req.http.X-Referer-Host == "sexymirror-app.com" ||
		req.http.X-Referer-Host == "taxes-in-serbia.192.168.56.102.xip.io" ||
		req.http.X-Referer-Host == "wunderbiz.com" ||
		req.http.X-Referer-Host == "thebathpoint.webdemo.es" ||
		req.http.X-Referer-Host == "www.restaurant-lemenhir.com" ||
		req.http.X-Referer-Host == "www.valdeure.fr" ||
		req.http.X-Referer-Host == "bpharm.ews.co.rs" ||
		req.http.X-Referer-Host == "teachersdunet.com" ||
		req.http.X-Referer-Host == "livesmartswmo.com" ||
		req.http.X-Referer-Host == "javiblog.com" ||
		req.http.X-Referer-Host == "portal.com.local" ||
		req.http.X-Referer-Host == "mi.etoilemedia.com" ||
		req.http.X-Referer-Host == "www.lens.org" ||
		req.http.X-Referer-Host == "blacknet.co.uk" ||
		req.http.X-Referer-Host == "my-faith-be-like.ghost.io" ||
		req.http.X-Referer-Host == "laravel.dev" ||
		req.http.X-Referer-Host == "fi-hpotts.2014-mansionhouse" ||
		req.http.X-Referer-Host == "mi.mailinbox.net" ||
		req.http.X-Referer-Host == "www.schulkeplusrewards.co.uk" ||
		req.http.X-Referer-Host == "sasha-project.s3.amazonaws.com" ||
		req.http.X-Referer-Host == "www.solarenaymar.com.ar" ||
		req.http.X-Referer-Host == "generate.visualwind.com" ||
		req.http.X-Referer-Host == "drupaltest.wgti.net" ||
		req.http.X-Referer-Host == "minasdev.org" ||
		req.http.X-Referer-Host == "ims-logistic.dev" ||
		req.http.X-Referer-Host == "viaresto.com" ||
		req.http.X-Referer-Host == "learn.logixml.com" ||
		req.http.X-Referer-Host == "ox.espadrill-admin" ||
		req.http.X-Referer-Host == "smallmu-sandbox.s3-ap-southeast-1.amazonaws.com" ||
		req.http.X-Referer-Host == "www.firstinternet.co.uk" ||
		req.http.X-Referer-Host == "m.facebook.com" ||
		req.http.X-Referer-Host == "www.ace.media" ||
		req.http.X-Referer-Host == "www.ewiretx.com" ||
		req.http.X-Referer-Host == "crisp.test.tdev.co.uk" ||
		req.http.X-Referer-Host == "www.mifabricavisual.com" ||
		req.http.X-Referer-Host == "www.targetintervention.no" ||
		req.http.X-Referer-Host == "www.couperogers.com" ||
		req.http.X-Referer-Host == "skyhighstaging.local.com" ||
		req.http.X-Referer-Host == "altorendimientoacademico.queretaro.itesm.mx" ||
		req.http.X-Referer-Host == "www.gall-holl.com" ||
		req.http.X-Referer-Host == "sbs-moad.s3-ap-southeast-2.amazonaws.com" ||
		req.http.X-Referer-Host == "firstint.recruitment-lite" ||
		req.http.X-Referer-Host == "www.sro.dk" ||
		req.http.X-Referer-Host == "www.menbur.com" ||
		req.http.X-Referer-Host == "libmanpro.com" ||
		req.http.X-Referer-Host == "blurayaustralia.com" ||
		req.http.X-Referer-Host == "www.adscendmedia.com" ||
		req.http.X-Referer-Host == "blog.vincentbrouillet.com" ||
		req.http.X-Referer-Host == "www.investiumonline.nl" ||
		req.http.X-Referer-Host == "burakkp.com" ||
		req.http.X-Referer-Host == "audreysystem.seeties.me" ||
		req.http.X-Referer-Host == "everestsalesconsultants.co.uk" ||
		req.http.X-Referer-Host == "accesswireless.usdphosting.com" ||
		req.http.X-Referer-Host == "frota.searh.rn.gov.br" ||
		req.http.X-Referer-Host == "qa.ugameplan.com" ||
		req.http.X-Referer-Host == "secure.yec.co" ||
		req.http.X-Referer-Host == "connect.eu.mulesoft.com" ||
		req.http.X-Referer-Host == "www.lastlongerreview.com" ||
		req.http.X-Referer-Host == "kommentatorskampen.lo" ||
		req.http.X-Referer-Host == "kido.bigroominternet.co.uk" ||
		req.http.X-Referer-Host == "ohmydev.se" ||
		req.http.X-Referer-Host == "www.bentogarcia.es" ||
		req.http.X-Referer-Host == "rearview.herokai.com" ||
		req.http.X-Referer-Host == "lecafelatin.resto-ready.com" ||
		req.http.X-Referer-Host == "html24-dev.dk" ||
		req.http.X-Referer-Host == "seecanadabetter.ddev" ||
		req.http.X-Referer-Host == "portal.ad1.wrvc.co.uk" ||
		req.http.X-Referer-Host == "garthwunsch.com" ||
		req.http.X-Referer-Host == "www.elitecustomsigns.com" ||
		req.http.X-Referer-Host == "kaptiva.com.br" ||
		req.http.X-Referer-Host == "nordicinox.com" ||
		req.http.X-Referer-Host == "www.nataktivisterna.lo" ||
		req.http.X-Referer-Host == "www.fidalgobaycoffee.com" ||
		req.http.X-Referer-Host == "mailinbox.net" ||
		req.http.X-Referer-Host == "www.tension.com" ||
		req.http.X-Referer-Host == "www.mccall.co.uk" ||
		req.http.X-Referer-Host == "petbucks.org" ||
		req.http.X-Referer-Host == "mulesoftcompdev.prod.acquia-sites.com" ||
		req.http.X-Referer-Host == "logidev.devcloud.acquia-sites.com" ||
		req.http.X-Referer-Host == "www.cuterunslive.com" ||
		req.http.X-Referer-Host == "ec2-54-86-27-137.compute-1.amazonaws.com" ||
		req.http.X-Referer-Host == "coloft.com" ||
		req.http.X-Referer-Host == "dev-yann.mailinbox.net" ||
		req.http.X-Referer-Host == "titistore.es" ||
		req.http.X-Referer-Host == "biztro.pl" ||
		req.http.X-Referer-Host == "zd.ews.co.rs" ||
		req.http.X-Referer-Host == "www.cafelatincaen.com" ||
		req.http.X-Referer-Host == "togume.com" ||
		req.http.X-Referer-Host == "connect.mulesoft.com" ||
		req.http.X-Referer-Host == "che.local" ||
		req.http.X-Referer-Host == "nataktivisterna.lo" ||
		req.http.X-Referer-Host == "livelean.co.uk" ||
		req.http.X-Referer-Host == "copyprint.nl" ||
		req.http.X-Referer-Host == "jayhathaway.com" ||
		req.http.X-Referer-Host == "rugsejis.epratybos.lt" ||
		req.http.X-Referer-Host == "media-env.elasticbeanstalk.com" ||
		req.http.X-Referer-Host == "id.snowfire.io" ||
		req.http.X-Referer-Host == "employme.at" ||
		req.http.X-Referer-Host == "booleanbrothers.com" ||
		req.http.X-Referer-Host == "www.fusiongroup.ie" ||
		req.http.X-Referer-Host == "skyhighnetworks.gravitatestaging.com" ||
		req.http.X-Referer-Host == "www.teachers.youtalkonline.com" ||
		req.http.X-Referer-Host == "sunshineandfrank.com" ||
		req.http.X-Referer-Host == "proof.acemedia.bigroominternet.co.uk" ||
		req.http.X-Referer-Host == "personaltrainersinlosangeles.com" ||
		req.http.X-Referer-Host == "www.shawn.co" ||
		req.http.X-Referer-Host == "solidproperty.com.my" ||
		req.http.X-Referer-Host == "www.nordicinox.com" ||
		req.http.X-Referer-Host == "tension.com" ||
		req.http.X-Referer-Host == "especiaiss3.gshow.globo.com" ||
		req.http.X-Referer-Host == "seebstore.com" ||
		req.http.X-Referer-Host == "packerz.uk" ||
		req.http.X-Referer-Host == "happyliving.jp" ||
		req.http.X-Referer-Host == "www.vacacionesdebuenrollito.com" ||
		req.http.X-Referer-Host == "plastpack.ind.br" ||
		req.http.X-Referer-Host == "finance.trunk.development.manhattan.gq1.yahoo.com" ||
		req.http.X-Referer-Host == "elearningpprd.biworldwide.com" ||
		req.http.X-Referer-Host == "millwardesque.com" ||
		req.http.X-Referer-Host == "icehotel.lo" ||
		req.http.X-Referer-Host == "ongair.im" ||
		req.http.X-Referer-Host == "mule01a.managed.contegix.com" ||
		req.http.X-Referer-Host == "ipated.org" ||
		req.http.X-Referer-Host == "cientifica-research.com" ||
		req.http.X-Referer-Host == "andreypopp.github.io" ||
		req.http.X-Referer-Host == "schools.medsense.in" ||
		req.http.X-Referer-Host == "d-ycl.cigna.com" ||
		req.http.X-Referer-Host == "romankorver.com" ||
		req.http.X-Referer-Host == "ihaveanidea.me" ||
		req.http.X-Referer-Host == "evoyan.org" ||
		req.http.X-Referer-Host == "cectserver.dyndns.org" ||
		req.http.X-Referer-Host == "test.idx.dev.rets.ly" ||
		req.http.X-Referer-Host == "vastgoedpro.dataquote.nl" ||
		req.http.X-Referer-Host == "sifopweb" ||
		req.http.X-Referer-Host == "instituteofselfmastery.com.au" ||
		req.http.X-Referer-Host == "www.automobrella.com" ||
		req.http.X-Referer-Host == "panel.mibubu.com" ||
		req.http.X-Referer-Host == "whsb.herokuapp.com" ||
		req.http.X-Referer-Host == "heastea.com" ||
		req.http.X-Referer-Host == "meishinkan.pl" ||
		req.http.X-Referer-Host == "manrepeller.staging.wpengine.com" ||
		req.http.X-Referer-Host == "derprecated.com" ||
		req.http.X-Referer-Host == "fobesfamily.com" ||
		req.http.X-Referer-Host == "tensionautomation.com" ||
		req.http.X-Referer-Host == "www.jesuisoriginale.com" ||
		req.http.X-Referer-Host == "www.domgonsa.com.ar" ||
		req.http.X-Referer-Host == "www.digitalpark.co.uk" ||
		req.http.X-Referer-Host == "debray.jerome.free.fr" ||
		req.http.X-Referer-Host == "rainmakerthinking.training" ||
		req.http.X-Referer-Host == "thespineauthority.com.au" ||
		req.http.X-Referer-Host == "pseudocubic.com" ||
		req.http.X-Referer-Host == "mi.sky8.it" ||
		req.http.X-Referer-Host == "iteo.staging.wpengine.com" ||
		req.http.X-Referer-Host == "adscend-q.dev" ||
		req.http.X-Referer-Host == "taxes-in-serbia.ews.co.rs" ||
		req.http.X-Referer-Host == "s.codepen.io" ||
		req.http.X-Referer-Host == "seecanadabetter.ca" ||
		req.http.X-Referer-Host == "www.werkbund.com.br" ||
		req.http.X-Referer-Host == "www.art365.co.za" ||
		req.http.X-Referer-Host == "tensionpackaging.com" ||
		req.http.X-Referer-Host == "ec2-54-164-179-111.compute-1.amazonaws.com" ||
		req.http.X-Referer-Host == "sms.loc" ||
		req.http.X-Referer-Host == "timeclock.neonandmore.com" ||
		req.http.X-Referer-Host == "silverblingblack.com" ||
		req.http.X-Referer-Host == "www.modulolanguage.com" ||
		req.http.X-Referer-Host == "visualise.today" ||
		req.http.X-Referer-Host == "pickinglist.constance.com.br" ||
		req.http.X-Referer-Host == "mobileshoppingapps.net" ||
		req.http.X-Referer-Host == "ashleyandbarry.com" ||
		req.http.X-Referer-Host == "www.planetgreen.cl" ||
		req.http.X-Referer-Host == "portal-intranet.ti.sabesp.com.br" ||
		req.http.X-Referer-Host == "gordonrecords.net" ||
		req.http.X-Referer-Host == "cce.pathlore.net" ||
		req.http.X-Referer-Host == "www.myclaimvalue.com" ||
		req.http.X-Referer-Host == "stage.mulesoft.org" ||
		req.http.X-Referer-Host == "javiblog.javigs.es"
	) {
		set req.http.X-Redir-URL = "https://legacy.polyfill.io" req.url;
		error 900 req.http.X-Redir-URL;
	}

	if (req.url ~ "^/v1/polyfill\." && req.url !~ "[\?\&]ua=") {
		set req.http.X-Orig-URL = req.url;
		set req.url = "/v1/normalizeUa?ua=" regsuball(regsuball(regsuball(req.http.User-Agent, {"%"}, {"%25"}), {" "}, {"%20"}), {"&"}, {"%26"});
	}

	return(lookup);
}

sub vcl_deliver {
#FASTLY deliver
	if (req.url ~ "^/v1/normalizeUa" && resp.status == 200) {
		set req.http.Fastly-force-Shield = "1";
		if (req.http.X-Orig-URL ~ "\?") {
			set req.url = req.http.X-Orig-URL "&ua=" resp.http.Normalized-User-Agent;
		} else {
			set req.url = req.http.X-Orig-URL "?ua=" resp.http.Normalized-User-Agent;
		}
		restart;
	} else if (req.url ~ "^/v1/polyfill\..*[\?\&]ua=" && req.http.X-Orig-URL && req.http.X-Orig-URL !~ "[\?\&]ua=") {
		set resp.http.Vary = "Accept-Encoding, User-Agent";
	}
	return(deliver);
}

sub vcl_error {
	if (obj.status == 900) {
		set obj.http.Location = obj.response;
		set obj.status = 301;
		set obj.response = "Moved Permanently";
		synthetic {"The referer header or request URI supplied in your request is known to be an attempt to use the previous version of polyfill.io, so for backwards compatibility we're redirecting you to legacy.polyfill.io which will handle your request using the old version of the service.  The legacy version will be discontinued in the future, so please update to the new version, and then let us know by raising an issue in our repo at https://github.com/financial-times/polyfill-service."};
		return (deliver);
	}
}

sub vcl_recv {
#FASTLY recv

	if (req.request != "HEAD" && req.request != "GET" && req.request != "FASTLYPURGE") {
		return(pass);
	}

	if (req.url ~ "^/v1/polyfill\." && req.url !~ "[\?\&]ua=") {
		set req.http.X-Orig-URL = req.url;
		set req.url = "/v1/normalizeUa?ua=" urlencode(req.http.User-Agent);
	}

	return(lookup);
}

sub vcl_deliver {
#FASTLY deliver
	if (req.url ~ "^/v1/normalizeUa" && resp.status == 200) {
		set req.http.Fastly-force-Shield = "1";
		if (req.http.X-Orig-URL ~ "\?") {
			set req.url = req.http.X-Orig-URL "&ua=" resp.http.Normalized-User-Agent;
		} else {
			set req.url = req.http.X-Orig-URL "?ua=" resp.http.Normalized-User-Agent;
		}
		restart;
	} else if (req.url ~ "^/v1/polyfill\..*[\?\&]ua=" && req.http.X-Orig-URL && req.http.X-Orig-URL !~ "[\?\&]ua=") {
		set resp.http.Vary = "Accept-Encoding, User-Agent";
	}
	return(deliver);
}


Add logging from fastly (#1010)

Add logging from fastly (#1010)

import boltsort;

sub vcl_recv {
#FASTLY recv

	# Only log 0.1% of requests.
	if (randombool(1, 1000)) {
		set req.http.log = "1";
	}

	# Attach a unique id to each request, can be useful when investigating logs
	if (!req.http.request-id) {
		set req.http.request-id =
			randomstr(8, "0123456789abcdef") "-"
			randomstr(4, "0123456789abcdef") "-4"
			randomstr(3, "0123456789abcdef") "-"
			randomstr(1, "89ab") randomstr(3, "0123456789abcdef") "-"
			randomstr(12, "0123456789abcdef");
	}

	if ( req.request == "FASTLYPURGE" ) {
		set req.http.Fastly-Purge-Requires-Auth = "1";
	}

	if (req.request != "HEAD" && req.request != "GET" && req.request != "FASTLYPURGE") {
		return(pass);
	}

	if (!req.http.Fastly-SSL) {
		if (req.http.Host == "cdn.polyfill.io" || req.http.Host == "polyfill.io") {
			error 751 "Redirect to prod HTTPS";
		}
		if (req.http.Host == "qa.polyfill.io") {
			error 752 "Redirect to QA HTTPS";
		}
	}

	if (req.http.Host ~ "polyfills.io") {
		error 751 "Canonicalise";
	}

	if (req.url ~ "^/v2/(polyfill\.|recordRumData)" && req.url !~ "[\?\&]ua=") {
		set req.http.X-Orig-URL = req.url;
		set req.url = "/v2/normalizeUa?ua=" urlencode(req.http.User-Agent);
	}

	if (req.url ~ "^/v2/recordRumData" && req.http.Normalized-User-Agent) {
		set req.http.Log = regsub(req.url, "^.*?\?(.*)$", "\1") "&ip=" client.ip "&refer_domain=" regsub(req.http.Referer, "^(https?\:\/\/)?(www\.)?(.+?)(\:\d+)?([\/\?].*)?$", "\3") "&country=" geoip.country_code "&data_center=" if(req.http.Cookie:FastlyDC, req.http.Cookie:FastlyDC, server.datacenter);
		error 204 "No Content";
	}

	set req.url = boltsort.sort(req.url);

	return(lookup);
}

sub vcl_deliver {
#FASTLY deliver

	call custom_syslog;

	# If we are debugging, it is useful to know what the request-id will be so
	# that we can look at the logs for our requests
	if (req.http.FT-Debug) {
		set resp.http.request-id = req.http.request-id;
	}

	# If the response is to a normalise request and there's a parked "original request", use the normalised UA response to modify the original request and restart it
	if (req.url ~ "^/v\d/normalizeUa" && resp.status == 200 && req.http.X-Orig-URL ~ "^/v2/(polyfill\.|recordRumData)") {
		set req.http.Fastly-force-Shield = "1";
		set req.http.Normalized-User-Agent = resp.http.Normalized-User-Agent;
		if (req.http.X-Orig-URL ~ "\?") {
			set req.url = req.http.X-Orig-URL "&ua=" resp.http.Normalized-User-Agent;
		} else {
			set req.url = req.http.X-Orig-URL "?ua=" resp.http.Normalized-User-Agent;
		}
		restart;

	# If the original request didn't specify a UA override, and we added one when the request was sent to the backend, the backend won't have included a Vary:user-agent header (correctly) but we need to add one
	} else if (req.url ~ "^/v\d/polyfill\..*[\?\&]ua=" && req.http.X-Orig-URL && req.http.X-Orig-URL !~ "[\?\&]ua=") {
		add resp.http.Vary = "User-Agent";
	}

	if (req.url ~ "[\&\?]rum=1") {
		add resp.http.Set-Cookie = "FastlyDC=" server.datacenter "; Path=/; HttpOnly; max-age=60";
	}

	return(deliver);
}

sub vcl_error {
#FASTLY error

	# We log all vcl_error calls as these are probably exceptional circumstances
	call custom_error_syslog;

	# Redirect to canonical prod/qa origins
	if (obj.status == 751 || obj.status == 752) {
		set obj.status = 301;
		set obj.response = "Moved Permanently";
		set obj.http.Location = "https://" if(obj.status == 751, "", "qa.") "polyfill.io" req.url;
		synthetic {""};
		return (deliver);
	}
}

sub custom_syslog {
	# The log function will only be called if the request is one of the 25%
	# which we labelled as having logging enabled
	if (req.http.log) {
		log {"syslog ${SERVICEID} Fastly :: serviceid=${SERVICEID}"}
			{" timestamp="} time.start.sec
			{" event="} {"REQUEST"}
			{" host="} req.http.host
			{" request-id="} req.http.request-id
			{" bytes="} resp.http.content-length
			{" client_ip="} req.http.Fastly-Client-IP
			{" method="} req.request
			{" useragent="} req.http.User-Agent
			{" url=""} req.url {"""}
			{" content_type=""} resp.http.Content-Type {"""}
			{" status="} resp.status
			{" content-length="} resp.http.content-length
			if(geoip.city,{" geoip_city=""} geoip.city {"""},{""})
			if(geoip.region,{" geoip_region=""} geoip.region {"""},{""})
			if(geoip.country_code,{" geoip_country="} geoip.country_code,{""})
			if(geoip.continent_code,{" geoip_continent="} geoip.continent_code,{""})
			{" fastly_region="} server.region
			{" fastly_datacenter="} server.datacenter
			{" fastly_node="} server.identity
			{" fastly_state="} fastly_info.state
			{" duration_ms="} time.elapsed.msec;
	}
}

sub custom_error_syslog {
	# The reason custom_error_syslog is different from custom_syslog is because when
	# vcl_error is entered, there will be no resp object, which is used inside
	# custom_syslog to log information about the response we are sending

	log {"syslog ${SERVICEID} Fastly :: serviceid=${SERVICEID}"}
		{" timestamp="} time.start.sec
		{" event="} {"REQUEST"}
		{" host="} req.http.host
		{" request-id="} req.http.request-id
		{" client_ip="} req.http.Fastly-Client-IP
		{" method="} req.request
		{" useragent="} req.http.User-Agent
		{" url=""} req.url {"""}
		if(geoip.city,{" geoip_city=""} geoip.city {"""},{""})
		if(geoip.region,{" geoip_region=""} geoip.region {"""},{""})
		if(geoip.country_code,{" geoip_country="} geoip.country_code,{""})
		if(geoip.continent_code,{" geoip_continent="} geoip.continent_code,{""})
		{" fastly_region="} server.region
		{" fastly_datacenter="} server.datacenter
		{" fastly_node="} server.identity
		{" fastly_state="} fastly_info.state
		{" duration_ms="} time.elapsed.msec;
}

import boltsort;

sub vcl_recv {
#FASTLY recv
	if ( req.request == "FASTLYPURGE" ) {
		set req.http.Fastly-Purge-Requires-Auth = "1";
	}

	if (req.request != "HEAD" && req.request != "GET" && req.request != "FASTLYPURGE") {
		return(pass);
	}

	if (!req.http.Fastly-SSL) {
		if (req.http.Host == "cdn.polyfill.io" || req.http.Host == "polyfill.io") {
			error 751 "Redirect to prod HTTPS";
		}
		if (req.http.Host == "qa.polyfill.io") {
			error 752 "Redirect to QA HTTPS";
		}
	}

	if (req.http.Host ~ "polyfills.io") {
		error 751 "Canonicalise";
	}

	if (req.url ~ "^/v2/(polyfill\.|recordRumData)" && req.url !~ "[\?\&]ua=") {
		set req.http.X-Orig-URL = req.url;
		set req.url = "/v2/normalizeUa?ua=" urlencode(req.http.User-Agent);
	}

	if (req.url ~ "^/v2/recordRumData" && req.http.Normalized-User-Agent) {
		set req.http.Log = regsub(req.url, "^.*?\?(.*)$", "\1") "&ip=" client.ip "&refer_domain=" regsub(req.http.Referer, "^(https?\:\/\/)?(www\.)?(.+?)(\:\d+)?([\/\?].*)?$", "\3") "&country=" geoip.country_code "&data_center=" if(req.http.Cookie:FastlyDC, req.http.Cookie:FastlyDC, server.datacenter);
		error 204 "No Content";
	}

	set req.url = boltsort.sort(req.url);

	return(lookup);
}

sub vcl_deliver {
#FASTLY deliver

	# If the response is to a normalise request and there's a parked "original request", use the normalised UA response to modify the original request and restart it
	if (req.url ~ "^/v\d/normalizeUa" && resp.status == 200 && req.http.X-Orig-URL ~ "^/v2/(polyfill\.|recordRumData)") {
		set req.http.Fastly-force-Shield = "1";
		set req.http.Normalized-User-Agent = resp.http.Normalized-User-Agent;
		if (req.http.X-Orig-URL ~ "\?") {
			set req.url = req.http.X-Orig-URL "&ua=" resp.http.Normalized-User-Agent;
		} else {
			set req.url = req.http.X-Orig-URL "?ua=" resp.http.Normalized-User-Agent;
		}
		restart;

	# If the original request didn't specify a UA override, and we added one when the request was sent to the backend, the backend won't have included a Vary:user-agent header (correctly) but we need to add one
	} else if (req.url ~ "^/v\d/polyfill\..*[\?\&]ua=" && req.http.X-Orig-URL && req.http.X-Orig-URL !~ "[\?\&]ua=") {
		add resp.http.Vary = "User-Agent";
	}

	if (req.url ~ "[\&\?]rum=1") {
		add resp.http.Set-Cookie = "FastlyDC=" server.datacenter "; Path=/; HttpOnly; max-age=60";
	}

	return(deliver);
}

sub vcl_error {

	# Redirect to canonical prod/qa origins
	if (obj.status == 751 || obj.status == 752) {
		set obj.status = 301;
		set obj.response = "Moved Permanently";
		set obj.http.Location = "https://" if(obj.status == 751, "", "qa.") "polyfill.io" req.url;
		synthetic {""};
		return (deliver);
	}
}


Revert "ensure multiple words can be matched such as `/v2/polyfill.production.min.js`"

This reverts commit c25c34d5a58b0a002dca18c49afbe46a14ab3f3f.

sub set_backend {
	# Calculate the ideal region to route the request to.
	declare local var.region STRING;
	if (server.region ~ "(APAC|Asia|North-America|South-America|US-Central|US-East|US-West)") {
		set var.region = "US";
	} else {
		set var.region = "EU";
	}

	# Gather the health of the shields and origins.
	declare local var.v3_eu_is_healthy BOOL;
	set req.backend = F_v3_eu;
	set var.v3_eu_is_healthy = req.backend.healthy;

	declare local var.v3_us_is_healthy BOOL;
	set req.backend = F_v3_us;
	set var.v3_us_is_healthy = req.backend.healthy;

	# Set some sort of default, that shouldn't get used.
	set req.backend = F_v3_eu;

	# Route EU requests to the nearest healthy shield or origin.
	if (var.region == "EU") {
		if (var.v3_eu_is_healthy) {
			set req.backend = F_v3_eu;
		} elseif (var.v3_us_is_healthy) {
			set req.backend = F_v3_us;
		} else {
			# Everything is on fire... but lets try the origin anyway just in case
			# it's the probes that are wrong
			# set req.backend = F_origin_last_ditch_eu;
		}
	}

	# Route US requests to the nearest healthy shield or origin.
	if (var.region == "US") {
		if (var.v3_us_is_healthy) {
			set req.backend = F_v3_us;
		} elseif (var.v3_eu_is_healthy) {
			set req.backend = F_v3_eu;
		} else {
			# Everything is on fire... but lets try the origin anyway just in case
			# it's the probes that are wrong
			# set req.backend = F_origin_last_ditch_us;
		}
	}

	# Persist the decision so we can debug the result.
	set req.http.Debug-Backend = req.backend;

	# The Fastly macro is inserted after the backend is selected because the
	# macro has the code to select the correct req.http.Host value based on the backend.
	#FASTLY recv
}

sub vcl_recv {
	if (req.http.Fastly-Debug) {
		call breadcrumb_recv;
	}

	if (req.method != "GET" && req.method != "HEAD" && req.method != "OPTIONS" && req.method != "FASTLYPURGE" && req.method != "PURGE") {
		error 911;
	}

	if (req.method == "OPTIONS") {
		error 912;
	}

	# Because the old service had a router which allowed any words between /v2/polyfill. and .js
	if (req.url ~ "^/v2/polyfill(\.\w+)\.js") {
		set req.url = regsub(req.url, "^/v2/polyfill(\.\w+)\.js", "/v2/polyfill.min.js");
	}

	# Override the v3 defaults with the defaults of v2
	if (req.url ~ "^/v2/polyfill(\.min)?\.js") {
		set req.url = regsub(req.url, "^/v2", "/v3");
		set req.url = querystring.set(req.url, "version", "3.25.1");
		declare local var.unknown STRING;
		set var.unknown = subfield(req.url.qs, "unknown", "&");
		set req.url = querystring.set(req.url, "unknown", if(var.unknown != "", var.unknown, "ignore"));
	}

	if (req.url ~ "^/v3/polyfill(\.min)?\.js") {
		call normalise_querystring_parameters_for_polyfill_bundle;
	}

	# Sort the querystring parameters alphabetically to improve chances of hitting a cached copy.
	# If querystring is empty, remove the ? from the url.
	set req.url = querystring.clean(querystring.sort(req.url));
	call set_backend;
}

sub vcl_hash {
	if (req.http.Fastly-Debug) {
		call breadcrumb_hash;
	}

	# We are not adding req.http.host to the hash because we want https://cdn.polyfill.io and https://polyfill.io to be a single object in the cache.
	# set req.hash += req.http.host;
	set req.hash += req.url;
	# We include return(hash) to stop the function falling through to the default VCL built into varnish, which for vcl_hash will add req.url and req.http.Host to the hash.
	return(hash);
}

sub vcl_miss {
	if (req.http.Fastly-Debug) {
		call breadcrumb_miss;
	}
}

sub vcl_pass {
	if (req.http.Fastly-Debug) {
		call breadcrumb_pass;
	}
}

sub vcl_fetch {
	if (req.http.Fastly-Debug) {
		call breadcrumb_fetch;
	}

	# These header are only required for HTML documents.
	if (beresp.http.Content-Type ~ "text/html") {
		# Enables the cross-site scripting filter built into most modern web browsers.
		set beresp.http.X-XSS-Protection = "1; mode=block";
	}
	# Prevents MIME-sniffing a response away from the declared content type.
	set beresp.http.X-Content-Type-Options = "nosniff";

	# Ensure the site is only served over HTTPS and reduce the chances of someone performing a MITM attack.
	set beresp.http.Strict-Transport-Security = "max-age=31536000; includeSubdomains; preload";

	# The Referrer-Policy header governs which referrer information, sent in the Referer header, should be included with requests made.
	# Send a full URL when performing a same-origin request, but only send the origin of the document for other cases.
	set beresp.http.Referrer-Policy = "origin-when-cross-origin";

	# Enable purging of all objects in the Fastly cache by issuing a purge with the key "polyfill-service".
	if (beresp.http.Surrogate-Key !~ "\bpolyfill-service\b") {
		set beresp.http.Surrogate-Key = if(beresp.http.Surrogate-Key, beresp.http.Surrogate-Key " polyfill-service", "polyfill-service");
	}

	set beresp.http.Timing-Allow-Origin = "*";

	if (req.http.Normalized-User-Agent) {
		set beresp.http.Normalized-User-Agent = req.http.Normalized-User-Agent;
		set beresp.http.Detected-User-Agent = req.http.useragent_parser_family "/"  req.http.useragent_parser_major "." req.http.useragent_parser_minor "." req.http.useragent_parser_patch;
	}
}

sub vcl_deliver {
	if (req.http.Fastly-Debug) {
		call breadcrumb_deliver;
	}

	set req.http.Fastly-Force-Shield = "yes";

	# Allow cross origin GET, HEAD, and OPTIONS requests to be made.
	if (req.http.Origin) {
		set resp.http.Access-Control-Allow-Origin = "*";
		set resp.http.Access-Control-Allow-Methods = "GET,HEAD,OPTIONS";
	}

	if (req.url ~ "^/v3/polyfill(\.min)?\.js") {
		# Need to add "Vary: User-Agent" in after vcl_fetch to avoid the
		# "Vary: User-Agent" entering the Varnish cache.
		# We need "Vary: User-Agent" in the browser cache because a browser
		# may update itself to a version which needs different polyfills
		# So we need to have it ignore the browser cached bundle when the user-agent changes.
		add resp.http.Vary = "User-Agent";
		add resp.http.Vary = "Accept-Encoding";
	}

	add resp.http.Server-Timing = fastly_info.state {", fastly;desc="Edge time";dur="} time.elapsed.msec;

	if (req.http.Fastly-Debug) {
		set resp.http.Debug-Backend = req.http.Debug-Backend;
		set resp.http.Debug-Host = req.http.Host;
		set resp.http.Debug-Fastly-Restarts = req.restarts;
		set resp.http.Debug-Orig-URL = req.http.Orig-URL;
		set resp.http.Debug-VCL-Route = req.http.X-VCL-Route;
		set resp.http.useragent_parser_family = req.http.useragent_parser_family;
		set resp.http.useragent_parser_major = req.http.useragent_parser_major;
		set resp.http.useragent_parser_minor = req.http.useragent_parser_minor;
		set resp.http.useragent_parser_patch = req.http.useragent_parser_patch;
	} else {
		unset resp.http.Server;
		unset resp.http.Via;
		unset resp.http.X-Cache;
		unset resp.http.X-Cache-Hits;
		unset resp.http.X-Served-By;
		unset resp.http.X-Timer;
		unset resp.http.Fastly-Restarts;
	}
}

sub vcl_error {
	if (obj.status == 911) {
		set obj.status = 405;
		set obj.response = "METHOD NOT ALLOWED";
		set obj.http.Content-Type = "text/html; charset=UTF-8";
		set obj.http.Cache-Control = "private, no-store";
		synthetic req.method " METHOD NOT ALLOWED";
		return (deliver);
	}
	if (obj.status == 912) {
		set obj.status = 200;
		set obj.response = "OK";
		set obj.http.Allow = "OPTIONS, GET, HEAD";
		return (deliver);
	}
}

sub set_backend {
	# Calculate the ideal region to route the request to.
	declare local var.region STRING;
	if (server.region ~ "(APAC|Asia|North-America|South-America|US-Central|US-East|US-West)") {
		set var.region = "US";
	} else {
		set var.region = "EU";
	}

	# Gather the health of the shields and origins.
	declare local var.v3_eu_is_healthy BOOL;
	set req.backend = F_v3_eu;
	set var.v3_eu_is_healthy = req.backend.healthy;

	declare local var.v3_us_is_healthy BOOL;
	set req.backend = F_v3_us;
	set var.v3_us_is_healthy = req.backend.healthy;

	# Set some sort of default, that shouldn't get used.
	set req.backend = F_v3_eu;

	# Route EU requests to the nearest healthy shield or origin.
	if (var.region == "EU") {
		if (var.v3_eu_is_healthy) {
			set req.backend = F_v3_eu;
		} elseif (var.v3_us_is_healthy) {
			set req.backend = F_v3_us;
		} else {
			# Everything is on fire... but lets try the origin anyway just in case
			# it's the probes that are wrong
			# set req.backend = F_origin_last_ditch_eu;
		}
	}

	# Route US requests to the nearest healthy shield or origin.
	if (var.region == "US") {
		if (var.v3_us_is_healthy) {
			set req.backend = F_v3_us;
		} elseif (var.v3_eu_is_healthy) {
			set req.backend = F_v3_eu;
		} else {
			# Everything is on fire... but lets try the origin anyway just in case
			# it's the probes that are wrong
			# set req.backend = F_origin_last_ditch_us;
		}
	}

	# Persist the decision so we can debug the result.
	set req.http.Debug-Backend = req.backend;

	# The Fastly macro is inserted after the backend is selected because the
	# macro has the code to select the correct req.http.Host value based on the backend.
	#FASTLY recv
}

sub vcl_recv {
	if (req.http.Fastly-Debug) {
		call breadcrumb_recv;
	}

	if (req.method != "GET" && req.method != "HEAD" && req.method != "OPTIONS" && req.method != "FASTLYPURGE" && req.method != "PURGE") {
		error 911;
	}

	if (req.method == "OPTIONS") {
		error 912;
	}

	# Because the old service had a router which allowed any words between /v2/polyfill. and .js
	if (req.url ~ "^/v2/polyfill(\.\w+)+\.js") {
		set req.url = regsub(req.url, "^/v2/polyfill(\.\w+)\.js", "/v2/polyfill.min.js");
	}

	# Override the v3 defaults with the defaults of v2
	if (req.url ~ "^/v2/polyfill(\.min)?\.js") {
		set req.url = regsub(req.url, "^/v2", "/v3");
		set req.url = querystring.set(req.url, "version", "3.25.1");
		declare local var.unknown STRING;
		set var.unknown = subfield(req.url.qs, "unknown", "&");
		set req.url = querystring.set(req.url, "unknown", if(var.unknown != "", var.unknown, "ignore"));
	}

	if (req.url ~ "^/v3/polyfill(\.min)?\.js") {
		call normalise_querystring_parameters_for_polyfill_bundle;
	}

	# Sort the querystring parameters alphabetically to improve chances of hitting a cached copy.
	# If querystring is empty, remove the ? from the url.
	set req.url = querystring.clean(querystring.sort(req.url));
	call set_backend;
}

sub vcl_hash {
	if (req.http.Fastly-Debug) {
		call breadcrumb_hash;
	}

	# We are not adding req.http.host to the hash because we want https://cdn.polyfill.io and https://polyfill.io to be a single object in the cache.
	# set req.hash += req.http.host;
	set req.hash += req.url;
	# We include return(hash) to stop the function falling through to the default VCL built into varnish, which for vcl_hash will add req.url and req.http.Host to the hash.
	return(hash);
}

sub vcl_miss {
	if (req.http.Fastly-Debug) {
		call breadcrumb_miss;
	}
}

sub vcl_pass {
	if (req.http.Fastly-Debug) {
		call breadcrumb_pass;
	}
}

sub vcl_fetch {
	if (req.http.Fastly-Debug) {
		call breadcrumb_fetch;
	}

	# These header are only required for HTML documents.
	if (beresp.http.Content-Type ~ "text/html") {
		# Enables the cross-site scripting filter built into most modern web browsers.
		set beresp.http.X-XSS-Protection = "1; mode=block";
	}
	# Prevents MIME-sniffing a response away from the declared content type.
	set beresp.http.X-Content-Type-Options = "nosniff";

	# Ensure the site is only served over HTTPS and reduce the chances of someone performing a MITM attack.
	set beresp.http.Strict-Transport-Security = "max-age=31536000; includeSubdomains; preload";

	# The Referrer-Policy header governs which referrer information, sent in the Referer header, should be included with requests made.
	# Send a full URL when performing a same-origin request, but only send the origin of the document for other cases.
	set beresp.http.Referrer-Policy = "origin-when-cross-origin";

	# Enable purging of all objects in the Fastly cache by issuing a purge with the key "polyfill-service".
	if (beresp.http.Surrogate-Key !~ "\bpolyfill-service\b") {
		set beresp.http.Surrogate-Key = if(beresp.http.Surrogate-Key, beresp.http.Surrogate-Key " polyfill-service", "polyfill-service");
	}

	set beresp.http.Timing-Allow-Origin = "*";

	if (req.http.Normalized-User-Agent) {
		set beresp.http.Normalized-User-Agent = req.http.Normalized-User-Agent;
		set beresp.http.Detected-User-Agent = req.http.useragent_parser_family "/"  req.http.useragent_parser_major "." req.http.useragent_parser_minor "." req.http.useragent_parser_patch;
	}
}

sub vcl_deliver {
	if (req.http.Fastly-Debug) {
		call breadcrumb_deliver;
	}

	set req.http.Fastly-Force-Shield = "yes";

	# Allow cross origin GET, HEAD, and OPTIONS requests to be made.
	if (req.http.Origin) {
		set resp.http.Access-Control-Allow-Origin = "*";
		set resp.http.Access-Control-Allow-Methods = "GET,HEAD,OPTIONS";
	}

	if (req.url ~ "^/v3/polyfill(\.min)?\.js") {
		# Need to add "Vary: User-Agent" in after vcl_fetch to avoid the
		# "Vary: User-Agent" entering the Varnish cache.
		# We need "Vary: User-Agent" in the browser cache because a browser
		# may update itself to a version which needs different polyfills
		# So we need to have it ignore the browser cached bundle when the user-agent changes.
		add resp.http.Vary = "User-Agent";
		add resp.http.Vary = "Accept-Encoding";
	}

	add resp.http.Server-Timing = fastly_info.state {", fastly;desc="Edge time";dur="} time.elapsed.msec;

	if (req.http.Fastly-Debug) {
		set resp.http.Debug-Backend = req.http.Debug-Backend;
		set resp.http.Debug-Host = req.http.Host;
		set resp.http.Debug-Fastly-Restarts = req.restarts;
		set resp.http.Debug-Orig-URL = req.http.Orig-URL;
		set resp.http.Debug-VCL-Route = req.http.X-VCL-Route;
		set resp.http.useragent_parser_family = req.http.useragent_parser_family;
		set resp.http.useragent_parser_major = req.http.useragent_parser_major;
		set resp.http.useragent_parser_minor = req.http.useragent_parser_minor;
		set resp.http.useragent_parser_patch = req.http.useragent_parser_patch;
	} else {
		unset resp.http.Server;
		unset resp.http.Via;
		unset resp.http.X-Cache;
		unset resp.http.X-Cache-Hits;
		unset resp.http.X-Served-By;
		unset resp.http.X-Timer;
		unset resp.http.Fastly-Restarts;
	}
}

sub vcl_error {
	if (obj.status == 911) {
		set obj.status = 405;
		set obj.response = "METHOD NOT ALLOWED";
		set obj.http.Content-Type = "text/html; charset=UTF-8";
		set obj.http.Cache-Control = "private, no-store";
		synthetic req.method " METHOD NOT ALLOWED";
		return (deliver);
	}
	if (obj.status == 912) {
		set obj.status = 200;
		set obj.response = "OK";
		set obj.http.Allow = "OPTIONS, GET, HEAD";
		return (deliver);
	}
}


Comment explaining the suggested method of implement purge in the VCL

# This is a sample VCL configuration file for varnish running in front
# of Alaveteli.  See the vcl(7) man page for details on VCL syntax and
# semantics.

#
# Default backend definition.  Set this to point to your content
# server.  In this case, apache + Passenger running on port 80
#

backend default {
    .host = "127.0.0.1";
    .port = "80";
    .connect_timeout = 600s;
    .first_byte_timeout = 600s;
    .between_bytes_timeout = 600s;
}

// set the servers alaveteli can issue a purge from
acl purge {
   "localhost";
   "127.0.0.1";
}

sub vcl_recv {

   # Handle IPv6
   if (req.http.Host ~ "^ipv6.*") {
        set req.http.host = regsub(req.http.host, "^ipv6\.(.*)","www\.\1");
   }

    # Sanitise X-Forwarded-For...
    remove req.http.X-Forwarded-For;
    set req.http.X-Forwarded-For = client.ip;

    # Remove Google Analytics, has_js, and last-seen cookies
    set req.http.Cookie = regsuball(req.http.Cookie, "(^|;\s*)(__[a-z]+|has_js|has_seen_country_message|seen_foi2)=[^;]*", "");

    # Normalize the Accept-Encoding header
    if (req.http.Accept-Encoding) {
        if (req.url ~ "\.(jpg|jpeg|png|gif|gz|tgz|bz2|tbz|mp3|ogg|swf|flv|pdf|ico)$") {
            # No point in compressing these
            remove 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 {
            # unknown algorithm
            remove req.http.Accept-Encoding;
        }
    }

    # Ignore empty cookies
    if (req.http.Cookie ~ "^\s*$") {
        remove req.http.Cookie;
    }

    if (req.request != "GET" &&
       req.request != "HEAD" &&
       req.request != "POST" &&
       req.request != "PUT" &&
       req.request != "PURGE" &&
       req.request != "DELETE" ) {
        # We don't allow any other methods.
        error 405 "Method Not Allowed";
    }

    if (req.request != "GET" && req.request != "HEAD" && req.request != "PURGE") {
        /* We only deal with GET and HEAD by default, the rest get passed direct to backend */
        return (pass);
    }

    # Ignore Cookies on images...
    if (req.url ~ "\.(png|gif|jpg|jpeg|swf|css|js|rdf|ico|txt)(\?.*|)$") {
        remove req.http.Cookie;
        return (lookup);
    }

    if (req.http.Authorization || req.http.Cookie) {
        return (pass);
    }
    # Let's have a little grace
    set req.grace = 30s;
    # Handle PURGE requests
    if (req.request == "PURGE") {
      if (!client.ip ~ purge) {
         error 405 "Not allowed.";
      }

      # For an explanation of the followng roundabout way of defining
      # ban lists, see
      # http://kristianlyng.wordpress.com/2010/07/28/smart-bans-with-varnish/

      # XXX in Varnish 2.x, the following would be
      # purge("obj.http.x-url ~ " req.url);
      ban("obj.http.x-url ~ " + req.url);
      error 200 "Banned";
    }
    return (lookup);
}

sub vcl_fetch {
    set beresp.http.x-url = req.url;
    if (req.url ~ "\.(png|gif|jpg|jpeg|swf|css|js|rdf|ico|txt)(\?.*|)$") {
    # Ignore backend headers..
        remove beresp.http.set-Cookie;
        set beresp.ttl = 3600s;
        return (deliver);
    }

     if (beresp.status == 404 || beresp.status == 301 || beresp.status == 500) {
        set beresp.ttl = 1m;
        return (deliver);
    }
}

# This is a sample VCL configuration file for varnish running in front
# of Alaveteli.  See the vcl(7) man page for details on VCL syntax and
# semantics.

#
# Default backend definition.  Set this to point to your content
# server.  In this case, apache + Passenger running on port 80
#

backend default {
    .host = "127.0.0.1";
    .port = "80";
    .connect_timeout = 600s;
    .first_byte_timeout = 600s;
    .between_bytes_timeout = 600s;
}

// set the servers alaveteli can issue a purge from
acl purge {
   "localhost";
   "127.0.0.1";
}

sub vcl_recv {

   # Handle IPv6
   if (req.http.Host ~ "^ipv6.*") {
        set req.http.host = regsub(req.http.host, "^ipv6\.(.*)","www\.\1");
   }

    # Sanitise X-Forwarded-For...
    remove req.http.X-Forwarded-For;
    set req.http.X-Forwarded-For = client.ip;

    # Remove Google Analytics, has_js, and last-seen cookies
    set req.http.Cookie = regsuball(req.http.Cookie, "(^|;\s*)(__[a-z]+|has_js|has_seen_country_message|seen_foi2)=[^;]*", "");

    # Normalize the Accept-Encoding header
    if (req.http.Accept-Encoding) {
        if (req.url ~ "\.(jpg|jpeg|png|gif|gz|tgz|bz2|tbz|mp3|ogg|swf|flv|pdf|ico)$") {
            # No point in compressing these
            remove 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 {
            # unknown algorithm
            remove req.http.Accept-Encoding;
        }
    }

    # Ignore empty cookies
    if (req.http.Cookie ~ "^\s*$") {
        remove req.http.Cookie;
    }

    if (req.request != "GET" &&
       req.request != "HEAD" &&
       req.request != "POST" &&
       req.request != "PUT" &&
       req.request != "PURGE" &&
       req.request != "DELETE" ) {
        # We don't allow any other methods.
        error 405 "Method Not Allowed";
    }

    if (req.request != "GET" && req.request != "HEAD" && req.request != "PURGE") {
        /* We only deal with GET and HEAD by default, the rest get passed direct to backend */
        return (pass);
    }

    # Ignore Cookies on images...
    if (req.url ~ "\.(png|gif|jpg|jpeg|swf|css|js|rdf|ico|txt)(\?.*|)$") {
        remove req.http.Cookie;
        return (lookup);
    }

    if (req.http.Authorization || req.http.Cookie) {
        return (pass);
    }
    # Let's have a little grace
    set req.grace = 30s;
    # Handle PURGE requests
    if (req.request == "PURGE") {
      if (!client.ip ~ purge) {
         error 405 "Not allowed.";
      }
      # XXX in Varnish 2.x, the following would be
      # purge("obj.http.x-url ~ " req.url);
      ban("obj.http.x-url ~ " + req.url);
      error 200 "Banned";
    }
    return (lookup);
}

sub vcl_fetch {
    set beresp.http.x-url = req.url;
    if (req.url ~ "\.(png|gif|jpg|jpeg|swf|css|js|rdf|ico|txt)(\?.*|)$") {
    # Ignore backend headers..
        remove beresp.http.set-Cookie;
        set beresp.ttl = 3600s;
        return (deliver);
    }

     if (beresp.status == 404 || beresp.status == 301 || beresp.status == 500) {
        set beresp.ttl = 1m;
        return (deliver);
    }
}


use a single header to enable proxies such as ft.com-cdn to modify the header on their end (#1925)

sub set_backend {
	# The Fastly macro is inserted before the backend is selected because the
	# macro has the code which defines the values avaiable for req.http.Host
	# but it also contains a default backend which is always set to the EU. I wish we could disable the default backend setting.
	#FASTLY recv

	# Calculate the ideal region to route the request to.
  	declare local var.region STRING;
	if (server.region ~ "(APAC|Asia|North-America|South-America|US-Central|US-East|US-West)") {
		set var.region = "US";
  	} else {
		set var.region = "EU";
  	}

	# Gather the health of the shields and origins.
	declare local var.v3_eu_is_healthy BOOL;
	set req.backend = F_v3_eu;
	set var.v3_eu_is_healthy = req.backend.healthy;

	declare local var.v3_us_is_healthy BOOL;
  	set req.backend = F_v3_us;
  	set var.v3_us_is_healthy = req.backend.healthy;

  	declare local var.shield_eu_is_healthy BOOL;
  	set req.backend = ssl_shield_london_city_uk;
  	set var.shield_eu_is_healthy = req.backend.healthy;

  	declare local var.shield_us_is_healthy BOOL;
  	set req.backend = ssl_shield_iad_va_us;
  	set var.shield_us_is_healthy = req.backend.healthy;

  	# Set some sort of default, that shouldn't get used.
  	set req.backend = F_v3_eu;

	declare local var.EU_shield_server_name STRING;
	set var.EU_shield_server_name = "LCY";

	declare local var.US_shield_server_name STRING;
	set var.US_shield_server_name = "IAD";

	# Route EU requests to the nearest healthy shield or origin.
  	if (var.region == "EU") {
		if (server.datacenter != var.EU_shield_server_name && req.http.Request_Came_From_Shield != var.EU_shield_server_name && var.shield_eu_is_healthy) {
			set req.backend = ssl_shield_london_city_uk;
		} elseif (var.v3_eu_is_healthy) {
			set req.backend = F_v3_eu;
			set req.http.Host = req.http.EU_Host;
		} elseif (var.shield_us_is_healthy) {
			set req.backend = ssl_shield_iad_va_us;
		} elseif (var.v3_us_is_healthy) {
			set req.backend = F_v3_us;
			set req.http.Host = req.http.US_Host;
		} else {
			# Everything is on fire... but lets try the origin anyway just in case
			# it's the probes that are wrong
			# set req.backend = F_origin_last_ditch_eu;
		}
  	}

	# Route US requests to the nearest healthy shield or origin.
  	if (var.region == "US") {
		if (server.datacenter != var.US_shield_server_name && req.http.Request_Came_From_Shield != var.US_shield_server_name && var.shield_us_is_healthy) {
			set req.backend = ssl_shield_iad_va_us;
		} elseif (var.v3_us_is_healthy) {
			set req.backend = F_v3_us;
			set req.http.Host = req.http.US_Host;
		} elseif (var.shield_eu_is_healthy) {
			set req.backend = ssl_shield_london_city_uk;
		} elseif (var.v3_eu_is_healthy) {
			set req.backend = F_v3_eu;
			set req.http.Host = req.http.EU_Host;
		} else {
			# Everything is on fire... but lets try the origin anyway just in case
			# it's the probes that are wrong
			# set req.backend = F_origin_last_ditch_us;
		}
	}

	# Persist the decision so we can debug the result.
  	set req.http.Debug-Backend = req.backend;
}

sub vcl_recv {
	if (req.http.Fastly-Debug) {
		call breadcrumb_recv;
	}

	if (req.method != "GET" && req.method != "HEAD" && req.method != "OPTIONS" && req.method != "FASTLYPURGE" && req.method != "PURGE") {
		error 911;
	}

	if (req.method == "OPTIONS") {
		error 912;
	}

	# Because the old service had a router which allowed any words between /v2/polyfill. and .js
	if (req.url.path ~ "^/v2/polyfill(\.\w+)(\.\w+)?" && req.url.ext == "js") {
		if (re.group.2) {
			set req.url = "/v2/polyfill.min.js?" req.url.qs;
		} else {
			set req.url = "/v2/polyfill.js?" req.url.qs;
		}
	}

	# Override the v3 defaults with the defaults of v2
	if (req.url ~ "^/v2/polyfill(\.min)?\.js") {
		set req.url = regsub(req.url, "^/v2", "/v3");
		set req.url = querystring.set(req.url, "version", "3.25.1");
		declare local var.unknown STRING;
		set var.unknown = subfield(req.url.qs, "unknown", "&");
		set req.url = querystring.set(req.url, "unknown", if(var.unknown != "", var.unknown, "ignore"));
	}

	if (req.url ~ "^/v3/polyfill(\.min)?\.js") {
		call normalise_querystring_parameters_for_polyfill_bundle;
		# Sort the querystring parameters alphabetically to improve chances of hitting a cached copy.
		# If querystring is empty, remove the ? from the url.
		set req.url = querystring.clean(querystring.sort(req.url));
		call set_backend;
	} else {
		# The request is to an endpoint which doesn't use query parameters, let's remove them to increase our cache-hit-ratio
		set req.url = querystring.remove(req.url);
		call set_backend;
	}
}

sub vcl_hash {
	if (req.http.Fastly-Debug) {
		call breadcrumb_hash;
	}

	# We are not adding req.http.host to the hash because we want https://cdn.polyfill.io and https://polyfill.io to be a single object in the cache.
	# set req.hash += req.http.host;
	set req.hash += req.url;
	# We include return(hash) to stop the function falling through to the default VCL built into varnish, which for vcl_hash will add req.url and req.http.Host to the hash.
	return(hash);
}

sub shielding_header {
	if (req.backend == ssl_shield_iad_va_us) {
		set req.http.Request_Came_From_Shield = server.datacenter;
	} elsif (req.backend == ssl_shield_london_city_uk) {
		set req.http.Request_Came_From_Shield = server.datacenter;
	}
}

sub vcl_miss {
	if (req.http.Fastly-Debug) {
		call breadcrumb_miss;
	}
	call shielding_header;
}

sub vcl_pass {
	if (req.http.Fastly-Debug) {
		call breadcrumb_pass;
	}
	call shielding_header;
}

sub vcl_fetch {
	set beresp.http.Request_Came_From_Shield = req.http.Request_Came_From_Shield;
	if (req.http.Fastly-Debug) {
		call breadcrumb_fetch;
	}

	# These header are only required for HTML documents.
	if (beresp.http.Content-Type ~ "text/html") {
		# Enables the cross-site scripting filter built into most modern web browsers.
		set beresp.http.X-XSS-Protection = "1; mode=block";
	}
	# Prevents MIME-sniffing a response away from the declared content type.
	set beresp.http.X-Content-Type-Options = "nosniff";

	# Ensure the site is only served over HTTPS and reduce the chances of someone performing a MITM attack.
	set beresp.http.Strict-Transport-Security = "max-age=31536000; includeSubdomains; preload";

	# The Referrer-Policy header governs which referrer information, sent in the Referer header, should be included with requests made.
	# Send a full URL when performing a same-origin request, but only send the origin of the document for other cases.
	set beresp.http.Referrer-Policy = "origin-when-cross-origin";

	# Enable purging of all objects in the Fastly cache by issuing a purge with the key "polyfill-service".
	if (beresp.http.Surrogate-Key !~ "\bpolyfill-service\b") {
		set beresp.http.Surrogate-Key = if(beresp.http.Surrogate-Key, beresp.http.Surrogate-Key " polyfill-service", "polyfill-service");
	}

	set beresp.http.Timing-Allow-Origin = "*";

	if (req.http.Normalized-User-Agent) {
		set beresp.http.Normalized-User-Agent = req.http.Normalized-User-Agent;
		set beresp.http.Detected-User-Agent = req.http.useragent_parser_family "/"  req.http.useragent_parser_major "." req.http.useragent_parser_minor "." req.http.useragent_parser_patch;
	}
}

sub vcl_deliver {
	if (req.http.Fastly-Debug) {
		call breadcrumb_deliver;
	}

	set req.http.Fastly-Force-Shield = "yes";

	# Allow cross origin GET, HEAD, and OPTIONS requests to be made.
	if (req.http.Origin) {
		set resp.http.Access-Control-Allow-Origin = "*";
		set resp.http.Access-Control-Allow-Methods = "GET,HEAD,OPTIONS";
	}

	if (req.url ~ "^/v3/polyfill(\.min)?\.js" && !resp.http.Request_Came_From_Shield && req.backend != ssl_shield_iad_va_us && req.backend != ssl_shield_london_city_uk) {
		# Need to add "Vary: User-Agent" in after vcl_fetch to avoid the
		# "Vary: User-Agent" entering the Varnish cache.
		# We need "Vary: User-Agent" in the browser cache because a browser
		# may update itself to a version which needs different polyfills
		# So we need to have it ignore the browser cached bundle when the user-agent changes.
		set resp.http.Vary = "User-Agent, Accept-Encoding";
	}

	add resp.http.Server-Timing = fastly_info.state {", fastly;desc="Edge time";dur="} time.elapsed.msec;

	if (req.http.Fastly-Debug) {
		set resp.http.Debug-Backend = req.http.Debug-Backend;
		set resp.http.Debug-Host = req.http.Host;
		set resp.http.Debug-Fastly-Restarts = req.restarts;
		set resp.http.Debug-Orig-URL = req.http.Orig-URL;
		set resp.http.Debug-VCL-Route = req.http.X-VCL-Route;
		set resp.http.useragent_parser_family = req.http.useragent_parser_family;
		set resp.http.useragent_parser_major = req.http.useragent_parser_major;
		set resp.http.useragent_parser_minor = req.http.useragent_parser_minor;
		set resp.http.useragent_parser_patch = req.http.useragent_parser_patch;
	} else {
		unset resp.http.Server;
		unset resp.http.Via;
		unset resp.http.X-Cache;
		unset resp.http.X-Cache-Hits;
		unset resp.http.X-Served-By;
		unset resp.http.X-Timer;
		unset resp.http.Fastly-Restarts;
		unset resp.http.X-PreFetch-Pass;
		unset resp.http.X-PreFetch-Miss;
		unset resp.http.X-PostFetch;
	}
}

sub vcl_error {
	if (obj.status == 911) {
		set obj.status = 405;
		set obj.response = "METHOD NOT ALLOWED";
		set obj.http.Content-Type = "text/html; charset=UTF-8";
		set obj.http.Cache-Control = "private, no-store";
		synthetic req.method " METHOD NOT ALLOWED";
		return (deliver);
	}
	if (obj.status == 912) {
		set obj.status = 200;
		set obj.response = "OK";
		set obj.http.Allow = "OPTIONS, GET, HEAD";
		return (deliver);
	}
}

sub set_backend {
	# The Fastly macro is inserted before the backend is selected because the
	# macro has the code which defines the values avaiable for req.http.Host
	# but it also contains a default backend which is always set to the EU. I wish we could disable the default backend setting.
	#FASTLY recv

	# Calculate the ideal region to route the request to.
  	declare local var.region STRING;
	if (server.region ~ "(APAC|Asia|North-America|South-America|US-Central|US-East|US-West)") {
		set var.region = "US";
  	} else {
		set var.region = "EU";
  	}

	# Gather the health of the shields and origins.
	declare local var.v3_eu_is_healthy BOOL;
	set req.backend = F_v3_eu;
	set var.v3_eu_is_healthy = req.backend.healthy;

	declare local var.v3_us_is_healthy BOOL;
  	set req.backend = F_v3_us;
  	set var.v3_us_is_healthy = req.backend.healthy;

  	declare local var.shield_eu_is_healthy BOOL;
  	set req.backend = ssl_shield_london_city_uk;
  	set var.shield_eu_is_healthy = req.backend.healthy;

  	declare local var.shield_us_is_healthy BOOL;
  	set req.backend = ssl_shield_iad_va_us;
  	set var.shield_us_is_healthy = req.backend.healthy;

  	# Set some sort of default, that shouldn't get used.
  	set req.backend = F_v3_eu;

	declare local var.EU_shield_server_name STRING;
	set var.EU_shield_server_name = "LCY";

	declare local var.US_shield_server_name STRING;
	set var.US_shield_server_name = "IAD";

	# Route EU requests to the nearest healthy shield or origin.
  	if (var.region == "EU") {
		if (server.datacenter != var.EU_shield_server_name && req.http.Request_Came_From_Shield != var.EU_shield_server_name && var.shield_eu_is_healthy) {
			set req.backend = ssl_shield_london_city_uk;
		} elseif (var.v3_eu_is_healthy) {
			set req.backend = F_v3_eu;
			set req.http.Host = req.http.EU_Host;
		} elseif (var.shield_us_is_healthy) {
			set req.backend = ssl_shield_iad_va_us;
		} elseif (var.v3_us_is_healthy) {
			set req.backend = F_v3_us;
			set req.http.Host = req.http.US_Host;
		} else {
			# Everything is on fire... but lets try the origin anyway just in case
			# it's the probes that are wrong
			# set req.backend = F_origin_last_ditch_eu;
		}
  	}

	# Route US requests to the nearest healthy shield or origin.
  	if (var.region == "US") {
		if (server.datacenter != var.US_shield_server_name && req.http.Request_Came_From_Shield != var.US_shield_server_name && var.shield_us_is_healthy) {
			set req.backend = ssl_shield_iad_va_us;
		} elseif (var.v3_us_is_healthy) {
			set req.backend = F_v3_us;
			set req.http.Host = req.http.US_Host;
		} elseif (var.shield_eu_is_healthy) {
			set req.backend = ssl_shield_london_city_uk;
		} elseif (var.v3_eu_is_healthy) {
			set req.backend = F_v3_eu;
			set req.http.Host = req.http.EU_Host;
		} else {
			# Everything is on fire... but lets try the origin anyway just in case
			# it's the probes that are wrong
			# set req.backend = F_origin_last_ditch_us;
		}
	}

	# Persist the decision so we can debug the result.
  	set req.http.Debug-Backend = req.backend;
}

sub vcl_recv {
	if (req.http.Fastly-Debug) {
		call breadcrumb_recv;
	}

	if (req.method != "GET" && req.method != "HEAD" && req.method != "OPTIONS" && req.method != "FASTLYPURGE" && req.method != "PURGE") {
		error 911;
	}

	if (req.method == "OPTIONS") {
		error 912;
	}

	# Because the old service had a router which allowed any words between /v2/polyfill. and .js
	if (req.url.path ~ "^/v2/polyfill(\.\w+)(\.\w+)?" && req.url.ext == "js") {
		if (re.group.2) {
			set req.url = "/v2/polyfill.min.js?" req.url.qs;
		} else {
			set req.url = "/v2/polyfill.js?" req.url.qs;
		}
	}

	# Override the v3 defaults with the defaults of v2
	if (req.url ~ "^/v2/polyfill(\.min)?\.js") {
		set req.url = regsub(req.url, "^/v2", "/v3");
		set req.url = querystring.set(req.url, "version", "3.25.1");
		declare local var.unknown STRING;
		set var.unknown = subfield(req.url.qs, "unknown", "&");
		set req.url = querystring.set(req.url, "unknown", if(var.unknown != "", var.unknown, "ignore"));
	}

	if (req.url ~ "^/v3/polyfill(\.min)?\.js") {
		call normalise_querystring_parameters_for_polyfill_bundle;
		# Sort the querystring parameters alphabetically to improve chances of hitting a cached copy.
		# If querystring is empty, remove the ? from the url.
		set req.url = querystring.clean(querystring.sort(req.url));
		call set_backend;
	} else {
		# The request is to an endpoint which doesn't use query parameters, let's remove them to increase our cache-hit-ratio
		set req.url = querystring.remove(req.url);
		call set_backend;
	}
}

sub vcl_hash {
	if (req.http.Fastly-Debug) {
		call breadcrumb_hash;
	}

	# We are not adding req.http.host to the hash because we want https://cdn.polyfill.io and https://polyfill.io to be a single object in the cache.
	# set req.hash += req.http.host;
	set req.hash += req.url;
	# We include return(hash) to stop the function falling through to the default VCL built into varnish, which for vcl_hash will add req.url and req.http.Host to the hash.
	return(hash);
}

sub shielding_header {
	if (req.backend == ssl_shield_iad_va_us) {
		set req.http.Request_Came_From_Shield = server.datacenter;
	} elsif (req.backend == ssl_shield_london_city_uk) {
		set req.http.Request_Came_From_Shield = server.datacenter;
	}
}

sub vcl_miss {
	if (req.http.Fastly-Debug) {
		call breadcrumb_miss;
	}
	call shielding_header;
}

sub vcl_pass {
	if (req.http.Fastly-Debug) {
		call breadcrumb_pass;
	}
	call shielding_header;
}

sub vcl_fetch {
	set beresp.http.Request_Came_From_Shield = req.http.Request_Came_From_Shield;
	if (req.http.Fastly-Debug) {
		call breadcrumb_fetch;
	}

	# These header are only required for HTML documents.
	if (beresp.http.Content-Type ~ "text/html") {
		# Enables the cross-site scripting filter built into most modern web browsers.
		set beresp.http.X-XSS-Protection = "1; mode=block";
	}
	# Prevents MIME-sniffing a response away from the declared content type.
	set beresp.http.X-Content-Type-Options = "nosniff";

	# Ensure the site is only served over HTTPS and reduce the chances of someone performing a MITM attack.
	set beresp.http.Strict-Transport-Security = "max-age=31536000; includeSubdomains; preload";

	# The Referrer-Policy header governs which referrer information, sent in the Referer header, should be included with requests made.
	# Send a full URL when performing a same-origin request, but only send the origin of the document for other cases.
	set beresp.http.Referrer-Policy = "origin-when-cross-origin";

	# Enable purging of all objects in the Fastly cache by issuing a purge with the key "polyfill-service".
	if (beresp.http.Surrogate-Key !~ "\bpolyfill-service\b") {
		set beresp.http.Surrogate-Key = if(beresp.http.Surrogate-Key, beresp.http.Surrogate-Key " polyfill-service", "polyfill-service");
	}

	set beresp.http.Timing-Allow-Origin = "*";

	if (req.http.Normalized-User-Agent) {
		set beresp.http.Normalized-User-Agent = req.http.Normalized-User-Agent;
		set beresp.http.Detected-User-Agent = req.http.useragent_parser_family "/"  req.http.useragent_parser_major "." req.http.useragent_parser_minor "." req.http.useragent_parser_patch;
	}
}

sub vcl_deliver {
	if (req.http.Fastly-Debug) {
		call breadcrumb_deliver;
	}

	set req.http.Fastly-Force-Shield = "yes";

	# Allow cross origin GET, HEAD, and OPTIONS requests to be made.
	if (req.http.Origin) {
		set resp.http.Access-Control-Allow-Origin = "*";
		set resp.http.Access-Control-Allow-Methods = "GET,HEAD,OPTIONS";
	}

	if (req.url ~ "^/v3/polyfill(\.min)?\.js" && !resp.http.Request_Came_From_Shield && req.backend != ssl_shield_iad_va_us && req.backend != ssl_shield_london_city_uk) {
		# Need to add "Vary: User-Agent" in after vcl_fetch to avoid the
		# "Vary: User-Agent" entering the Varnish cache.
		# We need "Vary: User-Agent" in the browser cache because a browser
		# may update itself to a version which needs different polyfills
		# So we need to have it ignore the browser cached bundle when the user-agent changes.
		add resp.http.Vary = "User-Agent";
		add resp.http.Vary = "Accept-Encoding";
	}

	add resp.http.Server-Timing = fastly_info.state {", fastly;desc="Edge time";dur="} time.elapsed.msec;

	if (req.http.Fastly-Debug) {
		set resp.http.Debug-Backend = req.http.Debug-Backend;
		set resp.http.Debug-Host = req.http.Host;
		set resp.http.Debug-Fastly-Restarts = req.restarts;
		set resp.http.Debug-Orig-URL = req.http.Orig-URL;
		set resp.http.Debug-VCL-Route = req.http.X-VCL-Route;
		set resp.http.useragent_parser_family = req.http.useragent_parser_family;
		set resp.http.useragent_parser_major = req.http.useragent_parser_major;
		set resp.http.useragent_parser_minor = req.http.useragent_parser_minor;
		set resp.http.useragent_parser_patch = req.http.useragent_parser_patch;
	} else {
		unset resp.http.Server;
		unset resp.http.Via;
		unset resp.http.X-Cache;
		unset resp.http.X-Cache-Hits;
		unset resp.http.X-Served-By;
		unset resp.http.X-Timer;
		unset resp.http.Fastly-Restarts;
		unset resp.http.X-PreFetch-Pass;
		unset resp.http.X-PreFetch-Miss;
		unset resp.http.X-PostFetch;
	}
}

sub vcl_error {
	if (obj.status == 911) {
		set obj.status = 405;
		set obj.response = "METHOD NOT ALLOWED";
		set obj.http.Content-Type = "text/html; charset=UTF-8";
		set obj.http.Cache-Control = "private, no-store";
		synthetic req.method " METHOD NOT ALLOWED";
		return (deliver);
	}
	if (obj.status == 912) {
		set obj.status = 200;
		set obj.response = "OK";
		set obj.http.Allow = "OPTIONS, GET, HEAD";
		return (deliver);
	}
}