1

Some details about my setup first:

  • I am serving a static webapp (HTML + JS) from default Nginx webroot
  • I have a PHP-FPM server running on localhost:9000
  • The destination file should be /api/webroot/index.php for FPM (always, no need to try_files etc.)
  • I need to forward all /api and /api-debug calls to arrive at localhost:9000, and the /app/webroot/index.php should handle all these requests.

I have the following working Nginx configuration:

upstream fastcgi_backend {
    server localhost:9000;
    keepalive 30;
}

server {
    listen   80;

    location / {
        root   /usr/share/nginx/html;
        index  index.html index.htm;

        location ~ ^/(api|api-debug)/ {
            root       /app/webroot;
            index      index.php;
            try_files  $uri /api/index.php$is_args$args;

            location ~ \.php$ {
                fastcgi_pass   fastcgi_backend;

                fastcgi_split_path_info ^(?:\/api\/)(.+\.php)(.*)$;
                fastcgi_param  SCRIPT_FILENAME /app/webroot/$fastcgi_script_name;

                include        fastcgi_params;
            }
        }
    }
}

I just want to make it more simple and efficient, because as I see it now it's a mess. I tried to adjust for example

try_files $uri /api/index.php$is_args$args;

to

try_files $uri /api/webroot/index.php$is_args$args;

and it failed... The only reason that it works is that /api/index.php includes /api/webroot/index.php, but I see it's inefficient.

I found debugging nginx config hard, because it's not easy to test.

Thank you very much for your help in advance!

4
  • According to your question, index.php is located at /app/webroot/index.php. But according to your working configuration file, the URI /api/index.php would resolve to a pathname of /app/webroot/api/index.php. Adding webroot to the URI make no sense, what are you trying to achieve exactly? Commented May 20, 2018 at 12:12
  • Hi Richard, Thanks for the response. Both files exist: /app/index.php and /app/webroot/index.php, where /app/index.php is just an include statement for /app/webroot/index.php. Please note that the files are located on the disk at /app/xxx and NOT at /api/xxx. The /api/ is just the URL. Commented May 20, 2018 at 15:29
  • The ultimate goal is to get this working: CakePHP docs With the following: - The rewrite rules only apply to URL-s starting with /api - The files are not available on the nginx server's host (try_files will fail, I also don't see any need for it, just pass all /api requests to localhost:9000/app/webroot/index.php in the proper rewrite form) Hope I made some clarification here. Thanks for your help! @RichardSmith Commented May 20, 2018 at 15:32
  • Ok, I didn't notice the fastcgi_split_path_info removing the /api/ prefix from the URI. Commented May 20, 2018 at 15:59

1 Answer 1

0

The simplest solution would be to hardwire SCRIPT_FILENAME with a value of /app/webroot/index.php and remove one of your location blocks altogether.

location / {
    root   /usr/share/nginx/html;
    index  index.html index.htm;
}

location ~ ^/(api|api-debug)/ {
    include        fastcgi_params;
    fastcgi_param  SCRIPT_FILENAME /app/webroot/index.php;
    fastcgi_pass   fastcgi_backend;
}

Alternatively, to keep the flexibility of specifying a URI with a .php extension, you could simplify the configuration with:

location / {
    root   /usr/share/nginx/html;
    index  index.html index.htm;

    rewrite ^/(api|api-debug)/ /index.php last;
}

location ~ \.php$ {
    include        fastcgi_params;
    fastcgi_param  SCRIPT_FILENAME /app/webroot$uri;
    fastcgi_pass   fastcgi_backend;
}
Sign up to request clarification or add additional context in comments.

6 Comments

Thanks Richard, I'll try this tomorrow and report back!
Hi Richard, the calls to /api end up correctly at PHP-FPM, but I have some rewrite issues, I pasted a diff of print_r($_SERVER); here. Your config's results are on the left, my working config on the right. The only issue with mine is that I do not know how it works and I don't like things that way... Should I replace all variables with fastcgi_param hardwiring them? Or is there a cleaner solution? Thank you!
In the top example, the URI is not rewritten so all of the FastCGI parameters are derived from the original request. Also, root is not in scope, so contains the nginx default value. All of these parameters are defined in the fastcgi_params file, so you can override them with what your application needs, or use the bottom example.
Dear Richard, after several hours of debugging, I found exactly what the app needs. I didn't pay attention to this in detail earlier because I was using apache with pre-made .htaccess files shipped with the framework. So it turns out that /api/some/path/here?sample=querystring should end up like this: /app/webroot/index.php/api/some/path/here?sample=querystring, and no other .php files will be processed ever, so no need for the second "location ~ \.php$" block (I guess?). Could you help me out please to make this as clean and efficiant as possible? Thank you very much for your generous help!
Sorry, I forgot that this should also work for /api-debug as well... Thank you once more!
|

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.