Reading non key/value POST data from PHP - php

I have a system that POSTs data to an URL without sending key/value pairs but instead using an XML payload. I need to read that XML data using PHP under Apache, but PHP's $_POST array is for key/value pairs and thus is blank as no keys are provided.
I tried reading from php://input and php://stdin, but that's also blank.
How can I read the raw POST data using PHP? I cannot control the input as it is being generated by a third-party application. Imagine this being a RESTful URL that accepts XML payload.

According to the PHP manual, php://input is not available with enctype="multipart/form-data".. If this is what's being POSTed to you, PHP will not allow you to access the raw data.
One workaround to this issue:
(source: https://stackoverflow.com/questions/1361673/get-raw-post-data)
Add this to your apache.conf:
<Location "/backend/XXX.php">
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
</Location>
As of PHP 5.4, there is also the "enable-post-data-reading" ini setting (http://php.net/manual/en/ini.core.php#ini.enable-post-data-reading).
From the PHP manual: "Disabling this option causes $_POST and $_FILES not to be populated. The only way to read postdata will then be through the php://input stream wrapper. This can be useful to proxy requests or to process the POST data in a memory efficient fashion."
Try disabling this setting and then reading from php://input.

You can check and see if there is any information stored in your post by doing:
print_r( $_POST );
What you would like to do might be sending the XML data in a key named xml or something like that resulting in $_POST['xml'] = 'your xml code'
EDIT:
It would also be nice if you could post the code you use to create the $_POST.

Related

PHP get PUT request body

I'm currently developing a Restful Json-API in PHP. I want to send a PUT-Request to items/:id to update a record. The data will be transferred as application/json.
I want to call the API with
curl -H "Content-Type: application/json" -X PUT -d '{"example" : "data"}' "http://localhost/items/someid"
On the server side, I'm not able the retrieve the request body. I tried
file_get_contents("php://input");
but this returns an empty string. Also a fopen()/fread() combination doesn't work.
When calling via POST, everything works great, I can read the json perfectly on the server side. But the API isn't Restful anymore. Does anyone have a solution for this? Is there another way to send and receive Json?
btw, I'm developing the API with the Slim Framework.
php://input is only readable once for PUT requests:
Note: A stream opened with php://input can only be read once; the stream does not support seek operations. However, depending on the SAPI implementation, it may be possible to open another php://input stream and restart reading. This is only possible if the request body data has been saved. Typically, this is the case for POST requests, but not other request methods, such as PUT or PROPFIND.
http://php.net/manual/en/wrappers.php.php
The Slim framework already reads the data upon request. Take the data from the Request object, into which it has been read.
On the server side, I'm not able the retrieve the request body. I tried file_get_contents("php://input");
You can only use file_get_contents( 'php://input', 'r' ); once per request. Retrieving its values will truncate the values as well, so if you call it twice, it'll return an empty string. Slim's request object contains the values you need, so:
<?php
$app = new Slim( );
$app->put( '/items/someid', function () use ( $app ) {
echo $app->request( )->put( 'example' ); // should display "data".
});
The example from the PHP manual uses fopen to access php://input in read mode. Have you tried doing it that way instead?
EDIT: The manual page for PHP:// says some stuff that seems to suggest that PUT data might not be available in some cases!
Note: A stream opened with php://input can only be read once; the
stream does not support seek operations. However, depending on the
SAPI implementation, it may be possible to open another php://input
stream and restart reading. This is only possible if the request body
data has been saved. Typically, this is the case for POST requests,
but not other request methods, such as PUT or PROPFIND.
I don't know where this will leave you regarding PUT processing. One page seems to say it's possible, the other seems to imply that it won't work under the wrong set of circumstances
I was reading the SLIM framework documentation the other day and it said that some browsers have problems with PUT and DELETE.
Excerpt:
Unfortunately, modern browsers do not provide native support for PUT requests. To work around this limitation, ensure your HTML form’s method is “post”, then add a method override parameter to your HTML form like this:
<form action="/books/1" method="post">
... other form fields here...
<input type="hidden" name="_METHOD" value="PUT"/>
<input type="submit" value="Update Book"/>
</form>
Source: http://www.slimframework.com/documentation/stable

Access PUT-data in PHP

I want to access JSON data sent with the PUT-method, as a payload to a PHP-backend.
From what I've read, the data should be available in the php://input stream, and I should be able to fetch it using.
file_get_contents('php://input');
This works for POST-requests, but just returns an empty string when using PUT,
although I can find the PUT-data as the first key in the $_POST variable, like this:
array(
"{"latLngPosition":null,"pixelPosition":null,"id":"1","marking":"012312312313"}" => ""
)
It doesn't seem right to fetch the data this way, so I wonder what I might do wrong when fetching using php://input.
I'm using nginx with fastcgi to run PHP.

receive in a php(server) a POST send by java (client)

i want to receive in a server a xml file sent by java by POST
how can e receive that ? and how can e parse the file, in this case a xml file...
regards.
There are numerous tutorials on handling file uploads (including: http://www.php.net/manual/en/features.file-upload.post-method.php ) if you're actually uploading a file. If, instead, you're posting the contents of the file, the contents will be in the $_POST and $_REQUEST arrays - PHP creates and populates these for you.
This is a broad (and basic) question, so a more specific answer will require you to read some tutorials, try some code, and post specific questions about problems you encounter.
If it's a file upload (enctype="multipart/form-data"), use the $_FILES superglobal: Handling File Uploads.
Otherwise, just refer to it by its form field name: $_POST['xmlfile'].
Either way, parse it using the DOM or SimpleXML.
if it's XMLRPC request, you have to use either $HTTP_RAW_POST_DATA or php://input wrapper.

HTTP_RAW_POST_DATA empty - alternate solution

I'm trying to use a script that is provided by an E-commerce site that obtains data from an XML feed that is posted to a URL on my site. The script gathers the data using....
$requestBodyXML = new DOMDocument();
# Load the request body into XML and check that the result has been parsed into XML
if ($requestBodyXML->loadXML($HTTP_RAW_POST_DATA) == true)
The problem is that there's no data being passed. I understand this is depreciated, but how else would I accomplish this?
$HTTP_RAW_POST_DATA requires an ini value to be set, using the input stream should work without any special ini settings and is also the 'prefered' method. It is worth noting that neither php://input or $HTTP_RAW_POST_DATA is available with enctype="multipart/form-data".
//The alternative method
$postData = file_get_contents('php://input')
Documentation

Receiving and handling a GET request in PHP

I'm trying to replace RSS polling with PubSubHubbub on my site. I'm able to use the subscriber library that google offers to send the subscription request. From the code it looks like it sends a post request via cURL with the RSS URL and a callback URL.
So this is where I need some direction:
In order to complete the subscription request my callback URL has to receive a GET request and then echo back a value from the GET request along with a 200 response. How do I get the parameters from the GET request? Is the echo done again via cURL? If so what option should include the 200 response?
This very simple script should be a start:
echo $_GET["request_name"];
this will output the GET parameter request_name and (implicitly) send a 200.
It's also a good idea to explicitly declare a content type before echoing, to prevent the default content type (usually "text/html") from kicking in:
header("Content-type: text/plain");
Note that when echoing external data, you may need to sanitize the output first - if the for example the output format is HTML, you would want to do something like echo htmlspecialchars($_GET["request_name"]); to prevent Cross-Site Scripting.
There was recently a thread on the php-dev mailing list about this. The reason you can't access 'hub.challenge' in the $_GET superglobal is due to register_globals. Basically PHP cleans up any argument names before creating the superglobals. Any dots will be converted to underscores. It's looking to be 'fixed' in PHP 6, but not before due to BC issues.
Here's the thread about it.

Categories