{% block version -%} vcl 4.0; {% endblock %} # This Varnish VCL has been adapted from the Four Kitchens VCL for Varnish 3. # Default backend definition. Points to Apache, normally. backend default { {% block backend -%} .host = "{{ varnish_default_backend_host }}"; .port = "{{ varnish_default_backend_port }}"; .first_byte_timeout = 300s; {% endblock %} } # Access control list for PURGE requests. acl purge { {% block acl_purge -%} "127.0.0.1"; {% endblock %} } # Respond to incoming requests. sub vcl_recv { {% block http_header -%} # Add an X-Forwarded-For header with the client IP address. if (req.restarts == 0) { if (req.http.X-Forwarded-For) { set req.http.X-Forwarded-For = req.http.X-Forwarded-For + ", " + client.ip; } else { set req.http.X-Forwarded-For = client.ip; } } {% endblock %} {% block method_purge -%} # Only allow PURGE requests from IP addresses in the 'purge' ACL. if (req.method == "PURGE") { if (!client.ip ~ purge) { return (synth(405, "Not allowed.")); } return (purge); } {% endblock %} {% block method_ban -%} # Only allow BAN requests from IP addresses in the 'purge' ACL. if (req.method == "BAN") { # Same ACL check as above: if (!client.ip ~ purge) { return (synth(403, "Not allowed.")); } # Logic for the ban, using the Cache-Tags header. For more info # see https://github.com/geerlingguy/drupal-vm/issues/397. if (req.http.Cache-Tags) { ban("obj.http.Cache-Tags ~ " + req.http.Cache-Tags); } else { return (synth(403, "Cache-Tags header missing.")); } # Throw a synthetic page so the request won't go to the backend. return (synth(200, "Ban added.")); } {% endblock %} {% block pass_post -%} # Only cache GET and HEAD requests (pass through POST requests). if (req.method != "GET" && req.method != "HEAD") { return (pass); } {% endblock %} {% block pass_admin -%} # Pass through any administrative or AJAX-related paths. if (req.url ~ "^/status\.php$" || req.url ~ "^/update\.php$" || req.url ~ "^/admin$" || req.url ~ "^/admin/.*$" || req.url ~ "^/flag/.*$" || req.url ~ "^.*/ajax/.*$" || req.url ~ "^.*/ahah/.*$") { return (pass); } {% endblock %} {% block cookies -%} # Removing cookies for static content so Varnish caches these files. if (req.url ~ "(?i)\.(pdf|asc|dat|txt|doc|xls|ppt|tgz|csv|png|gif|jpeg|jpg|ico|swf|css|js)(\?.*)?$") { unset req.http.Cookie; } # Remove all cookies that Drupal doesn't need to know about. We explicitly # list the ones that Drupal does need, the SESS and NO_CACHE. If, after # running this code we find that either of these two cookies remains, we # will pass as the page cannot be cached. if (req.http.Cookie) { # 1. Append a semi-colon to the front of the cookie string. # 2. Remove all spaces that appear after semi-colons. # 3. Match the cookies we want to keep, adding the space we removed # previously back. (\1) is first matching group in the regsuball. # 4. Remove all other cookies, identifying them by the fact that they have # no space after the preceding semi-colon. # 5. Remove all spaces and semi-colons from the beginning and end of the # cookie string. set req.http.Cookie = ";" + req.http.Cookie; set req.http.Cookie = regsuball(req.http.Cookie, "; +", ";"); set req.http.Cookie = regsuball(req.http.Cookie, ";(SESS[a-z0-9]+|SSESS[a-z0-9]+|NO_CACHE)=", "; \1="); set req.http.Cookie = regsuball(req.http.Cookie, ";[^ ][^;]*", ""); set req.http.Cookie = regsuball(req.http.Cookie, "^[; ]+|[; ]+$", ""); if (req.http.Cookie == "") { # If there are no remaining cookies, remove the cookie header. If there # aren't any cookie headers, Varnish's default behavior will be to cache # the page. unset req.http.Cookie; } else { # If there is any cookies left (a session or NO_CACHE cookie), do not # cache the page. Pass it on to Apache directly. return (pass); } } {% endblock %} } # Set a header to track a cache HITs and MISSes. sub vcl_deliver { {% block vcl_deliver -%} # Remove ban-lurker friendly custom headers when delivering to client. unset resp.http.X-Url; unset resp.http.X-Host; unset resp.http.Purge-Cache-Tags; if (obj.hits > 0) { set resp.http.X-Varnish-Cache = "HIT"; } else { set resp.http.X-Varnish-Cache = "MISS"; } {% endblock %} } # Instruct Varnish what to do in the case of certain backend responses (beresp). sub vcl_backend_response { {% block vcl_backend_response -%} # Set ban-lurker friendly custom headers. set beresp.http.X-Url = bereq.url; set beresp.http.X-Host = bereq.http.host; # Cache 404s, 301s, at 500s with a short lifetime to protect the backend. if (beresp.status == 404 || beresp.status == 301 || beresp.status == 500) { set beresp.ttl = 10m; } # Enable streaming directly to backend for BigPipe responses. if (beresp.http.Surrogate-Control ~ "BigPipe/1.0") { set beresp.do_stream = true; set beresp.ttl = 0s; } # Don't allow static files to set cookies. # (?i) denotes case insensitive in PCRE (perl compatible regular expressions). # This list of extensions appears twice, once here and again in vcl_recv so # make sure you edit both and keep them equal. if (bereq.url ~ "(?i)\.(pdf|asc|dat|txt|doc|xls|ppt|tgz|csv|png|gif|jpeg|jpg|ico|swf|css|js)(\?.*)?$") { unset beresp.http.set-cookie; } # Allow items to remain in cache up to 6 hours past their cache expiration. set beresp.grace = 6h; {% endblock %} }