How to properly send and receive XML using curl? - php

I've been trying to post XML and get response from the server but with no luck.
Here are the conditions on server side:
Requests to the server should be sent as XML over HTTP 1.1.
The following requirements apply to the HTTP request:
The request type should be POST;
A Content-Length header should be present, and the total length of the request should be below 16KB;
A Content-Type header should be present, containing the media type value text/xml;
Here is my script:
$url = "http://somedomain.com";
$xml = '<?xml version="1.0" encoding="UTF-8"?>
<Request PartnerID="asasdsadsa" Type="TrackSearch"> <TrackSearch> <Title>love</Title> <Tags> <MainGenre>Blues</MainGenre> </Tags> <Page Number="1" Size="20"/> </TrackSearch> </Request>';
$header = "POST HTTP/1.1 \r\n";
$header .= "Content-type: text/xml \r\n";
$header .= "Content-length: ".strlen($xml)." \r\n";
$header .= "Connection: close \r\n\r\n";
$header .= $xml;
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL,$url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $header);
$data = curl_exec($ch);
echo $data;
if(curl_errno($ch))
print curl_error($ch);
else
curl_close($ch);
This gives me:
HTTP Error 400. The request URL is invalid.
Bad Request - Invalid URL

Does this help?
<?php
$url = "http://stackoverflow.com";
$xml = '<?xml version="1.0" encoding="UTF-8"?><Request PartnerID="asasdsadsa" Type="TrackSearch"> <TrackSearch> <Title>love</Title> <Tags> <MainGenre>Blues</MainGenre> </Tags> <Page Number="1" Size="20"/> </TrackSearch> </Request>';
$headers = array(
"Content-type: text/xml",
"Content-length: " . strlen($xml),
"Connection: close",
);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL,$url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $xml);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
$data = curl_exec($ch);
echo $data;
if(curl_errno($ch))
print curl_error($ch);
else
curl_close($ch);
?>

From the documentation.
CURLOPT_CUSTOMREQUEST
A custom request method to use instead of "GET"
or "HEAD" when doing a HTTP request. This is useful for doing "DELETE"
or other, more obscure HTTP requests. Valid values are things like
"GET", "POST", "CONNECT" and so on; i.e. Do not enter a whole HTTP
request line here. For instance, entering "GET /index.html
HTTP/1.0\r\n\r\n" would be incorrect.
The parameter for CURLOPT_CUSTOMREQUEST should be simply POST and you can use CURLOPT_HTTPHEADER to set headers.

Related

Execute multiple parallel cURL against the same URL?

I need to execute 2 requests in parallel using cURL to get a reply from the web service.
The problem is that I need to get the encrypted password from the first XML's output and pass it to the second XML to get 100 success response from the API.
Currently, I have created 2 cURL to achieve this but the API responds "101 Password Expired" because the encrypted password is valid only for the first request.
Here is my code for reference:
1st cURL:
$soapUrl = "http://localhost:54934/frmMutualFund.asmx?op=getPassword"; // asmx URL of WSDL
// xml post structure
$xml_post_string = '<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<getPassword xmlns="http://tempuri.org/">
<pUserId>12345</pUserId>
<pPassword>98765</pPassword>
<pPasskey>ksjhdfksj</pPasskey>
</getPassword>
</soap:Body>
</soap:Envelope>'; // data from the form, e.g. some ID number
$headers = array(
"Content-type: text/xml;charset=\"utf-8\"",
"Accept: text/xml",
"Cache-Control: no-cache",
"Pragma: no-cache",
"SOAPAction: http://tempuri.org/getPassword",
"Content-length: ".strlen($xml_post_string),
); //SOAPAction: your op URL
$url = $soapUrl;
// PHP cURL for https connection with auth
$ch = curl_init();
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 1);
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
//curl_setopt($ch, CURLOPT_USERPWD, $soapUser.":".$soapPassword); // username and password - declared at the top of the doc
curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $xml_post_string); // the SOAP request
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
// converting
$response = curl_exec($ch);
2nd cURL:
$soapUrl = "http://localhost:54934/frmMutualFund.asmx"; // asmx URL of WSDL
// xml post structure
$xml_post_string = '<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<MFUAPI xmlns="http://tempuri.org/">
<pFlag>06</pFlag>
<pUserId>12345</pUserId>
<pEncPassword>'.$response.'</pEncPassword>
<pParam>some_parameters</pParam>
</MFUAPI>
</soap:Body>
</soap:Envelope>'; // data from the form, e.g. some ID number
$headers = array(
"Content-type: text/xml;charset=\"utf-8\"",
"Accept: text/xml",
"Cache-Control: no-cache",
"Pragma: no-cache",
"SOAPAction: http://tempuri.org/MFUAPI",
"Content-length: ".strlen($xml_post_string),
); //SOAPAction: your op URL
$url = $soapUrl;
// PHP cURL for https connection with auth
$ch = curl_init();
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 1);
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
//curl_setopt($ch, CURLOPT_USERPWD, $soapUser.":".$soapPassword); // username and password - declared at the top of the doc
curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $xml_post_string); // the SOAP request
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
// converting
$response = curl_exec($ch);
curl_close($ch);
// converting
$response1 = str_replace("<soap:Body>","",$response);
$response2 = str_replace("</soap:Body>","",$response1);
// convertingc to XML
$parser = simplexml_load_string($response2);
// user $parser to get your data out of XML response and to display it.
print_r($parser);
first
I need to execute 2 requests in parallel
then
The problem is that I need to get the encrypted password from the
first XML's output and pass it to the second XML to get 100 success
response from the API.
if the request body of the 2nd request depends on the response of the first request, then you cannot do these 2 requests in parallel.
(generally speaking. you might be able to do some micro-optimization where you send the first request, and partially send the 2nd request, then wait for the password of the first request to be retrieved, then finish the 2nd request, but it'd be difficult to pull off, the gains would probably be very small and if you time it wrong you'll probably get a timeout for the 2nd request and have to start the 2nd request all over again, which would be even slower than just doing the 2 requests sequentially in the first place. you'll also need reliable recovery code for 2nd request timeout'ed while waiting for the password of the 1st request, it would be easy to code it wrong.)

How can I send a SOAP message using PHP?

I want to send a SOAP message using SOAP client. I have a WSDL file for an example. I can use the WSDL file using SOAP UI.
But my requirement is: whenever I am sending a SOAP message to a particular device or somewhere else a message ID should be generated to me for each and every message.
How can I write that SOAP Request using PHP.
Any example/links much appreciated as I am very new to this.
Something like this?
<?php
//Data, connection, auth
$dataFromTheForm = $_POST['fieldName']; // request data from the form
$soapUrl = "https://connecting.website.com/soap.asmx?op=DoSomething"; // asmx URL of WSDL
$soapUser = "username"; // username
$soapPassword = "password"; // password
// xml post structure
$xml_post_string = '<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<GetItemPrice xmlns="http://connecting.website.com/WSDL_Service"> // xmlns value to be set to your's WSDL URL
<PRICE>'.$dataFromTheForm.'</PRICE>
</GetItemPrice >
</soap:Body>
</soap:Envelope>'; // data from the form, e.g. some ID number
$headers = array(
"Content-type: text/xml;charset=\"utf-8\"",
"Accept: text/xml",
"Cache-Control: no-cache",
"Pragma: no-cache",
"SOAPAction: http://connecting.website.com/WSDL_Service/GetPrice",
"Content-length: ".strlen($xml_post_string),
); //SOAPAction: your op URL
$url = $soapUrl;
// PHP cURL for https connection with auth
$ch = curl_init();
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_USERPWD, $soapUser.":".$soapPassword); // username and password - declared at the top of the doc
curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $xml_post_string); // the SOAP request
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
// converting
$response = curl_exec($ch);
curl_close($ch);
// converting
$response1 = str_replace("<soap:Body>","",$response);
$response2 = str_replace("</soap:Body>","",$response1);
// convertingc to XML
$parser = simplexml_load_string($response2);
// user $parser to get your data out of XML response and to display it.
?>

Recv failure: Connection was reset in Curl PHP

I want to fetch some data from 12.96.12.174 this IP address using http post by XML. I create curl PHP code for that
<?php
$url = "http://12.96.12.174";
$post_string = '<?xml version="1.0"?>
<CRMAcresMessage>
<Header ImmediateResponseRequired="true" OriginalBodyRequested="true">
<MessageID>25</MessageID>
<TimeStamp>2016-03-11T011:35:11</TimeStamp>
<Operation Operand="Request" Data="PlayerProfile" />
</Header>
<PlayerID>59979</PlayerID>
<Body>
</Body>
</CRMAcresMessage>';
$header = "POST HTTP/1.0 \r\n";
$header .= "Content-type: text/xml \r\n";
$header .= "Content-length: ".strlen($post_string)." \r\n";
$header .= "Content-transfer-encoding: text \r\n";
$header .= "Connection: close \r\n\r\n";
$header .= $post_string;
$ch = curl_init();
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_URL,$url);
//$fp = fopen('rss.xml', 'w');
curl_setopt($ch,CURLOPT_PORT, 8085);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_TIMEOUT, 0);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $header);
echo $data = curl_exec($ch);
if(curl_errno($ch))
print curl_error($ch);
else
curl_close($ch);
?>
When I hit that link from "http://example.com/members/check.php" this url this gives me Recv failure: Connection was reset in Curl.
And from my localhost I got Failed to connect
php version is also >5.3
I am beginner in Curl.
curl_setopt($ch, CURLOPT_URL, trim($url));
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
For Recv failure: Connection was reset in Curl PHP ==>
Declare like this :
CURLOPT_SSL_VERIFYPEER as 0
& make sure that you are using PHP version >5.3

Make a POST request

I would like to know how to make a HTTP POST request like it's described there http://code.google.com/apis/documents/docs/3.0/developers_guide_protocol.html#UploadingMetadata (Creating an empty document).
My code looks like this:
<?php
$headers = array(
"POST /feeds/default/private/full HTTP/1.1",
"Host: docs.google.com",
"GData-Version: 3.0",
"Content-Length: 287",
"Content-Type: application/atom+xml"
);
$data = "<?xml version='1.0' encoding='UTF-8'?>";
$data .= "<entry xmlns='http://www.w3.org/2005/Atom'>";
$data .= "<category scheme='http://schemas.google.com/g/2005#kind'";
$data .= "term='http://schemas.google.com/docs/2007#document'/>";
$data .= "<title>new document</title>";
$data .= "</entry>";
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "http://google.com/docs/feeds/default/private/full");
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HEADER, true);
$result = curl_exec($ch);
print_r($result);
?>
What's wrong there? Am I doing request correctly?
$data = "<?xml version='1.0' encoding='UTF-8'?>";
Replace with:
$data = "<"."?xml version='1.0' encoding='UTF-8'?".">";
And...
$data .= "term='http://schemas.google.com/docs/2007#document'/>";
With:
$data .= " term='http://schemas.google.com/docs/2007#document'/>";
Oh and finally, you shouldn't be print_ring the result; print_r is for arrays and objects, not strings (curl_exec returns a string or null/false), instead use var_dump($result);
Further, your custom headers look weird:
POST is not a header at all so that's plain wrong.
Host: is added by curl itself, no point in setting that.
Content-Length: is done by curl itself, you mostly risk confusing curl if you get it wrong.

cURL,WireShark. Setting headers to post data and get xml

Here is the dump from WireShark:
POST /drm/drm_production_v2.php HTTP/1.1
content-length: 278
content-type: text/xml
User-Agent: UserAgent 1.0
Connection: Keep-Alive
Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=
host: www.example.com
<methodCall>
<methodName>aMethod</methodName>
<params>
<param>
<value>
<base64>dXNlcm5hbWU6cGFzc3dvcmQ=</base64>
</value>
</param>
<param>
<value>
<struct/>
</value>
</param>
</params>
</methodCall>
I have the xml saved into a seperate file. Here's what I am doing:
<?php
function httpsPost($Url, $xml_data, $headers)
{
// Initialisation
$ch=curl_init();
// Set parameters
curl_setopt($ch, CURLOPT_FORBID_REUSE, 1);
curl_setopt($ch, CURLOPT_FRESH_CONNECT, 1);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_URL, $Url);
// Return a variable instead of posting it directly
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_USERPWD,"username:password");
// Activate the POST method
curl_setopt($ch, CURLOPT_POST, 1) ;
curl_setopt($ch,CURLOPT_USERAGENT,"UserAgent 1.0");
// Request
curl_setopt($ch, CURLOPT_POSTFIELDS, $xml_data);
curl_setopt($ch, CURLOPT_TIMEOUT, 999);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
// execute the connexion
$result = curl_exec($ch);
// Close it
curl_close($ch);
return $result;
}
$str='username:password';
$auth=base64_encode($str);
$request_file = "./request.xml";
$fh = fopen($request_file, 'r');
$filesize=filesize($request_file);
echo $filesize;
$xml_data = fread($fh,$filesize);
fclose($fh);
$url = 'http://www.example.com';
$header = array();
$header[] = "POST /drm/drm_production_v2.php HTTP/1.1";
$header[] = "Content-type: text/xml";
$header[] = "content-length: ".$filesize. "\r\n";
$header[] = "User-Agent: UserAgent 1.0";
$header[] = "Connection: Keep-Alive";
$header[] = "Authorization: Basic ".$auth;
$header[] = "host: www.example.com";
$Response = httpsPost($url, $xml_data, $header);
echo $Response;
?>
It returns a 'Bad Request' from the server. Any suggestions?
My first guess is that the extra "\r\n" after the content-length header makes the server think that the post content starts there. I'd also change "content-length", "Content-type", and "host" to "Content-Length", "Contnet-Type", and "Host", just in case.
Edit: That, and Ronald Bouman's answer.
I think your argument to
curl_setopt($ch, CURLOPT_POSTFIELDS, $xml_data);
is not correct. The postfields option should be URL encoded name/value pairs. From the docs:
"
This 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. If value is an array, the Content-Type header will be set to multipart/form-data
"
see http://php.net/manual/en/function.curl-setopt.php
There's the pcap2curl tool that allows one to convert a pcap file of HTTP requests into cURL.
But if you want to replay some web requests from your browser then you can do it without Wireshark and instead enter Web developer mode in the browser. You then go to the network requests view and right click on the request of interest then, in most modern browsers, there is an option to Copy as cURL after which you can then paste the resulting command into a terminal and rerun the captured command as you see fit using the curl tool. Some browsers (e.g. Mozilla) also offer the option to edit and resend from within the browser.

Categories