PHP How to Ready Body of File SENT to Script [duplicate] - php

I submit as POST to a php page the following:
{a:1}
This is the body of the request (a POST request).
In php, what do I have to do to extract that value?
var_dump($_POST);
is not the solution, not working.

To access the entity body of a POST or PUT request (or any other HTTP method):
$entityBody = file_get_contents('php://input');
Also, the STDIN constant is an already-open stream to php://input, so you can alternatively do:
$entityBody = stream_get_contents(STDIN);
From the PHP manual entry on I/O streamsdocs:
php://input is a read-only stream that allows you to read raw data
from the request body. In the case of POST requests, it is preferable
to use php://input instead of $HTTP_RAW_POST_DATA as it does not
depend on special php.ini directives. Moreover, for those cases where
$HTTP_RAW_POST_DATA is not populated by default, it is a potentially
less memory intensive alternative to activating
always_populate_raw_post_data. php://input is not available with
enctype="multipart/form-data".
Specifically you'll want to note that the php://input stream, regardless of how you access it in a web SAPI, is not seekable. This means that it can only be read once. If you're working in an environment where large HTTP entity bodies are routinely uploaded you may wish to maintain the input in its stream form (rather than buffering it like the first example above).
To maintain the stream resource something like this can be helpful:
<?php
function detectRequestBody() {
$rawInput = fopen('php://input', 'r');
$tempStream = fopen('php://temp', 'r+');
stream_copy_to_stream($rawInput, $tempStream);
rewind($tempStream);
return $tempStream;
}
php://temp allows you to manage memory consumption because it will transparently switch to filesystem storage after a certain amount of data is stored (2M by default). This size can be manipulated in the php.ini file or by appending /maxmemory:NN, where NN is the maximum amount of data to keep in memory before using a temporary file, in bytes.
Of course, unless you have a really good reason for seeking on the input stream, you shouldn't need this functionality in a web application. Reading the HTTP request entity body once is usually enough -- don't keep clients waiting all day while your app figures out what to do.
Note that php://input is not available for requests specifying a Content-Type: multipart/form-data header (enctype="multipart/form-data" in HTML forms). This results from PHP already having parsed the form data into the $_POST superglobal.

return value in array
$data = json_decode(file_get_contents('php://input'), true);

A possible reason for an empty $_POST is that the request is not POST, or not POST anymore... It may have started out as post, but encountered a 301 or 302 redirect somewhere, which is switched to GET!
Inspect $_SERVER['REQUEST_METHOD'] to check if this is the case.
See https://stackoverflow.com/a/19422232/109787 for a good discussion of why this should not happen but still does.

function getPost()
{
if(!empty($_POST))
{
// when using application/x-www-form-urlencoded or multipart/form-data as the HTTP Content-Type in the request
// NOTE: if this is the case and $_POST is empty, check the variables_order in php.ini! - it must contain the letter P
return $_POST;
}
// when using application/json as the HTTP Content-Type in the request
$post = json_decode(file_get_contents('php://input'), true);
if(json_last_error() == JSON_ERROR_NONE)
{
return $post;
}
return [];
}
print_r(getPost());

This is an exemple of how to create a php api with file_get_contents("php://input") and used in javascript using ajax with XMLHttpRequest.
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function () {
if (this.readyState == 4 && this.status == 200) {
console.log("done");
}
}
};
xhttp.open("POST", "http://127.0.0.1:8000/api.php", true);
xhttp.send(JSON.stringify({
username: $(this).val(),
email:email,
password:password
}));
$data = json_decode(file_get_contents("php://input"));
$username = $data->username;
$email = $data->email;
$password = $data->password;

Check the $HTTP_RAW_POST_DATA variable

If you have the pecl/http extension installed, you can also use this:
$request = new http\Env\Request();
$request->getBody();

If you have installed HTTP PECL extension, you can make use of the http_get_request_body() function to get body data as a string.

http_get_request_body() was explicitly made for getting the body of PUT and POST requests as per the documentation http://php.net/manual/fa/function.http-get-request-body.php

Related

How to get "php://input" data if I'm using Content-Type multipart/form-data

Is there an alternative?
I'm using Advanced Rest Client for testing an API I'm developing.
I send a JSON with POST.
In code, $_FILES is fine, but file_get_contents("php://input") is empty.
If I don't send any files, then I can use file_get_contents("php://input")
PHP version: 5.6.4
As GhostGambler states, php://input is not available with enctype="multipart/form-data".
You should not attach the JSON as a file to your request, you should add it as the request body to the post request, setting the Content-Type header (application/json). Then it will be available in php://input.
Ok, so I ended up giving a name to my JSON data, like 0=[{"q":"w"}] and then get it with $_POST['0']. And the files with $_FILES
Here's how it looks in Advanced REST Client:
Most likely accessing any of the POST/FILES superglobals consumes php://input.
In any case, if you send a JSON payload you cannot have a multipart-formdata payload too so $_FILES should be empty. If you need to handle both on the same page (bad idea IMO) make sure to check the content type header or some other information outside the request's body before accessing either $_FILES or php://input
php://input is a read-only stream that allows you to read raw data
from the request body. In the case of POST requests, it is preferable
to use php://input instead of $HTTP_RAW_POST_DATA as it does not
depend on special php.ini directives. Moreover, for those cases where
$HTTP_RAW_POST_DATA is not populated by default, it is a potentially
less memory intensive alternative to activating
always_populate_raw_post_data. php://input is not available with
enctype="multipart/form-data".
http://php.net/manual/de/wrappers.php.php
Since HTTP_RAW_POST_DATA is marked deprecated, I guess you are somewhat unlucky. I do not know alternatives.
Edit: Well, you could try php://stdin / STDIN, although I do not know if this works with PHP in a webserver ... maybe just try it out.

HTTP PUT, DELETE and I/O streams with PHP

Is there any way I can access data that was sent via HTTP PUT method other than $putdata = fopen("php://input", "r");?
I have never worked with PUT and DELETE methods and $putdata = fopen("php://input", "r"); seems a bit sketchy. Will it work everywhere is a specific server/php.ini configuration required?
I know that I can get the request method from $_SERVER['REQUEST_METHOD'];
But will the data be in $_REQUEST, if yes then what php://input is about?
And how do I access data that was sent via DELETE?
No, you will need to parse the request manually. $_REQUEST only contains data coming from GET and POST requests; for everything else you are on your own.
If your HTTP request has Content-Type: application/x-www-form-urlencoded, you can parse it back into a variables array very easily with parse_str like this:
parse_str(file_get_contents('php://input'), $vars);
print_r($vars);
You can use this content type with any HTTP method, there is no standard-imposed limitation.

XMLHttpRequest sending XML to PHP server

I was wondering if I could send some data from my client-side (2d application using HTML5's canvas) to the server-side in the XML format?
I tried something like this:
function send_xml_data_to_server(xml, url) {
var xmlhttp = new XMLHttpRequest();
xmlhttp.open("POST", url, true);
xmlhttp.setRequestHeader('Content-Type', 'text/xml');
xmlhttp.send(xml);
xmlhttp.onreadystatechange = function() {
callback_response_from_server(xmlhttp);
}
}
Because in the informations that I must send to the server-side, it contains a few texts and it doesn't seem to work quite right with the the MIME:
xmlhttp.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
But when I'm on the server-side I checked $_POST but there is nothing inside it, the same for $_REQUEST.
So, at the end, I was wondering if it is even possible to send XML data to the server-side PHP using XMLHttpRequest?
Thanks!
There's nothing wrong on the client side, but $_POST contains a parsed set of key/value pairs, but that's not what you're sending to the server. Use something like this:
file_get_contents('php://input');
Then you can parse the string using SimpleXML or whatever you like.
$_POST will be empty if you do not send data as application/x-www-form-urlencoded.
did you try this?
$xml = file_get_contents("php://input");
This way you will capture data in raw format and interpret it according to used mime type.

How to get body of a POST in php?

I submit as POST to a php page the following:
{a:1}
This is the body of the request (a POST request).
In php, what do I have to do to extract that value?
var_dump($_POST);
is not the solution, not working.
To access the entity body of a POST or PUT request (or any other HTTP method):
$entityBody = file_get_contents('php://input');
Also, the STDIN constant is an already-open stream to php://input, so you can alternatively do:
$entityBody = stream_get_contents(STDIN);
From the PHP manual entry on I/O streamsdocs:
php://input is a read-only stream that allows you to read raw data
from the request body. In the case of POST requests, it is preferable
to use php://input instead of $HTTP_RAW_POST_DATA as it does not
depend on special php.ini directives. Moreover, for those cases where
$HTTP_RAW_POST_DATA is not populated by default, it is a potentially
less memory intensive alternative to activating
always_populate_raw_post_data. php://input is not available with
enctype="multipart/form-data".
Specifically you'll want to note that the php://input stream, regardless of how you access it in a web SAPI, is not seekable. This means that it can only be read once. If you're working in an environment where large HTTP entity bodies are routinely uploaded you may wish to maintain the input in its stream form (rather than buffering it like the first example above).
To maintain the stream resource something like this can be helpful:
<?php
function detectRequestBody() {
$rawInput = fopen('php://input', 'r');
$tempStream = fopen('php://temp', 'r+');
stream_copy_to_stream($rawInput, $tempStream);
rewind($tempStream);
return $tempStream;
}
php://temp allows you to manage memory consumption because it will transparently switch to filesystem storage after a certain amount of data is stored (2M by default). This size can be manipulated in the php.ini file or by appending /maxmemory:NN, where NN is the maximum amount of data to keep in memory before using a temporary file, in bytes.
Of course, unless you have a really good reason for seeking on the input stream, you shouldn't need this functionality in a web application. Reading the HTTP request entity body once is usually enough -- don't keep clients waiting all day while your app figures out what to do.
Note that php://input is not available for requests specifying a Content-Type: multipart/form-data header (enctype="multipart/form-data" in HTML forms). This results from PHP already having parsed the form data into the $_POST superglobal.
return value in array
$data = json_decode(file_get_contents('php://input'), true);
A possible reason for an empty $_POST is that the request is not POST, or not POST anymore... It may have started out as post, but encountered a 301 or 302 redirect somewhere, which is switched to GET!
Inspect $_SERVER['REQUEST_METHOD'] to check if this is the case.
See https://stackoverflow.com/a/19422232/109787 for a good discussion of why this should not happen but still does.
function getPost()
{
if(!empty($_POST))
{
// when using application/x-www-form-urlencoded or multipart/form-data as the HTTP Content-Type in the request
// NOTE: if this is the case and $_POST is empty, check the variables_order in php.ini! - it must contain the letter P
return $_POST;
}
// when using application/json as the HTTP Content-Type in the request
$post = json_decode(file_get_contents('php://input'), true);
if(json_last_error() == JSON_ERROR_NONE)
{
return $post;
}
return [];
}
print_r(getPost());
This is an exemple of how to create a php api with file_get_contents("php://input") and used in javascript using ajax with XMLHttpRequest.
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function () {
if (this.readyState == 4 && this.status == 200) {
console.log("done");
}
}
};
xhttp.open("POST", "http://127.0.0.1:8000/api.php", true);
xhttp.send(JSON.stringify({
username: $(this).val(),
email:email,
password:password
}));
$data = json_decode(file_get_contents("php://input"));
$username = $data->username;
$email = $data->email;
$password = $data->password;
Check the $HTTP_RAW_POST_DATA variable
If you have the pecl/http extension installed, you can also use this:
$request = new http\Env\Request();
$request->getBody();
If you have installed HTTP PECL extension, you can make use of the http_get_request_body() function to get body data as a string.
http_get_request_body() was explicitly made for getting the body of PUT and POST requests as per the documentation http://php.net/manual/fa/function.http-get-request-body.php

XHR request to PHP

Hi i am having problems with an XHR post request.
in javascript:
self.xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
self.xhr.setRequestHeader("Method", "POST " + url + " HTTP/1.1");
In firebug:
Parametersapplication/x-www-form-urlencoded
{"u":"andrepadez","m":"\n...
JSON
m
"sfdsfsdfdsfdsf"
u
"andrepadez"
Source
{"u":"andrepadez","m":"\nsfdsfsdfdsfdsf"}
In .NET, I post this to an .ASHX, and in the ProcessRequest i do:
StreamReader sr = new StreamReader(context.Request.InputStream, context.Request.ContentEncoding);
javaScriptSerializer.Deserialize<MyClass>(message);
and I have no problems.
I don't know how to get the data in PHP, either $_POST and $_REQUEST are empty arrays.
Any help please?
thanks
You've not set a field name for the data being sent. PHP requires data coming in via POST to be in a fieldname=value format. _POST is an array like any other, and every value stored in a PHP array must have a key (which is the form field name).
You can try retrieving the data by reading from php://input:
$post_data = file_get_contents('php://input');
But the simplest solution is to provide a fieldname in your XHR call.
You are setting the Content-Type to application/x-www-form-urlencoded, but you are setting the content to json. I'm guessing this is confusing your PHP webserver. Try setting your POST contents to what you tell the server it will be (application/x-www-form-urlencoded) or read the raw HTTP contents in php://input.
If you set the Content-Type to application/x-www-form-urlencoded then naturally PHP will want to parse the POST body. But as the data does not actually constitute form data, it is discarded as invalid.
You need to set the correct CT application/json (actually doesn't matter) so PHP will leave it alone. Then it becomes available as php://input or $HTTP_RAW_POST_DATA

Categories