I need to write a PHP page which would accept an XML document sent over a POST request like this:
POST /mypage.php HTTP/1.1
Host: myhost.com
Content-Type: application/xml
Content-Length: ...
<?xml version="1.0" encoding="utf-8"?>
<data>
...
</data>
This is not data from some HTML form, just a plain XML document.
How can I access this XML in my PHP code?
Read from php://input. For example, you could use:
$rawdata = file_get_contents('php://input');
or
$rootNode = simplexml_load_file('php://input');
The alternative, using $HTTP_RAW_POST_DATA, works, too - but it's slower and needs the PHP configuration always_populate_raw_post_data.
Try the $HTTP_RAW_POST_DATA variable or the php://input stream.
http://us.php.net/manual/en/reserved.variables.httprawpostdata.php
$HTTP_RAW_POST_DATA should be available assuming the content-type of the request was not multipart/form-data
$HTTP_RAW_POST_DATA
or
php://input
You probably want to use the PHP input. Something like
$postText = trim(file_get_contents('php://input'));
Any of these would work:
$HTTP_RAW_POST_DATA variable or the php://input stream.
However, for the
$HTTP_RAW_POST_DATA variable
to work, you might need to change .ini setting in your configuration file
If you use print_r($_POST); you will be able to see what you got. Unless i'm missing something...
Edit: nvm, totaly forgot about Raw Data :/
Related
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.
I'm sending a POST request using WebClient.UploadData() method (C#) to my webserver. The packet sent to my webserver looks like so:
POST / HTTP/1.1
Host: {ip}
Content-Length: {length}
Expect: 100-continue
Connection: Keep-Alive
{buffer_content}
As the {buffer_content} is nowhere assigned in the $_POST array, I have the following question...
Question: How do I read the {buffer_content} with PHP?
I've stumbled upon file_get_contents('php://input'), but I'm unsure whether that is recommended to do.
Use the php://input stream:
$requestBody = file_get_contents('php://input');
This is the recommended way to do this and, in PHP 7.0, the only way. Previously, there was sometimes a global variable called $HTTP_RAW_POST_DATA, but whether it existed would depend on an INI setting, and creating it hurt performance. That variable was deprecated and removed.
Beware that prior to PHP 5.6, you can only read php://input once, so make sure you store it.
Once you have your body, you can then decode it from JSON or whatever, if you need that:
$requestBody = json_decode($requestBody) or die("Could not decode JSON");
I am having difficulties figuring this out. I can see I am posting XML and I see the length of it but I cannot figure out how to display or access the POST DATA
CONTENT-TYPE: text/xml<br />
CONTENT-LENGTH: 640<br />
separately I have
curl -k -H 'content-type: text/xml' -d 'XML_DATA_HERE' https://ip/page.php
Try
$xml = file_get_contents('php://input');
http://docs.php.net/manual/en/wrappers.php.php says:
php://input allows you to read raw POST data. It is a less memory intensive alternative to $HTTP_RAW_POST_DATA and does not need any special php.ini directives. php://input is not available with enctype="multipart/form-data".
OK n00b here with SOAP,
Would like some clarification on how to use SOAP.
Question:
I have a Java JSP that posts a WSDL (Looks like XML format) to my PHP script, but how do I get this in the PHP script? The URL for the WSDL will be different every time.
I'm sure it's very simple but just don't see how or am I not understanding this correctly?
You can try something like this:
try {
if (!($xml = file_get_contents('php://input'))) {
throw new Exception('Could not read POST data.');
}
} catch (Exception $e) {
print('Did not successfully process HTTP request: '.$e->getMessage());
exit;
}
This will read the body of the POST request to the $xml variable and print an error if there is one.
Do you mean that the JSP sends the WSDL in a POST request to the PHP script?
If so, have a look at the $_POST array. If you specify exactly how the JSP sends it, I can probably help you more.
Anyway, once you have the WSDL url in a variable in your PHP script, you can have at it with the SoapClient class.
Assuming the best scenario:
$soapClient = new SoapClient($wsdlUrl, $soapOptions);
$soapClient->callYourMethod();
But you're likely to hit a lot of brick walls when using SOAP. Here's the documentation for SoapClient.
Edit:
So, the WSDL is POST-ed. Then, you could access it either by using $HTTP_RAW_POST_DATA if the XML string was sent as the HTTP body, or by using the $_FILES superglobal if the XML string was send as a part of a multipart request.
Something like this:
$wsdl = $HTTP_RAW_POST_DATA;
$wsdlUrl = 'data:text/xml;base64,' . base64_encode($wsdl);
$soapClient = new SoapClient($wsdlUrl);
Anyway, $HTTP_RAW_POST_DATA is only available if the php.ini setting always_populate_raw_post_data is turned on. Also, if the request was multipart, this setting is ignored, $HTTP_RAW_POST_DATA is not populated but you get access to the posted parts using $_FILES. And you may, indeed, use php://input instead of $HTTP_RAW_POST_DATA.
Also, data URIs may only be used when allow_url_fopen is turned on in php.ini.
According to php manual nor php://input neither $HTTP_RAW_POST_DATA work with multipart/form-data POST-requests.
"php://input allows you to read raw POST data. It is a less memory intensive alternative to $HTTP_RAW_POST_DATA and does not need any special php.ini directives. php://input is not available with enctype="multipart/form-data"."
How can I get raw data for multipart/form-data forms?
Direct answer: you can not do that. PHP insists on parsing it itself, whenever it sees the multipart/form-data Content-Type. The raw data will not be available to you. Sadly. But you can hack around it.
I hit a similar problem, a partner was sending incorrectly formatted data as multipart/form-data, PHP could not parse it and was not giving it out so I could parse it myself.
The solution? I added this to my apache conf:
<Location "/backend/XXX.php">
SetEnvIf Content-Type ^(multipart/form-data)(.*) NEW_CONTENT_TYPE=multipart/form-data-alternate$2 OLD_CONTENT_TYPE=$1$2
RequestHeader set Content-Type %{NEW_CONTENT_TYPE}e env=NEW_CONTENT_TYPE
</Location>
This will change the Content-Type of incoming request to XXX.php from multipart/form-data to multipart/form-data-alternate, which is enough to block PHP from trying to parse it
After this you can finally read the whole raw data from php://input and parse it yourself.
It is ugly, but I have not found a better or in fact any other solution - short of asking the partner to fix their side.
NB! When you do what I described here, $_FILES will be empty.
You can set enable_post_data_reading = Off and PHP won't intercept multipart/form-data data.
Requires: PHP 5.4
I didn't implement this fully, but it looks like it should work. In Apache conf:
SetEnvIf Content-Type ^(multipart/form-data)(.*) MULTIPART_CTYPE=$1$2
RequestHeader set Content-Type application/x-httpd-php env=MULTIPART_CTYPE
RequestHeader set X-Real-Content-Type %{MULTIPART_CTYPE}e env=MULTIPART_CTYPE
Setting the Content-Type to application/x-httpd-php appears to solve the original problem of PHP parsing the body, and the problem Norbert Farkas reported: "Apache sends back PHP source code". The body is then available on php://input, and the real content type in the X-Real-Content-Type header. (That header may not be necessary for you -- the MULTIPART_CTYPE variable didn't seem to be showing up in my $_ENV, but the new header did.) All other requests should be handled as usual.
Thanks to Anti Veeranna for most of it! :)
EDIT: P.S. Obviously it's Apache-specific, but in some of the other configurations of PHP there may very well be easier ways.
//Get the raw POST data
$postBody = file_get_contents("php://input");