在您提问之前:我已经检查了每个已经有答案的类似问题,但提出的解决方案都不起作用。所以我希望有人能够注意到我代码中的一个错误。
当向谷歌提交cURL帖子时,我返回了一个411错误,"post请求需要一个内容长度头"
//Info required to authenticate
$URL = "https://www.google.com/accounts/ClientLogin";
$POST = http_build_query(array(
'Email' => 'XXXXXXX@gmail.com',
'Passwd' => 'XXXXXXXXXXXXXXX',
'source' => 'primary',
'service' => 'cl'
));
$ch = curl_init( $URL );
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $POST);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($ch, CURLOPT_HEADER, 1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$response = curl_exec($ch); //returns SID=<sid code>nLSID=<lsid code>nAuth=<auth code> or ERROR=<message>
if ( curl_errno($ch) )
die( 'Error contacting server' );
//Successful auth results in http code 200
if ( curl_getinfo($ch, CURLINFO_HTTP_CODE) != 200 )
die( 'Failed to authenticate' );
//Extract auth code - Authorization: GoogleLogin auth=yourAuthToken
$auth_code = substr($response, strpos($response, 'Auth=')+5);
//We're done here
curl_close($ch);
$url = "https://www.googleapis.com/calendar/v3/calendars/".urlencode('XXXXXXXXXXXXX@developer.gserviceaccount.com')."/events?sendNotifications=true&pp=1&key=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXx";
$post_data = http_build_query(array(
"end" => array("dateTime" => "2013-14-11T10:40:00.000-07:00"),
"start" => array("dateTime" => "2013-14-11T10:00:00.000-07:00"),
"summary" => "my_summary",
"description" => "my_description"
));
$headers = array(
'Authorization: GoogleLogin auth='.$auth_code.'',
'Content-Type: application/json'
);
$ch2 = curl_init();
curl_setopt($ch2, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch2, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch2, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch2, CURLOPT_POSTFIELDS, $post_data);
$output = curl_exec($ch2);
curl_close($ch2);
echo '<pre>'.print_r($output).'</pre>';
我尝试过的东西:
-添加"内容长度:".strlen($post_data)
-"x-www-form-urlencoded"的内容类型
-对post_data使用一个非常简单的json字符串,这样我就不用http_build_query 了
-尝试将其作为PUT而不是POST 发送
-在过去的几天里,还有一些我现在记不清的事情
目的:只使用PHP将事件添加到我的日历中,而不需要用户进行身份验证。这必须能够在php函数中异步运行(通过AJAX调用)
注意:不使用Wordpress或任何其他CMS
-Kyle
我认为您需要设置CURLOPT_HTTPHEADER
。您可以尝试将数据作为json字符串传递,如下所述。
$post_data = array(
"end" => array("dateTime" => "2013-14-11T10:40:00.000-07:00"),
"start" => array("dateTime" => "2013-14-11T10:00:00.000-07:00"),
"summary" => "my_summary",
"description" => "my_description"
);
$post_data = json_encode($post_data);
curl_setopt($ch2, CURLOPT_HTTPHEADER, array(
'Content-Type: application/json',
'Content-Length: ' . strlen($post_data),)
);
所以我只是快速地使用curl_getinfo
调用来查看发送了什么(不完全是你的建议,但先尝试一下会更快)。。。果不其然。。。任何地方都没有内容长度。我尝试了两种方式,内容长度头由我声明,而不是由我声明。这两种选择都产生了你所看到的:
同样值得注意的是,它说content_type
=text.html。。。尽管我已经宣布它为application/json
正在使用:
curl_setopt($ch2, CURLOPT_HTTPHEADER, array(
'Authorization: GoogleLogin auth='.$auth_code,
'Content-Type: application/json',
'Content-length:' . strlen($post_data))
);
以下是curl_getinfo
:的输出
Array (
[url] => https://www.googleapis.com/calendar/v3/calendars/XXXXXXXXXX%40developer.gserviceaccount.com/events?sendNotifications=true&pp=1&key=XXXXXXXX-XXXXXXXXXXXXXXXXXXXXXX
[content_type] => text/html; charset=UTF-8
[http_code] => 411
[header_size] => 147
[request_size] => 737
[filetime] => -1
[ssl_verify_result] => 0
[redirect_count] => 0
[total_time] => 0.104391
[namelookup_time] => 0.000687
[connect_time] => 0.025284
[pretransfer_time] => 0.079614
[size_upload] => 159
[size_download] => 934
[speed_download] => 8947
[speed_upload] => 1523
[download_content_length] => 934
[upload_content_length] => 159
[starttransfer_time] => 0.104356
[redirect_time] => 0
[certinfo] => Array
(
)
[primary_ip] => 2607:f8b0:400e:c04::5f
[primary_port] => 443
[local_ip] => 2600:3c01::f03c:91ff:fe69:4a05
[local_port] => 57581
[redirect_url] => )
我收到了与您相同的内容错误,发现我的头中有一个错误的换行符,这是由我包含的变量引起的。
我使用curl_setopt($ch, CURLINFO_HEADER_OUT, true);
追踪到了这一点,这使得curl_getinfo()
在其输出中包含请求的头。
在变量上使用trim()
将其固定。
我为类似的问题挣扎了一段时间。在我的例子中,这是因为我在标题中设置的一个值以换行符结尾。这意味着接收帖子的服务器会看到双换行符,并过早地认为标题已经完成(这阻止了Content-Length标题的读取)。解决方案是修剪换行符。
更新答案
在第二个curl调用中,您似乎对一行使用了错误的句柄。。。
curl_setopt($ch, CURLOPT_POST, true);
应该是
curl_setopt($ch2, CURLOPT_POST, true);
原始答案你没有传球。您是否尝试以这种格式将内容长度作为标头传递?
curl_setopt($ch,CURLOPT_HTTPHEADER,array('HeaderName: HeaderValue'));
您的标题当前只是数字1
curl_setopt($ch,CURLOPT_HTTPHEADER,array('Content-length:'.strlen($post_data)));