2

Some PHP URLs are being downloaded instead of executed by Nginx. I have an existing web application which is functioning fine. I'm tasked with adding additional mounted applications within folders of the primary application. Each of these applications has its own front controller index.php script.

For this setup, I've created symlinks inside $document_root/app, and the symlinks point to a folder containing an index.php front controller.

When I navigate to most URLs, everything works fine, the primary application front controller is executed, and I get expected results. When I navigate to a non-existent app, I get 404 Not Found from nginx, which is expected. But when I navigate to one of the applications, the browser downloads the application front controller.

root                    /my/web/root;

location / {
    try_files           $uri
                        /$server_name$uri
                        /shared$uri
                        /index.php$is_args$args;
}

location ~ [^/]\.php(/|$) {
    disable_symlinks    off;
    fastcgi_split_path_info ^(.+\.php\b)(.*)$;
    fastcgi_param       SERVER_NAME $host;
    fastcgi_param       PATH_INFO $fastcgi_path_info;
    fastcgi_param       SCRIPT_FILENAME $document_root$fastcgi_script_name;
    fastcgi_param       SCRIPT_NAME /index.php;
    fastcgi_index       index.php;
    include             fastcgi.conf;
    fastcgi_pass        php-fpm;
}

location ~ ^/app/([a-z-]+)(/.*)?$ {
    try_files           $uri
                        /app/$1/index.php$is_args$args
                        =404;
}

URL which triggers download: /app/my-app/ (exists)
URL which 404s: /app/foo/ (does not exist)
URL which executes: /foo

1
  • Try to set location for php to location ~ [^/]\.php(/|$) Commented Jun 28, 2016 at 21:17

1 Answer 1

3
+50

The .php file needs to be processed by the location ~ [^/]\.php(/|$) block. You have a common document root which makes things simpler.

However, look at this document regarding the location directive.

You will see that the regex locations are considered in order and the first matching location will be used to process the request.

In short, you need to place the location ~ [^/]\.php(/|$) block before any other conflicting regex location, if you want your .php files to be processed correctly.

Sign up to request clarification or add additional context in comments.

3 Comments

No change in behavior. Explicit .../app/index.php URL executes, implicit .../app/ URL downloads, non-app URLs execute.
You have an error in your last try_files directive. Remove the =404. The /app/$1/index.php$is_args$args element must be last on the line. See this document for details.
More on why =404 breaks things: try_files serves “the first found file” from its list “in the current context”. For /app/my-app, that context is the location ~ ^/app/([a-z-]+)(/.*)?$ block, which doesn’t handle PHP — so nginx sends out the raw /app/my-app/index.php source file. However, the last item in a try_files list is redirected to. When /app/$1/index.php is last, it’s redirected to the location ~ [^/]\.php(/|S) block, which does handle PHP — so after removing =404, the my-app front controller runs.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.