1+ # VCL version 5.0 is not supported so it should be 4.0 even though actually used Varnish version is 5
12vcl 4.0 ;
23
34import std;
4- import directors;
5+ # The minimal Varnish version is 5.0
6+ # For SSL offloading, pass the following header in your proxy server or load balancer: 'X-Forwarded-Proto: https'
57
6- #AUTOGENERATED_START
7- backend apache_1 {
8+ backend default {
89 .host = "apache" ;
910 .port = "80" ;
11+ .first_byte_timeout = 600s ;
12+ .probe = {
13+ .url = "/pub/health_check.php" ;
14+ .timeout = 2s ;
15+ .interval = 5s ;
16+ .window = 10 ;
17+ .threshold = 5 ;
18+ }
1019}
1120
12- sub vcl_init {
13- new cluster1 = directors.round_robin();
14- cluster1.add_backend(apache_1);
15- }
16-
17- sub vcl_recv {
18- set req.backend _hint = cluster1.backend ();
19- }
20- #AUTOGENERATED_END
21-
2221acl purge {
2322 "apache" ;
2423}
@@ -28,10 +27,18 @@ sub vcl_recv {
2827 if (client.ip !~ purge) {
2928 return (synth(405 , "Method not allowed" ));
3029 }
31- if (! req.http.X-Magento-Tags-Pattern ) {
32- return (synth(400 , "X-Magento-Tags-Pattern header required" ));
30+ # To use the X-Pool header for purging varnish during automated deployments, make sure the X-Pool header
31+ # has been added to the response in your backend server config. This is used, for example, by the
32+ # capistrano-magento2 gem for purging old content from varnish during it's deploy routine.
33+ if (! req.http.X-Magento-Tags-Pattern && ! req.http.X-Pool ) {
34+ return (synth(400 , "X-Magento-Tags-Pattern or X-Pool header required" ));
35+ }
36+ if (req.http.X-Magento-Tags-Pattern ) {
37+ ban("obj.http.X-Magento-Tags ~ " + req.http.X-Magento-Tags-Pattern );
38+ }
39+ if (req.http.X-Pool ) {
40+ ban("obj.http.X-Pool ~ " + req.http.X-Pool );
3341 }
34- ban("obj.http.X-Magento-Tags ~ " + req.http.X-Magento-Tags-Pattern );
3542 return (synth(200 , "Purged" ));
3643 }
3744
@@ -51,21 +58,55 @@ sub vcl_recv {
5158 return (pass );
5259 }
5360
54- # Bypass shopping cart and checkout requests
55- if (req.url ~ "/checkout" ) {
61+ # Bypass shopping cart, checkout and search requests
62+ if (req.url ~ "/checkout" || req.url ~ "/catalogsearch" ) {
5663 return (pass );
5764 }
5865
66+ # Bypass health check requests
67+ if (req.url ~ "/pub/health_check.php" ) {
68+ return (pass );
69+ }
70+
71+ # Set initial grace period usage status
72+ set req.http.grace = "none" ;
73+
5974 # normalize url in case of leading HTTP scheme and domain
6075 set req.url = regsub (req.url , "^http[s]?://" , "" );
6176
6277 # collect all cookies
6378 std.collect (req.http.Cookie );
6479
65- # static files are always cacheable. remove SSL flag and cookie
66- if (req.url ~ "^/(pub/)?(media|static)/.*\. (ico|css|js|jpg|jpeg|png|gif|tiff|bmp|mp3|ogg|svg|swf|woff|woff2|eot|ttf|otf)$" ) {
67- unset req.http.Https ;
68- unset req.http.Cookie ;
80+ # Compression filter. See https://www.varnish-cache.org/trac/wiki/FAQ/Compression
81+ if (req.http.Accept-Encoding ) {
82+ if (req.url ~ "\. (jpg|jpeg|png|gif|gz|tgz|bz2|tbz|mp3|ogg|swf|flv)$" ) {
83+ # No point in compressing these
84+ unset req.http.Accept-Encoding ;
85+ } elsif (req.http.Accept-Encoding ~ "gzip" ) {
86+ set req.http.Accept-Encoding = "gzip" ;
87+ } elsif (req.http.Accept-Encoding ~ "deflate" && req.http.user-agent !~ "MSIE" ) {
88+ set req.http.Accept-Encoding = "deflate" ;
89+ } else {
90+ # unknown algorithm
91+ unset req.http.Accept-Encoding ;
92+ }
93+ }
94+
95+ # Remove all marketing get parameters to minimize the cache objects
96+ if (req.url ~ "(\? |&)(gclid|cx|ie|cof|siteurl|zanpid|origin|fbclid|mc_[a-z]+|utm_[a-z]+|_bta_[a-z]+)=" ) {
97+ set req.url = regsuball (req.url , "(gclid|cx|ie|cof|siteurl|zanpid|origin|fbclid|mc_[a-z]+|utm_[a-z]+|_bta_[a-z]+)=[-_A-z0-9+()%.]+&?" , "" );
98+ set req.url = regsub (req.url , "[?|&]+$" , "" );
99+ }
100+
101+ # Static files caching
102+ if (req.url ~ "^/(pub/)?(media|static)/" ) {
103+ # Static files should not be cached by default
104+ return (pass );
105+
106+ # But if you use a few locales and don't use CDN you can enable caching static files by commenting previous line (#return (pass);) and uncommenting next 3 lines
107+ #unset req.http.Https;
108+ #unset req.http.X-Forwarded-Proto;
109+ #unset req.http.Cookie;
69110 }
70111
71112 return (hash );
@@ -76,9 +117,37 @@ sub vcl_hash {
76117 hash_data(regsub (req.http.cookie , "^.*?X-Magento-Vary=([^;]+);*.*$" , "\1 " ));
77118 }
78119
120+ # For multi site configurations to not cache each other's content
121+ if (req.http.host ) {
122+ hash_data(req.http.host );
123+ } else {
124+ hash_data(server.ip );
125+ }
126+
127+ # To make sure http users don't see ssl warning
128+ if (req.http.X-Forwarded-Proto ) {
129+ hash_data(req.http.X-Forwarded-Proto );
130+ }
131+
132+
133+ if (req.url ~ "/graphql" ) {
134+ call process_graphql_headers ;
135+ }
136+ }
137+
138+ sub process_graphql_headers {
139+ if (req.http.Store ) {
140+ hash_data(req.http.Store );
141+ }
142+ if (req.http.Content-Currency ) {
143+ hash_data(req.http.Content-Currency );
144+ }
79145}
80146
81147sub vcl_backend_response {
148+
149+ set beresp.grace = 3d ;
150+
82151 if (beresp.http.content-type ~ "text" ) {
83152 set beresp.do_esi = true ;
84153 }
@@ -87,6 +156,10 @@ sub vcl_backend_response {
87156 set beresp.do_gzip = true ;
88157 }
89158
159+ if (beresp.http.X-Magento-Debug ) {
160+ set beresp.http.X-Magento-Cache-Control = beresp.http.Cache-Control ;
161+ }
162+
90163 # cache only successfully responses and 404s
91164 if (beresp.status != 200 && beresp.status != 404 ) {
92165 set beresp.ttl = 0s ;
@@ -98,35 +171,44 @@ sub vcl_backend_response {
98171 return (deliver );
99172 }
100173
101- if (beresp.http.X-Magento-Debug ) {
102- set beresp.http.X-Magento-Cache-Control = beresp.http.Cache-Control ;
103- }
104-
105174 # validate if we need to cache it and prevent from setting cookie
106- # images, css and js are cacheable by default so we have to remove cookie also
107175 if (beresp.ttl > 0s && (bereq.method == "GET" || bereq.method == "HEAD" )) {
108176 unset beresp.http.set-cookie ;
109- if (bereq.url !~ "\. (ico|css|js|jpg|jpeg|png|gif|tiff|bmp|gz|tgz|bz2|tbz|mp3|ogg|svg|swf|woff|woff2|eot|ttf|otf)(\? |$)" ) {
110- set beresp.http.Pragma = "no-cache" ;
111- set beresp.http.Expires = "-1" ;
112- set beresp.http.Cache-Control = "no-store, no-cache, must-revalidate, max-age=0" ;
113- set beresp.grace = 1m ;
114- }
115177 }
178+
179+ # If page is not cacheable then bypass varnish for 2 minutes as Hit-For-Pass
180+ if (beresp.ttl <= 0s ||
181+ beresp.http.Surrogate-control ~ "no-store" ||
182+ (! beresp.http.Surrogate-Control &&
183+ beresp.http.Cache-Control ~ "no-cache|no-store" ) ||
184+ beresp.http.Vary == "*" ) {
185+ # Mark as Hit-For-Pass for the next 2 minutes
186+ set beresp.ttl = 120s ;
187+ set beresp.uncacheable = true ;
188+ }
189+
116190 return (deliver );
117191}
118192
119193sub vcl_deliver {
120194 if (resp.http.X-Magento-Debug ) {
121195 if (resp.http.x-varnish ~ " " ) {
122196 set resp.http.X-Magento-Cache-Debug = "HIT" ;
197+ set resp.http.Grace = req.http.grace ;
123198 } else {
124199 set resp.http.X-Magento-Cache-Debug = "MISS" ;
125200 }
126201 } else {
127202 unset resp.http.Age ;
128203 }
129204
205+ # Not letting browser to cache non-static files.
206+ if (resp.http.Cache-Control !~ "private" && req.url !~ "^/(pub/)?(media|static)/" ) {
207+ set resp.http.Pragma = "no-cache" ;
208+ set resp.http.Expires = "-1" ;
209+ set resp.http.Cache-Control = "no-store, no-cache, must-revalidate, max-age=0" ;
210+ }
211+
130212 unset resp.http.X-Magento-Debug ;
131213 unset resp.http.X-Magento-Tags ;
132214 unset resp.http.X-Powered-By ;
@@ -135,3 +217,24 @@ sub vcl_deliver {
135217 unset resp.http.Via ;
136218 unset resp.http.Link ;
137219}
220+
221+ sub vcl_hit {
222+ if (obj.ttl >= 0s ) {
223+ # Hit within TTL period
224+ return (deliver );
225+ }
226+ if (std.healthy(req.backend _hint)) {
227+ if (obj.ttl + 300s > 0s ) {
228+ # Hit after TTL expiration, but within grace period
229+ set req.http.grace = "normal (healthy server)" ;
230+ return (deliver );
231+ } else {
232+ # Hit after TTL and grace expiration
233+ return (miss);
234+ }
235+ } else {
236+ # server is not healthy, retrieve from cache
237+ set req.http.grace = "unlimited (unhealthy server)" ;
238+ return (deliver );
239+ }
240+ }
0 commit comments