Why does display_errors change the HTTP status code? - php

As pointed out in many other questions, turning display_errors to Off in php.ini makes the web server answer with status code 500 Internal server error instead of 200 OK when encountering a fatal error. I set up a simple test with an undefined function to explain the behaviour:
php.ini
display_errors = On
index.php
<?php test();
Gives:
Fatal error: Call to undefined function test()
in D:\xampp\htdocs\index.php on line 1
or just a blank page if i silence the function call like this:
<?php #test();
In both cases answer headers are as following:
HTTP/1.1 200 OK
Date: Tue, 10 Jul 2012 20:08:22 GMT
Server: Apache/2.2.21 (Win32) mod_ssl/2.2.21 OpenSSL/1.0.0e PHP/5.3.8 mod_perl/2.0.4 Perl/v5.10.1
X-Powered-By: PHP/5.3.8
Content-Length: 0
Keep-Alive: timeout=5, max=100
Connection: Keep-Alive
Content-Type: text/html
While changing php.ini to:
display_errors = Off
Causes:
HTTP/1.0 500 Internal Server Error
Date: Tue, 10 Jul 2012 20:10:35 GMT
Server: Apache/2.2.21 (Win32) mod_ssl/2.2.21 OpenSSL/1.0.0e PHP/5.3.8 mod_perl/2.0.4 Perl/v5.10.1
X-Powered-By: PHP/5.3.8
Content-Length: 0
Connection: close
Content-Type: text/html
Can anybody explain me the underlaying mechanism that makes the web server answer with 500 when display_errors is Off?

The reason is that with display_errors = On, you are essentially asking PHP to give you a decent HTTP response even when there are errors in your script. Think of it like an additional layer between your script and the response. It's no longer your script controlling the output, it's PHP.
When you turn this option on, you are in effect saying, "If there is an error, please still give me a valid HTTP response page (it may even include decent markup), since I will be looking at that instead of my logs."
With it set to Off, the HTTP response should be meaningless, and therefore a 500. With it On, a PHP error is anticipated, so the request on the whole is not 500, even though your script failed.

Related

Headers sent already before any output with PHP, Nginx on Azure

I have two hosting environments, one is running PHP 7.4 with Apache, and the other one is running PHP 8.1 with Nginx both on Azure.
I run this PHP script on both:
<?php ini_set("display_errors", 1); header('Status: 301 Moved Permanently', true, 301); ?>
When I run this code on host 1, I get what I expect; the headers are output as 301:
D:\home\site\wwwroot>curl -is test.php
HTTP/1.1 301 Moved Permanently
Content-Length: 0
Content-Type: text/html; charset=utf-8
Date: Fri, 25 Nov 2022 08:46:09 GMT
Server: Microsoft-IIS/10.0
X-Powered-By: PHP/7.4.30
X-Powered-By: ASP.NET
Running the same script om the Nginx environement under PHP 8.1 I get:
root:/home# curl -is localhost:8080
HTTP/1.1 200 OK
Server: nginx/1.22.1
Date: Fri, 25 Nov 2022 08:45:33 GMT
Content-Type: text/html; charset=UTF-8
Transfer-Encoding: chunked
Connection: keep-alive
X-Powered-By: PHP/8.1.9
<br />
<b>Warning</b>: Cannot modify header information - headers already sent by (output started at /home/site/wwwroot/index.php:1) in <b>/home/site/wwwroot/index.php</b> on line <b>1</b><br />
As you can see the header 301 could not be sent because the 200 header was already sent.
There is absolutely nothing before the first <?php-tag.
I have tried lots of things with the Nginx config, but no result. Is this something that is inside PHP.INI?
What is causing the header 200 to be sent before any line of my PHP script?
Solution: output_buffering is apparently disabled by default, you can turn it on in the INI of PHP, like so:
Create a folder inside /home/site called ini
Add a file there with the extention .ini, like site.ini
Add this line and save:
output_buffering = on
Go to your azure portal to the webapp and inside Configuration add an application setting with name = PHP_INI_SCAN_DIR and value = /usr/local/etc/php/conf:/home/site/ini
Then save the application setting witch will restart your app.

PHP file_get_contents errors at 128K

I am searching for clues as to why post requests larger than 128K are dying with a returned 500 or 404.
The php script includes similar to this portion
$arContext['http']['timeout'] = 60;
$context = stream_context_create($arContext);
$FileContents = file_get_contents('php://input', 0, $context);
syslog(LOG_INFO, "File length = " . strlen($FileContents);
Server side:
post_max_size = 8M
memory_limit = 32M
syslog shows file length is 131702 on these failed posts.
At this point, this seems to only be a problem with satellite connections, but not sure how that plays into the problem.
Wireshark from serverside includes:
POST /Farms/somewhere.php?id=lalala HTTP/1.1
Host: nowhere.net
Content-Length: 96
Expect: 100-continue
Connection: Keep-Alive
.G.c.!.......&.>...&..K..-.)..^B?.(..4XH..veU..kU..w...I..Xr.&C...+^H...`.............x..C=.2...HTTP/1.1 100 Continue
HTTP/1.1 200 OK
Date: Fri, 27 May 2016 22:32:39 GMT
Server: Apache/2.2.31 (Unix) mod_ssl/2.2.31 OpenSSL/1.0.1e-fips mod_bwlimited/1.4
X-Powered-By: PHP/5.5.30
Cache-Control: no-transform
Keep-Alive: timeout=5, max=100
Connection: Keep-Alive
Transfer-Encoding: chunked
Content-Type: text/html; charset=Windows-1252
10
."5.......E..>..
0
POST /Farms/somewhere.php?id=lalala HTTP/1.1
Host: nowhere.net
Content-Length: 1745376
Expect: 100-continue
HTTP/1.1 100 Continue
.G.c.!.......&.>.--->data-->Y.I*#WHTTP/1.1 500 Internal Server Error
Date: Fri, 27 May 2016 22:32:41 GMT
Server: Apache/2.2.31 (Unix) mod_ssl/2.2.31 OpenSSL/1.0.1e-fips mod_bwlimited/1.4
Content-Length: 798
Connection: close
Content-Type: text/html; charset=iso-8859-1
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>500 Internal Server Error</title>
</head><body>
<h1>Internal Server Error</h1>
<p>The server encountered an internal error or
misconfiguration and was unable to complete
your request.</p>
<p>Please contact the server administrator,
webmaster#nowhere.net and inform them of the time the error occurred,
and anything you might have done that may have
caused the error.</p>
<p>More information about this error may be available
in the server error log.</p>
<p>Additionally, a 500 Internal Server Error
error was encountered while trying to use an ErrorDocument to handle the request.</p>
<hr>
<address>Apache/2.2.31 (Unix) mod_ssl/2.2.31 OpenSSL/1.0.1e-fips mod_bwlimited/1.4 Server at nowhere.net Port 80</address>
</body></html>
apache error logs show
[Sat May 28 10:47:53 2016] [error] [client nn.nn.176.108] Handler for (null) returned invalid result code 70008
[Sat May 28 10:47:53 2016] [error] [client nn.nn.176.108] File does not exist: /home/somewhere/public_html/500.shtml
It also seems that H___net is inserting Connection: Keep-Alive in the header.

php - Output Compression problems

I'm facing a problem trying to use php output compression , I've been searching for many hours and I still have no clues...
Lets see a simple script :
<?php
$response = "abcdefghabcdefghabcdefghabcdefghabcdefghabcdefghabcdefghabcdefgh";
if(function_exists('ob_gzhandler'))
{
ob_start('ob_gzhandler');
}
else {
ob_start();
}
echo $response;
ob_end_flush();
This is a method I've found all over the internet, and it used to work for me ... but not any more (and I've got no idea why) .
If i look at the http headers when I call this script :
Request :
Host: 192.168.51.191
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:43.0) Gecko/20100101 Firefox/43.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: fr,fr-FR;q=0.8,en-US;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
Connection: keep-alive
Cache-Control: max-age=0
Response :
Connection: Keep-Alive
Content-Type: text/html
Date: Tue, 26 Jan 2016 15:19:07 GMT
Keep-Alive: timeout=5, max=100
Server: Apache/2.4.9 (Win64) OpenSSL/1.0.1g PHP/5.5.12
Transfer-Encoding: chunked
Vary: Accept-Encoding
X-Powered-By: PHP/5.5.12
You can see that the response is NOT zipped (Firebird gives me a 0.06ko response), and the server sends the responses using chunked encoding.
I tried an alternate method to send zipped responses :
<?php
$response = "abcdefghabcdefghabcdefghabcdefghabcdefghabcdefghabcdefghabcdefgh";
$replyBody = gzencode($response, 9, FORCE_GZIP);
header("Content-Encoding: gzip");
echo $replyBody;
And the response headers are as follow (the request headers are always the same):
Response :
Connection: Keep-Alive
Content-Type: text/html
Date: Tue, 26 Jan 2016 15:29:01 GMT
Keep-Alive: timeout=5, max=100
Server: Apache/2.4.9 (Win64) OpenSSL/1.0.1g PHP/5.5.12
Transfer-Encoding: chunked
X-Powered-By: PHP/5.5.12
As you can see, this is basically the same behavior as in the first method.
Then if I try this :
<?php
$response = "abcdefghabcdefghabcdefghabcdefghabcdefghabcdefghabcdefghabcdefgh";
$replyBody = gzencode($response, 9, FORCE_GZIP);
echo $replyBody;
I receive something that looks like a zipped response (random characters), and the output size is 0.03ko .
Here a the corresponding response http headers :
Connection: Keep-Alive
Content-Length: 31
Content-Type: text/html
Date: Tue, 26 Jan 2016 15:32:46 GMT
Keep-Alive: timeout=5, max=100
Server: Apache/2.4.9 (Win64) OpenSSL/1.0.1g PHP/5.5.12
X-Powered-By: PHP/5.5.12
It lets me think that the zipping part is working correctly because the output size has been reduced (it is obviously not readable because the browser can't know that it is zipped content).
That's where I'm lost ...
If I understand it right, when I manually send zipped data (using gzencode) , If I set the header"Content-Encoding: gzip" , the webserver/php seems to UNZIP it before sending it to the browser ??? How is it possible ?
And Why is it sending it as "chunked" data instead of setting the Content-Length header ?
I tried to set the Content-Length manually in the response; it doesn't change anything (it won't appear in the response headers, I'll still have a "chunked" response.
I've seen somewhere that I have to write the "Content-Length" header before sending other data or header to avoid the "chunked" response, I tried it and still had the same results.
I thought it could be a problem with BOM characters at the beginning of my php test script, but it is saved in UTF-8 without BOM encoding so I don't think it 's the problem.
I have this problem on my dev computer (using wampserver) AND in the production environment (IIS), previously it was working on both servers.
I have this problem using several browsers, and I checked the response sizes I wrote previously with fiddler.
Does anyone see where the problem could be ?
Thanks in advance
I'd go through the following checklist if I were you.
1. Check zlib extension is installed or not.
ob_gzhandler needs the zlib extension to work. Without which it just silently falls back to default settings.
2. Verify that you don't have zlib.output_compression enabled in your php.ini.
As explained here, even though zlib.output_compression is preferred over ob_gzhandler(), you can not use both simultaneously. So your code becomes..
if (extension_loaded('zlib') && !ini_get('zlib.output_compression')){
ob_start('ob_gzhandler');
}
3. Check if headers have already been sent eg. something got output-ted before the
ob_start(ob_gzhandler) This will prevent the compressed output from being detected as such. eg. Having some character before <?php or an echo somewhere up in the code.
4. Make sure you aren't using all of the above in addition to the gzipping in apache(mod_deflate).
This will only cause the output to be double gzipped which most probably will confuse the browser.

Symfony2 SonataAdminBundle Google Chrome ERR_RESPONSE_HEADERS_TOO_BIG

Using Syfony 2.2 in dev environment, trying to display a list view of the SonataAdminBundle.
I'm getting Error 325 / ERR_RESPONSE_HEADERS_TOO_BIG in Google Chrome. No problems in Safari and Firefox. This only happens in the dev environment and on every list view, edit views are ok.
Checked the headers via curl, seems fine:
curl -I http://project.local/app_dev.php/admin/project/site/user/list
HTTP/1.1 200 OK
Date: Sat, 23 Mar 2013 22:47:37 GMT
Server: Apache/2.2.24 (Unix) mod_ssl/2.2.24 OpenSSL/1.0.1e DAV/2 PHP/5.3.22
X-Powered-By: PHP/5.3.22
Set-Cookie: PHPSESSID=hgfp4kdmjtl9neodli2d83e1i0; path=/
Cache-Control: no-cache
X-Debug-Token: 514e3109e09ae
Content-Type: text/html; charset=UTF-8
Disabled XDebug and APC, but no change there.
Thanks a lot for any pointers.
Check in your config_dev.yml for following lines and comment them.
#chrome:
#type: chromephp
#level: info
Why do you get this error?
It enables support of some sort of debugger for chrome like firephp in firefox...
http://www.chromephp.com/
Problem is that the response header is too big to print out the info because of a configuration setting on your server. If you increase the allowed size in your server config the problem will also disappear.

Zend_Amf headers

I'm using charles proxy to debug a zend amf response. The headers are coming back as:
HTTP/1.1 200 OK
Date: Sat, 29 Aug 2009 10:04:32 GMT
Server: Apache/2.2.11 (Unix) mod_ssl/2.2.11 OpenSSL/0.9.8k DAV/2 PHP/5.3.0
X-Powered-By: PHP/5.3.0
Content-Length: 33
Content-Type: text/html; charset=utf-8
Should the content type be application/x-amf.
Does apache need something special to do this?
Thanks
The headers should be x-amf. Something in my php script was corrupting the output. The charles proxy item should have an 'A' icon. I didn't have to add anything in Apache.

Categories