cURL';需要内容长度';错误三天的搜寻,没有运气


cURL 'Content-length required' error... 3 days of searching, no luck

在您提问之前:我已经检查了每个已经有答案的类似问题,但提出的解决方案都不起作用。所以我希望有人能够注意到我代码中的一个错误。

当向谷歌提交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)));