-
Notifications
You must be signed in to change notification settings - Fork 123
/
Copy pathrecv.vcl
180 lines (161 loc) · 7.99 KB
/
recv.vcl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
# Don't allow clients to force a pass, mess with rate limiting or admin path
if (req.restarts == 0) {
unset req.http.x-pass;
unset req.http.Rate-Limit;
unset req.http.magento-admin-path;
}
unset req.http.x-long-cache;
# When using Magento tester to test whether your site is configured properly
# this uses a bypass secret. By default we will use service ID as the bypass secret
# however user can override this by defining a bypass_secret key in the
# magentomodule_config edge dictionary
if ( req.http.bypass-secret ) {
declare local var.bypass-secret STRING;
set var.bypass-secret = table.lookup(magentomodule_config, "bypass_secret", "NONE");
if ( var.bypass-secret == req.http.bypass-secret ) {
set req.http.x-pass = "1";
set var.fastly_req_do_shield = false;
set req.hash_always_miss = true;
set req.esi = false;
} else if ( var.bypass-secret == "NONE" && req.http.bypass-secret == req.service_id ) {
set req.http.x-pass = "1";
set var.fastly_req_do_shield = false;
set req.hash_always_miss = true;
set req.esi = false;
} else {
error 403 "Bypass Secret incorrect";
}
if (req.url == "/fastly-io-tester") {
# IO won't work for PASS requests
unset req.http.x-pass;
# IO requires shielding
set var.fastly_req_do_shield = true;
set req.hash_always_miss = true;
set req.http.X-Fastly-Imageopto-Api = "fastly";
}
}
# VCL required to support maintenance mode. Don't maintenance mode admin pages and supporting assets
if (table.lookup(magentomodule_config, "allow_super_users_during_maint", "0") == "1" &&
!req.http.Fastly-Client-Ip ~ maint_allowlist &&
!req.url ~ "^/(index\.php/)?####ADMIN_PATH####/" &&
!req.url ~ "^/pub/(static|errors?)/") {
# If we end up here after a restart and there is a ResponseObject it means we got here after error
# page VCL restart. We shouldn't touch it. Otherwise return a plain 503 error page
if ( req.restarts > 0 && req.http.ResponseObject ) {
set req.http.ResponseObject = "970";
} else {
error 503 "Maintenance mode";
}
}
# We want to force long cache times on any of the versioned assets
if (req.url.path ~ "^/static/version\d*/") {
set req.http.x-long-cache = "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;
}
# User's store cookie also needs to be varied upon
if (req.http.cookie:store) {
set req.http.X-Store-Cookie = req.http.cookie:store;
} else {
unset req.http.X-Store-Cookie;
}
############################################################################################################
# Following code block controls purge by URL. By default we want to protect all URL purges. In general this
# is addressed by adding Fastly-Purge-Requires-Auth request header in vcl_recv however this runs the risk of
# exposing API tokens if user attempts to purge non-https URLs. For this reason inside the Magento module
# we use X-Purge-Token. Unfortunately this breaks purge from the Fastly UI. Therefore in the next code block
# we check for presence of X-Purge-Token. If it's not present we force the Fastly-Purge-Requires-Auth
if (req.request == "FASTLYPURGE") {
# extract token signature and expiration
if (req.http.X-Purge-Token && req.http.X-Purge-Token ~ "^([^_]+)_(.*)" ) {
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;
}
} else {
set req.http.Fastly-Purge-Requires-Auth = "1";
}
}
# set HTTPS header for offloaded TLS
if (req.http.Fastly-SSL) {
set req.http.Https = "on";
}
# Add support for Brotli static compression
if (req.http.Fastly-Orig-Accept-Encoding) {
if (req.http.Fastly-Orig-Accept-Encoding ~ "\bbr\b") {
set req.http.Accept-Encoding = "br";
}
}
if (fastly.ff.visits_this_service > 0) {
# 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;
}
# Make sure we lookup end user geo not shielding. More at https://docs.fastly.com/vcl/geolocation/#using-geographic-variables-with-shielding
set client.geo.ip_override = req.http.Fastly-Client-IP;
if ((req.request == "GET" || req.request == "HEAD") && req.url.path ~ "/graphql" && req.url.qs ~ "query=") {
set req.http.graphql = "1";
} else {
unset req.http.graphql;
}
# geoip lookup
if (req.url.path ~ "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 || req.http.cookie:fastly_geo_store) {
error 980 "GeoIP already processed";
} else {
# append parameter with country code only if it doesn't exist already
if ( req.url.qs !~ "country_code=" ) {
set req.url = querystring.set(req.url, "country_code", if ( req.http.geo_override, req.http.geo_override, client.geo.country_code));
}
}
} else if ( req.url.path !~ "/graphql" ) {
# Per suggestions in https://github.com/sdinteractive/SomethingDigital_PageCacheParams
# we'll strip out query parameters used in Google AdWords, Mailchimp tracking by default
# and allow custom parameters to be set. List of parameters is configurable in admin
set req.http.Magento-Original-URL = req.url;
# Change the list of ignored parameters by configuring them in the Advanced section
set req.url = querystring.regfilter(req.url, {"^(####QUERY_PARAMETERS####)$"});
}
# 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.http.x-long-cache && req.url ~ "/(checkout|customer/section/load)") {
set req.http.x-pass = "1";
# Pass all admin actions
# ####ADMIN_PATH#### is replaced with value of frontName from app/etc/env.php
} else if ( req.url ~ "^/(index\.php/)?####ADMIN_PATH####/" ) {
set req.http.x-pass = "1";
set req.http.magento-admin-path = "1";
} else {
# Sort the query arguments to increase cache hit ratio with query arguments that
# may be out od order. In case you want to restore the unsorted URL add a snippet
# after this one that sets req.url to req.http.Magento-Original-URL
if ( !req.http.x-pass ) {
set req.url = boltsort.sort(req.url);
}
}
# static files are always cacheable. remove SSL flag and cookie
if (req.http.x-long-cache || req.url ~ "^/(pub/)?(media|static)/.*") {
unset req.http.Https;
unset req.http.Cookie;
}
# GraphQL special headers handling because this area doesn't rely on X-Magento-Vary cookie
if (req.http.graphql && !req.http.X-Magento-Cache-Id && req.http.Authorization ~ "^Bearer" ) {
unset req.http.graphql;
set req.http.x-pass = "1";
}