sending xml and headers via curl - php

wondering how I can set all this data in a curl session, via php:
POST /feeds/api/users/default/uploads HTTP/1.1
Host: uploads.gdata.youtube.com
Authorization: AuthSub token="DXAA...sdb8"
GData-Version: 2
X-GData-Key: key=adf15ee97731bca89da876c...a8dc
Slug: video-test.mp4
Content-Type: multipart/related; boundary="f93dcbA3"
Content-Length: 1941255
Connection: close
--f93dcbA3
Content-Type: application/atom+xml; charset=UTF-8
<?xml version="1.0"?>
<entry xmlns="http://www.w3.org/2005/Atom"
xmlns:media="http://search.yahoo.com/mrss/"
xmlns:yt="http://gdata.youtube.com/schemas/2007">
<media:group>
<media:title type="plain">Bad Wedding Toast</media:title>
<media:description type="plain">
I gave a bad toast at my friend's wedding.
</media:description>
<media:category
scheme="http://gdata.youtube.com/schemas/2007/categories.cat">People
</media:category>
<media:keywords>toast, wedding</media:keywords>
</media:group>
</entry>
--f93dcbA3
Content-Type: video/mp4
Content-Transfer-Encoding: binary
<Binary File Data>
--f93dcbA3--
I don't understand why have some headers, then the --f93dcbA3 more headers (what's the boundary?), some xml (why here ?), more headers and the content of a file.
I know how to make the request without the xml part and the 'boundary'.
Any help will be appreciated :D

The boundary is required because the form enctype is multipart/form-data, rather in this case multipart/related. The boundary is a unique string that cannot appear anywhere else in the request, and it is used to separate each element from the form, whether it is the value of a text input, or a file upload. Each boundary has its own content-type.
Curl cannot do multipart/related for you, so you will need to use a workaround, see this message from the curl mailing list for suggestions. Basically, you will have to construct most of the message yourself.
Note, the last boundary has an additional -- at the end.
This code should hopefully help get you started:
<?php
$url = 'http://uploads.gdata.youtube.com/feeds/api/users/default/uploads';
$authToken = 'DXAA...sdb8'; // token you got from google auth
$boundary = uniqid(); // generate uniqe boundary
$headers = array("Content-Type: multipart/related; boundary=\"$boundary\"",
"Authorization: AuthSub token=\"$authToken\"",
'GData-Version: 2',
'X-GData-Key: key=adf15....a8dc',
'Slug: video-test.mp4');
$postData = "--$boundary\r\n"
."Content-Type: application/atom+xml; charset=UTF-8\r\n\r\n"
.$xmlString . "\r\n" // this is the xml atom data
."--$boundary\r\n"
."Content-Type: video/mp4\r\n"
."Content-Transfer-Encoding: binary\r\n\r\n"
.$videoData . "\r\n" // this is the content of the mp4
."--$boundary--";
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $postData);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
$response = curl_exec($ch);
curl_close($ch);
Hope that helps.

Related

How to send request for "multipart/related" Content-Type using PHP-curl?

Following are the soap envelop and header info:
POST /tf6/services/xdsrepositoryb HTTP/1.1
Content-Type: multipart/related;
boundary=MIMEBoundaryurn_uuid_566EAD10FEBB55C5A61257193478449;
type="application/xop+xml"; start="
<0.urn:uuid:566EAD10FEBB55C5A61257193478450#apache.org>"; start-
info="application/soap+xml";
action="urn:ihe:iti:2007:ProvideAndRegisterDocumentSet-b"
--MIMEBoundaryurn_uuid_566EAD10FEBB55C5A61257193478449
Content-Type: application/xop+xml; charset=UTF-8; type="application/soap+xml"
Content-Transfer-Encoding: binary
Content-ID: <0.urn:uuid:566EAD10FEBB55C5A61257193478450#apache.org>
<?xml version='1.0' encoding='UTF-8'?>
<soapenv:Envelope xmlns:soapenv="http://www.w3.org/2003/05/soap-envelope"
xmlns:wsa="http://www.w3.org/2005/08/addressing">
<soapenv:Header>
<wsa:To>http://localhost:5000/tf6/services/xdsrepositoryb</wsa:To>
<wsa:MessageID soapenv:mustUnderstand="true">urn:uuid:566EAD10FEBB55C5A61257193478400</wsa:MessageID>
<wsa:Action>urn:ihe:iti:2007:ProvideAndRegisterDocumentSet-b</wsa:Action>
</soapenv:Header>
<soapenv:Body>
<xdsb:ProvideAndRegisterDocumentSetRequest xmlns:xdsb="urn:ihe:iti:xds-b:2007">
<lcm:SubmitObjectsRequest xmlns:lcm="urn:oasis:names:tc:ebxml-regrep:xsd:lcm:3.0">
<rim:RegistryObjectList xmlns:rim="urn:oasis:names:tc:ebxml-regrep:xsd:rim:3.0">
<rim:ExtrinsicObject id="Document01" mimeType="text/plain"
objectType="urn:uuid:7edca82f-054d-47f2-a032-9b2a5b5186c1">
</lcm:SubmitObjectsRequest>
<xdsb:Document id="Document01">
<xop:Include href="cid:1.urn:uuid:566EAD10FEBB55C5A61257193478499#apache.org"
xmlns:xop="http://www.w3.org/2004/08/xop/include"/>
</xdsb:Document>
</xdsb:ProvideAndRegisterDocumentSetRequest>
</soapenv:Body>
</soapenv:Envelope>
--MIMEBoundaryurn_uuid_566EAD10FEBB55C5A61257193478449
Content-Type: text/plain
Content-Transfer-Encoding: binary
Content-ID: <1.urn:uuid:566EAD10FEBB55C5A61257193478499#apache.org>
This is my document.
It is great!
--MIMEBoundaryurn_uuid_566EAD10FEBB55C5A61257193478449--
How can I write a PHP script using CURL to send a request?
I am getting HTTP-400 error whenever I am trying to call the service, please advise.
Thanks.
This is the code I am trying:
$body= $body = '<s:Envelope xmlns:a="http://www.w3.org/2005/08/addressing" xmlns:s="http://www.w3.org/2003/05/soap-envelope">
<s:Header>
<a:Action s:mustUnderstand="1">urn:ihe:iti:2007:ProvideAndRegisterDocumentSet-b</a:Action>
<a:From>
<a:Address>urn:oid:2.16.840.1.113883.3.1259.10.1003</a:Address>
</a:From>
<a:To>https://CDACert.hawaiihie.org:20000/repository</a:To>
</s:Header>
<s:Body>
<ProvideAndRegisterDocumentSetRequest xmlns="urn:ihe:iti:xds-b:2007" xmlns:xop="http://www.w3.org/2004/08/xop/include">
<lcm3:SubmitObjectsRequest xmlns:lcm3="urn:oasis:names:tc:ebxml-regrep:xsd:lcm:3.0" xmlns:rim="urn:oasis:names:tc:ebxml-regrep:xsd:rim:3.0">
<rim:RegistryObjectList>
<rim:ExtrinsicObject id="Document1" mimeType="text/xml" objectType="urn:uuid:7edca82f-054d-47f2-a032-9b2a5b5186c1">
</rim:Association>
</rim:RegistryObjectList>
</lcm3:SubmitObjectsRequest>
<Document id=\"Document1\">
<xop:Include href="cid:test_ID_123"
xmlns:xop="http://www.w3.org/2004/08/xop/include"/></Document>
</ProvideAndRegisterDocumentSetRequest>
</s:Body>
';
$text = 'dGhpcyBpcyBTaGl2J3MgZG9j';// base64 of content
$boundary = 'MIMEBoundaryurn_uuid_'.uniqid();
$postData = "--$boundary\n"
."Content-Type: application/xop+xml; charset=UTF-8; type=\"application/soap+xml\n"
."Content-Transfer-Encoding: binary\n"
."Content-length:".strlen($body)."\n"
."Content-ID:test_start\n"
.$body."\n\n"
."--$boundary\n"
."Content-Type: text/plain;\n"
."Content-Transfer-Encoding: binary\n"
."Content-length:".strlen($text)."\n"
."Content-ID:test_ID_123\n"
.$text."\n"
."--$boundary--";
$header1 = array (
"Content-Type: multipart/related; type=\"application/xop+xml\"; start=\"test_start\"; start-info=\"application/soap+xml\"; action=\"urn:ihe:iti:2007:ProvideAndRegisterDocumentSet-b\"",
"Content-length:".strlen($postData),
"Transfer-Encoding:chunked",
"User-Agent:" .$_SERVER ['HTTP_USER_AGENT'],
"Host:" .$_SERVER['HTTP_HOST']
);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $soapUrl);
curl_setopt($ch, CURLINFO_HEADER_OUT, 1);
curl_setopt($ch, CURLINFO_, 1);
curl_setopt($ch, CURLOPT_HTTPHEADER, $header1);
curl_setopt($ch, CURLOPT_HEADER, 1);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, array($postData)); // the SOAP request
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$response = curl_exec($ch); // 400 HTTP error from curl_info

PHP Curl POST, GET, PUT and DELETE does not work

I have Centos 5.5 machine running PHP 5.3. I am trying to do curl POST, GET, PUT and DELETE. None of them are working. I am getting HTTP 401 error.
Actual documentation here:
https://www.igniterealtime.org/projects/openfire/plugins/userservice/readme.html
Here is the POST info:
Header: Authorization: Basic YWRtaW46MTIzNDU=
Header: Content-Type: application/xml
POST http://example.org:9090/plugins/userService/users
Payload Example 1 (required parameters):
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<user>
<username>test3</username>
<password>p4ssword</password>
</user>
Below is the PHP code:
if ($method_name == 'POST')
{
$headers = array(
'Accept: application/xml',
'Authorization: Basic '. $secret,
'Content-Type: application/xml'
);
print_r($headers);
$body= <<<EOD
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<user>
<username>testuser</username>
<password>p4ssword</password>
<name>Test User</name>
<email>test#localhost.de</email>
<properties>
<property key="keyname" value="value1"/>
<property key="anotherkey" value="value2"/>
</properties>
</user>
EOD;
$api_request_url .= '/users';
echo "api_request_url=". $api_request_url. "<BR>";
curl_setopt($ch, CURLOPT_POST, TRUE);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($body)); //$body
print_r($body);
//curl_setopt($ch, CURLOPT_POSTFIELDS,http_build_query($api_request_parameters));
}
/*
Here you can set the Response Content Type you prefer to get :
application/json, application/xml, text/html, text/plain, etc
*/
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers );
/*
Let's give the Request Url to Curl
*/
curl_setopt($ch, CURLOPT_URL, $api_request_url);
/*
Yes we want to get the Response Header
(it will be mixed with the response body but we'll separate that after)
*/
curl_setopt($ch, CURLOPT_HEADER, TRUE);
/*
Allows Curl to connect to an API server through HTTPS
*/
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
/*
Let's get the Response !
*/
$api_response = curl_exec($ch);
/*
We need to get Curl infos for the header_size and the http_code
*/
$api_response_info = curl_getinfo($ch);
/*
Don't forget to close Curl
*/
curl_close($ch);
/*
Here we separate the Response Header from the Response Body
*/
$api_response_header = trim(substr($api_response, 0, $api_response_info['header_size']));
$api_response_body = substr($api_response, $api_response_info['header_size']);
// Response HTTP Status Code
echo $api_response_info['http_code']. "<BR>";
// Response Header
echo $api_response_header. "<BR>";

Youtube Oauth 2.0 API Videos Upload Failed

So i managed to built oauth 2.0 youtube video upload, but everytime i upload a video i get an HTTP 400 ERROR with a invalid request.
But the weirdest thing is that the video is uploading to youtube while having : Failed (upload aborted).
im not using any framework, cause google doesnt have yet any to oauth 2.0, so i built all of my code on my own.
And also i did managed to send comments, and stuff.... the only problem is the video upload itself.
My code:
public function uploadVideo($video, $title, $description, $category, $keywords) {
$url = 'http://uploads.gdata.youtube.com/feeds/api/users/FacebookDevelopersIL/uploads';
$boundary = uniqid();
$accessToken = $this->refreshAccessToken("13", "11313", 'REFRESHTOKEN');
$xmlString = "<?xml version='1.0'?><entry xmlns='http://www.w3.org/2005/Atom' xmlns:media='http://search.yahoo.com/mrss/' xmlns:yt='http://gdata.youtube.com/schemas/2007'><media:group><media:title type='plain'>".$title."</media:title><media:description type='plain'>".$description."</media:description> <media:category scheme='http://gdata.youtube.com/schemas/2007/categories.cat'>".$category."</media:category><media:keywords>".$keywords."</media:keywords></media:group></entry>";
$videoData = file_get_contents($video);
$headers = array(
'POST /feeds/api/users/FacebookDevelopersIL/uploads HTTP/1.1',
'Host: uploads.gdata.youtube.com',
'Authorization: Bearer '.$accessToken,
'GData-Version: 2',
'X-GData-Key: key='.YOUTUBE_SRM_DEVELOPER_KEY,
'Slug: IMG_0047.mp4',
'Content-Type: multipart/related; boundary='.$boundary,
'Content-Length:'.strlen($videoData),
'Connection: close'
);
$postData = "--".$boundary . "\r\n"
."Content-Type: application/atom+xml; charset=UTF-8\r\n\r\n"
.$xmlString . "\r\n"
."--".$boundary . "\r\n"
."Content-Type: video/mp4\r\n"
."Content-Transfer-Encoding: binary\r\n\r\n"
.$videoData . "\r\n"
."--".$boundary . "--";
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $postData);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($ch, CURLOPT_HEADER, 1);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 0);
$response = curl_exec($ch);
curl_close($ch);
Trace::dump($response); }
The error im getting: HTTP/1.1 400 Bad Request Server: HTTP Upload Server Built on May 7 2012 18:16:42 (1336439802) Content-Type: text/html; charset=UTF-8 X-GUploader-UploadID: AEnB2Uq7cHcf6rS4bcamu18ChAF3gnKJqsF6U_dk2qB4WR9GhAoTL_-iUejitgead-Gh-1fpJcke1z68TAxoopS2vYiGmCW69A Date: Thu, 10 May 2012 11:55:24 GMT Pragma: no-cache Expires: Fri, 01 Jan 1990 00:00:00 GMT Cache-Control: no-cache, no-store, must-revalidate Content-Length: 15 Connection: close
Invalid Request
thanx everyone!
Couple of things I notice: hard coding the POST and Host headers is poor form, because curl will take care of them automatically for you. I suspect part of the problem is the insertion of the carriage return/line feed between the $videoData and the last boundary marker. That will be interpreted as part of the video file. All you need are line feeds as line separators. Maybe the carriage return renders the video file invalid?
Maybe curl_setopt($ch, CURLOPT_VERBOSE, true) will provide some illumination.
This works for me (on a Linux host):
/*
** https://developers.google.com/youtube/2.0/developers_guide_protocol_direct_uploading
*/
private function send_to_youtube($video_file, $video_info) {
// Refresh access token
log_msg("Obtaining access token");
$response = http_post($this->config['token_url'], array(
'client_id' => $this->config['client_id'],
'client_secret' => $this->config['client_secret'],
'refresh_token' => $video_info->refresh_key,
'grant_type' => $this->config['grant_type']
));
if ($response['http_code'] != 200)
throw new Exception("Unable to obtain access token. ".print_r($response, true));
$authorization = json_decode($response['contents'], true);
// Build multi-part upload request
// api xml and then video file contents
$boundary = uniqid();
$location = '';
if ($video_info->latitude && $video_info->longitude)
$location = '
<georss:where>
<gml:Point>
<gml:pos>'. $video_info->latitude .' '. $video_info->longitude .'</gml:pos>
</gml:Point>
</georss:where>';
$content = '--'.$boundary.'
Content-Type: application/atom+xml; charset=UTF-8
<?xml version="1.0"?>
<entry xmlns="http://www.w3.org/2005/Atom"
xmlns:media="http://search.yahoo.com/mrss/"
xmlns:yt="http://gdata.youtube.com/schemas/2007"
xmlns:georss="http://www.georss.org/georss"
xmlns:gml="http://www.opengis.net/gml">
<media:group>
<media:title type="plain">'. $video_info->title .'</media:title>
<media:description type="plain">
'. $video_info->description .'
</media:description>
<media:category
scheme="http://gdata.youtube.com/schemas/2007/categories.cat">
'. $video_info->category .'
</media:category>
<media:keywords>'. implode(', ', $video_info->tags) .'</media:keywords>
</media:group>
'. $location .'
</entry>
--'.$boundary.'
Content-Type: '. $video_info->type .'
Content-Transfer-Encoding: binary
'.file_get_contents($video_file).'
--'.$boundary.'--';
$headers = array(
'Authorization: '.$authorization['token_type'].' '.$authorization['access_token'],
'GData-Version: 2',
'X-GData-Key: key='.$this->config['dev_key'],
'Slug: '.$video_info->filename,
'Content-Type: multipart/related; boundary="'.$boundary.'"',
'Content-Length: '.strlen($content),
'Connection: close'
);
// Upload video
log_msg("Sending video '{$video_info->title}', {$video_info->url}");
$ch = curl_init($this->config['upload_url']);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $content);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_HEADER, false);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 0);
$response = curl_exec($ch);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if (!$http_code == 201) { // Something other than 'New Entry'
log_msg("Upload Failed: ".print_r($response, true));
return new SimpleXMLElement();
}
$entry = new SimpleXMLElement($response);
$yt_link = $entry->link[0]->attributes()->href;
log_msg("Upload Complete: ".$yt_link);
return $entry;
}

Sending XML via php and getting back a response

I'm having problems sending the follwoing XML via PHP. I can't seem to get the script right it just comes back with a blank page. Any suggestions would be great. I am not coming up with any errors just nothing seems to happen.
POST /PubServices/WebServices/PublicationWebServices.asmx HTTP/1.1
Host: www.geminifund.com
Content-Type: application/soap+xml; charset=utf-8
Content-Length: length
POST /PubServices/WebServices/PublicationWebServices.asmx HTTP/1.1
Host: www.geminifund.com
Content-Type: application/soap+xml; charset= utf-8
Content-Length: length
<?xml version="1.0" encoding="utf-8"?>
<soap12:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap12="http://www.w3.org/2003/05/soap-envelope">
<soap12:Body>
<GetHistroricalNav xmlns="http://www.geminifund.com/webservices/">
<startDate>dateTime</startDate>
<endDate>dateTime</endDate>
<portfolio>string</portfolio>
</GetHistroricalNav>
</soap12:Body>
</soap12:Envelope>
and my script is as follows
<?php
$url = "http://www.geminifund.com";
$post_string = '<?xml version="1.0" encoding="UTF-8"?>
<rootNode>
<innerNode>
<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>
<GetHistroricalNav xmlns="http://www.geminifund.com/webservices/">
<startDate>2011-06-30</startDate>
<endDate>2011-7-30</endDate>
<portfolio>1778/portfolio>
</GetHistroricalNav>
</soap:Body>
</soap:Envelope>
</innerNode>
</rootNode>';
$header = "POST /PubServices/WebServices/PublicationWebServices.asmx HTTP/1.1 \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, 0);
curl_setopt($ch, CURLOPT_URL,$url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_TIMEOUT, 4);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $header);
$data = curl_exec($ch);
if(curl_errno($ch))
print curl_error($ch);
else
curl_close($ch);
?>
When you write "it just comes back with a blank page " are you referring to a web browser response when you enter the url? If this is what you are referring to, what web browser are you using? I recommend you try different web browsers (Safari, FireFox, Chrome) and see what results you get.
Why are you using headers to set a POST method and doing a custom request? Curl is perfectly capable of doing a POST as is:
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $post_string);
custom request is for when you want to do a less-common method, such as a HEAD or PUT request.
and PHP have SoapClient class to handle SOAP protocol. Are you sure you want to do it in hand-written manner, friend? :)

Getting a POST requests require a Content-length header response(411 error)

I have been trying to upload video on video on you tube using my own code.
During one step when i try to upload videos meta data on you tube to get the token and url for the video to upload i get a
POST requests require a Content-length header. That’s all we know.
(411)
My code is as follows:
$xml = '<?xml version="1.0"?>
<entry xmlns="http://www.w3.org/2005/Atom"
xmlns:media="http://search.yahoo.com/mrss/"
xmlns:yt="http://gdata.youtube.com/schemas/2007">
<media:group>
<media:title type="plain">Video.loc</media:title>
<media:description type="plain">
Video.loc first vid
</media:description>
<media:category
scheme="http://gdata.youtube.com/schemas/2007/categories.cat">People
</media:category>
<media:keywords>Video.loc</media:keywords>
</media:group>
</entry>';
$headers = array('Authorization: AuthSub token="'.$_SESSION['AuthSubSessToken'],
'GData-Version: 2',
'X-GData-Key: key='.$key,
'Content-length:'.strlen($xml),
'Content-Type:application/atom+xml; charset=UTF-8'
);
$curl = curl_init('http://gdata.youtube.com/action/GetUploadToken');
curl_setopt($curl, CURLOPT_HTTPHEADER,$headers);
curl_setopt($curl, CURLOPT_POSTFIELDS, $xml);
curl_setopt($curl, CURLOPT_HEADER, 0);
$response = simplexml_load_string(curl_exec($curl));
$response = curl_exec($curl);
$arrToken = explode('=',$response);
print('<pre>');print_r($arrToken);die();
curl_close($curl)
Does any one knows that if it is error on my side or on the google?.
Regards
Himanshu Sharma
You are missing a closing " after
AuthSub token="'.$_SESSION['AuthSubSessToken'],
that might be messing up the headers.

Categories