PHP curl issue - Trying to send XML post request - php

I am attempting to make an xml post request which expects a response using curl to build the headers and content. Here is my code:
<?php
function post_xml($url, $xml) {
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HEADER, true);
curl_setopt($ch, CURLINFO_HEADER_OUT, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, Array("Content-Type: application/xml; charset=utf-8"));
curl_setopt($ch, CURLOPT_USERPWD, 'myusername:mypassword');
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $xml);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
$result = curl_exec($ch);
$info = curl_getinfo($ch);
curl_close($ch);
return $result;
}
$xml = '<?xml version="1.0" encoding="UTF-8"?><testing><test type="integer">1</test></testing>';
$url = "http://example.com/api/test.php";
$result = post_xml($url, $xml);
echo "<pre>"; print_r($result); echo "</pre>";
?>
To view my outgoing request I use:
$info = curl_getinfo($ch);
echo($info['request_header']);
The resulting HTTP request that is sent is:
POST /api/test.php HTTP/1.1
Authorization: Basic pwmtJdCVwNEawdaODH
Host: example.com
Accept: */*
Content-Type: application/xml; charset=utf-8
Content-Length: 95
The content-length is 95, but then it shows none of the xml content below. This results in a 422 Unprocessable Entity error. Am I completely missing something? I expected to be able to see the XML in the request sent.

You haven't specified a fieldname for your XML content, so PHP has nowhere to assign it in the POST request. As the manual states:
This parameter can either be passed as a urlencoded string like 'para1=val1&para2=val2&...' or as an array with the field name as key and field data as value.
So try:
curl_setopt($ch, CURLOPT_POSTFIELDS, array('xml' => $xml));
Don't know if this is what your API is expecting, but it's one thing to look into.
As for displaying the XML, remember that browsers can/will interpret it as HTML, and any unknown tags will simply not be displayed. Try doing your output as:
echo "<pre>";
echo htmlspecialchars($result);
echo "</pre>";
and/or outputting header('Content-type: text/plain') so that the XML tags will be displayed as-is and not be interpreted as unknown html tags.

echo($info['request_header']);
will only show the header that was sent. It will not show the post data, so you should not see the XML string.

It works when I removed the header line:
//curl_setopt($ch, CURLOPT_HTTPHEADER, ...
Final code:
curl_setopt($ch, CURLOPT_HEADER, 1);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, array('data' => $xml));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_FRESH_CONNECT, 1);

Related

cURL returns an empty string

I have following code which returns an empty string (in variable $result)
$createdURL = "https://telenorcsms.com.pk:27677/corporate_sms2/api/sendsms.jsp?session_id=123&to=92315&text=test&mask=1"
curl_setopt($ch, CURLOPT_URL, "$createdURL");
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 15);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: text/xml; charset=utf-8')) ;
curl_setopt($ch, CURLOPT_HEADER, 0);
$result = curl_exec($ch);
echo var_dump($result);
if(curl_errno($ch)){
echo 'Curl error: ' . curl_error($ch);
}
curl_close($ch);
Whereas when I run the link given in first line in browser address bar it returns following XML.
<corpsms>
<command>Submit_SM</command>
<data>Error 102</data>
<response>Error</response>
</corpsms>
Please help where am I wrong.
You are missing curl_init()
So use this code and you'll get a response from the API:
<?php
$createdURL = "https://telenorcsms.com.pk:27677/corporate_sms2/api/sendsms.jsp?session_id=123&to=92315&text=test&mask=1";
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $createdURL);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 15);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: text/xml; charset=utf-8')) ;
curl_setopt($ch, CURLOPT_HEADER, 0);
$result = curl_exec($ch);
echo var_dump($result);
if(curl_errno($ch)){
echo 'Curl error: ' . curl_error($ch);
}
curl_close($ch);
You should also check whether you need to send the Content-Tye: text/xml header and whether you should be using a POST or a GET.
This was due to space given in parameters of link like below
$createdURL = "https://telenorcsms.com.pk:27677/corporate_sms2/api/sendsms.jsp?session_id=123&to=92315&text=test and test&mask=my mask";
After removing space it is now giving output, but now need to tackle matter of spaces.
You can enable the CURLOPT_VERBOSE option:
curl_setopt($ch, CURLOPT_VERBOSE, true);
When CURLOPT_VERBOSE is set, output is written to STDERR or the file specified using CURLOPT_STDERR. The output is very informative.
You can also use tcpdump or wireshark to watch the network traffic.

url returns XML on browser, but doesn't when using cURL

I'm sending few parameters, via post to an url using CURL, the url is supposed to return the results in a XML, but instead it returns a string with the result.
If I copy the url and my variables and paste it in the browser, it returns the desired XML.
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL,$url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $variables);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HEADER, false);
$result = curl_exec($ch);
$error = curl_error($ch);
curl_close($ch);
print_r($result);
That's the piece of code that I'm using. Am I missing something?
Thanks in advance.
Take the string that cURL returns and turn it into an XML object
$xml = simplexml_load_string($result);
SimpleXML documentation HERE
Try to add http headers:
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Content-type: text/xml;charset=\"utf-8\"",
"Accept: text/xml",
]);

PHP Curl - Knowing the Content-type

Below is an example without CURLOPT_HTTPHEADER, and it works fine.
<?php
$URL = "http://someurl.info";
$data = 'x_test_request=0&x_version=3.1&x_delim_data=true&x_relay_response=false';
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $URL);
curl_setopt($ch, CURLOPT_TIMEOUT, 1800);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HEADER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
$response = curl_exec($ch);
?>
Does Curl auto-detect the type of data we Post, and auto-count the string length?
Or should we always specify Both?
Or does it largely depend on the destination's rules and expectations?
To be safe, I usually add the header info like this:
<?php
$contentlen = strlen(trim($data));
$headersARR = array(
"Content-type: application/x-www-form-urlencoded",
"Content-length: ".$contentlen,
);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headersARR);
?>
I read http://us1.php.net/curl_setopt, but haven't noticed any details on defaulted content-type parameters.
If you do not specify anything about Content-type but use the CURLOPT_POSTFIELDS then the header is always Content-type: application/x-www-form-urlencoded as default. Also it sets the Content-length: automatically.
For this reason, when we post JSON content through the POST we need to override the content-type through HTTPHEADER option. It is similar to XML or any other specific type of content.

Curl request - invalid xml request when posting user&password after xml

I need to send the following request, which is XML with a username and password on the end of the xml. I can get this to work as a URL when I paste into the browser:
URL?XML=<>...</>&user=123456&password=123456
But when I try to create the curl call it says it's an invalid XML request.
I've tried having the user&password within the POSTFIELDS. I've also tried setting them as a variable before $trial ='&user=123456&password=123456' but still can't seem to get it to work.
$xml = <<<ENDOFXML
<?xml version="1.0" encoding="UTF-8"?><xmldata>...</xmldata>
ENDOFXML;
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-type: application/x-www-form-urlencoded'));
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, 'xml='.urlencode($xml).urlencode('&user=123456&password=123456'));
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_close($ch);
This is wrong:
curl_setopt($ch, CURLOPT_POSTFIELDS, 'xml='.urlencode($xml).urlencode('&user=123456&password=123456'));
urlencode only the variable names and the values (or only values if you know the variable names are ok):
curl_setopt($ch, CURLOPT_POSTFIELDS, 'xml='.urlencode($xml).'&user=' . urlencode('123456').'&password=' . urlencode('123456'));

how to receive this curl post?

What do I have to do on the server page and how to receive this xml file? I'm stuck.
The xml is fine, it is checked with simplexml_load_string.
$var='caca';
$login_xml ='<xml>'.
'<action>log_in</action>'.
'<parameters>'.
'<username>'.$var.'</username>'.
'<pass>abdef01</pass>'.
'</parameters>'.
'</xml>';
$URL = "http://myurl.com/login.php/";
$ch = curl_init($URL);
curl_setopt($ch, CURLOPT_MUTE, 1);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: text/xml'));
curl_setopt($ch, CURLOPT_POSTFIELDS, "$login_xml");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$output = curl_exec($ch);
curl_close($ch);
Thank you for your time.
Since the data is send as text/xml and not as url-encoded form-data, you can't use $_POST. You have to read the raw request from the php://input stream
$xml = file_get_contents('php://input');
You have an error in your CURLOPT_POST_FIELDS:
This option, must be an array:
...
$data = array('xml' => $login_xml);
...
And then:
...
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
...
This sends the value 'xml' as post field;
Hope this helps.

Categories