2

I'm building Drupal multisite with 35 sites (~60 different domains) and I'd like to redirect non-www urls to www regardless of domain.

Nginx is redirecting all domains to Drupal install folder.

I've tried to redirect domains with Nginx without success (is that even possible because of varnish?)

I was able to redirect single domain with Varnish (something like "if domain == xxx then redirect to www.domain.tld"), but I don't want to make own redirect rule for every domain.

4 Answers 4

1

I was able to do it with the following nginx config:

if ($host !~* ^www\.) {
   rewrite ^(.*)$ http://www.$host$1 permanent;
}
1
  • 1
    if varnish actually in front of nginx, it needs to redirect first, otherwise you will get multiple cookies and sessions, etc
    – ADM
    Apr 22, 2015 at 9:10
1
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);
   }
}
0

something like this from Varnish manuals will work:

sub vcl_recv {
    if (req.http.host ~ "^([-0-9a-zA-Z]+)\.([a-zA-Z]+)$") {
        error 750 regsub(req.http.host, "^([-0-9a-zA-Z]+)\.([a-zA-Z]+)$", "http:///www.\1.\2" + req.url);
    }


sub vcl_error {
    if (obj.status == 750) {
        set obj.http.Location = obj.response;
        set obj.status = 301;
        return(deliver);
    }
}
0

Non www to www redirections should be handled by Varnish before requesting backend, to avoid weird errors such as loops, no backend connection...

In sub vcl_recv (this is VCL 4 syntax) :

sub vcl_recv {
    #THIS IS THE IMPORTANT POINT
    #redirect non www to www domains ip no subdomain defined
    if (req.http.host ~ "^([-0-9a-zA-Z]+)\.([a-zA-Z]+)$") {
       return (synth (750, ""));
    }

    # Normalize the header, remove the port
    set req.http.host = regsub(req.http.host, ":[0-9]+", "");

    #OFTEN SHIPS WITH THIS OTHER ONE, COMMENT IT OTHERWISE IT WILL FAIL
    #set req.http.Host = regsub(req.http.Host, "^www\.", "");

    # For the sake of example, a couple of custom backends, 
    # note www is specified in the req.http.host
    if (req.http.host ~ "foo.example.tld") {
         set req.backend_hint = example;
    }
     elseif (req.http.host ~ "www.other.com") {
         set req.backend_hint = other;
    }

In sub vcl_synth, add this :

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

Finally, in your vhosts, it is not necessary anymore to have two server blocks, you can comment or remove the non www one

#server {
#        listen 1.2.3.4:8080;
#        server_name example.tld;
#        return 301 http://www.example.tld;
#}

server {
        listen 1.2.3.4:8080;
        server_name www.example.tld;

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.