how to redirect from www to non-www varnish

How do I go about automatically redirect any link of the type www.example.com to example.com.

I would like to do this for all link that hits the varnish instance (so i don't have to individually define the value for all domain that hits the server).

I tried using the following:

if(req.http.host ~ "^www\.(.+)$"){
    set req.http.host = regsub(req.http.host, "^www\.", "");
}

It works, but the problem with that is it's hitting the right backend, but it's not redirecting. I understand from here: https://www.varnish-cache.org/vmod/redirect you can redirect to a url, but I am not sure how to get the "full" url from varnish to strip out the www and redirect.

Any help would be appreciated!

Thanks a lot!

Jason


Solution 1:

Varnish does not have a native mechanism for redirection from vcl_recv(). Instead you have to throw an error from vcl_recv() to be caught in vcl_error(). This is because vcl_recv() doesn't have access to the response object. You can read about how this is done. Below is my attempt at an answer in terms of your situation.

In vcl_recv():

if (req.http.host ~ "^www\.") {
  error 750 regsub(req.http.host, "^www\.(.*)", "http://\1"); //Capture everything after the www. and place it after a http://
}

In vcl_error():

if (obj.status == 750) {
    set obj.http.Location = obj.response;
    set obj.status = 302;
    return(deliver);
}

Solution 2:

vcl 4.0;

sub vcl_recv {
   if (req.http.host ~ "^([-0-9a-zA-Z]+)\.([a-zA-Z]+)$") {
    return (synth (750, ""));
   }
}

sub vcl_synth {
   if (resp.status == 750) {
    set resp.status = 301;
    set resp.http.Location = "http://www." + req.http.host + req.url;
    return(deliver);
   }
}