nginx chain reaction when using try_files when server returns status code 500 results in double submission

Toskan asked:

following config:

 location ~ /{
        try_files /$uri /$uri/ /index.php?q=$uri&$args;
    }

this will try several things when the server returns 500. It will walk down the chain and try the next thing. But: as it is a form that is failing, the form is resubmitted, and the things that happen until the faulty code, happen thus twice. Is there a way to only try one thing with try_files or an alternative to try_files?

using =500 at the end is not a solution, because it will not show the error page.

EDIT I add the complete server block.

I have a bit a complex setup with wordpress and laravel. WordPress is at home in the main folder, whereas all calls to caup_api and subfolders need to go to the laravel installation. Thus i have a softlink
caup_api -> ./caup_laravel/public/

that is so i can use all calls normally made the caup_api folder are sent directly to laravel and not processed by wordpress. The problematic config is the one with caup_api

server {
    listen 80;

 server_name dev.myapp.org;

     root /var/www/html/dev.myapp.org/public;

    index index.html index.htm index.php;


    access_log  /var/log/nginx/nginx_lukas23.com.access.log;
    error_log  /var/log/nginx/nginx_lukas23.com.error.log;

    location = /favicon.ico { access_log off; log_not_found off; }
    location = /robots.txt { access_log off; log_not_found off; }
    location = /apple-touch-icon.png { access_log off; log_not_found off; }
    location = /apple-touch-icon-precomposed.png { access_log off; log_not_found off; }
    location ~ /\.ht { deny  all; access_log off; log_not_found off; }


location / {
try_files $uri $uri/ /index.php?q=$uri&$args;

    }

   location ~ \.php$ {
        proxy_intercept_errors on;
        error_page 500 501 502 503 = @fallback;
        fastcgi_buffers 8 256k;
        fastcgi_buffer_size 128k;
        fastcgi_intercept_errors on;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        ##fastcgi_pass   127.0.0.1:9900;
        fastcgi_pass unix:/var/run/php/php7.0-fpm.sock;
        ##fastcgi_pass hhvm;
    }
    location @fallback {
        fastcgi_buffers 8 256k;
        fastcgi_buffer_size 128k;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        ##fastcgi_pass   127.0.0.1:9900;
        fastcgi_pass unix:/var/run/php/php7.0-fpm.sock;

        ##fastcgi_pass jcrdev;
    }
    location ~* .(css|js|png|jpg|jpeg|gif|ico)$ { expires 1d; }

   location ~ /caup_api {
        try_files /caup_api/$uri /caup_api/$uri/ /caup_api/index.php?q=$uri&$args;
    }

    location ~ /causes {
        try_files /caup_api/$uri /caup_api/$uri/ /caup_api/index.php?q=$uri&$args;
    }
}

My answer:


Your code is running twice because you explicitly asked for it to be run twice.

First, try_files finds your URL, or more specifically it doesn’t find your URL, and so it runs your PHP script because you ended it with /index.php?.... This causes nginx to execute your script using the directives within location ~ \.php$.

When this returns a 500 error, the error_page 500 ... directive in that location kicks in. This tells nginx to deliver a specific document instead of its own internal 500 error page. In your case, it tells nginx to hit the @fallback location, which has the effect of calling your PHP code again.

To resolve the problem, you need to think more carefully about what you want to happen when a 500 error occurs in your program, or perhaps better yet, not return 500 errors.


View the full question and answer on Server Fault.

Creative Commons License
This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License.