configuration-templates – Diff between revs 48 and 60

Subversion Repositories:
Rev:
Only display areas with differencesIgnore whitespace
Rev 48 Rev 60
1 vcl 4.0; 1 vcl 5.0;
2 ########################################################################### 2 ###########################################################################
3 ## Copyright (C) Wizardry and Steamworks 2016 - License: GNU GPLv3 ## 3 ## Copyright (C) Wizardry and Steamworks 2016 - License: GNU GPLv3 ##
4 ## Please see: http://www.gnu.org/licenses/gpl.html for legal details, ## 4 ## Please see: http://www.gnu.org/licenses/gpl.html for legal details, ##
5 ## rights of fair usage, the disclaimer and warranty conditions. ## 5 ## rights of fair usage, the disclaimer and warranty conditions. ##
6 ########################################################################### 6 ###########################################################################
7 ## Derived from the original by Mattias Geniar as a starting template. ## 7 ## Derived from the original by Mattias Geniar as a starting template. ##
8 ########################################################################### 8 ###########################################################################
9   9  
10 import std; 10 import std;
11 import directors; 11 import directors;
12   12  
13 backend server1 { # Define one backend 13 backend server1 { # Define one backend
14 .host = "192.168.0.10"; # IP or Hostname of backend 14 .host = "192.168.0.10"; # IP or Hostname of backend
15 .port = "80"; # Port Apache or whatever is listening 15 .port = "80"; # Port Apache or whatever is listening
16 .max_connections = 300; # Number of allowed connections 16 .max_connections = 300; # Number of allowed connections
17   17  
18 .probe = { 18 .probe = {
19 #.url = "/"; # short easy way (GET /) 19 #.url = "/"; # short easy way (GET /)
20 # We prefer to only do a HEAD / 20 # We prefer to only do a HEAD /
21 .request = 21 .request =
22 "HEAD / HTTP/1.1" 22 "HEAD / HTTP/1.1"
23 "Host: grimore.org" 23 "Host: grimore.org"
24 "Connection: close" 24 "Connection: close"
25 "User-Agent: Varnish Health Probe"; 25 "User-Agent: Varnish Health Probe";
26   26  
27 .interval = 5s; # check the health of each backend every 5 seconds 27 .interval = 5s; # check the health of each backend every 5 seconds
28 .timeout = 1s; # timing out after 1 second. 28 .timeout = 1s; # timing out after 1 second.
29 .window = 5; # If 3 out of the last 5 polls succeeded the backend is considered healthy, otherwise it will be marked as sick 29 .window = 5; # If 3 out of the last 5 polls succeeded the backend is considered healthy, otherwise it will be marked as sick
30 .threshold = 3; 30 .threshold = 3;
31 } 31 }
32   32  
33 .first_byte_timeout = 300s; # How long to wait before we receive a first byte from our backend? 33 .first_byte_timeout = 300s; # How long to wait before we receive a first byte from our backend?
34 .connect_timeout = 5s; # How long to wait for a backend connection? 34 .connect_timeout = 5s; # How long to wait for a backend connection?
35 .between_bytes_timeout = 2s; # How long to wait between bytes received from our backend? 35 .between_bytes_timeout = 2s; # How long to wait between bytes received from our backend?
36 } 36 }
37   37  
38 acl purge { 38 acl purge {
39 # ACL we'll use later to allow purges 39 # ACL we'll use later to allow purges
40 "localhost"; 40 "localhost";
41 "127.0.0.1"; 41 "127.0.0.1";
42 /* "::1"; */ 42 /* "::1"; */
43 } 43 }
44   44  
45 /* 45 /*
46 acl editors { 46 acl editors {
47 # ACL to honor the "Cache-Control: no-cache" header to force a refresh but only from selected IPs 47 # ACL to honor the "Cache-Control: no-cache" header to force a refresh but only from selected IPs
48 "localhost"; 48 "localhost";
49 "127.0.0.1"; 49 "127.0.0.1";
50 "::1"; 50 "::1";
51 } 51 }
52 */ 52 */
53   53  
54 sub vcl_init { 54 sub vcl_init {
55 # Called when VCL is loaded, before any requests pass through it. 55 # Called when VCL is loaded, before any requests pass through it.
56 # Typically used to initialize VMODs. 56 # Typically used to initialize VMODs.
57   57  
58 new vdir = directors.round_robin(); 58 new vdir = directors.round_robin();
59 vdir.add_backend(server1); 59 vdir.add_backend(server1);
60 # vdir.add_backend(server...); 60 # vdir.add_backend(server...);
61 # vdir.add_backend(servern); 61 # vdir.add_backend(servern);
62 } 62 }
63   63  
64 sub vcl_recv { 64 sub vcl_recv {
65 ### Conditional routing based on host header requests with subdomain support - split domain. 65 ### Conditional routing based on host header requests with subdomain support - split domain.
66 ## Suppose that you have multiple backends (configured at the top of this file) that route to 66 ## Suppose that you have multiple backends (configured at the top of this file) that route to
67 ## diferent backends that also have different websites. 67 ## diferent backends that also have different websites.
68 ## In that scenario you would want to, say: 68 ## In that scenario you would want to, say:
69 ## * route example1.tld or www.example1.tld to the server1 (192.168.0.10) backend 69 ## * route example1.tld or www.example1.tld to the server1 (192.168.0.10) backend
70 ## * route example2.tld or www.example2.tld to the server2 (192.168.0.20) backend 70 ## * route example2.tld or www.example2.tld to the server2 (192.168.0.20) backend
71 #if (req.http.host ~ "^(.*\.)?example1\.com$") { 71 #if (req.http.host ~ "^(.*\.)?example1\.com$") {
72 # set req.backend_hint = server1; 72 # set req.backend_hint = server1;
73 # return (hash); 73 # return (hash);
74 #} 74 #}
75 #if (req.http.host ~ "^(.*\.)?example2\.com$") { 75 #if (req.http.host ~ "^(.*\.)?example2\.com$") {
76 # set req.backend_hint = server2; 76 # set req.backend_hint = server2;
77 # return (hash); 77 # return (hash);
78 #} 78 #}
79 79
80 # Called at the beginning of a request, after the complete request has been received and parsed. 80 # Called at the beginning of a request, after the complete request has been received and parsed.
81 # Its purpose is to decide whether or not to serve the request, how to do it, and, if applicable, 81 # Its purpose is to decide whether or not to serve the request, how to do it, and, if applicable,
82 # which backend to use. 82 # which backend to use.
83 # also used to modify the request 83 # also used to modify the request
84   84  
85 set req.backend_hint = vdir.backend(); # send all traffic to the vdir director 85 set req.backend_hint = vdir.backend(); # send all traffic to the vdir director
86   86  
87 ### Brotli encoding support. 87 ### Brotli encoding support.
88 if(req.http.Accept-Encoding ~ "br" && req.url !~ "\.(jpg|png|gif|gz|mp3|mov|avi|mpg|mp4|swf|wmf)$") { 88 if(req.http.Accept-Encoding ~ "br" && req.url !~ "\.(jpg|png|gif|gz|mp3|mov|avi|mpg|mp4|swf|wmf)$") {
89 set req.http.X-brotli = "true"; 89 set req.http.X-brotli = "true";
90 } 90 }
91 91
92 # When CloudFlare is in front of varnish, send the real IP address through X-Forwarded-For 92 # When CloudFlare is in front of varnish, send the real IP address through X-Forwarded-For
93 # otherwise if CloudFlare is not involved, set the X-Forwarded-For to the client IP address. 93 # otherwise if CloudFlare is not involved, set the X-Forwarded-For to the client IP address.
94 unset req.http.X-Forwarded-For; 94 unset req.http.X-Forwarded-For;
95 if (req.http.cf-connecting-ip) { 95 if (req.http.cf-connecting-ip) {
96 set req.http.X-Forwarded-For = req.http.cf-connecting-ip; 96 set req.http.X-Forwarded-For = req.http.cf-connecting-ip;
97 } else { 97 } else {
98 set req.http.X-Forwarded-For = client.ip; 98 set req.http.X-Forwarded-For = client.ip;
99 } 99 }
100   100  
101 # Normalize the header, remove the port (in case you're testing this on various TCP ports) 101 # Normalize the header, remove the port (in case you're testing this on various TCP ports)
102 set req.http.Host = regsub(req.http.Host, ":[0-9]+", ""); 102 set req.http.Host = regsub(req.http.Host, ":[0-9]+", "");
103   103  
104 # Remove the proxy header (see https://httpoxy.org/#mitigate-varnish) 104 # Remove the proxy header (see https://httpoxy.org/#mitigate-varnish)
105 unset req.http.proxy; 105 unset req.http.proxy;
106   106  
107 # Normalize the query arguments 107 # Normalize the query arguments
108 set req.url = std.querysort(req.url); 108 set req.url = std.querysort(req.url);
109   109  
110 # Allow purging 110 # Allow purging
111 if (req.method == "PURGE") { 111 if (req.method == "PURGE") {
112 if (!client.ip ~ purge) { # purge is the ACL defined at the begining 112 if (!client.ip ~ purge) { # purge is the ACL defined at the begining
113 # Not from an allowed IP? Then die with an error. 113 # Not from an allowed IP? Then die with an error.
114 return (synth(405, "This IP is not allowed to send PURGE requests.")); 114 return (synth(405, "This IP is not allowed to send PURGE requests."));
115 } 115 }
116 # If you got this stage (and didn't error out above), purge the cached result 116 # If you got this stage (and didn't error out above), purge the cached result
117 return (purge); 117 return (purge);
118 } 118 }
119   119  
120 # Only deal with "normal" types 120 # Only deal with "normal" types
121 if (req.method != "GET" && 121 if (req.method != "GET" &&
122 req.method != "HEAD" && 122 req.method != "HEAD" &&
123 req.method != "PUT" && 123 req.method != "PUT" &&
124 req.method != "POST" && 124 req.method != "POST" &&
125 req.method != "TRACE" && 125 req.method != "TRACE" &&
126 req.method != "OPTIONS" && 126 req.method != "OPTIONS" &&
127 req.method != "PATCH" && 127 req.method != "PATCH" &&
128 req.method != "DELETE" && 128 req.method != "DELETE" &&
129 req.method != "PROPFIND" && 129 req.method != "PROPFIND" &&
130 req.method != "REPORT") { 130 req.method != "REPORT") {
131 /* Non-RFC2616 or CONNECT which is weird. */ 131 /* Non-RFC2616 or CONNECT which is weird. */
132 return (pipe); 132 return (pipe);
133 } 133 }
134   134  
135 # Implementing websocket support (https://www.varnish-cache.org/docs/4.0/users-guide/vcl-example-websockets.html) 135 # Implementing websocket support (https://www.varnish-cache.org/docs/4.0/users-guide/vcl-example-websockets.html)
136 if (req.http.Upgrade ~ "(?i)websocket") { 136 if (req.http.Upgrade ~ "(?i)websocket") {
137 return (pipe); 137 return (pipe);
138 } 138 }
139   139  
140 # Only cache GET or HEAD requests. This makes sure the POST requests are always passed. 140 # Only cache GET or HEAD requests. This makes sure the POST requests are always passed.
141 if (req.method != "GET" && req.method != "HEAD") { 141 if (req.method != "GET" && req.method != "HEAD") {
142 return (pass); 142 return (pass);
143 } 143 }
144   144  
145 # Some generic URL manipulation, useful for all templates that follow 145 # Some generic URL manipulation, useful for all templates that follow
146 # First remove the Google Analytics added parameters, useless for our backend 146 # First remove the Google Analytics added parameters, useless for our backend
147 if (req.url ~ "(\?|&)(utm_source|utm_medium|utm_campaign|utm_content|gclid|cx|ie|cof|siteurl)=") { 147 if (req.url ~ "(\?|&)(utm_source|utm_medium|utm_campaign|utm_content|gclid|cx|ie|cof|siteurl)=") {
148 set req.url = regsuball(req.url, "&(utm_source|utm_medium|utm_campaign|utm_content|gclid|cx|ie|cof|siteurl)=([A-z0-9_\-\.%25]+)", ""); 148 set req.url = regsuball(req.url, "&(utm_source|utm_medium|utm_campaign|utm_content|gclid|cx|ie|cof|siteurl)=([A-z0-9_\-\.%25]+)", "");
149 set req.url = regsuball(req.url, "\?(utm_source|utm_medium|utm_campaign|utm_content|gclid|cx|ie|cof|siteurl)=([A-z0-9_\-\.%25]+)", "?"); 149 set req.url = regsuball(req.url, "\?(utm_source|utm_medium|utm_campaign|utm_content|gclid|cx|ie|cof|siteurl)=([A-z0-9_\-\.%25]+)", "?");
150 set req.url = regsub(req.url, "\?&", "?"); 150 set req.url = regsub(req.url, "\?&", "?");
151 set req.url = regsub(req.url, "\?$", ""); 151 set req.url = regsub(req.url, "\?$", "");
152 } 152 }
153   153  
154 # Strip hash, server doesn't need it. 154 # Strip hash, server doesn't need it.
155 if (req.url ~ "\#") { 155 if (req.url ~ "\#") {
156 set req.url = regsub(req.url, "\#.*$", ""); 156 set req.url = regsub(req.url, "\#.*$", "");
157 } 157 }
158   158  
159 # Strip a trailing ? if it exists 159 # Strip a trailing ? if it exists
160 if (req.url ~ "\?$") { 160 if (req.url ~ "\?$") {
161 set req.url = regsub(req.url, "\?$", ""); 161 set req.url = regsub(req.url, "\?$", "");
162 } 162 }
163   163  
164 # Some generic cookie manipulation, useful for all templates that follow 164 # Some generic cookie manipulation, useful for all templates that follow
165 # Remove the "has_js" cookie 165 # Remove the "has_js" cookie
166 set req.http.Cookie = regsuball(req.http.Cookie, "has_js=[^;]+(; )?", ""); 166 set req.http.Cookie = regsuball(req.http.Cookie, "has_js=[^;]+(; )?", "");
167   167  
168 # Remove any CloudFlare cookies 168 # Remove any CloudFlare cookies
169 set req.http.Cookie = regsuball(req.http.Cookie, "cf_.=[^;]+(; )?", ""); 169 set req.http.Cookie = regsuball(req.http.Cookie, "cf_.=[^;]+(; )?", "");
170   170  
171 # Remove any Google Analytics based cookies 171 # Remove any Google Analytics based cookies
172 set req.http.Cookie = regsuball(req.http.Cookie, "__utm.=[^;]+(; )?", ""); 172 set req.http.Cookie = regsuball(req.http.Cookie, "__utm.=[^;]+(; )?", "");
173 set req.http.Cookie = regsuball(req.http.Cookie, "_ga=[^;]+(; )?", ""); 173 set req.http.Cookie = regsuball(req.http.Cookie, "_ga=[^;]+(; )?", "");
174 set req.http.Cookie = regsuball(req.http.Cookie, "_gat=[^;]+(; )?", ""); 174 set req.http.Cookie = regsuball(req.http.Cookie, "_gat=[^;]+(; )?", "");
175 set req.http.Cookie = regsuball(req.http.Cookie, "utmctr=[^;]+(; )?", ""); 175 set req.http.Cookie = regsuball(req.http.Cookie, "utmctr=[^;]+(; )?", "");
176 set req.http.Cookie = regsuball(req.http.Cookie, "utmcmd.=[^;]+(; )?", ""); 176 set req.http.Cookie = regsuball(req.http.Cookie, "utmcmd.=[^;]+(; )?", "");
177 set req.http.Cookie = regsuball(req.http.Cookie, "utmccn.=[^;]+(; )?", ""); 177 set req.http.Cookie = regsuball(req.http.Cookie, "utmccn.=[^;]+(; )?", "");
178   178  
179 # Remove DoubleClick offensive cookies 179 # Remove DoubleClick offensive cookies
180 set req.http.Cookie = regsuball(req.http.Cookie, "__gads=[^;]+(; )?", ""); 180 set req.http.Cookie = regsuball(req.http.Cookie, "__gads=[^;]+(; )?", "");
181   181  
182 # Remove the Quant Capital cookies (added by some plugin, all __qca) 182 # Remove the Quant Capital cookies (added by some plugin, all __qca)
183 set req.http.Cookie = regsuball(req.http.Cookie, "__qc.=[^;]+(; )?", ""); 183 set req.http.Cookie = regsuball(req.http.Cookie, "__qc.=[^;]+(; )?", "");
184   184  
185 # Remove the AddThis cookies 185 # Remove the AddThis cookies
186 set req.http.Cookie = regsuball(req.http.Cookie, "__atuv.=[^;]+(; )?", ""); 186 set req.http.Cookie = regsuball(req.http.Cookie, "__atuv.=[^;]+(; )?", "");
187   187  
188 # Remove a ";" prefix in the cookie if present 188 # Remove a ";" prefix in the cookie if present
189 set req.http.Cookie = regsuball(req.http.Cookie, "^;\s*", ""); 189 set req.http.Cookie = regsuball(req.http.Cookie, "^;\s*", "");
190   190  
191 # Are there cookies left with only spaces or that are empty? 191 # Are there cookies left with only spaces or that are empty?
192 if (req.http.cookie ~ "^\s*$") { 192 if (req.http.cookie ~ "^\s*$") {
193 unset req.http.cookie; 193 unset req.http.cookie;
194 } 194 }
195   195  
196 if (req.http.Cache-Control ~ "(?i)no-cache") { 196 if (req.http.Cache-Control ~ "(?i)no-cache") {
197 #if (req.http.Cache-Control ~ "(?i)no-cache" && client.ip ~ editors) { # create the acl editors if you want to restrict the Ctrl-F5 197 #if (req.http.Cache-Control ~ "(?i)no-cache" && client.ip ~ editors) { # create the acl editors if you want to restrict the Ctrl-F5
198 # http://varnish.projects.linpro.no/wiki/VCLExampleEnableForceRefresh 198 # http://varnish.projects.linpro.no/wiki/VCLExampleEnableForceRefresh
199 # Ignore requests via proxy caches and badly behaved crawlers 199 # Ignore requests via proxy caches and badly behaved crawlers
200 # like msnbot that send no-cache with every request. 200 # like msnbot that send no-cache with every request.
201 if (! (req.http.Via || req.http.User-Agent ~ "(?i)bot" || req.http.X-Purge)) { 201 if (! (req.http.Via || req.http.User-Agent ~ "(?i)bot" || req.http.X-Purge)) {
202 #set req.hash_always_miss = true; # Doesn't seems to refresh the object in the cache 202 #set req.hash_always_miss = true; # Doesn't seems to refresh the object in the cache
203 return(purge); # Couple this with restart in vcl_purge and X-Purge header to avoid loops 203 return(purge); # Couple this with restart in vcl_purge and X-Purge header to avoid loops
204 } 204 }
205 } 205 }
206   206  
207 # Large static files are delivered directly to the end-user without 207 # Large static files are delivered directly to the end-user without
208 # waiting for Varnish to fully read the file first. 208 # waiting for Varnish to fully read the file first.
209 # Varnish 4 fully supports Streaming, so set do_stream in vcl_backend_response() 209 # Varnish 4 fully supports Streaming, so set do_stream in vcl_backend_response()
210 if (req.url ~ "^[^?]*\.(7z|avi|bz2|flac|flv|gz|mka|mkv|mov|mp3|mp4|mpeg|mpg|ogg|ogm|opus|rar|tar|tgz|tbz|txz|wav|webm|xz|zip)(\?.*)?$") { 210 if (req.url ~ "^[^?]*\.(7z|avi|bz2|flac|flv|gz|mka|mkv|mov|mp3|mp4|mpeg|mpg|ogg|ogm|opus|rar|tar|tgz|tbz|txz|wav|webm|xz|zip)(\?.*)?$") {
211 unset req.http.Cookie; 211 unset req.http.Cookie;
212 return (hash); 212 return (hash);
213 } 213 }
214   214  
215 # Remove all cookies for static files 215 # Remove all cookies for static files
216 # A valid discussion could be held on this line: do you really need to cache static files that don't cause load? Only if you have memory left. 216 # A valid discussion could be held on this line: do you really need to cache static files that don't cause load? Only if you have memory left.
217 # Sure, there's disk I/O, but chances are your OS will already have these files in their buffers (thus memory). 217 # Sure, there's disk I/O, but chances are your OS will already have these files in their buffers (thus memory).
218 # Before you blindly enable this, have a read here: https://ma.ttias.be/stop-caching-static-files/ 218 # Before you blindly enable this, have a read here: https://ma.ttias.be/stop-caching-static-files/
219 if (req.url ~ "^[^?]*\.(7z|avi|bmp|bz2|css|csv|doc|docx|eot|flac|flv|gif|gz|ico|jpeg|jpg|js|less|mka|mkv|mov|mp3|mp4|mpeg|mpg|odt|otf|ogg|ogm|opus|pdf|png|ppt|pptx|rar|rtf|svg|svgz|swf|tar|tbz|tgz|ttf|txt|txz|wav|webm|webp|woff|woff2|xls|xlsx|xml|xz|zip)(\?.*)?$") { 219 if (req.url ~ "^[^?]*\.(7z|avi|bmp|bz2|css|csv|doc|docx|eot|flac|flv|gif|gz|ico|jpeg|jpg|js|less|mka|mkv|mov|mp3|mp4|mpeg|mpg|odt|otf|ogg|ogm|opus|pdf|png|ppt|pptx|rar|rtf|svg|svgz|swf|tar|tbz|tgz|ttf|txt|txz|wav|webm|webp|woff|woff2|xls|xlsx|xml|xz|zip)(\?.*)?$") {
220 unset req.http.Cookie; 220 unset req.http.Cookie;
221 return (hash); 221 return (hash);
222 } 222 }
223   223  
224 # Send Surrogate-Capability headers to announce ESI support to backend 224 # Send Surrogate-Capability headers to announce ESI support to backend
225 set req.http.Surrogate-Capability = "key=ESI/1.0"; 225 set req.http.Surrogate-Capability = "key=ESI/1.0";
226   226  
227 if (req.http.Authorization) { 227 if (req.http.Authorization) {
228 # Not cacheable by default 228 # Not cacheable by default
229 return (pass); 229 return (pass);
230 } 230 }
231   231  
232 return (hash); 232 return (hash);
233 } 233 }
234   234  
235   235  
236 sub vcl_pipe { 236 sub vcl_pipe {
237 # Called upon entering pipe mode. 237 # Called upon entering pipe mode.
238 # In this mode, the request is passed on to the backend, and any further data from both the client 238 # In this mode, the request is passed on to the backend, and any further data from both the client
239 # and backend is passed on unaltered until either end closes the connection. Basically, Varnish will 239 # and backend is passed on unaltered until either end closes the connection. Basically, Varnish will
240 # degrade into a simple TCP proxy, shuffling bytes back and forth. For a connection in pipe mode, 240 # degrade into a simple TCP proxy, shuffling bytes back and forth. For a connection in pipe mode,
241 # no other VCL subroutine will ever get called after vcl_pipe. 241 # no other VCL subroutine will ever get called after vcl_pipe.
242   242  
243 ## Note that only the first request to the backend will have 243 ## Note that only the first request to the backend will have
244 ## X-Forwarded-For set. If you use X-Forwarded-For and want to 244 ## X-Forwarded-For set. If you use X-Forwarded-For and want to
245 ## have it set for all requests, make sure to have: 245 ## have it set for all requests, make sure to have:
246 ## set bereq.http.connection = "close"; 246 ## set bereq.http.connection = "close";
247 ## here. It is not set by default as it might break some broken web 247 ## here. It is not set by default as it might break some broken web
248 ## applications, like IIS with NTLM authentication. 248 ## applications, like IIS with NTLM authentication.
249 # set bereq.http.Connection = "Close"; 249 # set bereq.http.Connection = "Close";
250   250  
251 # Implementing websocket support (https://www.varnish-cache.org/docs/4.0/users-guide/vcl-example-websockets.html) 251 # Implementing websocket support (https://www.varnish-cache.org/docs/4.0/users-guide/vcl-example-websockets.html)
252 if (req.http.upgrade) { 252 if (req.http.upgrade) {
253 set bereq.http.upgrade = req.http.upgrade; 253 set bereq.http.upgrade = req.http.upgrade;
254 } 254 }
255   255  
256 return (pipe); 256 return (pipe);
257 } 257 }
258   258  
259 sub vcl_pass { 259 sub vcl_pass {
260 # Called upon entering pass mode. In this mode, the request is passed on to the backend, and the 260 # Called upon entering pass mode. In this mode, the request is passed on to the backend, and the
261 # backend's response is passed on to the client, but is not entered into the cache. Subsequent 261 # backend's response is passed on to the client, but is not entered into the cache. Subsequent
262 # requests submitted over the same client connection are handled normally. 262 # requests submitted over the same client connection are handled normally.
263   263  
264 # return (pass); 264 # return (pass);
265 } 265 }
266   266  
267 # The data on which the hashing will take place 267 # The data on which the hashing will take place
268 sub vcl_hash { 268 sub vcl_hash {
269 # Called after vcl_recv to create a hash value for the request. This is used as a key 269 # Called after vcl_recv to create a hash value for the request. This is used as a key
270 # to look up the object in Varnish. 270 # to look up the object in Varnish.
271   271  
272 hash_data(req.url); 272 hash_data(req.url);
273   273  
274 if (req.http.host) { 274 if (req.http.host) {
275 hash_data(req.http.host); 275 hash_data(req.http.host);
276 } else { 276 } else {
277 hash_data(server.ip); 277 hash_data(server.ip);
278 } 278 }
279   279  
280 # hash cookies for requests that have them 280 # hash cookies for requests that have them
281 if (req.http.Cookie) { 281 if (req.http.Cookie) {
282 hash_data(req.http.Cookie); 282 hash_data(req.http.Cookie);
283 } 283 }
284   284  
285 ### Brotli encoding support. 285 ### Brotli encoding support.
286 if(req.http.X-brotli == "true") { 286 if(req.http.X-brotli == "true") {
287 hash_data("brotli"); 287 hash_data("brotli");
288 } 288 }
289 } 289 }
290   290  
291 sub vcl_hit { 291 sub vcl_hit {
292 # Called when a cache lookup is successful. 292 # Called when a cache lookup is successful.
293   293  
294 if (obj.ttl >= 0s) { 294 if (obj.ttl >= 0s) {
295 # A pure unadultered hit, deliver it 295 # A pure unadultered hit, deliver it
296 return (deliver); 296 return (deliver);
297 } 297 }
298   298  
299 # https://www.varnish-cache.org/docs/trunk/users-guide/vcl-grace.html 299 # https://www.varnish-cache.org/docs/trunk/users-guide/vcl-grace.html
300 # When several clients are requesting the same page Varnish will send one request to the backend and place the others on hold while fetching one copy from the backend. In some products this is called request coalescing and Varnish does this automatically. 300 # When several clients are requesting the same page Varnish will send one request to the backend and place the others on hold while fetching one copy from the backend. In some products this is called request coalescing and Varnish does this automatically.
301 # If you are serving thousands of hits per second the queue of waiting requests can get huge. There are two potential problems - one is a thundering herd problem - suddenly releasing a thousand threads to serve content might send the load sky high. Secondly - nobody likes to wait. To deal with this we can instruct Varnish to keep the objects in cache beyond their TTL and to serve the waiting requests somewhat stale content. 301 # If you are serving thousands of hits per second the queue of waiting requests can get huge. There are two potential problems - one is a thundering herd problem - suddenly releasing a thousand threads to serve content might send the load sky high. Secondly - nobody likes to wait. To deal with this we can instruct Varnish to keep the objects in cache beyond their TTL and to serve the waiting requests somewhat stale content.
302 # if (!std.healthy(req.backend_hint) && (obj.ttl + obj.grace > 0s)) { 302 # if (!std.healthy(req.backend_hint) && (obj.ttl + obj.grace > 0s)) {
303 # return (deliver); 303 # return (deliver);
304 # } else { 304 # } else {
305 # return (fetch); 305 # return (miss);
306 # } 306 # }
307   307  
308 # We have no fresh fish. Lets look at the stale ones. 308 # We have no fresh fish. Lets look at the stale ones.
309 if (std.healthy(req.backend_hint)) { 309 if (std.healthy(req.backend_hint)) {
310 # Backend is healthy. Limit age to 10s. 310 # Backend is healthy. Limit age to 10s.
311 if (obj.ttl + 10s > 0s) { 311 if (obj.ttl + 10s > 0s) {
312 #set req.http.grace = "normal(limited)"; 312 #set req.http.grace = "normal(limited)";
313 return (deliver); 313 return (deliver);
314 } else { 314 } else {
315 # No candidate for grace. Fetch a fresh object. 315 # No candidate for grace. Fetch a fresh object.
316 return(fetch); 316 return (miss);
317 } 317 }
318 } else { 318 } else {
319 # backend is sick - use full grace 319 # backend is sick - use full grace
320 if (obj.ttl + obj.grace > 0s) { 320 if (obj.ttl + obj.grace > 0s) {
321 #set req.http.grace = "full"; 321 #set req.http.grace = "full";
322 return (deliver); 322 return (deliver);
323 } else { 323 } else {
324 # no graced object. 324 # no graced object.
325 return (fetch); 325 return (miss);
326 } 326 }
327 } 327 }
328   328  
329 # fetch & deliver once we get the result 329 # fetch & deliver once we get the result
330 return (fetch); # Dead code, keep as a safeguard 330 return (miss); # Dead code, keep as a safeguard
331 } 331 }
332   332  
333 sub vcl_miss { 333 sub vcl_miss {
334 # Called after a cache lookup if the requested document was not found in the cache. Its purpose 334 # Called after a cache lookup if the requested document was not found in the cache. Its purpose
335 # is to decide whether or not to attempt to retrieve the document from the backend, and which 335 # is to decide whether or not to attempt to retrieve the document from the backend, and which
336 # backend to use. 336 # backend to use.
337   337  
338 return (fetch); 338 return (fetch);
339 } 339 }
340   340  
341 # Handle the HTTP request coming from our backend 341 # Handle the HTTP request coming from our backend
342 sub vcl_backend_response { 342 sub vcl_backend_response {
343 # Called after the response headers has been successfully retrieved from the backend. 343 # Called after the response headers has been successfully retrieved from the backend.
344   344  
345 # Pause ESI request and remove Surrogate-Control header 345 # Pause ESI request and remove Surrogate-Control header
346 if (beresp.http.Surrogate-Control ~ "ESI/1.0") { 346 if (beresp.http.Surrogate-Control ~ "ESI/1.0") {
347 unset beresp.http.Surrogate-Control; 347 unset beresp.http.Surrogate-Control;
348 set beresp.do_esi = true; 348 set beresp.do_esi = true;
349 set beresp.ttl = 24h; # Set 24h ESI 349 set beresp.ttl = 24h; # Set 24h ESI
350 } 350 }
351 351
352 ### Brotli encoding support. 352 ### Brotli encoding support.
353 if(bereq.http.X-brotli == "true") { 353 if(bereq.http.X-brotli == "true") {
354 set bereq.http.Accept-Encoding = "br"; 354 set bereq.http.Accept-Encoding = "br";
355 unset bereq.http.X-brotli; 355 unset bereq.http.X-brotli;
356 } 356 }
357   357  
358 ### Set content expiration. 358 ### Set content expiration.
359 ## You may want to disable any expiration on the backend (ie: for Apache, disable mod_expires). 359 ## You may want to disable any expiration on the backend (ie: for Apache, disable mod_expires).
360 # 1 Year 360 # 1 Year
361 if(beresp.http.content-type ~ "(?i)(application/(javascript|x\-javascript))|(text/(javascript|css))|(application/(atom\+xml|rdf\+xml|rss\+xml))") { 361 if(beresp.http.content-type ~ "(?i)(application/(javascript|x\-javascript))|(text/(javascript|css))|(application/(atom\+xml|rdf\+xml|rss\+xml))") {
362 set beresp.http.Expires = "" + (now + 1y); 362 set beresp.http.Expires = "" + (now + 1y);
363 } 363 }
364 # 1 Month 364 # 1 Month
365 if(beresp.http.content-type ~ "(?i)(application/(vnd\.ms\-fontobject|font\-woff|x\-font\-(ttf|woff)))|(audio/ogg)|(font/(eot|opentype|woff))|(image/(bmp|gif|jp2|jpeg|png|svg\+xmlwebp))|(video/(mp4|ogg|webm))") { 365 if(beresp.http.content-type ~ "(?i)(application/(vnd\.ms\-fontobject|font\-woff|x\-font\-(ttf|woff)))|(audio/ogg)|(font/(eot|opentype|woff))|(image/(bmp|gif|jp2|jpeg|png|svg\+xmlwebp))|(video/(mp4|ogg|webm))") {
366 set beresp.http.Expires = "" + (now + 24w); 366 set beresp.http.Expires = "" + (now + 24w);
367 } 367 }
368 # 1 Week 368 # 1 Week
369 if(beresp.http.content-type ~ "(?i)(image/(vnd\.microsoft\.icon|x\-icon))|(application/manifest\+json)|(text/x\-cross\-domain\-policy)") { 369 if(beresp.http.content-type ~ "(?i)(image/(vnd\.microsoft\.icon|x\-icon))|(application/manifest\+json)|(text/x\-cross\-domain\-policy)") {
370 set beresp.http.Expires = "" + (now + 1w); 370 set beresp.http.Expires = "" + (now + 1w);
371 } 371 }
372 # Immediately 372 # Immediately
373 # Not exactly "immediately" since we do not want to have to recache on fast reloads - ideally, set this to average page load time. 373 # Not exactly "immediately" since we do not want to have to recache on fast reloads - ideally, set this to average page load time.
374 if(beresp.http.content-type ~ "(?i)(application/(json|ld\+json|schema\+json|vnd\.geo\+jsonxml|x\-web\-app\-manifest\+json))|(text/(xml|cache\-manifest|html))") { 374 if(beresp.http.content-type ~ "(?i)(application/(json|ld\+json|schema\+json|vnd\.geo\+jsonxml|x\-web\-app\-manifest\+json))|(text/(xml|cache\-manifest|html))") {
375 set beresp.http.Expires = "" + (now + 3s); 375 set beresp.http.Expires = "" + (now + 3s);
376 } 376 }
377   377  
378 ### GZip content if not already compressed. 378 ### GZip content if not already compressed.
379 ## You may want to disable any compression on the backend (ie: for Apache, disable mod_deflate). 379 ## You may want to disable any compression on the backend (ie: for Apache, disable mod_deflate).
380 if(beresp.http.content-type ~ "(?i)(application/(atom\+xml|javascript|json|ld\+json|manifest\+json|rdf\+xml|rss\+xml|schema\+json|vnd\.geo\+json|vnd\.ms\-fontobject|x\-(font\-ttf|javascript|web\-app\-manifest\+json)|xhtml\+xml|xml)|font/(eot|opentype))|(image/(bmp|svg\+xml|vnd\.microsoft\.icon|x\-icon))|(text/(cache\-manifest|css|html|javascript|plain|vcard|vnd\.rim\.location\.xloc|vcalendar|vtt|x\-component|x\-cross\-domain\-policy|xml))") { 380 if(beresp.http.content-type ~ "(?i)(application/(atom\+xml|javascript|json|ld\+json|manifest\+json|rdf\+xml|rss\+xml|schema\+json|vnd\.geo\+json|vnd\.ms\-fontobject|x\-(font\-ttf|javascript|web\-app\-manifest\+json)|xhtml\+xml|xml)|font/(eot|opentype))|(image/(bmp|svg\+xml|vnd\.microsoft\.icon|x\-icon))|(text/(cache\-manifest|css|html|javascript|plain|vcard|vnd\.rim\.location\.xloc|vcalendar|vtt|x\-component|x\-cross\-domain\-policy|xml))") {
381 # Compress object for sending. 381 # Compress object for sending.
382 set beresp.do_gzip = true; 382 set beresp.do_gzip = true;
383 } 383 }
384   384  
385 ### Enable cache for all static files 385 ### Enable cache for all static files
386 ## The same argument as the static caches from above: monitor your cache size, if you get data nuked out of it, consider giving up the static file cache. 386 ## The same argument as the static caches from above: monitor your cache size, if you get data nuked out of it, consider giving up the static file cache.
387 ## Before you blindly enable this, have a read here: https://ma.ttias.be/stop-caching-static-files/ 387 ## Before you blindly enable this, have a read here: https://ma.ttias.be/stop-caching-static-files/
388 if(beresp.http.content-type ~ "(?i)(application/(java\-vm|javascript|json|msword|pdf|postscript|rtf|vnd\.ms\-(excel|fontobject|powerpoint)|vnd\.oasis\.opendocument\.text|vnd\.openxmlformats\-officedocument\.(presentationml\.presentation|spreadsheetml\.sheet|wordprocessingml\.document)|x\-(7z\-compressed|bzip2|gzip|rar\-compressed|shockwave\-flash|tar)|x\-font\-(bdf|ghostscript|linux\-psf|otf|pcf|snf|ttf|type1|woff)|xz|xml|zip))|(audio/((mpeg|ogg)|(x\-(flac|matroska|ms\-wma|wav))))|(image/((bmp|gif|jp2|jpeg|png|svg\+xml|vnd\.wap\.wbmp|webp|x\-(icon|pict))))|(text/((css|csv|javascript|plain)))|(video/((mp4|quicktime|webm|x\-(flv|matroska|ms\-wmv|msvideo))))") { 388 if(beresp.http.content-type ~ "(?i)(application/(java\-vm|javascript|json|msword|pdf|postscript|rtf|vnd\.ms\-(excel|fontobject|powerpoint)|vnd\.oasis\.opendocument\.text|vnd\.openxmlformats\-officedocument\.(presentationml\.presentation|spreadsheetml\.sheet|wordprocessingml\.document)|x\-(7z\-compressed|bzip2|gzip|rar\-compressed|shockwave\-flash|tar)|x\-font\-(bdf|ghostscript|linux\-psf|otf|pcf|snf|ttf|type1|woff)|xz|xml|zip))|(audio/((mpeg|ogg)|(x\-(flac|matroska|ms\-wma|wav))))|(image/((bmp|gif|jp2|jpeg|png|svg\+xml|vnd\.wap\.wbmp|webp|x\-(icon|pict))))|(text/((css|csv|javascript|plain)))|(video/((mp4|quicktime|webm|x\-(flv|matroska|ms\-wmv|msvideo))))") {
389 unset beresp.http.set-cookie; 389 unset beresp.http.set-cookie;
390 } 390 }
391   391  
392 # Large static files are delivered directly to the end-user without 392 # Large static files are delivered directly to the end-user without
393 # waiting for Varnish to fully read the file first. 393 # waiting for Varnish to fully read the file first.
394 # Varnish 4 fully supports Streaming, so use streaming here to avoid locking. 394 # Varnish 4 fully supports Streaming, so use streaming here to avoid locking.
395 if (bereq.url ~ "^[^?]*\.(7z|ace|avi|bin|bz2|flac|flv|gz|iso|mka|mkv|mov|mp3|mp4|mpeg|mpg|ogg|ogm|opus|rar|tar|tgz|tbz|txz|wav|webm|wma|wmv|xz|zip)(\?.*)?$") { 395 if (bereq.url ~ "^[^?]*\.(7z|ace|avi|bin|bz2|flac|flv|gz|iso|mka|mkv|mov|mp3|mp4|mpeg|mpg|ogg|ogm|opus|rar|tar|tgz|tbz|txz|wav|webm|wma|wmv|xz|zip)(\?.*)?$") {
396 unset beresp.http.set-cookie; 396 unset beresp.http.set-cookie;
397 set beresp.do_stream = true; # Check memory usage it'll grow in fetch_chunksize blocks (128k by default) if the backend doesn't send a Content-Length header, so only enable it for big objects 397 set beresp.do_stream = true; # Check memory usage it'll grow in fetch_chunksize blocks (128k by default) if the backend doesn't send a Content-Length header, so only enable it for big objects
398 } 398 }
399   399  
400 # Sometimes, a 301 or 302 redirect formed via Apache's mod_rewrite can mess with the HTTP port that is being passed along. 400 # Sometimes, a 301 or 302 redirect formed via Apache's mod_rewrite can mess with the HTTP port that is being passed along.
401 # This often happens with simple rewrite rules in a scenario where Varnish runs on :80 and Apache on :8080 on the same box. 401 # This often happens with simple rewrite rules in a scenario where Varnish runs on :80 and Apache on :8080 on the same box.
402 # A redirect can then often redirect the end-user to a URL on :8080, where it should be :80. 402 # A redirect can then often redirect the end-user to a URL on :8080, where it should be :80.
403 # This may need finetuning on your setup. 403 # This may need finetuning on your setup.
404 # 404 #
405 # To prevent accidental replace, we only filter the 301/302 redirects for now. 405 # To prevent accidental replace, we only filter the 301/302 redirects for now.
406 if (beresp.status == 301 || beresp.status == 302) { 406 if (beresp.status == 301 || beresp.status == 302) {
407 set beresp.http.Location = regsub(beresp.http.Location, ":[0-9]+", ""); 407 set beresp.http.Location = regsub(beresp.http.Location, ":[0-9]+", "");
408 } 408 }
409   409  
410 # Set 2min cache if unset for static files 410 # Set 2min cache if unset for static files
411 if (beresp.ttl <= 0s || beresp.http.Set-Cookie || beresp.http.Vary == "*") { 411 if (beresp.ttl <= 0s || beresp.http.Set-Cookie || beresp.http.Vary == "*") {
412 set beresp.ttl = 120s; # Important, you shouldn't rely on this, SET YOUR HEADERS in the backend 412 set beresp.ttl = 120s; # Important, you shouldn't rely on this, SET YOUR HEADERS in the backend
413 set beresp.uncacheable = true; 413 set beresp.uncacheable = true;
414 return (deliver); 414 return (deliver);
415 } 415 }
416   416  
417 # Don't cache 50x responses 417 # Don't cache 50x responses
418 if (beresp.status == 500 || beresp.status == 502 || beresp.status == 503 || beresp.status == 504) { 418 if (beresp.status == 500 || beresp.status == 502 || beresp.status == 503 || beresp.status == 504) {
419 return (abandon); 419 return (abandon);
420 } 420 }
421   421  
422 # Allow stale content, in case the backend goes down. 422 # Allow stale content, in case the backend goes down.
423 # make Varnish keep all objects for 6 hours beyond their TTL 423 # make Varnish keep all objects for 6 hours beyond their TTL
424 set beresp.grace = 6h; 424 set beresp.grace = 6h;
425   425  
426 return (deliver); 426 return (deliver);
427 } 427 }
428   428  
429 # The routine when we deliver the HTTP request to the user 429 # The routine when we deliver the HTTP request to the user
430 # Last chance to modify headers that are sent to the client 430 # Last chance to modify headers that are sent to the client
431 sub vcl_deliver { 431 sub vcl_deliver {
432 # Called before a cached object is delivered to the client. 432 # Called before a cached object is delivered to the client.
433   433  
434 if (obj.hits > 0) { # Add debug header to see if it's a HIT/MISS and the number of hits, disable when not needed 434 if (obj.hits > 0) { # Add debug header to see if it's a HIT/MISS and the number of hits, disable when not needed
435 set resp.http.X-Cache = "HIT"; 435 set resp.http.X-Cache = "HIT";
436 } else { 436 } else {
437 set resp.http.X-Cache = "MISS"; 437 set resp.http.X-Cache = "MISS";
438 } 438 }
439   439  
440 # Please note that obj.hits behaviour changed in 4.0, now it counts per objecthead, not per object 440 # Please note that obj.hits behaviour changed in 4.0, now it counts per objecthead, not per object
441 # and obj.hits may not be reset in some cases where bans are in use. See bug 1492 for details. 441 # and obj.hits may not be reset in some cases where bans are in use. See bug 1492 for details.
442 # So take hits with a grain of salt 442 # So take hits with a grain of salt
443 set resp.http.X-Cache-Hits = obj.hits; 443 set resp.http.X-Cache-Hits = obj.hits;
444   444  
445 ### 445 ###
446 ## Remove some headers: PHP version 446 ## Remove some headers: PHP version
447 unset resp.http.X-Powered-By; 447 unset resp.http.X-Powered-By;
448 ## Remove some headers: Apache version & OS 448 ## Remove some headers: Apache version & OS
449 unset resp.http.Server; 449 unset resp.http.Server;
450 unset resp.http.X-Drupal-Cache; 450 unset resp.http.X-Drupal-Cache;
451 unset resp.http.X-Varnish; 451 unset resp.http.X-Varnish;
452 unset resp.http.Via; 452 unset resp.http.Via;
453 unset resp.http.Link; 453 unset resp.http.Link;
454 unset resp.http.X-Generator; 454 unset resp.http.X-Generator;
455 unset resp.http.X-Powered-By; 455 unset resp.http.X-Powered-By;
456   456  
457 return (deliver); 457 return (deliver);
458 } 458 }
459   459  
460 sub vcl_purge { 460 sub vcl_purge {
461 # Only handle actual PURGE HTTP methods, everything else is discarded 461 # Only handle actual PURGE HTTP methods, everything else is discarded
462 if (req.method != "PURGE") { 462 if (req.method != "PURGE") {
463 # restart request 463 # restart request
464 set req.http.X-Purge = "Yes"; 464 set req.http.X-Purge = "Yes";
465 return(restart); 465 return(restart);
466 } 466 }
467 } 467 }
468   468  
469 sub vcl_synth { 469 sub vcl_synth {
470 if (resp.status == 720) { 470 if (resp.status == 720) {
471 # We use this special error status 720 to force redirects with 301 (permanent) redirects 471 # We use this special error status 720 to force redirects with 301 (permanent) redirects
472 # To use this, call the following from anywhere in vcl_recv: return (synth(720, "http://host/new.html")); 472 # To use this, call the following from anywhere in vcl_recv: return (synth(720, "http://host/new.html"));
473 set resp.http.Location = resp.reason; 473 set resp.http.Location = resp.reason;
474 set resp.status = 301; 474 set resp.status = 301;
475 return (deliver); 475 return (deliver);
476 } elseif (resp.status == 721) { 476 } elseif (resp.status == 721) {
477 # And we use error status 721 to force redirects with a 302 (temporary) redirect 477 # And we use error status 721 to force redirects with a 302 (temporary) redirect
478 # To use this, call the following from anywhere in vcl_recv: return (synth(720, "http://host/new.html")); 478 # To use this, call the following from anywhere in vcl_recv: return (synth(720, "http://host/new.html"));
479 set resp.http.Location = resp.reason; 479 set resp.http.Location = resp.reason;
480 set resp.status = 302; 480 set resp.status = 302;
481 return (deliver); 481 return (deliver);
482 } 482 }
483   483  
484 return (deliver); 484 return (deliver);
485 } 485 }
486   486  
487   487  
488 sub vcl_fini { 488 sub vcl_fini {
489 # Called when VCL is discarded only after all requests have exited the VCL. 489 # Called when VCL is discarded only after all requests have exited the VCL.
490 # Typically used to clean up VMODs. 490 # Typically used to clean up VMODs.
491   491  
492 return (ok); 492 return (ok);
493 } 493 }
494   494  
495 sub vcl_backend_error { 495 sub vcl_backend_error {
496 # Called when the backend cannot be reached. 496 # Called when the backend cannot be reached.
497 # Display an HTML file located at /etc/varnish/500.html 497 # Display an HTML file located at /etc/varnish/500.html
498 set beresp.http.Content-Type = "text/html; charset=utf-8"; 498 set beresp.http.Content-Type = "text/html; charset=utf-8";
499 synthetic(std.fileread("/etc/varnish/500.html")); 499 synthetic(std.fileread("/etc/varnish/500.html"));
500 return (deliver); 500 return (deliver);
501 } 501 }
502   502