TransWikia.com

nginx geoip redirect for first time only leads to redirect loop

Server Fault Asked by cortopy on November 27, 2020

I’m trying to configure nginx to perform geoIP checks on first-time visitors only.

The idea is that first-time visitors should be redirected to the page version which has been customised for their language/country.

I’m able to check whether or not a certain cookie exists. If it does, then nginx can proceed and not redirect.

This set up means that all first-time visitors will be redirected to what it’s likely to be the most appropriate version of the page for their country/language. And at the same time, those users that wish to, can still browse freely all versions available afterwards.

I believe Google recommends this type of set up for multilingual/multisite webpages too.

The problem is that I get a redirect loop if the rewrite directive is placed outside the root location. Yet, because the US version is the same as /root, rewrites within locations have proven even more difficult to configure.

The geo_IP values are passed OK via fastcgi to php if no rewrite is specified, so I don’t think there is anything wrong with the setup apart from the rewrite itself.

This is my config:

map $geoip2_data_country_code $country_url {
  default example.com; ##This is the US version
  GB      example.com/uk;
  CA      example.com/ca;
}

server {
    listen 443 ssl spdy default_server;
    server_name example.com;
    root /var/www/html;

    if ($http_cookie !~ "cookie_to_check") {        
       rewrite ^ https://$country_url break;
       #Appending $request_uri to the rewrite yields very similar results
    }    


    location / {
    try_files $uri $uri/ /index.php?$args; 
    }

    location /uk {
    try_files $uri $uri/ /uk/index.php?$args;   
    }

    location /ca {  
    try_files $uri $uri/ /ca/index.php?$args;   
     }

##Other locations
}

One Answer

After a lot of trial and error, this is the configuration that would work and perform as expected.

The problem with my previous version was double:

  • Nginx rewrites outside locations were messy and they would just refuse to work by creating nasty loops
  • Nginx was checking the existence of a cookie which is set by a php application behind nginx. Thanks to @AlexeyTen for pointing this out. Setting an extra cookie conditionally with nginx did the trick

    map $geoip2_data_country_code $country_url {
         default example.com; ##This is the US version
         GB      example.com/uk;
         CA      example.com/ca;
    }
    
    server {
        listen 443 ssl spdy default_server;
        server_name example.com;
        root /var/www/html;
    
        location / {
            try_files $uri $uri/ /index.php?$args; 
            if ($http_cookie !~ "country=set") {                            
                add_header Set-Cookie "country=set;Max-Age=31536000";
                rewrite ^ $scheme://$country_url$request_uri break;
                }
        }
    
        location /uk {
            try_files $uri $uri/ /uk/index.php?$args;  
            if ($http_cookie !~ "country=set") {                            
                add_header Set-Cookie "country=set;Max-Age=31536000";
                rewrite ^ $scheme://$country_url$request_uri break;
                } 
        }
    
        location /ca {  
            try_files $uri $uri/ /ca/index.php?$args;   
            if ($http_cookie !~ "country=set") {                            
                add_header Set-Cookie "country=set;Max-Age=31536000";
                rewrite ^ $scheme://$country_url$request_uri break;
                }
        }
    
        ##Other locations
        }
    

Answered by cortopy on November 27, 2020

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP