Skip to content

Instantly share code, notes, and snippets.

@eksiscloud
Last active February 7, 2021 14:33
Show Gist options
  • Save eksiscloud/935a1af43c4586f0868a00cabcf7df6f to your computer and use it in GitHub Desktop.
Save eksiscloud/935a1af43c4586f0868a00cabcf7df6f to your computer and use it in GitHub Desktop.
default.vcl for Varnish (Wordpress, Woocommerce, LearnDash)
## Jakke Lehtonen
## by several sources
## Varnish default.vcl for Wordpress, Woocommerce, LearnDash, PMPro, bbPress etc.
## Just for one domain and one server, but can use for several servers AFAIK
#
# Lets's start caching
#
# Marker to tell the VCL compiler that this VCL has been adapted to the 4.0 format.
vcl 4.0;
# import directors; # Load the vmod_directors
import std; # Load the std, not STD for god sake
# Default backend definition. Set this to point to your content server.
backend default { # use your servers instead default if you have more than just one
.host = "127.0.0.1"; # IP or Hostname of backend
.port = "8080"; # Apache or whatever is listening
.max_connections = 800; # That's it enough
.first_byte_timeout = 300s; # How long to wait before we receive a first byte from our backend?
.connect_timeout = 300s; # How long to wait for a backend connection?
.between_bytes_timeout = 300s; # How long to wait between bytes received from our backend?
.probe = { # Is the backend healthy?
.url = "/index.html"; # Checking out root
.timeout = 2s; # How long should wait for respons; DO is slow, so I can't use 40ms
.interval = 5s; # How often shall we poll
.window = 4; # Out of this many tries...
.threshold = 3; # ...this many must be under timeout, otherwise giving gracetime
}
}
# Only allow purging from specific IPs
acl purge {
"localhost";
"127.0.0.1";
"1p-address"; # eth0
}
#################### vcl_init ##################
# Called when VCL is loaded, before any requests pass through it. Typically used to initialize VMODs.
# You have to define server at backend definition too.
# If using default, keep this commented
sub vcl_init {
#new cluster1 = directors.round_robin();
#cluster1.add_backend(server1);
#cluster1.add_backend(server2);
}
##################### vcl_recv #################
# vcl_recv function is used when a request is send by a HTTP client (Browser)
# Called at the beginning of a request, after the complete request has been received and parsed.
# Its purpose is to decide whether or not to serve the request, how to do it, and, if applicable,
# which backend to use.
# Also used to modify the request
sub vcl_recv {
# Your lifeline: Turn OFF cache
# For caching keep this commented
# return(pass);
# drops amp
if (req.url ~ "/amp/") {
return (pass);
}
# Fix Wordpress visual editor issues, must be the first one to work
if (req.url ~ "/wp-(login|admin|comments-post.php|cron)" || req.url ~ "preview=true" || req.url ~ "xmlrpc.php") {
return (pass);
}
# send all traffic to the vdir director
#set req.backend_hint = cluster1.backend();
# Normalize the header, remove the port (in case you're testing this on various TCP ports)
set req.http.Host = regsub(req.http.Host, ":[0-9]+", "");
# Normalize hostname to avoid double caching
set req.http.host = regsub(req.http.host,
"^example\.com$", "www.example.com");
# Remove the proxy header (see https://httpoxy.org/#mitigate-varnish)
unset req.http.proxy;
# Save Origin in a custom header
set req.http.X-Saved-Origin = req.http.Origin;
# Remove Origin from the request so that backend doesn’t add CORS headers.
unset req.http.Origin;
# Allow purging from ACL
if (req.method == "PURGE") {
# If not allowed then a error 405 is returned
if (!client.ip ~ purge) {
return(synth(405, "This IP is not allowed to send PURGE requests."));
}
# If allowed, do a cache_lookup -> vlc_hit() or vlc_miss()
return (purge);
}
# Only deal with "normal" types
if (req.method != "GET" &&
req.method != "HEAD" &&
req.method != "PUT" &&
req.method != "POST" &&
req.method != "TRACE" &&
req.method != "OPTIONS" &&
req.method != "PATCH" &&
req.method != "DELETE") {
# Non-RFC2616 or CONNECT which is weird. */
# Why send the packet upstream, while the visitor is using a non-valid HTTP method? */
return (synth(404, "Non-valid HTTP method!"));
}
# Implementing websocket support (https://www.varnish-cache.org/docs/4.0/users-guide/vcl-example-websockets.html)
if (req.http.Upgrade ~ "(?i)websocket") {
return (pipe);
}
# Some generic URL manipulation, useful for all templates that follow
# First remove URL parameters used to track effectiveness of online marketing campaigns
if (req.url ~ "(\?|&)(utm_[a-z]+|gclid|cx|ie|cof|siteurl|fbclid)=") {
set req.url = regsuball(req.url, "(utm_[a-z]+|gclid|cx|ie|cof|siteurl|fbclid)=[-_A-z0-9+()%.]+&?", "");
set req.url = regsub(req.url, "[?|&]+$", "");
}
# Strip hash, server doesn't need it.
if (req.url ~ "\#") {
set req.url = regsub(req.url, "\#.*$", "");
}
# Strip a trailing ? if it exists
if (req.url ~ "\?$") {
set req.url = regsub(req.url, "\?$", "");
}
# Enable smart refreshing
# Remember your header Cache-Control must be set something else than no-cache
# Otherwise everythiong will miss
if (req.http.Cache-Control ~ "no-cache" && client.ip ~ purge) {
set req.hash_always_miss = true;
}
# If you are using SSL and it doesn't forward http to https when URL is given without protocol
if ( req.http.X-Forwarded-Proto !~ "(?i)https" ) {
set req.http.x-Redir-Url = "https://" + req.http.host + req.url;
return ( synth( 750 ));
}
# Setting http headers for backend
set req.http.X-Forwarded-For = client.ip;
set req.http.X-Forwarded-Proto = "https";
# Unset headers that might cause us to cache duplicate infos
unset req.http.Accept-Language;
unset req.http.User-Agent;
### Do not Cache: special cases ###
# Do not cache AJAX requests.
if (req.http.X-Requested-With == "XMLHttpRequest") {
return(pass);
}
# Post requests will not be cached
if (req.http.Authorization || req.method == "POST") {
return (pass);
}
## Wordpress, Woocommerce, etc ##
# Don't cache post and edit pages
if (req.url ~ "/wp-(post.php|edit.php)") {
return(pass);
}
# Don't cache logged-in user and cart
if ( req.http.cookie ~ "wordpress_logged_in|resetpass" ) {
return( pass );
}
#fixed non AJAX cart problem
if (req.http.cookie ~ "woocommerce_(cart|session)|wp_woocommerce_session") {
#return(lookup); # not worked for me, return can¨t be lookup. Trying pass instead
return(pass);
}
#Hit everything else, you propably don't have all this
if (!req.url ~ "/wp-(login|admin|cron)|logout|lost-password|wc-api|cart|my-account|checkout|addons|administrator|member|course|product|resetpass") {
unset req.http.cookie;
}
# This is for phpmyadmin
if (req.http.Host == "pmadomain.com") {
return (pass);
}
# Pass the Woocommerce related
if (req.url ~ "/(cart|my-account|checkout|wc-api|addons|logout|lost-password|administrator|\?wc-ajax=get_refreshed_fragments)") {
return (pass);
}
# Pass the Store related
if (req.url ~ "/(store|product)") {
return (pass);
}
# Page of contact form
if (req.url ~ "/(contact)") {
return (pass);
}
# Pass Let's Encrypt
if (req.url ~ "^/\.well-known/acme-challenge/") {
return (pass);
}
# Did not cache the RSS feed
if (req.url ~ "/feed") {
return (pass);
}
# Must Use plugins I reckon
if (req.url ~ "/mu-.*") {
return (pass);
}
# Paid memberships Pro
if ( req.url ~ "(membership-account|membership-account|membership-checkout|#login-panel)" ) {
return (pass);
}
# phpBB Logged in users and ACP
if ( req.url ~ "(/forumPM/adm/|ucp.php?mode=|\?mode=edit)" ) {
return (pass);
}
# Pass through the WooCommerce API
if (req.url ~ "\?wc-api=" ) {
return (pass);
}
# Pass through the WooCommerce add to cart
if (req.url ~ "\?add-to-cart=" ) {
return (pass);
}
if (req.url ~ "\?wc-ajax=" ) {
return (pass);
}
## Cookies
# Remove the "has_js" cookie
set req.http.Cookie = regsuball(req.http.Cookie, "has_js=[^;]+(; )?", "");
# Remove any Google Analytics based cookies
set req.http.Cookie = regsuball(req.http.Cookie, "__utm.=[^;]+(; )?", "");
set req.http.Cookie = regsuball(req.http.Cookie, "_ga=[^;]+(; )?", "");
set req.http.Cookie = regsuball(req.http.Cookie, "_gali=[^;]+(; )?", "");
set req.http.Cookie = regsuball(req.http.Cookie, "_gid=[^;]+(; )?", "");
set req.http.Cookie = regsuball(req.http.Cookie, "utmctr=[^;]+(; )?", "");
set req.http.Cookie = regsuball(req.http.Cookie, "utmcmd.=[^;]+(; )?", "");
set req.http.Cookie = regsuball(req.http.Cookie, "utmccn.=[^;]+(; )?", "");
# Remove the Quant Capital cookies (added by some plugin, all __qca)
set req.http.Cookie = regsuball(req.http.Cookie, "__qc.=[^;]+(; )?", "");
# Remove the wp-settings-1 cookie
set req.http.Cookie = regsuball(req.http.Cookie, "wp-settings-1=[^;]+(; )?", "");
# Remove the wp-settings-time-1 cookie
set req.http.Cookie = regsuball(req.http.Cookie, "wp-settings-time-1=[^;]+(; )?", "");
# Remove the wp test cookie
set req.http.Cookie = regsuball(req.http.Cookie, "wordpress_test_cookie=[^;]+(; )?", "");
# Remove the phpBB cookie. This will help us cache bots and anonymous users.
#set req.http.Cookie = regsuball(req.http.Cookie, "style_cookie=[^;]+(; )?", "");
#set req.http.Cookie = regsuball(req.http.Cookie, "phpbb3_psyfx_track=[^;]+(; )?", "");
# Remove the PHPSESSID in members area cookie
set req.http.Cookie = regsuball(req.http.Cookie, "PHPSESSID=[^;]+(; )?", "");
# Remove DoubleClick offensive cookies
set req.http.Cookie = regsuball(req.http.Cookie, "__gads=[^;]+(; )?", "");
# Remove the AddThis cookies
set req.http.Cookie = regsuball(req.http.Cookie, "__atuv.=[^;]+(; )?", "");
# Remove Woocommerce cookies, all three
set req.http.Cookie = regsuball(req.http.Cookie, "woocommerce_cart_hash=[^;]+(; )?", "");
set req.http.Cookie = regsuball(req.http.Cookie, "woocommerce_items_in_cart=[^;]+(; )?", "");
set req.http.Cookie = regsuball(req.http.Cookie, "wp_woocommerce_session_=[^;]+(; )?", "");
# Remove PMPro
set req.http.Cookie = regsuball(req.http.Cookie, "pmpro_visit=[^;]+(; )?", "");
# Jetpack by Automattic, are this really needed? I don't think so
#set req.http.Cookie = regsuball(req.http.Cookie, "tk_or=[^;]+(; )?", "");
#set req.http.Cookie = regsuball(req.http.Cookie, "tk_r3d=[^;]+(; )?", "");
#set req.http.Cookie = regsuball(req.http.Cookie, "tk_lr=[^;]+(; )?", "");
#set req.http.Cookie = regsuball(req.http.Cookie, "tk_ni=[^;]+(; )?", "");
#set req.http.Cookie = regsuball(req.http.Cookie, "tk_ai=[^;]+(; )?", "");
#set req.http.Cookie = regsuball(req.http.Cookie, "tk_qs=[^;]+(; )?", "");
# Facebook Ads, same here, useless
#set req.http.Cookie = regsuball(req.http.Cookie, "_fbp=[^;]+(; )?", "");
# _wp_session
set req.http.Cookie = regsuball(req.http.Cookie, "_wp_session=[^;]+(; )?", "");
# Check the cookies for wordpress-comment items I reckon
if (req.http.Cookie ~ "comment_") {
return (pass);
}
# Do not pass other cookies
if (!req.http.cookie) {
unset req.http.cookie;
}
# Are there cookies left with only spaces or that are empty?
if (req.http.cookie ~ "^ *$") {
unset req.http.cookie;
}
## Back to more general things
# Normalize the query arguments.
# Note: Placing this above the "do not cache" section breaks some WP theme elements and admin functionality.
set req.url = std.querysort(req.url);
# Large static files are delivered directly to the end-user without
# waiting for Varnish to fully read the file first.
# Varnish 4 fully supports Streaming, so see do_stream in vcl_backend_response() to witness the glory.
if (req.url ~ "^[^?]*\.(mp[34]|rar|tar|tgz|wav|zip|bz2|xz|7z|avi|mov|ogm|mpe?g|mk[av])(\?.*)?$") {
unset req.http.Cookie;
return (hash);
}
# Cache all static files by Removing all cookies for static files
# Remember, do you really need to cache static files that don't cause load? Only if you have memory left.
# Here I decide to cache these static files. For me, most of them are handled by the CDN anyway.
if (req.url ~ "^[^?]*\.(bmp|bz2|css|doc|eot|flv|gif|ico|jpeg|jpg|js|less|pdf|png|rtf|swf|txt|woff|xml)(\?.*)?$") {
unset req.http.Cookie;
return (hash);
}
# Normalize Accept-Encoding header and compression
# https://www.varnish-cache.org/docs/3.0/tutorial/vary.html
if (req.http.Accept-Encoding) {
# Do no compress compressed files...
if (req.url ~ "\.(jpg|png|gif|gz|tgz|bz2|tbz|mp3|ogg)$") {
unset req.http.Accept-Encoding;
} elsif (req.http.Accept-Encoding ~ "gzip") {
set req.http.Accept-Encoding = "gzip";
} elsif (req.http.Accept-Encoding ~ "deflate") {
set req.http.Accept-Encoding = "deflate";
} else {
unset req.http.Accept-Encoding;
}
}
# Cache all static files by Removing all cookies for static files.
if (req.url ~ "^[^?]*\.(html|htm|gz)(\?.*)?$") {
unset req.http.Cookie;
return (hash);
}
# Do not cache HTTP authentication and HTTP Cookie
if (req.http.Authorization || req.http.Cookie) {
return (pass);
}
# Send Surrogate-Capability headers to announce ESI support to backend
set req.http.Surrogate-Capability = "key=ESI/1.0";
# Cache all others requests if they reach this point
return (hash);
}
################### vcl_pipe #######################
# Called upon entering pipe mode.
# In this mode, the request is passed on to the backend, and any further data from both the client
# and backend is passed on unaltered until either end closes the connection. Basically, Varnish will
# degrade into a simple TCP proxy, shuffling bytes back and forth. For a connection in pipe mode,
# no other VCL subroutine will ever get called after vcl_pipe.
# Note that only the first request to the backend will have
# X-Forwarded-For set. If you use X-Forwarded-For and want to
# have it set for all requests, make sure to have:
# set bereq.http.connection = "close";
# here. It is not set by default as it might break some broken web
# applications, like IIS with NTLM authentication.
sub vcl_pipe {
# set bereq.http.Connection = "Close";
# Implementing websocket support (https://www.varnish-cache.org/docs/4.0/users-guide/vcl-example-websockets.html)
if (req.http.upgrade) {
set bereq.http.upgrade = req.http.upgrade;
}
return (pipe);
}
################### vcl_pass #######################
# Called upon entering pass mode. In this mode, the request is passed on to the backend, and the
# backend's response is passed on to the client, but is not entered into the cache. Subsequent
# requests submitted over the same client connection are handled normally.
sub vcl_pass {
#return (pass);
}
################### vcl_hash #######################
# The data on which the hashing will take place
# Called after vcl_recv to create a hash value for the request. This is used as a key
# to look up the object in Varnish.
sub vcl_hash {
hash_data(req.url);
if (req.http.host) {
hash_data(req.http.host);
} else {
hash_data(server.ip);
}
# hash cookies for requests that have them
if (req.http.Cookie) {
hash_data(req.http.Cookie);
}
# If the client supports compression, keep that in a different cache
if (req.http.Accept-Encoding) {
hash_data(req.http.Accept-Encoding);
}
return (lookup);
#this is to store cache based on PHPSESSID or woocommerce cookie so cart doesn't show 0
if (req.http.cookie) {
hash_data(req.http.cookie);
}
#fix flexible ssl css
if (req.http.x-forwarded-proto) {
hash_data(req.http.x-forwarded-proto);
}
}
################### vcl_hit #################
# Call if cached
#
sub vcl_hit {
if (obj.ttl >= 0s) {
# A pure unadultered hit, deliver it
return (deliver);
}
}
################# vcl_miss #####################
#
# Called after a cache lookup if the requested document was not found in the cache
#
sub vcl_miss {
return (fetch);
}
#################### vcl_backend_response ###################
# Handle the HTTP request coming from our backend
# Called after the response headers has been successfully retrieved from the backend.
sub vcl_backend_response {
# Pause ESI request and remove Surrogate-Control header
if (beresp.http.Surrogate-Control ~ "ESI/1.0") {
unset beresp.http.Surrogate-Control;
set beresp.do_esi = true;
}
# Sometimes, a 301 or 302 redirect formed via Apache's mod_rewrite can mess with the HTTP port that is being passed along.
# This often happens with simple rewrite rules in a scenario where Varnish runs on :80 and Apache on :8080 on the same box.
# A redirect can then often redirect the end-user to a URL on :8080, where it should be :80.
# This may need fine tuning on your setup.
# To prevent accidental replace, we only filter the 301/302 redirects for now.
if (beresp.status == 301 || beresp.status == 302) {
set beresp.http.Location = regsub(beresp.http.Location, ":[0-9]+", "");
}
# fix for empty cart issue
if (!(bereq.url ~ "wp-(login|admin)|^cart|^my-account|^checkout|wc-api|resetpass") &&
!bereq.http.cookie ~ "wordpress_logged_in|woocommerce_cart_hash|woocommerce_items_in_cart|wp_woocommerce_session_|resetpass" &&
!beresp.status == 302 ) {
unset beresp.http.set-cookie;
set beresp.ttl = 1w;
set beresp.grace = 1h;
}
## Overall TTL
## Note: The TTL is designed to be somewhat aggressive here, to keep things in cache.
#
# Lets get this party started.
#Varnish keep 1 year (or when purged), client 24 hour
if (beresp.ttl > 0s) {
#use this if you want use max-age
# Remove Expires from backend, it's not long enough
unset beresp.http.expires;
# Set the clients TTL on this object
set beresp.http.cache-control = "max-age=86400";
# Set how long Varnish will keep it
set beresp.ttl = 1y;
# marker for vcl_deliver to reset Age
set beresp.http.magicmarker = "1";
#or this one, if you want to use expires header
# We are using seconds
#set beresp.http.x-obj-ttl = beresp.ttl + "s";
}
# Allow stale content, in case the backend goes down.
# make Varnish keep all objects for x hours beyond their TTL
set beresp.grace = 8h;
# Enable cache for all static files
# Monitor your cache size, if you get data nuked out of it, consider giving up the static file cache.
# More reading here: https://ma.ttias.be/stop-caching-static-files/
if (bereq.url ~ "^[^?]*\.(bmp|bz2|css|doc|eot|flv|gif|ico|jpeg|jpg|js|less|mp[34]|pdf|png|rar|rtf|swf|tar|tgz|txt|wav|woff|xml|zip)(\?.*)?$") {
set beresp.ttl = 365d; # set a TTL for these optional.
unset beresp.http.set-cookie;
}
# Cache all static files by Removing all cookies for static files - Note: These file extensions are generated by WordPress WP Super Cache.
if (bereq.url ~ "^[^?]*\.(html|htm|gz)(\?.*)?$") {
set beresp.ttl = 365d; # set a TTL for these optional.
unset beresp.http.set-cookie;
}
## Targeted TTL
# Members section is very dynamic and uses cookies (see cookie settings in vcl_recv).
if (bereq.url ~ "/members/") {
set beresp.ttl = 1d;
}
# My Shop section is fairly static when browsing the catalog, but woocommerce is passed in vcl_recv.
if (bereq.url ~ "/store/") {
set beresp.ttl = 1d;
}
# phBB Forum
# Note: Cookies are dropped for phpBB in vcl_recv which disables the forums cookies, however, logged in users still get a hash.
# I set the anonymous user as a bot in phpBB admin settings. As bots dont use cookies, this gives 99% hit rate.
#if (bereq.url ~ "/forumPM/") {
#set beresp.ttl = 1h;
#}
# Long ttl sites
#if (bereq.url ~ "(example.com|example2.com)") {
# set beresp.ttl = 1w;
#}
# Large static files are delivered directly to the end-user without
# waiting for Varnish to fully read the file first.
# Varnish 4 fully supports Streaming, so use streaming here to avoid locking.
# I do not stream large files from my server, I use a CDN or dropbox, so I have not tested this.
if (bereq.url ~ "^[^?]*\.(mp[34]|rar|tar|tgz|wav|zip|bz2|xz|7z|avi|mov|ogm|mpe?g|mk[av])(\?.*)?$") {
unset beresp.http.set-cookie;
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
set beresp.do_gzip = false; # Don't try to compress it for storage
}
# don't cache response to posted requests or those with basic auth
if ( bereq.method == "POST" || bereq.http.Authorization ) {
set beresp.uncacheable = true;
set beresp.ttl = 120s;
return (deliver);
}
# Don't cache search results
if ( bereq.url ~ "\?s=" ){
set beresp.uncacheable = true;
set beresp.ttl = 120s;
return (deliver);
}
# Only cache status ok
if ( beresp.status != 200 ) {
set beresp.uncacheable = true;
set beresp.ttl = 120s;
return (deliver);
}
# Don't cache 50x responses
if (beresp.status == 500 || beresp.status == 502 || beresp.status == 503 || beresp.status == 504) {
return (abandon);
}
# Set 2min cache if unset for static files
# if (beresp.ttl <= 0s || beresp.http.Set-Cookie || beresp.http.Vary == "*") {
# set beresp.ttl = 120s; # Important, you shouldn't rely on this, SET YOUR HEADERS in the backend
# set beresp.uncacheable = true;
# return (deliver);
# }
return (deliver);
}
####################### vcl_deliver ########################
# The routine when we deliver the HTTP request to the user
# Last chance to modify headers that are sent to the client
# Called before a cached object is delivered to the client.
sub vcl_deliver {
if (req.http.X-Saved-Origin == "https://www.example.com"
|| req.http.X-Saved-Origin == "https://cdn.example.com"
|| req.http.X-Saved-Origin == "https://cdn2.example.com") {
set resp.http.Access-Control-Allow-Origin =
req.http.X-Saved-Origin;
}
if (resp.http.Vary) {
set resp.http.Vary = resp.http.Vary + ",Origin";
} else {
set resp.http.Vary = "Origin";
}
# HIT & MISS
if (obj.hits > 0) { # Add debug header to see if it's a HIT/MISS and the number of hits, disable when not needed
set resp.http.X-Mood = "HIT!";
} else {
set resp.http.X-Mood = "MISS...";
}
# Please note that obj.hits behaviour changed in 4.0, now it counts per objecthead, not per object
set resp.http.X-Cache-Wham = (obj.hits);
# If we are on max-age:
# Earlier we set 1 year for Varnish and 24 hour for client. Now it will finished
if (resp.http.magicmarker) {
# Remove the magic marker
unset resp.http.magicmarker;
# By definition we have a fresh object
set resp.http.age = "0";
}
# Or if you wanted to use headers instead:
# Dynamically set the Expires header on every request from the web.
#if (resp.http.x-obj-ttl) {
# 1. Calculate and reset the Expires header. (3600s is just a fallback value)
#set resp.http.Expires = "" + (now + std.duration(resp.http.x-obj-ttl, 604800s));
# 2. Delete the temporary header from the response.
#unset resp.http.x-obj-ttl;
#}
# Remove some headers:
unset resp.http.Server;
unset resp.http.X-Powered-By;
unset resp.http.X-Drupal-Cache;
unset resp.http.X-Varnish;
unset resp.http.Age;
unset resp.http.Via;
unset resp.http.Link;
unset resp.http.X-Generator;
unset resp.http.X-Mod-Pagespeed;
## You know you can set headers here?
set resp.http.Server = "WhiteHat v0.1";
set resp.http.X-Powered-by = "Talisker and one drop water";
set resp.http-X-Mood = "some good old blues";
return (deliver);
}
#################### vcl_purge #################
#
#
sub vcl_purge {
# Only handle actual PURGE HTTP methods, everything else is discarded
if (req.method == "PURGE") {
# restart request
set req.http.X-Purge = "Yes";
return (restart);
}
}
##################### vcl_synth #####################
#
#
sub vcl_synth {
if (resp.status == 720) {
# We use this special error status 720 to force redirects with 301 (permanent) redirects
# To use this, call the following from anywhere in vcl_recv: return (synth(720, "http://host/new.html"));
set resp.http.Location = resp.reason;
set resp.status = 301;
return (deliver);
} elseif (resp.status == 721) {
# And we use error status 721 to force redirects with a 302 (temporary) redirect
# To use this, call the following from anywhere in vcl_recv: return (synth(720, "http://host/new.html"));
set resp.http.Location = resp.reason;
set resp.status = 302;
return (deliver);
}
return (deliver);
# because of force to https - or something
if (resp.status == 750) {
set resp.status = 301;
set resp.http.Location = req.http.x-Redir-Url;
return(deliver);
}
}
####################### vcl_fini #######################
#
sub vcl_fini {
# Called when VCL is discarded only after all requests have exited the VCL.
# Typically used to clean up VMODs.
return (ok);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment