2

This is related to an old question I asked on SO years ago, for which I never got a proper answer. I'm just setting up a new server (Ubuntu 16.04, Nginx 1.10, PHP 7) and coming back to this.

I have a Question2Answer instance running in a sub folder, with other PHP code running from the root. For the root stuff, I have this in my server block:

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

location ~ \.php$ {
    include snippets/fastcgi-php.conf;
    fastcgi_pass unix:/run/php/php7.0-fpm.sock;
}

For Q2A, what I had on my old server was:

location /qa/ {
    if (!-e $request_filename) {
        rewrite ^/qa/(.*)$ /qa/index.php?qa-rewrite=$1 last;
    }
}

This does work, but I don't think it's how it should be done (if is evil, etc). I'm sure it must be possible using only try_files. I've tried this:

location /qa/ {
    try_files $uri $uri/ /qa/index.php?qa-rewrite=$uri&$args;
}

But it doesn't work because /qa/ is passed in qa-rewrite. It should just pass everything after that in the path. Is there some way to remove /qa/ from the $uri variable?

I've also tried this:

location ~ ^/qa/(.*) {
    try_files $uri $uri/ /qa/index.php?qa-rewrite=$1;
}

But this instead starts a download of the PHP code for index.php! How do I get it to pass that on to the PHP engine?

DisgruntledGoat
  • 2,569
  • 4
  • 26
  • 34

1 Answers1

2

If is evil but as the documentation states, it is ok for rewrite ... last statements.

However, an alternative approach (which still extracts just a portion of the $uri) is to use a named location at the end of the try_files statement:

location /qa/ {
    try_files $uri $uri/ @qa;
}
location @qa {
    rewrite ^/qa/(.*)$ /qa/index.php?qa-rewrite=$1 last;
}

The regex location approach is also valid. But regex locations are evaluated differently to prefix locations. You need to place the location ~ \.php$ block above the location ~ ^/qa/(.*) block, so that URIs ending with .php are processed in the correct location.

Richard Smith
  • 11,859
  • 2
  • 18
  • 26
  • 1
    Thanks, seems to be working! Is there a difference between the "named location" and "regex location" approaches? Is one more performant? – DisgruntledGoat Jun 12 '16 at 12:19
  • 1
    The regular expression in the location statement needs to be executed for almost every URI. The regular expression in the rewrite statement is only executed for those URIs that enter the enclosing block. The named location approach is probably the more efficient. – Richard Smith Jun 12 '16 at 13:09