Reputation: 737
I am writing a service to receive data from an energy monitoring device in my house. The only way the device can push data is by using an HTTP POST
, with Transfer-Encoding: chunked
, and no Content-Length
, and the data as XML in the request body.
I would like to be able to read this data in a PHP script (behind Apache) and store it in my database.
It appears that the most correct way to read the HTTP request body in PHP these days is to open and read php://input
. However, comments from users on PHP's website indicate (and my testing confirms), that if no Content-Length
header is specified by the client, php://input
returns no data (even if there is data being sent by the client in chunked encoding).
Is there an alternate way to get access to the request body? Can I configure Apache (with .htaccess) to decode the chunked data and call my script once it gets it all, and include Content-Length
? Or configure PHP so it will be able to handle this?
Thanks!
Upvotes: 5
Views: 5070
Reputation: 876
I faced a similar issue recently with Apache 2.4.58 and PHP 8.2.15 (empty $_POST
when the Content-Encoding: chunked
header is persent), and fixed it by adding the following line in the Apache configuration:
SetEnv proxy-sendcl 1
This configuration is related to mod_proxy, which is used to handle PHP FPM. The line above should be added near ProxyPass
(something similar is seen in the mod_proxy docs):
<Location "/buggyappserver/">
ProxyPass "http://buggyappserver:7001/foo/"
SetEnv proxy-sendcl 1
</Location>
Or as in my case (in Amazon Lightsail / Bitnami) near the SetHandler "proxy:..."
directive in /opt/bitnami/apache/conf/bitnami/php-fpm.conf
, like this:
<IfDefine USE_PHP_FPM>
<Proxy "unix:/opt/bitnami/php/var/run/www.sock|fcgi://www-fpm" timeout=300>
</Proxy>
<FilesMatch \.php$>
<If "-f %{REQUEST_FILENAME}">
SetEnv proxy-sendcl 1
SetHandler "proxy:fcgi://www-fpm"
</If>
</FilesMatch>
</IfDefine>
Related Apache issues:
But since you asked about php://input
, I will add that according to the PHP docs:
php://input
is not available in POST requests withenctype="multipart/form-data"
ifenable_post_data_reading
option is enabled.
So be sure to check that option too.
Upvotes: 2
Reputation: 7054
Might as well write this as an answer I suppose.
The issue you describe is documented here: https://bugs.php.net/bug.php?id=60826
Highlights from the thread:
So here is what I found. If you send chunked http request but do not send the content-length (as we should do using HTTP 1.1 protocol) the body part of the request is empty (php://input returns nothing). This result remains valid for the following configuration where PHP runs via FastCGI :
The same configuration with PHP running as mod_php is fine, the body request is available through php://input.
And
Essentially, PHP is following the spec, and not reading beyond the FastCGI CONTENT_LENGTH header value - so correct fixes are necessarily above PHP, in the FastCGI or web server implementation.
Possible Workarounds:
0) Use httpd with mod_php
1) Use a different web server.
2) Look at patches for mod_fcgid
3) Maybe (not recommended) flip always_populate_raw_post_data
and see if there is anything in $HTTP_RAW_POST_DATA
Upvotes: 6