Skip to content

Commit 121aeaf

Browse files
committed
Update default.vcl
1 parent 6964a05 commit 121aeaf

File tree

1 file changed

+77
-146
lines changed

1 file changed

+77
-146
lines changed

varnish/default.vcl

Lines changed: 77 additions & 146 deletions
Original file line numberDiff line numberDiff line change
@@ -16,37 +16,55 @@ acl purge {
1616
"::1";
1717
}
1818

19-
sub vcl_recv {
19+
sub vcl_recv {
20+
# Announce support for Edge Side Includes by setting the Surrogate-Capability header
21+
set req.http.Surrogate-Capability = "Varnish=ESI/1.0";
22+
2023
# Remove empty query string parameters
21-
# e.g.: www.example.com/index.html?
24+
# e.g.: www.example.com/index.html?
2225
if (req.url ~ "\?$") {
2326
set req.url = regsub(req.url, "\?$", "");
2427
}
2528

2629
# Remove port number from host header
2730
set req.http.Host = regsub(req.http.Host, ":[0-9]+", "");
28-
29-
# Sorts query string parameters alphabetically for cache normalization purposes
31+
32+
# Sorts query string parameters alphabetically for cache normalization purposes.
3033
set req.url = std.querysort(req.url);
31-
34+
3235
# Remove the proxy header to mitigate the httpoxy vulnerability
33-
# See https://httpoxy.org/
36+
# See https://httpoxy.org/
3437
unset req.http.proxy;
35-
36-
# Purge logic to remove objects from the cache.
37-
# Tailored to the Proxy Cache Purge
38-
if(req.method == "PURGE") {
38+
39+
# Add X-Forwarded-Proto header when using https
40+
if (!req.http.X-Forwarded-Proto && (std.port(server.ip) == 443)) {
41+
set req.http.X-Forwarded-Proto = "https";
42+
}
43+
44+
# Ban logic to remove multiple objects from the cache at once. Tailored to Drupal's cache invalidation mechanism
45+
if(req.method == "BAN") {
3946
if(!client.ip ~ purge) {
40-
return(synth(405,"PURGE not allowed for this IP address"));
47+
return(synth(405, "BAN not allowed for this IP address"));
48+
}
49+
50+
if (req.http.Purge-Cache-Tags) {
51+
ban("obj.http.Purge-Cache-Tags ~ " + req.http.Purge-Cache-Tags);
4152
}
42-
if (req.http.X-Purge-Method == "regex") {
53+
else {
4354
ban("obj.http.x-url ~ " + req.url + " && obj.http.x-host == " + req.http.host);
44-
return(synth(200, "Purged"));
4555
}
46-
ban("obj.http.x-url == " + req.url + " && obj.http.x-host == " + req.http.host);
47-
return(synth(200, "Purged"));
56+
57+
return (synth(200, "Ban added."));
4858
}
4959

60+
# Purge logic to remove objects from the cache
61+
if(req.method == "PURGE") {
62+
if(!client.ip ~ purge) {
63+
return(synth(405,"PURGE not allowed for this IP address"));
64+
}
65+
return (purge);
66+
}
67+
5068
# Only handle relevant HTTP request methods
5169
if (
5270
req.method != "GET" &&
@@ -60,7 +78,7 @@ sub vcl_recv {
6078
) {
6179
return (pipe);
6280
}
63-
81+
6482
# Remove tracking query string parameters used by analytics tools
6583
if (req.url ~ "(\?|&)(utm_source|utm_medium|utm_campaign|utm_content|gclid|cx|ie|cof|siteurl)=") {
6684
set req.url = regsuball(req.url, "&(utm_source|utm_medium|utm_campaign|utm_content|gclid|cx|ie|cof|siteurl)=([A-z0-9_\-\.%25]+)", "");
@@ -70,8 +88,7 @@ sub vcl_recv {
7088
}
7189

7290
# Only cache GET and HEAD requests
73-
if (req.method != "GET" && req.method != "HEAD") {
74-
set req.http.X-Cacheable = "NO:REQUEST-METHOD";
91+
if ((req.method != "GET" && req.method != "HEAD") || req.http.Authorization) {
7592
return(pass);
7693
}
7794

@@ -83,158 +100,72 @@ sub vcl_recv {
83100
return(hash);
84101
}
85102

86-
# No caching of special URLs, logged in users and some plugins
87-
if (
88-
req.http.Cookie ~ "wordpress_(?!test_)[a-zA-Z0-9_]+|wp-postpass|comment_author_[a-zA-Z0-9_]+|woocommerce_cart_hash|woocommerce_items_in_cart|wp_woocommerce_session_[a-zA-Z0-9]+|wordpress_logged_in_|comment_author|PHPSESSID" ||
89-
req.http.Authorization ||
90-
req.url ~ "add_to_cart" ||
91-
req.url ~ "edd_action" ||
92-
req.url ~ "nocache" ||
93-
req.url ~ "^/addons" ||
94-
req.url ~ "^/bb-admin" ||
95-
req.url ~ "^/bb-login.php" ||
96-
req.url ~ "^/bb-reset-password.php" ||
97-
req.url ~ "^/cart" ||
98-
req.url ~ "^/checkout" ||
99-
req.url ~ "^/control.php" ||
100-
req.url ~ "^/login" ||
101-
req.url ~ "^/logout" ||
102-
req.url ~ "^/lost-password" ||
103-
req.url ~ "^/my-account" ||
104-
req.url ~ "^/product" ||
105-
req.url ~ "^/register" ||
106-
req.url ~ "^/register.php" ||
107-
req.url ~ "^/server-status" ||
108-
req.url ~ "^/signin" ||
109-
req.url ~ "^/signup" ||
110-
req.url ~ "^/stats" ||
111-
req.url ~ "^/wc-api" ||
112-
req.url ~ "^/wp-admin" ||
113-
req.url ~ "^/wp-comments-post.php" ||
114-
req.url ~ "^/wp-cron.php" ||
115-
req.url ~ "^/wp-login.php" ||
116-
req.url ~ "^/wp-activate.php" ||
117-
req.url ~ "^/wp-mail.php" ||
118-
req.url ~ "^/wp-login.php" ||
119-
req.url ~ "^\?add-to-cart=" ||
120-
req.url ~ "^\?wc-api=" ||
121-
req.url ~ "^/preview=" ||
122-
req.url ~ "^/\.well-known/acme-challenge/"
123-
) {
124-
set req.http.X-Cacheable = "NO:Logged in/Got Sessions";
125-
if(req.http.X-Requested-With == "XMLHttpRequest") {
126-
set req.http.X-Cacheable = "NO:Ajax";
103+
# Don't cache the following pages
104+
if (req.url ~ "^/status.php$" ||
105+
req.url ~ "^/update.php$" ||
106+
req.url ~ "^/cron.php$" ||
107+
req.url ~ "^/admin$" ||
108+
req.url ~ "^/admin/.*$" ||
109+
req.url ~ "^/flag/.*$" ||
110+
req.url ~ "^.*/ajax/.*$" ||
111+
req.url ~ "^.*/ahah/.*$" ||
112+
req.url ~ "^/\.well-known/acme-challenge/") {
113+
return (pass);
114+
}
115+
116+
# Remove all cookies except the session & NO_CACHE cookies
117+
if (req.http.Cookie) {
118+
set req.http.Cookie = ";" + req.http.Cookie;
119+
set req.http.Cookie = regsuball(req.http.Cookie, "; +", ";");
120+
set req.http.Cookie = regsuball(req.http.Cookie, ";(S?SESS[a-z0-9]+|NO_CACHE)=", "; \1=");
121+
set req.http.Cookie = regsuball(req.http.Cookie, ";[^ ][^;]*", "");
122+
set req.http.Cookie = regsuball(req.http.Cookie, "^[; ]+|[; ]+$", "");
123+
124+
if (req.http.cookie ~ "^\s*$") {
125+
unset req.http.cookie;
126+
} else {
127+
return(pass);
127128
}
128-
return(pass);
129129
}
130-
131-
# Remove x-cache-status header
132-
unset req.http.x-cache-status;
133-
134-
# Remove any cookies left
135-
unset req.http.Cookie;
136130
return(hash);
137131
}
138132

139133
sub vcl_hash {
140-
if(req.http.X-Forwarded-Proto) {
141-
# Create cache variations depending on the request protocol
142-
hash_data(req.http.X-Forwarded-Proto);
143-
}
144-
}
145-
146-
sub vcl_hit {
147-
set req.http.x-cache-status = "HIT";
148-
if (obj.ttl <= 0s && obj.grace > 0s) {
149-
set req.http.x-cache-status = "HIT graced";
150-
}
151-
152-
if (req.method == "PURGE") {
153-
return(synth(200, "OK"));
154-
}
155-
}
156-
157-
sub vcl_miss {
158-
set req.http.x-cache-status = "MISS";
159-
160-
if (req.method == "PURGE") {
161-
return(synth(404, "Not cached"));
162-
}
163-
}
164-
165-
sub vcl_pass {
166-
set req.http.x-cache-status = "PASS";
167-
}
168-
169-
sub vcl_pipe {
170-
set req.http.x-cache-status = "pipe uncacheable";
171-
}
172-
173-
sub vcl_synth {
174-
set req.http.x-cache-status = "synth synth";
175-
# uncomment the following line to show the information in the response
176-
set resp.http.x-cache-status = req.http.x-cache-status;
177-
178-
# redirect for http
179-
if (resp.status == 750) {
180-
set resp.status = 301;
181-
set resp.http.Location = req.http.x-redir;
182-
return(deliver);
183-
}
134+
# Create cache variations depending on the request protocol
135+
hash_data(req.http.X-Forwarded-Proto);
184136
}
185137

186138
sub vcl_backend_response {
187139
# Inject URL & Host header into the object for asynchronous banning purposes
188140
set beresp.http.x-url = bereq.url;
189141
set beresp.http.x-host = bereq.http.host;
190142

191-
# If we dont get a Cache-Control header from the backend
192-
# we default to 1h cache for all objects
193-
if (!beresp.http.Cache-Control) {
194-
set beresp.ttl = 1h;
195-
set beresp.http.X-Cacheable = "YES:Forced";
196-
}
143+
# Serve stale content for 2 minutes after object expiration
144+
# Perform asynchronous revalidation while stale content is served
145+
set beresp.grace = 120s;
197146

198147
# If the file is marked as static we cache it for 1 day
199148
if (bereq.http.X-Static-File == "true") {
200149
unset beresp.http.Set-Cookie;
201-
set beresp.http.X-Cacheable = "YES:Forced";
202150
set beresp.ttl = 1d;
203151
}
204152

205-
# Remove the Set-Cookie header when a specific Wordfence cookie is set
206-
if (beresp.http.Set-Cookie ~ "wfvt_|wordfence_verifiedHuman") {
207-
unset beresp.http.Set-Cookie;
153+
# If we dont get a Cache-Control header from the backend
154+
# we default to 1h cache for all objects
155+
if (!beresp.http.Cache-Control) {
156+
set beresp.ttl = 1h;
208157
}
209-
210-
if (beresp.http.Set-Cookie) {
211-
set beresp.http.X-Cacheable = "NO:Got Cookies";
212-
} elseif(beresp.http.Cache-Control ~ "private") {
213-
set beresp.http.X-Cacheable = "NO:Cache-Control=private";
214-
}
215-
}
216158

217-
sub vcl_deliver {
218-
# oh noes backend is down
219-
if (resp.status == 503) {
220-
return(restart);
221-
}
222-
223-
# Debug header
224-
if(req.http.X-Cacheable) {
225-
set resp.http.X-Cacheable = req.http.X-Cacheable;
226-
} elseif(obj.uncacheable) {
227-
if(!resp.http.X-Cacheable) {
228-
set resp.http.X-Cacheable = "NO:UNCACHEABLE";
229-
}
230-
} elseif(!resp.http.X-Cacheable) {
231-
set resp.http.X-Cacheable = "YES";
159+
# Parse Edge Side Include tags when the Surrogate-Control header contains ESI/1.0
160+
if (beresp.http.Surrogate-Control ~ "ESI/1.0") {
161+
unset beresp.http.Surrogate-Control;
162+
set beresp.do_esi = true;
232163
}
164+
}
233165

234-
set resp.http.x-cache-status = req.http.x-cache-status;
235-
set resp.http.x-varnish = resp.http.x-varnish + " " + req.http.x-cache-status;
236-
166+
sub vcl_deliver {
237167
# Cleanup of headers
238168
unset resp.http.x-url;
239-
unset resp.http.x-host;
169+
unset resp.http.x-host;
170+
unset req.http.X-Static-File;
240171
}

0 commit comments

Comments
 (0)