Nginx - in try_files, php file downloaded in place of execution

advertisements

If I request /maintenance.php, it gets executed.

If I request /foo (and maintenance.php exists), maintenance.php gets downloaded.

What am I missing ?

location / {
    try_files $uri /maintenance.php @rewriteapp;
}
location @rewriteapp {
    rewrite ^(.*)$ /app_prod.php/$1 last;
}
location ~ ^/(app_prod|maintenance)\.php(/|$) {
    fastcgi_pass unix:/var/run/php5-fpm.sock;
    fastcgi_split_path_info ^(.+\.php)(/.*)$;
    include fastcgi_params;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    fastcgi_param HTTPS off;
}

NB: It seems like

location ~ ^/(app_prod|maintenance)\.php(/|$)

is not triggered after

try_files $uri /maintenance.php @rewriteapp;


As explained here, try_files itself will not issue an internal redirect for anything but the last parameter.

So, if maintenance.php exists,

try_files $uri /maintenance.php @rewriteapp;

will simply serve the file as plain text or download it depending on your default_type configuration setting.

Solution

NB: According to the doc, it is perfectly fine to use if in this situation.

if (-f $document_root/maintenance.php) {
    return 503;
}
error_page 503 @maintenance;
location @maintenance {
    rewrite ^(.*)$ /maintenance.php;
}

Actually, I wanted to show the logo in the maintenance page, so I ended up with a few extra lines to allow assets to be served.

if (-f $document_root/maintenance.php) {
    return 503;
}
error_page 503 @maintenance_or_assets;
location @maintenance_or_assets {
    try_files $uri @maintenance;
}
location @maintenance {
    rewrite ^(.*)$ /maintenance.php;
}