12

注:最後に解決策

1024 文字を超える HTTP POST を実行しようとすると失敗します。なんで?最小限の例を次に示します。

受信者.php:

<?php
if (strlen(file_get_contents('php://input')) > 1000
    || strlen($HTTP_RAW_POST_DATA) > 1000) {
 echo "This was a triumph.";
}
?>

送信者.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で動作すると言います。

4

4 に答える 4

23

明示的なリクエストヘッダーを設定することで、PHPのcurlバックエンドに100-continue-thingの実行を停止するように説得できます。

curl_setopt($ch, CURLOPT_HTTPHEADER, array('Expect:'));

このようにして、リクエストをいつでも投稿でき、curlはデュアルフェーズ投稿を行いません。

私はこれについてほぼ2年前にブログを書きました。

于 2009-01-20T21:48:55.687 に答える
3

最初の考え...

curl_setoptのマニュアルページには、CURLOPT_POSTFIELDSについて記載されています。

「HTTP「POST」操作で投稿する完全なデータ。ファイルを投稿するには、ファイル名の前に@を付け、絶対パスを使用します。これは、「para1 = val1&para2 = val2&...」のようなurlencoded文字列として渡すことができます。または、フィールド名をキー、フィールドデータを値として持つ配列として。」

あなたの値がurlencodedであるかのように扱われているため、値のない大きな長い名前のように見える可能性があります。どこかでその名前を切り捨てることを決定しています。

多分あなたはそれを次のようなものに変えることができます

$post_data = "data=".str_repeat('x', $char_count);

これは簡単すぎて、問題はもう少し深刻でした。では、どのようにデバッグするのですか?

CURLがサーバーに送信するものを正確に調べます

別のデバッグ戦術は、同じことを実現するcurlコマンドラインを作成し、HTTPリクエストの詳細を出力するようにすることです。

サーバーを手動でテストする

手動でリクエストを実行することで、サーバーを方程式から除外できます。たとえば、サーバーのポート80にtelnetして、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サーバーはこれを気に入らないようです。

CURLOPT_HTTP_VERSION=>CURL_HTTP_VERSION_1_0curl_setoptオプション配列でHTTP/1.0を使用するように強制することで、CURLがこれを実行しないようにすることができます。

于 2009-01-20T21:27:19.707 に答える
0

Suhosinパッチが有効になっているかどうかを確認してください。デフォルトでは、特定の数のインデックスの後にPOSTデータをカットします。Suhosinconfigthoでバイパスできます。

于 2011-03-04T14:45:50.287 に答える
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:" を追加すると、問題が解決しました。

このスレッドをどうもありがとうございました!

于 2009-05-05T17:18:43.390 に答える