php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Doc Bug #66763 always_populate_raw_post_data=0 BC issue with in-built web server
Submitted: 2014-02-24 19:12 UTC Modified: 2015-04-06 09:28 UTC
Votes:5
Avg. Score:4.2 ± 1.0
Reproduced:4 of 5 (80.0%)
Same Version:3 (75.0%)
Same OS:2 (50.0%)
From: sixd@php.net Assigned: tyrael (profile)
Status: Closed Package: Built-in web server
PHP Version: 5.6Git-2014-02-24 (Git) OS: Linux
Private report: No CVE-ID: None
 [2014-02-24 19:12 UTC] sixd@php.net
Description:
------------
Always_populate_raw_post_data=0 causes the in-built web server to
display a deprecatation warning.  Backwards compatibility is broken
because headers are sent.

The warning should only ever be sent when always_populate_raw_post_data=1
though this is debatable because any warning would break code similar to 
the testcase.

Test script:
---------------
A testcase is based on
http://www.whitewashing.de/2014/01/31/soap_and_php_in_2014.html

Create these two files:

server.php

  <?php

  // server.php

  class MyService
  {
      public function add($x, $y)
      {
          return $x + $y;
      }
  }

  $options = array(
      'uri' => 'http://localhost/namespace',
      'location' => 'http://localhost:8899/server.php',
  );

  $server = new SOAPServer(null, $options);
  $server->setObject(new MyService());
  $server->handle();

  ?>

client.php:

  <?php

  // client.php

  $options = array(
      'uri' => 'http://localhost/namespace',
      'location' => 'http://localhost:8899/server.php',
  );
  $client = new SOAPClient(null, $options);
  echo $client->add(10, 10);

  ?>



Expected result:
----------------
Start the PHP 5.6 in-built webserver with:

  $ php56 -d always_populate_raw_post_data=-1 -S 0.0.0.0:8899

or use PHP 5.5:

  $ php55 -d always_populate_raw_post_data=0 -S 0.0.0.0:8899

Then execute the client in a terminal shell:

  $ php56 client.php

The expected output of '20' is displayed.

Starting the PHP 5.6 server with always_populate_raw_post_data=0
should similarly allow client.php to work:

  $ php56 -d always_populate_raw_post_data=0 -S 0.0.0.0:8899


Actual result:
--------------
With the default php.ini files, then either of these two PHP 5.6 cases
cause the test to fail.  This is a BC break.

  $ php56 -d always_populate_raw_post_data=0 -S 0.0.0.0:8899

or with the default php.ini value (which is always_populate_raw_post_data=0):

  $ php56 -S 0.0.0.0:8899

Then the client fails with the text:

  Fatal error: Uncaught SoapFault exception: [Client] looks like we got no XML document in /home/cjones/public_html/soap/client.php:10
  Stack trace:
  #0 /home/cjones/public_html/soap/client.php(10): SoapClient->__call('add', Array)
  #1 /home/cjones/public_html/soap/client.php(10): SoapClient->add(10, 10)
  #2 {main}
    thrown in /home/cjones/public_html/soap/client.php on line 10

The web server displays:

  [Mon Feb 24 10:56:46 2014] PHP Deprecated:  Automatically populating $HTTP_RAW_POST_DATA is deprecated and will be removed in a future version. To avoid this warning set 'always_populate_raw_post_data' to '-1' in php.ini and use the php://input stream instead. in Unknown on line 0
  [Mon Feb 24 10:56:46 2014] PHP Warning:  Cannot modify header information - headers already sent in Unknown on line 0
  [Mon Feb 24 10:56:46 2014] PHP Warning:  Cannot modify header information - headers already sent in /home/cjones/public_html/soap/server.php on line 20
  [Mon Feb 24 10:56:46 2014] PHP Warning:  Cannot modify header information - headers already sent in /home/cjones/public_html/soap/server.php on line 20
  [Mon Feb 24 10:56:46 2014] 127.0.0.1:47848 [200]: /server.php


Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2014-03-25 09:32 UTC] mike@php.net
-Status: Open +Status: Suspended -Assigned To: +Assigned To: tyrael
 [2014-03-25 09:32 UTC] mike@php.net
This is the way the RMs wanted it to be.
 [2014-04-18 16:02 UTC] tyrael@php.net
I think mike's summary a bit too compact/dense.
The current warning is indeed was my idea to allow the introducion of mike's slim post data rfc in 5.6:
https://wiki.php.net/rfc/slim_post_data
the original implementation would have caused more serious BC breaks, you can read more about it in the "[RFC] Slim POST data (was: PHP-5.6 and $HTTP_RAW_POST_DATA)" thread.
I guess we can improve the current situation for the developer server though.
 [2014-04-18 16:57 UTC] mike@php.net
Sorry, no offense intended! :)

I doubt it classifies as a *real* BC break because a production server should probably not output any warning, I agree though, that it might pop up in development, and that, as far as I am concerned, is a very good thing.

I really appreciate that Ferenc made it possible to bring this enhancement into 5.6
 [2014-10-19 22:40 UTC] matt at piwik dot org
Currently the message implies that we are using  $HTTP_RAW_POST_DATA but actually it's not used. 

Maybe it would be worth updating the error message to explain that the setting should be set to -1 even in cases where $HTTP_RAW_POST_DATA is not used?

Or maybe you could only show the Warning when $HTTP_RAW_POST_DATA is used?

Looking online a lot of people have a problem that this warning is output by default in 5.6 configuration and this seems to confuse many users including advanced PHP users.

Also we noticed that always_populate_raw_post_data  cannot be set with ini_set(), it must be set in php.ini which requires admin access to the server.

Reference: issue on Piwik project https://github.com/piwik/piwik/issues/6465
 [2014-10-20 12:56 UTC] tyrael@php.net
"Currently the message implies that we are using  $HTTP_RAW_POST_DATA but actually it's not used."
you are potentially using the $HTTP_RAW_POST_DATA if you have anything but always_populate_raw_post_data=-1 in your config.
always_populate_raw_post_data=0 does not mean, that $HTTP_RAW_POST_DATA won't be populated, it only means, that it will be only populated when a supported MIME type is present.
as I've stated in my recent email(http://news.php.net/php.internals/78156) unfortunatelly it isn't possible (in an acceptable manner) to detect if your code actually touches the $HTTP_RAW_POST_DATA variable, but we still wanted to add a deprecated notice so people can start moving away from $HTTP_RAW_POST_DATA and won't be surprised when the support for it is dropped in a future version.

As I mentioned in my email, I'm planning to better explain the situation in the online documentation/migration guide.
 [2014-10-21 04:01 UTC] matt at piwik dot org
> always_populate_raw_post_data=0 does not mean, that $HTTP_RAW_POST_DATA won't be populated, it only means, that it will be only populated when a supported MIME type is present.

The message only mentions $HTTP_RAW_POST_DATA and does not mention MIME type. Maybe the error message could explain that the MIME type used is relevant to the warning being raised if applicable?

> won't be surprised when the support for it is dropped in a future version.

Likely from my experience even more people will be surprised when the BC is broken in PHP 5.6 because of un-documented MIME types (and possibly other codepaths) that throw a "headers already sent" error. Breaking BC with a not so useful error message that mentions a feature that is not used and not found in most codebases.

Asking confirmation: maybe the error is also thrown because we use 'php://input' ? 

if that's the case could the error message be updated to mention that both HTTP_RAW_POST_DATA and php://input and MIME types cause the warning to be raised? 

Ideally PHP should not break BC in this way, because PHP should not require users to have access to their php.ini to fix default PHP 5.6 config. As a popular PHP app maker we would still kindly request to consider setting this to -1. 

PS: dozens of people online with this issue and already 4-5 hours on our end spent understanding this. We are PHP experts.... imagine what normal PHP users will go through. Thanks for considering :-)
 [2014-10-21 12:56 UTC] tyrael@php.net
"The message only mentions $HTTP_RAW_POST_DATA and does not mention MIME type. Maybe the error message could explain that the MIME type used is relevant to the warning being raised if applicable?"
I disagree.
The current error message tells you the problem ($HTTP_RAW_POST_DATA is deprecated, and will be gone in a future version), and how to remove the warning (always_populate_raw_post_data=-1) and what should you use instead of $HTTP_RAW_POST_DATA(php://input).
I don't think it would be a good idea to start documenting the various ways which can trigger the population of the $HTTP_RAW_POST_DATA variable in the error message, you can check out the online documentation for that. 
I do agree, that the current way for triggering the deprecated message is a bit sub-optimal (we don't show you the message when you try to access the $HTTP_RAW_POST_DATA variable, but when $HTTP_RAW_POST_DATA is populated.
This is a technical limitation which we can't really help ($HTTP_RAW_POST_DATA is not a super global, but a normal global variable, so adding a check which emits the warning when a global variable accessed with this name would slow down every access to any global variable),

"Likely from my experience even more people will be surprised when the BC is broken in PHP 5.6 because of un-documented MIME types (and possibly other codepaths) that throw a "headers already sent" error. Breaking BC with a not so useful error message that mentions a feature that is not used and not found in most codebases."
I disagree.
1, We don't consider adding new warnings/notices/deprecated messages BC breaks, because those shouldn't affect your production code (running with display_errors=On in production is a bad practice). 
2, Having a clear error message which also tells you how to fix the problem is a much better thing than changing the default behavior causing some random error in your app about $HTTP_RAW_POST_DATA being undefined. 

"Ideally PHP should not break BC in this way, because PHP should not require users to have access to their php.ini to fix default PHP 5.6 config. As a popular PHP app maker we would still kindly request to consider setting this to -1. "
As I mentioned we don't consider deprecated error messages as BC breaks (even thought that it is a sad truth that some/many people do use display_errors=On in production).
I'm hesitant to change the default value to -1 in a micro version, as it would change the default behavior and we would start getting the complaints about $HTTP_RAW_POST_DATA not getting populated, because many/most people depending on this variable does not explicitly specified always_populate_raw_post_data in their php.ini either.

"dozens of people online with this issue and already 4-5 hours on our end spent understanding this. We are PHP experts.... imagine what normal PHP users will go through. Thanks for considering :-)"
imo a normal user would just either change this in the php.ini or complain to their hoster/developer to fix the issue after upgrading their php installation.
I think that most of the confusion will be cleared after the documentation gets updated to exmplain the situation.
 [2014-10-21 12:58 UTC] tyrael@php.net
and ofc. feel free to escalate this issue (drop a mail to internals@) if you think that it would require a bigger audience than those following this bugreport.
 [2014-10-21 22:54 UTC] matt at piwik dot org
> The current error message tells you the problem ($HTTP_RAW_POST_DATA is deprecated, and will be gone in a future version), and how to remove the warning (always_populate_raw_post_data=-1) and what should you use instead of $HTTP_RAW_POST_DATA(php://input).

Just to repeat/confirm: we do not use $HTTP_RAW_POST_DATA and we only use php://input. Yet the deprecated notice is thrown. Isn't that a bug?

at least the error message should be changed because it is currently incorrect? (It suggests us to use php://input but this is what we are already using this AFAIK.)


> running with display_errors=On in production is a bad practice

It's bad practise but it's also the default configuration. Bad practise == default == widespread (ie. dozens of thousands of servers running with display_errors on). 

> imo a normal user would just either change this in the php.ini or complain to their hoster/developer to fix the issue after upgrading their php installation.

agreed but still it means thousands of hours of frustration for users. 


Now I have an idea that could solve the problem nicely for us: could you make ini_set work for this setting value?

ini_set('always_populate_raw_post_data', -1);

This would provide very nice workaround for us and many other PHP apps that could just add this ini_set.  Thanks for considering!
 [2014-10-22 01:06 UTC] tyrael@php.net
"Just to repeat/confirm: we do not use $HTTP_RAW_POST_DATA and we only use php://input. Yet the deprecated notice is thrown. Isn't that a bug?"
the deprecated notice only presented when $HTTP_RAW_POST_DATA is populated, regardless if you touch the $HTTP_RAW_POST_DATA variable or not.
but I think I already mentioned this, and also explained why we can't only throw the deprecated notice when the variable is actually accessed.

"at least the error message should be changed because it is currently incorrect? (It suggests us to use php://input but this is what we are already using this AFAIK.)"
it suggests you to change your php.ini and use php://input instead of $HTTP_RAW_POST_DATA.
if you aren't using $HTTP_RAW_POST_DATA you only have to change your php.ini to explicitly opt-out from populating $HTTP_RAW_POST_DATA.

"It's bad practise but it's also the default configuration. Bad practise == default == widespread (ie. dozens of thousands of servers running with display_errors on). "
you are right about that one. I've started a thread back like 2 years ago to sync our defaults with what we have in php.ini-production but we didn't get a consensus on it.

"Now I have an idea that could solve the problem nicely for us: could you make ini_set work for this setting value?"
when your code(containing your ini_set call) is executed, the population of this variable already happened, so ini_set won't work for it.
and afaik we don't have a way for jit population for non-superglobal variables (as I mentioned $HTTP_RAW_POST_DATA is not a superglobal unfortunatelly).
 [2014-10-22 01:33 UTC] matt at piwik dot org
Thanks for the reply!

> when your code(containing your ini_set call) is executed, the population of this variable already happened, so ini_set won't work for it.

that's a bummer but I understand that it's not possible.

> but I think I already mentioned this, and also explained why we can't only throw the deprecated notice when the variable is actually accessed.

I am still confused which I think shows something can be improved. The error message is: "Automatically populating $HTTP_RAW_POST_DATA is deprecated and will be removed in a future version. To avoid this warning set 'always_populate_raw_post_data' to '-1' in php.ini and use the php://input stream instead."

Maybe you could change it to: "Automatically populating $HTTP_RAW_POST_DATA is deprecated and will be removed in a future version. To avoid this warning set 'always_populate_raw_post_data' to '-1' in php.ini. And if you use $HTTP_RAW_POST_DATA then change it to use the php://input stream instead."

This will certainly help some like me understand the meaning of the message. Thank you!
 [2014-10-27 12:54 UTC] tyrael@php.net
-Status: Suspended +Status: Open
 [2014-10-27 12:54 UTC] tyrael@php.net
I would rephrase that a bit, but I can see how splitting that part into it's own sentence would be less confusing.
 [2014-11-06 05:27 UTC] matt at piwik dot org
FYI first case of a user confused who did not understand the message and then is asking us for help: http://forum.piwik.org/read.php?2,121546
 [2014-11-06 08:36 UTC] matt at piwik dot org
FYI: Bramus! whom I don't know blogged about it here: http://www.bram.us/2014/10/26/php-5-6-automatically-populating-http_raw_post_data-is-deprecated-and-will-be-removed-in-a-future-version/

tl;dr The default value for always_populate_raw_post_data in PHP 5.6 is doing more harm than good. Perfectly good code will spit out that error whenever it receives a request that has a (non-application/x-www-form-urlencoded encoded) payload. To fix it, explicitly set the value of always_populate_raw_post_data to -1 in your php.ini.
 [2014-11-06 12:02 UTC] tyrael@php.net
I've posted a reply there with some additional clarification(for example that you need both display_errors and display_startup_errors enabled to have a realistic chance to be affected by the deprecated message introduced in 5.6 other than having a some additional lines in your php error log.
 [2015-04-06 09:28 UTC] tyrael@php.net
-Status: Assigned +Status: Closed -Type: Bug +Type: Documentation Problem
 [2015-04-06 09:28 UTC] tyrael@php.net
I've updated the docs to make it more explicit when is the error triggered and how to fix this problem:
http://svn.php.net/viewvc?view=revision&revision=336371
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Tue Mar 19 08:01:29 2024 UTC