PHP curl changes the Content-Type to application/x-www-form-urlencoded. Shouldn't do that
Solution 1
According to the documentation section regarding the options' parameter setting the HTTP method to POST
defaults to content type being set to application/x-www-form-urlencoded
. So my suspicion is that setting all the options at once, results in your Content-Type
being overwritten.
My suggestion would be to set the content type in a single statement, after you've set the method, i.e.
$curlConfig = array(
CURLOPT_URL => 'http://uploads.gdata.youtube.com/feeds/api/users/default/uploads',
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_BINARYTRANSFER => true,
CURLOPT_POSTFIELDS => $content,
);
curl_setopt_array($ch, $curlConfig);
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
'Authorization: ' . sprintf('GoogleLogin auth=%s', $this->accessToken),
'GData-Version: 2',
'X-GData-Key: ' . sprintf('key=%s', $this->developerKey),
'Slug: ' . sprintf('%s', $this->video->getFilename()),
'Content-Type: ' . sprintf('multipart/related; boundary="%s"',
$this->boundaryString),
'Content-Length: ' . strlen($content),
'Connection: close'
));
Solution 2
Accepted answer was not helpful for me and I found another problem in your code. According to the current PHP documentation CURLOPT_HTTPHEADER must be set like this:
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
'Content-type: text/plain',
'Content-length: 100'
));
It must be a list of strings, not a hash like array('Content-Type' => 'text/plain')
.
Hope it will save someone's debugging time.
Comments
-
Johannes Klauß almost 2 years
I want to upload a video direct to Youtube from my server for which I am using PHP curl.
I need this request format:
POST /feeds/api/users/default/uploads HTTP/1.1 Host: uploads.gdata.youtube.com Authorization: Bearer ACCESS_TOKEN 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--
This is what I have:
$content = $this->buildRequestContent(); $ch = curl_init(); $curlConfig = array( CURLOPT_URL => 'http://uploads.gdata.youtube.com/feeds/api/users/default/uploads', CURLOPT_POST => true, CURLOPT_RETURNTRANSFER => true, CURLOPT_BINARYTRANSFER => true, CURLOPT_POSTFIELDS => $content, CURLOPT_HTTPHEADER, array( "Authorization" => sprintf("GoogleLogin auth=%s", $this->accessToken), "GData-Version" => 2, "X-GData-Key" => sprintf("key=%s", $this->developerKey), "Slug" => sprintf("%s", $this->video->getFilename()), "Content-Type" => sprintf("multipart/related; boundary=\"%s\"", $this->boundaryString), "Content-Length" => strlen($content), "Connection" => "close" ), ); curl_setopt_array($ch, $curlConfig); $result = curl_exec($ch);
Dumping the result shows me that curl changed the
Content-Type
toapplication/x-www-form-urlencoded
which is of course not supported by youtube.I put my binary content (the video) into
CURLOPT_POSTFIELDS
, maybe this is wrong, but I don't know how to set the request body other than that.So how do I preserve my Content-Type that I set?
-
andreszs over 9 yearsIn other words, you cannot pass an associative array to CURLOPT_HTTPHEADER, only simple arrays. This issue drove me mad for hours...
-
John Congdon about 9 yearsPlease update your example, it's not a two dimensional array. It should be: array("Authorization: " . sprintf..., "Content-Type: " . sprintf....)
-
Havelock about 9 years@JohnCongdon: correct, thanks! It's funny nobody noticed it in just over two years, three upvotes and "accepted answer". (I'm sure you meant "not an associative array" instead of "not a two dimensional array" ;) )
-
NeverEndingQueue over 7 yearsShame for the PHP cURL. Not only
CURLOPT_POST
overrides theContent-Type
, but prevents the other HTTP headers to be set at the same time. Thanks for that solution ! -
dmarra almost 5 yearsI can't get this solution to work. I have separated the setting of the header from the rest of the options and it STILL adds the additional content-type.
-
Havelock almost 5 years@dmarra I'd suggest to just use a dedicated client library like GuzzleHttp for instance