It seems that there is some weird behavior when using http_get_request_body() with fopen('php://input'). Specifically, reading the input with the fopen('php://input') routine before calling http_get_request_body() on a PUT HTTP request.
Here are some examples:
A POST request:
*********************************************************
PUT http://example.com/requestbodytest.php HTTP/1.1
Host: example.com
Keep-Alive: 300
Connection: keep-alive
Content-Type: text/xml
Content-Length: 58
<?xml version="1.0" encoding="utf-8" ?>
<body>test</body>
*********************************************************
with the following script:
*********************************************************
<?php
$body = '';
$fh = @fopen('php://input', 'r');
if ($fh)
{
while (!feof($fh))
{
$s = fread($fh, 1024);
if (is_string($s))
{
$body .= $s;
}
}
fclose($fh);
}
print("-------------- PHP Input Stream ----------------\n$body\n\n");
$body2 = http_get_request_body();
print("---------- http_get_request_body() -------------\n$body2\n\n");
?>
*********************************************************
outputs this:
*********************************************************
-------------- PHP Input Stream ----------------
<?xml version="1.0" encoding="utf-8" ?>
<body>test</body>
---------- http_get_request_body() -------------
<?xml version="1.0" encoding="utf-8" ?>
<body>test</body>
*********************************************************
The same request to the same script using an HTTP PUT request, however, outputs this:
*********************************************************
-------------- PHP Input Stream ----------------
<?xml version="1.0" encoding="utf-8" ?>
<body>test</body>
---------- http_get_request_body() -------------
*********************************************************
It seems a valid workaround is to put a call to http_get_request_body() to cache the body content before an expected read to php://input (i.e. simply calling the function without manually storing the result caches the content for subsequent calls).
http_get_request_body
(PECL pecl_http >= 0.10.0)
http_get_request_body — Récupère le corps demandé sous la forme d'une chaîne de caractères
Description
string http_get_request_body
( void
)
Récupère le corps demandé (e.g. données POST ou PUT).
Cette fonction ne peut pas être utilisée après la fonction http_get_request_body_stream() si la méthode de la demande est autre chose que POST.
Liste de paramètres
Valeurs de retour
Retourne le corps demandé sous la forme d'une chaîne de
caractères, ou NULL si une erreur survient.
Voir aussi
- http_get_request_body_stream() - Récupère le corps demandé sous la forme d'un flux
- http_get_request_headers() - Récupère les en-têtes sous la forme d'un tableau
- la classe HttpResponse si vous utilisez PHP 5.1 et supérieur
Tim Trinidad ¶
3 years ago
osborn dot steven at gmail dot com ¶
5 years ago
For those of you without the HTTP extension, try:
<?php
$body = @file_get_contents('php://input');
?>
slave at codegrunt dot com ¶
19 days ago
In case this saves anyone else some frustration, the "Content-Length" header decides what will be returned for "php://input". If you leave it out while testing, nothing will be returned for "php://input" or $HTTP_RAW_POST_DATA.
For example, if you are trying to test out a custom SOAP server app and you send a request like this without a Content-Length set:
-----
POST /soap_service.php HTTP/1.1
Authorization: Basic abcdefgh
User-Agent: SOAPy McSOAPclient
Host: example.com
Accept: */*
MIME-Version: 1.0
Content-type: text/xml; charset=utf-8
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:cat="http://com.soapy/foobar"><soapenv:Header/><soapenv:Body><foo:ManageBar><foo:task id="1"><foo:getBar type="helloworld"/></foo:task></foo:ManageBar></soapenv:Body></soapenv:Envelope>
----
"php://input" will always return and empty string.
neil at foo dot co dot za ¶
5 years ago
Like php://input and http_get_request_body_stream(), http_get_request_body() doesn't seem to work with enctype="multipart/form-data".
