Add the following code into VCL_RECV:
vcl 4.0;
import std;
sub vcl_recv {
# Normalize trailing slash for directory & manage 301 redirection internally
if (req.http.Host !~ "^www\." ||
(req.url !~ {"(?x)
(?:/$) # last character isn't a slash
| # or
(?:/\?) # query string isn't immediately preceded by a slash
"}
&&
req.url ~ {"(?x)
(?:/[^./]+$) # last path segment doesn't contain a . no query string
| # or
(?:/[^.?]+\?) # last path segment doesn't contain a . with a query string
"}
)
)
{
return (synth(720,"Moved Permanently"));
}
}
Add the following code into 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;
set resp.http.Location = "http://";
set resp.http.Host = req.http.Host;
if (resp.http.Host !~ "^www\.") {
set resp.http.Host = "www." + resp.http.Host;
}
set resp.http.Location = resp.http.Location + resp.http.Host;
if (req.url ~ "(?:/[^./]+$)|(?:/[^.?]+\?)") {
# no . in last path segment before optional query string
if (req.url !~ "/$" && req.url !~ "\?") {
# no trailing slash and no query string
set resp.http.Location = resp.http.Location + req.url + "/";
} elseif (req.url ~ "[^/]\?") {
# no trailing slash and with query string, preserve it
set resp.http.Location = resp.http.Location + regsub(req.url, "([^?]+)\?.*", "\1") + "/" + regsub(req.url, "[^?]+(\?.*)", "\1");
} elseif (resp.http.Host != req.http.Host) {
# trailing slash rule met, handle missing www. scenario
set resp.http.Location = resp.http.Location + req.url;
}
} elseif (resp.http.Host != req.http.Host) {
# last path segment contains a . so handle missing www. scenario
set resp.http.Location = resp.http.Location + req.url;
}
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);
}