3

I'm trying to achieve something with nginx and redirect rules which seems like it should be pretty straightforward, but I've run into a stumbling block.

Having had a look through many questions and answers, I can't seem to find a solution that works for me.

What I want to achieve is the following:

If someone navigates to my website with any of the following URLs:

http://mywebsite.com
http://mywebsite.com/
http://mywebsite.com/foo

the person will be re-directed to:

http://mywebsite.com/en/
http://mywebsite.com/en/
http://mywebsite.com/en/foo/

This is what I have in my nginx configuration file so far in the order in which I have them in the file:

location ^/en/(.*) {
    try_files $uri /index.php$is_args$args last;
}

location / {
    if ( $uri !~ ^/(index\.php|css|jpg|png|images|core|uploads|js|robots\.txt|favicon\.ico) ) {
        return 301 /en/$uri;
    }
}

However, with the above configuration, I am running into an infinite redirect loop and the URL in the address bar ends up like this before the server gives up:

http://mywebsite.com/en//en/en/en/en/en/en/en/en/en/en/en/en/en/en/en/en/en/en/en/

Can someone please:

a) Explain to me why my configuration has not had the intended effect so I can understand it and not repeat the same errors in the future

b) Propose a solution that works and if possible improve upon my configuration

c) If possible, take it further and explain with examples how I can get nginx to automatically determine the locale associated with the request and dynamically transform the request to include it in the fashion described above.

Thanks

newbie
  • 133
  • 1
  • 3

1 Answers1

4

Explain to me why my configuration has not had the intended effect so I can understand it and not repeat the same errors in the future

location ^/en/(.*) is not a valid directive.

You might have been confused with location ^~ /en/(.*). This matches any query beginning with /en/ followed by anything.

Actually, request always match the location / directive so that it brings you into an infinite loop.

Propose a solution that works and if possible improve upon my configuration

Just use the Path prefix within the location directive :

location /en/ {
   try_files $uri $uri/ =404;
}

location / {
   return 301 /en$uri;
}
krisFR
  • 12,830
  • 3
  • 31
  • 40
  • @krisFR, Thanks for the feedback, much appreciated. However, there is a problem when using your solution, an extra slash is added to the URL, so the URL always ends up like: /en//foo, /en// etc.. I have tried a few modifications to see if it would help but with no luck. – newbie Jun 15 '15 at 19:27
  • @newbie Right, ok solved using `return 301 /en$uri` instead of `return 301 /en/$uri` – krisFR Jun 15 '15 at 22:06
  • great that worked a treat. I could have sworn I tried that but maybe my browser was caching the previous responses. I guess I'll have to figure out point c) on my own. ;) thanks for your help, much appreciated! – newbie Jun 16 '15 at 20:02