php cURL 'Content-length required' 错误... 3 天的搜索,没有运气

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/20487785/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-25 03:14:32  来源:igfitidea点击:

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

phpcurlgoogle-calendar-api

提问by Kyle

Before you ask: I have already checked every similar question that already had an answer, and none of the proposed solutions work. So I'm hoping someone may be able to notice a mistake in my code.

在你提问之前:我已经检查了每个已经有答案的类似问题,但没有一个建议的解决方案有效。所以我希望有人能够注意到我的代码中的错误。

When submitting a cURL post to Google, I am returned with a 411 error, "POST requests require a Content-length header"

向 Google 提交 cURL 帖子时,返回 411 错误,“POST 请求需要内容长度标头”

//Info required to authenticate
$URL = "https://www.google.com/accounts/ClientLogin";
$POST = http_build_query(array(
 'Email' => '[email protected]',
 '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('[email protected]')."/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>';

Things I have tried:

我尝试过的事情:

-Adding the 'Content-length: '.strlen($post_data)

- 添加'内容长度:'.strlen($post_data)

-Content-type of 'x-www-form-urlencoded'

-“x-www-form-urlencoded”的内容类型

-using a very simply json string for post_data so that I didn't use http_build_query

- 为 post_data 使用一个非常简单的 json 字符串,所以我没有使用 http_build_query

-Trying to make it send as a PUT instead of POST

- 尝试将其作为 PUT 而不是 POST 发送

-And a few other things over the course of the last few days that I can't quite recall right now

-以及过去几天的其他一些事情,我现在不太记得了

Intent: To add an event to only MY calendar using only PHP with no authentication steps required by the user. This must be able to run all within a php function, asynchronously (called via AJAX)

意图:仅使用 PHP 将事件添加到我的日历,无需用户执行身份验证步骤。这必须能够在 php 函数中异步运行(通过 AJAX 调用)

NOTE: Not using Wordpress or any other CMS

注意:不使用 Wordpress 或任何其他 CMS

-Kyle

-凯尔

回答by Roopendra

I think you need to set CURLOPT_HTTPHEADER. You can tried with pass data as a json string.

我认为你需要设置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),)  
 );  

回答by nick

I was receiving the same content error as you and found that I had an erroneous line break in my header, caused by a variable I was including.

我收到与您相同的内容错误,并发现我的标题中有一个错误的换行符,这是由我包含的变量引起的。

I tracked this down using curl_setopt($ch, CURLINFO_HEADER_OUT, true);which makes curl_getinfo()include the request's headers in its output.

我使用curl_setopt($ch, CURLINFO_HEADER_OUT, true);which curl_getinfo()make 在其输出中包含请求的标头进行了跟踪。

Using trim()on the variable fixed it.

trim()在变量上使用固定它。

回答by Kyle

So I just quickly used a curl_getinfocall to see what was being sent (not quite your recommendation, but it was faster to try this first)... and sure enough... there's no content-length anywhere. I tried it both with the Content-length header being declared by me, and NOT being declared by me. Both options resulted in what you see:

所以我很快就用一个curl_getinfo电话来查看发送的内容(不是你的推荐,但首先尝试这个会更快)......果然......任何地方都没有内容长度。我尝试了我声明的 Content-length 标头,而不是我声明的内容。这两个选项都产生了你所看到的:

It's also worth noting that is says content_type= text/html... even though I had it declared as application/json

还值得注意的是 say content_type= text/html ... 即使我将它声明为application/json

being used:

正在使用:

curl_setopt($ch2, CURLOPT_HTTPHEADER, array(
   'Authorization: GoogleLogin auth='.$auth_code,
   'Content-Type: application/json',  
   'Content-length:' . strlen($post_data))
 );

Here's the output of curl_getinfo:

这是输出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] =>  )

回答by Lenny

Updated answer...

更新答案...

In the second curl call you seem to have used the wrong handle for one line...

在第二个 curl 调用中,您似乎对一行使用了错误的句柄...

curl_setopt($ch, CURLOPT_POST, true);

is supposed to be

应该是

curl_setopt($ch2, CURLOPT_POST, true);

Original answer...You're not passing a header. Did you try passing the content-length as a header in this format?

原始答案...您没有传递标题。您是否尝试以这种格式将内容长度作为标头传递?

curl_setopt($ch,CURLOPT_HTTPHEADER,array('HeaderName: HeaderValue'));

Your header is currently just the number 1

您的标题目前只是数字 1

curl_setopt($ch,CURLOPT_HTTPHEADER,array('Content-length:'.strlen($post_data)));

回答by Daniel Howard

I was struggling for a while with a similar problem. In my case it was because one of the values I was setting in my headers ended with a newline character. This meant that the server receiving the post would see the double-newline and prematurely think the headers were finished (which stopped the Content-Length header from being read). Solution was to trim the newline char.

我在类似的问题上挣扎了一段时间。就我而言,这是因为我在标题中设置的值之一以换行符结尾。这意味着接收帖子的服务器会看到双换行符并过早地认为标头已完成(这会阻止读取 Content-Length 标头)。解决方案是修剪换行符。