NOTE: This needs some organization work...
The certificate pricing and options are not laid out clearly. As of July 30, 2020:
“In addition to further clarify your concerns with pricing with Fastly TLS the first five domains are free. This could be a mix of apex domains and wildcards that add up to five. With the shared certificates if you purchase one for the wildcard for $275, the apex is included as well in that pricing. If you purchase the shared certificate for $100 this would include one domain.” - Marita
“Yes Fastly TLS does cover wildcard domains. Fastly TLS offers the frist 5 domains for free so both the apex domain and wildcard (assuming those are the only two domains) would be free.” - Ben
WARNING: The above "Free" (5 or less) certs exist as SAN on a shared cert, so there will be random other entries from other customers on the cert as well. No, there is NO CONTROL over what types of domains may appear there. Some may be offensive. This is the business risk associated with these "free" options.
You can programatically retrieve the SANs available on a cert with the following command:
domain='nike.com'
printf "Q" | openssl s_client -connect $domain:443 -servername $domain 2>&1 | \
openssl x509 -in /dev/stdin -text -noout -certopt \
no_header,no_version,no_serial,no_signame,no_validity,no_subject,no_issuer,no_pubkey,no_sigdump,no_aux 2>&1 | \
grep -o -P "DNS:.*" | sed 's/, /\n/g' | tr -d "DNS:"
Beyond the "free" option, you can purchase a $600/mo enterprise cert[31], or upload your own cert. Note that 3rd party certs must be uploaded via their ssl upload tool
- Always configure a shield.
- Select the shield location CLOSEST to your origin.
- POP traffic to your SHIELD traverses a private, low-latency network.
- Understand Request Collapsing & Hit-For-Pass
- This is a key desirable as it prevents surge traffic, such as that incurred when running campaigns, from overloading your backend.
- WARNING: Be cautious of disabling request collapsing by issuing a return(pass) from within vcl_recv.
- This is a key desirable as it prevents surge traffic, such as that incurred when running campaigns, from overloading your backend.
You can limit the connections a single Fastly cache server will make to a specific origin server.
Fastly's IO Service is SUPERIOR. It facilitates the dynamic use of IO against images by simply affixing the IO controls as query parameters on the resource URL. When compared to other CDNs such as Akamai, which require all "versions" of the asset to be created and uploaded piecemeal, it becomes a very attractive feature.
- Upload the max resolution that your product requires, and leverage IO controls to downsize/scale the asset.
- DO NOT upload pre-optimized images, but instead use high-quality assets, and rely on the 'quality' control to adjust as required.
NOTE: Purge all requests are logged in event logs. Key purge requests cannot be logged.
- Using PURGE ALL
- Not batching requests when forced to use PURGE ALL against a service.
- If a system would issue a purge-all request, then it MUST submit it to a queue which will collapse multiple requests for a given period.
The Fastly purge system is called Powderhorn, and leverages a bimodal multicast protocol propagate its messages across POPs.
Refs:
There's a good amount of activity that doesn't surface in Fastly service logs, including PURGE ALL events. Such events must be accessed via the web console, or via the Events API. If PURGE ALL Requests are required in the service logs, then they must retrieved and then forwarded into the service log collector.
There is no existing solution for this, but you'd want to use a Lambda for it.
See here (removed) for the scripts. This repository includes such treasures as:
- IP Whitelisting
- Image Optimization
- Two SEO Redirect Handling Options:
- strings (Handles special character encodings such as %20 and %3F)
- regex
- APEX redirects
- User Agent Parsing
- API Purge Logging
- Basic Authentication
- Setting 'Access-Control-Allow-Origin: yes' for allowed hosts only
- Sumologic Logging Configurations
- Plus field extraction rules
- Ready to go Main.vcl examples for:
- Web Server
- GraphQL
- DAM
- URL Facadeing
- Cloning a Service
- Adjusting Service Limits
Get the code here (removed), and see the Fiddle (removed) to run these query string manipulations. Uses:
- Busting Cache Busting
- Mitigating injection attacks
- Reducing URL sprawl
- Fastly will clone an entire service for you on demand. Include the service Name, ID, and Version to clone.
- Fastly /CAN/ adjust service limits for you, but will assess risk to their operations first.
- Domains per Service - Defaults to 20, but CAN be increased on request. Best reserved for non-prod services where evaluation counts will be lower.
Prior to launching a site, it is preferable to pre-warm the Fastly cache layer, which means at minimum crawling the sitemap.xml. Some considerations here are whether or not you use a shield, and whether or not you're in the same region as the target market. If you're launching a global site, with equally dispersed audience, you will be using a shield, no doubt, and crawling the sitemap would be the best that you could do. If you're launching a site for a specific region, you can pre-warm specific POPs in the area, which will mitigate misses, and the potential of your origin falling over. This is the use case for this script[48]. To accommodate the script, you will have to get the hostnames for the POPs in the region. AFAIK, unless you're in the region and can discover it via the diagnostics method below, you'll have to open a ticket with Fastly.
Curling Fastly services while setting the debug header enables the service to respond with additional debug info. See the doc for more details. https://docs.fastly.com/guides/debugging/checking-cache#using-a-fastly-debug-header-with-curl[49] Example:
curl -svo /dev/null -H "Fastly-Debug: true" www.fastly.com
Cache hosts, as indicated by the 'X-Served-By' header (minus the trailing '-XXX') all have the full hostname of .hosts.fastly.net.
[root@host ~]# curl -sSkIL 2>&1 | grep X-Served-By
X-Served-By: cache-mdw17353-MDW
[root@host ~]# nslookup cache-mdw17353.hosts.fastly.net[52]
Server: 10.98.4.75
Address: 10.98.4.75#53
Non-authoritative answer:
hosts.fastly.net[51] dname = hosts.secretcdn.net[53].
cache-mdw17353.hosts.fastly.net[52] canonical name = cache-mdw17353.hosts.secretcdn.net[54].
Name: _cache-mdw17353.hosts.secretcdn.net_
Address: 157.52.75.53# <<<<<< CACHE IP ADDRESS
Point of Presence = POP = 'X-Served-By' header value. This is useful for working with HIT/MISS, TTL, or content validation.
curl -svo /dev/null -H "Fastly-Debug: true" www.fastly.com -x .hosts.fastly.net:80
Example:
user@host:../~$ curl -sSkIL -H "Host: <[55]your domain>" https://*cache-mdw17346*.hosts.fastly.net/path/to/resource.foo
HTTP/1.1 200 OK
Content-Type: application/javascript; charset=UTF-8
Server: nginx/1.12.1
X-Powered-By: Express
X-Frame-Options: DENY
X-Content-Type-Options: nosniff
Last-Modified: Fri, 13 Sep 2019 19:41:57 GMT
ETag: W/"22c687-16d2c257d76"
Cache-Control: max-age=31536000, public
Expires: Thu, 17 Sep 2020 15:33:01 GMT
Content-Length: 2279047
Accept-Ranges: bytes
Date: Wed, 18 Sep 2019 15:33:02 GMT
Via: 1.1 varnish
Age: 2
Connection: keep-alive
X-Served-By: *cache-mdw17346-MDW*
X-Cache: MISS
X-Cache-Hits: 0
X-Timer: S1568820781.845812,VS0,VE1984
Vary: Accept-Encoding
Strict-Transport-Security: max-age=604800;includeSubDomains
Useful for seeing exactly what your request/response looks like when a POP communicates directly with the origin. NOTE: This flag is disabled by the Main.vlc's special treatment of POP assignment.
curl -svo /dev/null-H"Fastly-Debug: true"-H"Fastly-No-Shield: true" www.fastly.com
Disabling Shielding is useful when diagnosing Surrogate-Key issues.
[user@host ~]# curl -IH "Fastly-Debug: true" -H "Fastly-No-Shield: true" "<[56]URL>"
HTTP/1.1 200 OK
...
Surrogate-Key: inventory cart <userIdHash>
...
Via: 1.1 varnish
...
Fastly-Debug-Path: (D cache-chi21136-CHI 1568051322) (F cache-chi21136-CHI 1568051322) (D cache-lhr6334-LHR 1568051321) (F cache-lhr6334-LHR 1568051321)
Fastly-Debug-TTL: (M cache-chi21136-CHI - - 0) (M cache-lhr6334-LHR - - 0)
Fastly-Debug-Digest: 6bea4765138367ba1e560ae04625c6c563c0dbae8a8f6630ce4feb4fece1b1b1
X-Served-By: cache-lhr6334-LHR, cache-chi21136-CHI
X-Cache: Miss from cloudfront, MISS, MISS
X-Cache-Hits: 0, 0
X-Timer: S1568051321.314909,VS0,VE372
Here we can see that the Surrogate-Key header is being set.
Useful for testing GZIP.
[root@host ~]# curl -SkIL -H "Fastly-Debug: true" https://www.domain.com/ 2>&1 | grep Length
Content-Length: 1204847
[root@host ~]# curl -SkIL --compressed -H "Fastly-Debug: true" https://www.domain.com 2>&1 | grep Length
Content-Length: 99739
The --resolve flag forces CURL to use a custom IP for a given hostname and port. Useful for validating a service setup in Fastly without pointing DNS at it, or adjusting your /etc/hosts file. Note: Depends on the service being setup, AND the domain having been added to a shared or hosted cert in your Fastly account.
curl -SkIL --resolve 'www.domain.com:443:157.52.75.53' https://www.domain.com
You can verify IO functionality by running a curl with an IO triggering query string, as shown below. Do NOT include a username/password if you're hitting a PROD endpoint. See here for more on the Fastly-IO-Info header.
$ curl -svo /dev/null -H "Fastly-Debug: true" https://www.domain.com/uri/to/image.jpg?width=200
...< Fastly-Io-Info: ifsz=46994 idim=1600x1200 ifmt=png ofsz=1924 odim=200x150 ofmt=png
< Fastly-Stats: io=1
...
< Fastly-Debug-Path: (D cache-chi21131-CHI 1562183657) (F cache-chi21121-CHI 1562183657) (D cache-lhr6324-LHR 1562183657) (F cache-lhr6341-LHR 1562181547)< Fastly-Debug-TTL: (M cache-chi21131-CHI - - 2110) (H cache-lhr6324-LHR 84290.041 43200.000 2110)
< Fastly-Debug-Digest: 6207eadf45e601b507cda9778a57fe35df9db34084f419ec850c1bb2cc31bd54
< X-Served-By: cache-lhr6324-LHR, cache-chi21131-CHI
< X-Cache: HIT, MISS
< X-Cache-Hits: 2, 0
< X-Timer: S1562183657.983333,VS0,VE388
...
Save the following as fastly-io-bench.sh.
NOTE: The 'result' simply checks that there was no IO warning. This needs a bit more polish. cms.domain.com[58] is hardcoded. This was just a quick tool in a moment...
#!/usr/bin/env bash
env="$1"
endpoint="$2"
asset='/path/to/some/image.jpg'
title="IO Benchmark For: ${endpoint}"
printf"\n${title}"
printf'\n%*s'"$((${COLUMNS}-$((${COLUMNS}-$(wc -c<<<$title)+1))))"| tr' '-
origSize=$(curl -sI https://_cms.domain.com_${asset} 2>&1 | grep -i 'Content-Length' | awk '{print $2}' | tr -d '\r\n')
foriin50 100 200 400 600 800 1000 1200 1400 1600 1800 2000;do
result=pass
ts=$(date +%s%N)
curl -svo /dev/null-H"Fastly-Debug: true"${endpoint}${asset}?width=${i} 2>&1 | grep -q'Fastly-Io-Warning'&& result=fail
ioSize=$(curl -sI ${endpoint}${asset}?width=${i} 2>&1 | grep -i'Content-Length'| awk'{print $2}'| tr -d'\r\n')
tt=$((($(date +%s%N) - $ts)/1000000))
printf"\nIO (${i}px Wide) Total Time: $tt ms - $result - Original: ${origSize} B - Optimized: ${ioSize} B"
done
printf"\n"
Example Output:
user@host:../~$ ./fastlyIOBench.sh prod https://domain.com
IO Benchmark For: https://domain.com_
------------------------------------
IO (50px Wide) Total Time: 579 ms - pass - Original: 824072 B - Optimized: 1406 B
IO (100px Wide) Total Time: 588 ms - pass - Original: 824072 B - Optimized: 2001 B
IO (200px Wide) Total Time: 593 ms - pass - Original: 824072 B - Optimized: 3536 B
IO (400px Wide) Total Time: 583 ms - pass - Original: 824072 B - Optimized: 8558 B
IO (600px Wide) Total Time: 603 ms - pass - Original: 824072 B - Optimized: 15959 B
IO (800px Wide) Total Time: 621 ms - pass - Original: 824072 B - Optimized: 25169 B
IO (1000px Wide) Total Time: 679 ms - pass - Original: 824072 B - Optimized: 36694 B
IO (1200px Wide) Total Time: 1021 ms - pass - Original: 824072 B - Optimized: 51697 B
IO (1400px Wide) Total Time: 736 ms - pass - Original: 824072 B - Optimized: 67783 B
IO (1600px Wide) Total Time: 665 ms - pass - Original: 824072 B - Optimized: 85003 B
IO (1800px Wide) Total Time: 668 ms - pass - Original: 824072 B - Optimized: 103754 B
IO (2000px Wide) Total Time: 679 ms - pass - Original: 824072 B - Optimized: 123239 B
Cause & Resolution The Certificate hostname and SNI hostname are not aligned. Ensure they're aligned.
Install Pre-requisites
sudo yum -y install git-core zlib zlib-devel gcc-c++ patch readline readline-devel libyaml-devel libffi-devel openssl-devel make bzip2 autoconf automake libtool bison curl sqlite-devel
Install rbenv NOTE: This will issue an error due to 'rbenv' not existing within your PATH. Continue on.
curl -sL https://github.com/rbenv/rbenv-installer/raw/master/bin/rbenv-installer | bash -
Configure your ~/.bashrc file
echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bashrc
echo 'eval "$(rbenv init -)"' >> ~/.bashrc
source ~/.bashrc
Verify rbenv installation. The following should report that it is a function.
type rbenv
Setup Ruby using rbenv
rbenv install -l # list all avialable versions
rbenv install 2.7.0 # install version 2.7.0 (subsitute latest version)
rbenv global 2.7.0 # Use Ruby 2.7.0 globally (substitute latest version)
rbenv versions # see installed versions
Install FastlyCTL
gem install fastlyctl
Some useful commands
Login
fastlyctl login
Watch stats on a service
fastlyctl watch --s <serviceId>
Download service configuration NOTE: This is required to work with a service
fastlyctl download --s <serviceId>
Create 5 blank services
for i in {1..5}; do fastlyctl create_service "Market_Blank-$i" ; done
Clone the config from a template service to the five blanks created above
svc=1; for i in <serviceId1> <serviceId2> <serviceId3> <serviceId4> <serviceId5>; do fastlyctl clone --v 6 <templateServiceId> $i; fastlyctl domain --s $i create blank${svc}.foo.com; (( svc++ )) ; fastlyctl activate --s $i ; done
# Name : seo_redirect-GENERIC-1-of-3_recv.vcl
# Subroutine : init
# Priority : 100
#
# NOTE: Name 1-of-3 to qualify that suite of redirects if desired.
# For example you may have different snippets for different properties/cammppaigns/etc.
# 2-of-3, and 3-of-3 will catch all redirects from all snippets generated from the 1-of-3 template.
#
# REQUIRES:
# - All THREE redirect snippets
# - 1-of-3 CUSTOMIZED snippet with your redirects
# - 2-of-3 GENERIC
# - 3-of-3 GENERIC
table seo_redirects {
"/source1": "/dest1",
"/source2": "/dest2"
}
# Name : seo_redirect_<CC>-1-of-2.vcl
# Subroutine : vcl_recv
# Priorty : 0
#
# REQUIRES:
# - All THREE redirect snippets
if (table.lookup(seo_redirects, req.url.path)) {
error 799 "redirect";
}
# Name : seo_redirect_<CC>-2-of-2.vcl
# Subroutine : vcl_error
# Priority : 100
#
# REQUIRES:
# - All THREE redirect snippets
if (obj.status == 799 && obj.response == "redirect") {
set obj.status = 302;
set obj.response = "Moved Temporarily";
set obj.http.Location = "https://" + req.http.host + table.lookup(seo_redirects, req.url.path) + if(req.url.qs != "", "?" + req.url.qs, "");
return (deliver);
}
# Name : seo_redirect_REGEX_1-of-2.vcl
# Subroutine : vcl_recv
# Priorty : 0
#
# REQUIRES:
# - BOTH redirect snippets
#
# FASTLY REGEX REFERENCE:
# https://docs.fastly.com/en/guides/vcl-regular-expression-cheat-sheet
if (req.url ~ "^/to/be/redirected/") {
error 799 "redirect example 1";
} else if (req.url ~ "foo_(\d+)\.(\d+)") {
error 799 "redirect example 2";
}
# Name : seo_redirect_REGEX-2-of-2.vcl
# Subroutine : vcl_error
# Priority : 100
#
# REQUIRES:
# - Both REGEX redirect snippets
if (obj.status == 799 && obj.response == "redirect example 1") {
set req.url = "/redirected-1/" + if(req.url.qs != "", "?" + req.url.qs, "");
} else if (obj.status == 799 && obj.response == "redirect example 2") {
set req.url = "/redirected-2" + if(req.url.qs != "", "?" + req.url.qs, "");
}
if (obj.status == 799) {
set obj.status = 302;
set obj.response = "Moved Temporarily";
set obj.http.Location = "https://" + req.http.host + req.url;
return (deliver);
}
# SEO & other uses:
# - include 3rd party resources under own domain
# - mask ads/trackers from blockers (source based)
# - facilitate multiple url based origins
# Name : url_facades.vcl
# Description : Serve a resource from a different url
# Subrouteine : vcl_recv
# Priority : 100
if (req.url == "/foo") {
set req.url = "/content/dam/foo.jpg";
} else if (req.url == "/bar") {
set req.url = "/content/dam/bar.jpg";
}
if (req.url == "/googlebasdf.html") {
set req.url = "/content/dam/sitename/gsc/googlebasdf.html";
}
#!/usr/bin/env bash
# the_purge.sh
# ------------
# NOTE: Sleeps for 15 seconds to mitigate origin overload
#
service_urls=(
https://serviceurl.com
)
echo -e "\nNOTE: This script purges alphabetically."
for i in ${service_urls[@]}; do
echo -e "\nPurging: $i..."
curl -sS -X PURGE -H Fastly-Key:${api_key} $i
echo -e "Sleeping for 15s..."
sleep 15
done
#!/usr/bin/env bash
# fastly_io_bench.sh
# ./fastly_io_bench.sh prod www.prod.foo.com
# Update CMS Backend below to enable the script to get the original file
env="$1"
endpoint="$2"
asset='/content/dam/some/image/file.jpg'
title="IO Benchmark For: ${endpoint}"
printf "\n${title}"
printf '\n%*s' "$((${COLUMNS}-$((${COLUMNS}-$(wc -c<<<$title)+1))))" | tr ' ' -
origSize=$(curl -sI https://cms.${env}.backend.com${asset} 2>&1 | grep -i 'Content-Length' | awk '{print $2}' | tr -d '\r\n')
for i in 50 100 200 400 600 800 1000 1200 1400 1600 1800 2000; do
result=pass
ts=$(date +%s%N)
curl -svo /dev/null -H "Fastly-Debug: true" ${endpoint}${asset}?width=${i} 2>&1 | grep -q 'Fastly-Io-Warning' && result=fail
ioSize=$(curl -sI ${endpoint}${asset}?width=${i} 2>&1 | grep -i 'Content-Length' | awk '{print $2}' | tr -d '\r\n')
tt=$((($(date +%s%N) - $ts)/1000000))
printf "\nIO (${i}px Wide) Total Time: $tt ms - $result - Original: ${origSize} B - Optimized: ${ioSize} B"
done
printf "\n"
#!/usr/bin/env bash
# warm-fastly-cache.sh
# --------------------------------------------------------------------------------------------------
# HELP
# --------------------------------------------------------------------------------------------------
help="\
NAME
warm-fastly-cache.sh
SYNOPSIS
${0##*/} [-h] [-d \e[04mdomain\e[0m] [-c \e[04mcache\e[0m>
DESCRIPTION
Crawls the sitemap.xml of the specified domain against the specified cache.
-h Print this menu.
-d \e[04mdomain\e[0m
Specify the domain to crawl. The script will automatically parse the sitemap.xml
located at the root of the domain. (<loc></loc>)
-c \e[04mcache\e[0m
Specify the fastly cache to warm.
Example: cache12345.hosts.fastly.net
See here for more on discovering cache hosts:
https://confluence.criticalmass.com/display/GT/Fastly#Fastly-CacheHosts
EXAMPLES
./warm-fastly-cache.sh -d www.domain.com -c cache-mdw17353.hosts.fastly.net
"
printHelp() {
echo -e "$help" >&2
}
if [[ "$1" == '-h' ]]; then
printHelp
exit 1
fi
# --------------------------------------------------------------------------------------------------
# ARGUMENTS
# --------------------------------------------------------------------------------------------------
OPTIND=1
while getopts "hd:c:" opt; do
case $opt in
h)
printHelp
exit 0
;;
d)
arg_d='set'
arg_d_val="$OPTARG"
;;
c)
arg_c='set'
arg_c_val="$OPTARG"
;;
*)
echo -e "\e[01;31mERROR\e[00m: Invalid argument!"
printHelp
exit 1
;;
esac
done
shift $((OPTIND-1))
# --------------------------------------------------------------------------------------------------
# SANITY
# --------------------------------------------------------------------------------------------------
if ! dig +noall +answer $arg_d_val | grep -v -e '^$' >/dev/null 2>&1; then
echo -e "\e[01;31mERROR\e[00m: Specified domain does not exist!\n"
exit 1
fi
if ! grep -q '<loc>.*</loc>' sitemap.xml; then
echo -e "\e[01;31mERROR\e[00m: sitemap.xml does NOT contain <loc></loc> child entries to parse!\n"
exit 1
fi
# --------------------------------------------------------------------------------------------------
# VARS
# --------------------------------------------------------------------------------------------------
host="$arg_d_val"
cache="$arg_c_val"
urls=$(curl -sS https://${host}/sitemap.xml | grep -o -P '(?<=<loc>).*?(?=</loc>)' | sed "s/https:\/\/${host}//g")
urlCount=$(wc -w <<< $urls)
warmCount=0
# --------------------------------------------------------------------------------------------------
# MAIN OPERATIONS
# --------------------------------------------------------------------------------------------------
echo -e "\n\nWARMING: ${host} on Fastly POP ${cache}..."
# WARM CACHE -- SILENT
for url in $urls; do
curl -sSk -o /dev/null --max-time 0.25 -H "Host: ${host}" https://${cache}${url} > /dev/null 2>&1
done
# VERIFY CACHE WARMTH
for url in $urls; do
responseCode=$(curl -sSkIf -o /dev/null -w "%{http_code}" -H "Host: ${host}" https://${cache}${url})
if [[ "$responseCode" =~ 200|301 ]]; then
((warmCount++))
else
echo "ERROR: $responseCode - $url"
fi
done
echo -e "\nURLS: ${urlCount}"
echo -e "WARM: $warmCount"
echo -e "\n"
curl -svo /dev/null -H "Fastly-Debug: true" https://www.fastly.com
[root@host ~]# curl -SkIL https://www.fastly.com 2>&1 | grep X-Served-By
X-Served-By: cache-sjc3147-SJC, cache-mdw17370-MDW
[root@host ~]# nslookup cache-mdw17364.hosts.fastly.net
Server: 10.98.4.75
Address: 10.98.4.75#53
Non-authoritative answer:
hosts.fastly.net dname = hosts.secretcdn.net.
cache-mdw17364.hosts.fastly.net canonical name = cache-mdw17364.hosts.secretcdn.net.
Name: cache-mdw17364.hosts.secretcdn.net
Address: 157.52.75.64 # <<<<<<<<<<<<<<< The Cache Server IP
CACHE SERVER NAMES == "x-served-by: cache-mdw17346-MDW" MINUS the trailing -XXX ie: cache-mdw17346 FQDN: cache-mdw17346.hosts.fastly.net
curl -svo /dev/null -H "Fastly-Debug: true" www.fastly.com -x <cache-node>.hosts.fastly.net:80
user@host:../~$ curl -sSkIL -H "Host: www.fastly.com" https://cache-mdw17346.hosts.fastly.net/js/main.bundle.adf89c82d7525cd029b8.js
curl -svo /dev/null -H "Fastly-Debug: true" -H "Fastly-No-Shield: true" www.fastly.com
[root@host ~]# curl -SkIL --compressed https://www.fastly.com 2>&1 | grep Length
Content-Length: 11527
[root@host ~]# curl -SkIL https://www.fastly.com 2>&1 | grep Length
Content-Length: 50187
curl -SkIL -H "Fastly-Debug: true" https://www.fastly.com/assets/io/1-95dedb9c9cbad11892a73a34c42611d85270c0499d5abdb191e393b84ed19f38.jpg?width=400
if (req.method == "FASTLYPURGE") {
log {"syslog "} req.service_id {" Sumologic :: "} "[" strftime({"%d/%b/%Y:%H:%M:%S %z"}, time.start) "] " req.request " - URL: " json.escape(req.url) ", Client IP: " req.http.Fastly-Client-IP;
}
- https://docs.fastly.com/guides/streaming-logs/custom-log-formats
- https://docs.fastly.com/guides/streaming-logs/useful-variables-to-log
%h %l %u %t %A %{Fastly-Orig-Host}i %{Host}i "%r" %{regsub(fastly_info.state, "^(HIT-(SYNTH)|(HITPASS|HIT|MISS|PASS|ERROR|PIPE)).*", "\\2\\3") }V %>s %b
set req.http.X-Shield = "0"; if (req.http.fastly-ff) { set req.http.X-Shield = "1"; }
log {"syslog xxxxx logging-endpoint :: "}
{" client_ip="} req.http.Fastly-Client-IP
{" timestamp="} now.sec
{" reqmethod="} req.request
{" host="} req.http.host
{" url="} {"""}req.url{"""}
{" contenttype="} resp.http.content-type
{" status="} resp.status
{" response="} {"""}resp.response{"""}
{" infostate="} fastly_info.state
{" age="} resp.http.age
{" setcookie="} {"""}resp.http.Set-Cookie{"""}
{" size="} resp.bytes_written
{" pop="} server.datacenter
{" shield="} req.http.x-shield
{" fastlyregion="} server.region
{" clientcontinent="} geoip.continent_code
{" clientcountry="} geoip.country_code
{" clientregion="} geoip.region
{" referrer="} {"""}req.http.referer{"""}
{" useragent="} req.http.Orig-User-Agent
{" hits="} obj.hits
{" restarts="} req.restarts
{" elapsed="} time.elapsed.msec
{" ttl="} obj.ttl
{" grace="} obj.grace;
{" serving stale content="} fastly_info.state;
See here for more: https://docs.fastly.com/guides/performance-tuning/shielding
Use req.http.fastly-ff to test if the node is in a shield POP. If it's set the request has passed through another POP already.
Example:
# Rewrite req.url when hitting a specific backend.
sub vcl_miss { if (req.backend == F_special_origin) { set bereq.url = regsub(bereq.url, "^/p/special/", "/"); } }