8

I want pass any api/* route to php-fpm. Specifically to index.php as I use Symfony. This is the only route that should use php. Anything else will be loaded from /usr/share/nginx/html/public (just HTML files and CSS).

I've attempted this, but I'm getting an error:

FastCGI sent in stderr: "Primary script unknown" while reading response header from upstream

My nginx config is below:

upstream php {
  server php:9000;
}

server {
  listen 80 default_server;
  server_name impressive.local;
  index index.html index.php;
  root /usr/share/nginx/html/public;

  location /api {
    root /usr/share/nginx/html/api;
    try_files $uri /index.php;
  }

  location ~ \.php$ {
    fastcgi_pass php;
    fastcgi_split_path_info ^(.+\.php)(/.*)$;
    include fastcgi.conf;
  }
}

I get the following error:

php_1  | [13-Jan-2019 23:22:54] NOTICE: fpm is running, pid 1
php_1  | [13-Jan-2019 23:22:54] NOTICE: ready to handle connections
php_1  | 172.25.0.3 -  13/Jan/2019:23:22:57 +0000 "GET /api/index.php" 404
web_1  | 2019/01/13 23:22:57 [error] 10#10: *1 FastCGI sent in stderr: "Primary script unknown" while reading response header from upstream,
client: 172.25.0.1, server: impressive.local, request: "GET /api/index.php HTTP/1.1", upstream: "fastcgi://172.25.0.2:9000", host: "127.0.0.1:8080"
web_1  | 172.25.0.1 - - [13/Jan/2019:23:22:57 +0000] "GET /api/index.php HTTP/1.1" 404 27 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36" "-"

I've googled for hours, viewwed multiple other answers on Stack Exchange. I can't seem to figure out what is causing this. I use docker. Below is my docker-compose.yml

version: '3'
services:
  web:
    image: nginx:alpine
    volumes:
      - ./web:/usr/share/nginx/html
      - ./conf/impressive.template:/etc/nginx/conf.d/default.conf
    ports:
      - "8080:80"
    links:
      - php

  php:
    image: php:7.3.1-fpm-alpine
    volumes:
      - ./web:/usr/share/nginx/html

/usr/share/nginx/html is structured like so:

- api
    index.php
- public
    index.html
    something.html
    ...

api is a JSON API, and public is the static site.

I want any requests to api/* to call api/index.php and anything else to go via /usr/share/nginx/html/public.

BugHunterUK
  • 331
  • 1
  • 2
  • 10

2 Answers2

9

I finally solved it!

Turns out that the root location had to match the location of the files on the php-fpm container as that's what was being past through via:

fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name

I didn't need to specify that line as it was included in: include fastcgi.conf;.

I'm not sure if this is the most elegant solution:

upstream php {
  server php:9000;
}

server {
  listen 80 default_server;
  server_name _;
  index index.html index.php;
  root /usr/share/nginx/html/public;

  location /api {
    root /usr/share/nginx/html;
    try_files $uri /api/index.php$is_args$args;

    location ~ \.php$ {
      fastcgi_pass php;
      fastcgi_split_path_info ^(.+\.php)(/.*)$;
      include fastcgi.conf;
      internal;
    }
  }
}
BugHunterUK
  • 331
  • 1
  • 2
  • 10
  • 3
    Well, if I remove my SCRIPT_FILENAME then all I get is an empty, white, blank page. No error messages either. :/ – Bert Nov 05 '19 at 09:04
  • As say Bert, In my case when i remove the SCRIPT_FILENAME i get is an empty page, blank page, no error, no messages and the log fpm figurated with 200 status – Ivan Fretes May 17 '20 at 15:26
  • 1
    This is the correct answer; apparently nginx passes the absolute path to php-fpm. So app files need to be in the same path in two containers. – Birkhoff Lee Dec 19 '21 at 13:16
3

I can't add an comment,but answer.

If anyone runs in the same "problem" as Bert or Ivan Fretes, please check Point 4 in the Notes of: https://www.nginx.com/resources/wiki/start/topics/examples/phpfcgi

An empty page with 200 is normal, if SCRIPT_FILENAME is not set.

If this parameter is not set, PHP FPM responses 200 OK with empty content, and there is no error or warning. For more informaton about the CGI params, please refer to nginx beginners guide, $_SERVER in PHP and RFC3875.

The solution is not to leave it empty, but may to set it to an correct value. First, just try to add the most working default value:

fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;

But sometimes, thats not enough. For example, I run a wordpress-fpm container, which wants its files in /var/www/html. But on my host, the files a placed in /opt/wordpress/wordpress_data.

Solution one: move it from /opt/... to /var/...

Solution two: Define root normal in nginx:

root /opt/wordpress/wordpress_data;

but fix the SCRIPT_FILENAME paramter, by adding/overwriting it:

fastcgi_param SCRIPT_FILENAME /var/www/html/$fastcgi_script_name;

(I replaced the variable $document_root with the hardcoded path, there the files are visible inside the fpm-container)

qupfer
  • 31
  • 2