PHP file_get_contents('php://input'

2019-07-30 02:18发布

问题:

I have a complex PHP application that uses an ESB model built with Zend Framework v1.x. Performance has become an issue, and now I know why: reading the php://input stream is consistently taking almost exactly 10 seconds.

Here is a snippet from an XDebug trace log:

0.3985    6935880    -> Zend_Controller_Request_Http->getRawBody() /var/www/vas/Adapters/Database/application/controllers/AdapterController.php:473
0.3985    6936104    -> file_get_contents() /usr/share/php/ZendFramework-1.12.0/library/Zend/Controller/Request/Http.php:961
10.4134   6936096    -> trim() /usr/share/php/ZendFramework-1.12.0/library/Zend/Controller/Request/Http.php:963

We deploy a ESB model, with requests going fro the portal, to the ESB, to the data base adapter. Hitting any one server by itself doesn't seem to be problematic, but as soon as the request goes between servers (which are actually vhosts on the same server), the problem rears itself.

回答1:

It turns out this is a bug in either Apache httpd or PHP, as well as a bug in Zend Framework v 1.x.

The bug occurs when a content-length header's value exceeds the actual content length.

For example,

curl http://localhost/index.php -H "Content-Length: 3" --data "12"

In the above example, a 10 second timeout must be reached after calling file_get_contents('php://input') before the request body is returned.

In Zend Framework v1.x, setting the raw body of a Zend_HTTP_Client object causes a Content-Length header to be calculated and injected into the request. However, unless the request is a POST, PUT or DELETE request, the content will be omitted from the actual request, which, in turn, triggers the Apache/PHP invalid-content-length bug.

I have opened a bug with PHP and will also open a bug with Zend Framework.