2

I'm trying to get Nginx to rewrite a fake directory to a query string to be used as the language. For example:

/fr/example.php

should look like that in the URL, but should rewrite to

/example.php?language=fr

Here is the code I have tried in my Nginx config:

rewrite "^(/(fr|en))?/(.*).php$" /$3.php?language=$2 last;

When I visit example.php, I get the correct page, but when I visit /fr/example.php, I get a 404 error.

Edit: This seems to be somehow related to the fact that it is a .php extension. If I try with .html instead, it works. But unfortunately I need it to be php. Here is a little more of my nginx.conf that might be helpful, found just a little later than the code I posted above:

location / {
    root   /var/www/example.com;
    index  index.php index.html index.htm;

    rewrite "^(/(fr|en))?/(.*).php$" /$3.php?language=$2 last;
}

error_page 404 /404.php;
location /404.php {
    root /var/www/example.com;
}

location ~ \.php$ {
    include snippets/fastcgi-php.conf;

    # CUSTOM
    fastcgi_connect_timeout 60;
    fastcgi_send_timeout 180;
    fastcgi_read_timeout 180;
    fastcgi_buffer_size 128k;
    fastcgi_buffers 256 16k;
    fastcgi_busy_buffers_size 256k;
    fastcgi_temp_file_write_size 256k;
    fastcgi_intercept_errors on;
    # END CUSTOM

    # With php7.0-fpm:
    fastcgi_pass unix:/run/php/php7.0-fpm.sock;
}
Jonathan
  • 6,507
  • 5
  • 37
  • 47
  • It works for me. Which block is the `rewrite...last` enclosed within? – Richard Smith Apr 13 '18 at 16:18
  • It is enclosed with `location / {`, just before the fastcgit block I added. – Jonathan Apr 13 '18 at 16:24
  • That is the problem. It needs to be in a context when `.php` URIs are processed, which means `server` context, or `location ~ \.php$`. If you place it in `location ~ \.php$` - use `rewrite...break` instead. – Richard Smith Apr 13 '18 at 16:28
  • I think I don't quite understand: I just tried moving it down into the `location ~ \.php$` block, and my server was showing error 500. Edit: and my whole posted configuration is within a `server {` block. – Jonathan Apr 13 '18 at 16:30
  • Use `rewrite...break` inside the `location` block. – Richard Smith Apr 13 '18 at 16:33
  • Ah, I just had to put it before the snippets! Thanks a bunch. If you post it as an answer, I will accept it. – Jonathan Apr 13 '18 at 16:37

1 Answers1

4

The rewrite statement needs to be within a context that processes URIs ending with .php, which means the server block or the location ~ \.php$ block.

The disadvantage of placing the rewrite in the server block, is that nginx tests the regular expression for every URI rather than only those ending with .php.

The rewrite statement should use the break suffix when the rewritten URI is processed within the same location block. See this document for details.

For example:

location ~ \.php$ {
    rewrite ^(/(fr|en))?/(.*)$ /$3?language=$2 break;
    ...
}

Your regular expression currently matches every URI (with or without a language prefix). If this is not a requirement, remove the ? from the regular expression. For example:

rewrite ^/(fr|en)/(.*)$ /$2?language=$1 break;
Richard Smith
  • 45,711
  • 6
  • 82
  • 81