Due to development needs, I want to display PHP errors loud and clear to the browser. So I set my php.ini
:
display_errors = on
This works as expected.
But this messes up the Nginx status code if there is an error. As commented here https://www.php.net/manual/en/errorfunc.configuration.php#126734 :
It’s important to note that when display_errors is "on", PHP will send a HTTP 200 OK status code even when there is an error.
I already tried to set fastcgi_intercept_errors on
(or off
) as reccomended somewhere else, but it doesn’t seem to make any difference.
So, the question is: how can I have both display_errors = on
and HTTP 500 on errors?
My relevant Nginx config is:
location ~ .php$ {
try_files $uri =404;
include fastcgi_params;
fastcgi_intercept_errors on;
fastcgi_pass unix:/run/php/php-fpm.sock;
fastcgi_param SCRIPT_FILENAME $request_filename;
}
Tests
I created a PHP file with a missing semicolon for testing. The PHP error is
Parse error: syntax error, unexpected end of file in test.php on line 2
PHP error with display_errors = on
Nginx returns 200 eve if there is an error:
192.168.0.1 - - [27/Sep/2022:08:50:49 +0200] "GET /test.php HTTP/2.0" 200 304 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/106.0.0.0 Safari/537.36"
PHP error with display_errors = off
Nginx returns 500:
192.168.0.1 - - [27/Sep/2022:08:53:52 +0200] "GET /test.php HTTP/2.0" 500 0 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/106.0.0.0 Safari/537.36"
4
Answers
Have you tried to put:
on top of you`re php page?
You should set the default status to
500
.At the beginning of the code put
http_response_code(500);
At the end of the code put
http_response_code(200);
May be like this
Here is a solution based on auto-prepend.
You will need to set the
auto_prepend_file
directive:The prepended script calls
register_shutdown_function()
toinstall a handler that will be executed when the main script ends. The handler checks whether an error has occurred;
when it is the case, the HTTP status is set to 500.
This technique is effective even for parse errors.
Remark: to ensure that headers have not already been sent when the status is set, output buffering is enabled.
Content of prepend.php:
In fact, in the example you give, nothing surprises me :
The preprocessor fails to evaluate your php file because of the syntax error, nothing is done by your script (because it’s not a runtime error).
With
display_error = Off
(default and production suggested value) in php.ini, PHP alerts via the protocol (500
). Withdisplay_error = On
it outputs something in the browser, so a200
response is absolutely legitimate.You don’t explain why you want be able to generate both a protocol error and a regular error message, so I assume it could be to do a mix between a test and a production site. If I’m not wrong, the only way I know is to create a separate PHP pool on another port.
It means :
Keep
display_errors = off
default value in your php.iniCopy
/etc/php/7.x/fpm/pool.d/www.conf
with another name (test.conf for example)In this file, change the [www] name to [test]
Change the listen directive with this name
[Edit] Uncomment and modify the following line :
Adapt your nginx.conf, creating a new
server
section, listening on another port :This way, the regular access to your website gives error 500, and the :8098 "super user" access shows the errors, as much as we can hope ^^
(credits to french resource https://www.skyminds.net/php-configurer-un-pool-php-pour-chaque-site/)