1

I just created an API for my flashy new website and was hoping to return error responses with relevant status codes. However, I already configured normal paths to use error pages with the error_page directive which I would prefer not removing.

I have one index.php file that handles all requests for the API and website.

server {
    listen 80;
    listen 443 ssl http2;
    server_name ~^(.+)\.flashy\.local$;
    root "/home/vagrant/flashy/core/www";

    index index.html index.htm index.php;

    charset utf-8;

    error_page 400 /error/error-400.html;
    error_page 403 /error/error-403.html;
    error_page 404 /error/error-404.html;
    error_page 500 501 /error/error-500.html;
    error_page 502 503 504 /error/error-503.html;

    location ~ ^/error/error-(403|404|500|503)\.html$ {
       internal;
       root /home/vagrant/flashy;
    }

    location ~ \.php$ {
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_pass unix:/var/run/php/php7.1-fpm.sock;
        fastcgi_index index.php;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;

         fastcgi_buffer_size 16k;
         fastcgi_buffers 4 16k;
         fastcgi_connect_timeout 300;
         fastcgi_send_timeout 300;
         fastcgi_read_timeout 300;
         fastcgi_intercept_errors on;
     }

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

     access_log off;
     error_log  /var/log/nginx/~^(.+)\.flashy\.local$-error.log error;

     sendfile off;

     client_max_body_size 100m;

     location ~ /\.ht {
         deny all;
     }

     ssl_certificate     /etc/nginx/ssl/~^(.+)\.flashy\.local$.crt;
     ssl_certificate_key /etc/nginx/ssl/~^(.+)\.flashy\.local$.key;


}

Now, some of you might be wondering? What have I tried?

I tried adding a /api/ location to change the fastcgi_intercept_errors parameter to off, but it seems to get set back to on as it's going to hit a php file anyways.

location /api/ {
     fastcgi_intercept_errors off;
     try_files $uri $uri/ /index.php?$query_string;
}

I also tried an if statement to see if maybe I could match this based on content headers. However I don't want to use if statements if possible as it seems to be a bad idea.

     ...
     fastcgi_send_timeout 300;
     fastcgi_read_timeout 300;
     if ($content_type != "application/json") {
          fastcgi_intercept_errors on;
     }
}
...

My question is pretty similar to this question but it does not have an answer either. Hopefully my questions is slightly different and perhaps better explained?

How can I turn off fastcgi_intercept_errors for specific api path?

Uberswe
  • 159
  • 3
  • 9

1 Answers1

0

You will need to duplicate the FastCGI configuration within a new location for the URI of the API. Most of the fastcgi directives can be moved into the server block and will be inherited by the location ~ \.php$ block and the new location block. See this document for details.

An exact match location block has highest precedence, so the order of the blocks in this example is not important (see this document for details):

include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $request_filename;

fastcgi_buffer_size 16k;
fastcgi_buffers 4 16k;
fastcgi_connect_timeout 300;
fastcgi_send_timeout 300;
fastcgi_read_timeout 300;

location = /api/api.php {
    fastcgi_pass unix:/var/run/php/php7.1-fpm.sock;
}

location ~ \.php$ {
    fastcgi_pass unix:/var/run/php/php7.1-fpm.sock;
    fastcgi_intercept_errors on;
}

The fastcgi_split_path_info and fastcgi_index directives are not relevant to your configuration.

Richard Smith
  • 12,834
  • 2
  • 21
  • 29
  • The key to a manageable Nginx configuration is a lot of organized include files. There's no way to avoid duplication. – Zenexer Aug 12 '17 at 09:31
  • Something like this could work but I would prefer a solution that could do this without using two separate php files. I want to keep trying a bit more but perhaps this really is the best solution. – Uberswe Aug 14 '17 at 07:24