注意:最后的解决方案
如果我尝试执行超过1024个字符的HTTP POST,则会失败。为什么?这是一个最小的例子:
recipient.php:
<?php
if (strlen(file_get_contents('php://input')) > 1000
|| strlen($HTTP_RAW_POST_DATA) > 1000) {
echo "This was a triumph.";
}
?>
sender.php:
<?php
function try_to_post($char_count) {
$url = 'http://gpx3quaa.joyent.us/test/recipient.php';
$post_data = str_repeat('x', $char_count);
$c = curl_init();
curl_setopt_array($c,
array( CURLOPT_URL => $url,
CURLOPT_HEADER => false,
CURLOPT_CONNECTTIMEOUT => 999,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => 1,
CURLOPT_POSTFIELDS => $post_data
)
);
$result = curl_exec($c);
echo "{$result}\n";
curl_close($c);
}
for ($i=1020;$i<1030;$i++) {
echo "Trying {$i} - ";
try_to_post($i);
}
?>
输出:
Trying 1020 - This was a triumph.
Trying 1021 - This was a triumph.
Trying 1022 - This was a triumph.
Trying 1023 - This was a triumph.
Trying 1024 - This was a triumph.
Trying 1025 -
Trying 1026 -
Trying 1027 -
Trying 1028 -
Trying 1029 -
配置:
PHP Version 5.2.6
libcurl/7.18.0 OpenSSL/0.9.8g zlib/1.2.3 libidn/1.8
lighttpd-1.4.19
解决方案
为cURL添加以下选项:
curl_setopt($ch,CURLOPT_HTTPHEADER,array("Expect:"));
原因似乎是任何超过1024个字符的POST都会导致发送“Expect:100-continue”HTTP标头,而Lighttpd 1.4。*不支持它。我找到了一张票:http://redmine.lighttpd.net/issues/show/1017
他们说它适用于1.5。
答案 0 :(得分:22)
您可以通过设置显式请求标头来说服PHP的curl后端停止执行100-continue-thing:
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Expect:'));
通过这种方式,您可以发布请求,无论您想要多长时间,卷曲都不会进行双阶段发布。
我差不多两年前blogged about this。
答案 1 :(得分:3)
curl_setopt的手册页说明了CURLOPT_POSTFIELDS
“要在HTTP”POST“中发布的完整数据 操作。要发布文件,请预先添加 带@的文件名并使用完整路径。 这可以作为一个传递 urlencoded字符串就像 'para1 = val1&amp; para2 = val2&amp; ...'或作为 数组,字段名称为键和 字段数据作为值。“
可能是你的价值被视为urlencoded,因此看起来像一个没有价值的长名。某处某处决定截断该名称。
也许你可以把它改成像
这样的东西$post_data = "data=".str_repeat('x', $char_count);
事实证明这太容易了,问题更深一些。那么,如何调试?
另一种调试策略可能是制定一个实现相同功能的curl命令行,并让它在输出时输出HTTP请求的详细信息。
您可以通过手动执行请求来消除等式中的服务器,例如远程登录到服务器上的端口80并向其发送请求&gt; 1024个字符
POST /test/recipient.php HTTP/1.0
Host: gpx3quaa.joyent.us
Content-Length:1028
xxxxx(I put 1028 chars here, no point copying them all here!)
我得到了这个回复
HTTP/1.0 200 OK
Connection: close
Content-type: text/html; charset=UTF-8
Content-Length: 19
Date: Tue, 20 Jan 2009 21:35:16 GMT
Server: lighttpd/1.4.19
This was a triumph.Connection closed by foreign host.
所以至少你现在知道它在客户端,可能是某些CURL选项或配置设置:(
这个问题引起了我的兴趣,所以我挖得更深了
如果您使用CURLOPT_VERBOSE=>true
,则会看到CURL会在较大的帖子上发送额外的标头:Expect: 100-Continue
。你的lighttpd服务器看起来不喜欢这样。
您可以通过强制它在curl_setopt选项数组中使用带有CURLOPT_HTTP_VERSION=>CURL_HTTP_VERSION_1_0
的HTTP / 1.0来阻止CURL执行此操作。
答案 2 :(得分:0)
我使用SSL v3与IIS服务器有类似的问题。
当CURLOPT_POSTFIELDS超过1024时,我一直收到以下cURL错误:
52 - SSL read: error:1408F10B:SSL routines:SSL3_GET_RECORD:wrong version number, errno 0
添加CURLOPT_HTTPHEADER:“Expect:”为我解决了这个问题。
非常感谢你这个帖子!
答案 3 :(得分:0)
检查您是否启用了Suhosin补丁。默认情况下,它会在特定数量的索引之后切断POST数据。你可以在Suhosin配置中绕过它。