こんにちは、スタックオーバーフラワーです!
クライアントからサーバーへの通信に関して、プロジェクトに問題があります。C++ プログラムからサーバーにデータを転送したいと考えています。このため、通信プロトコルとして HTTP を選択しました。同様の PHP スクリプトを介して Web サーバーで処理するのが簡単だからです。C++ プログラムは HTTP POST 経由でデータ (またはコマンド) をサーバーに送信し、サーバーは PHP スクリプト経由でプレーン テキスト応答 (Mime-Type text/plain) を生成します。生成された応答は比較的短く、短い成功または失敗のメッセージと、おそらく小さな「ペイロード」 (すべてプレーン テキスト) が含まれます。
私の開発マシン (ローカル Apache サーバーlampp ) では、すべてがうまく機能しているようです。しかし、今日、ライブWebサーバー(Apache + PHP + MySQLを実行する仮想Webサーバーサービス)でテスト目的でサーバーPHPスクリプトを移動しようとしましたが、何かが機能しなくなりました...
問題
1 つのサーバー側 PHP スクリプトを使用して、C++ アプリケーションからのデータを MySQL データベースに格納します。MySQL データベースに保存したいデータは生の json 文字列です (後で処理される実験データです)。json 文字列は、C++ アプリケーションによって形成されます。これは約 70 kB の大きさで (大きいので!)、POST マルチパート リクエストを介して Web サーバーに送信されます。マルチパート リクエストは、libcurl を介して形成されます。
foreach (const HttpKeyValuePair& kv, localServerCommand.httpKeyValuePairs) {
if (curl_formadd(&httpPostFirst, &httpPostLast, CURLFORM_PTRNAME, kv.key.c_str(),
CURLFORM_NAMELENGTH, (long) kv.key.size(),
CURLFORM_PTRCONTENTS, kv.value.c_str(),
CURLFORM_CONTENTSLENGTH, (long) kv.value.size(),
CURLFORM_CONTENTTYPE, "text/plain",
CURLFORM_END) != 0) {
cerr << "Error assembling form data" << endl;
}
}
[...]
CURL* curl = curl_easy_init();
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &receiveData);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &receiveBuffer);
curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
if (useSimplePost) { // Only true if postString.size() < 200 byte
curl_easy_setopt(curl, CURLOPT_POST, 1);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, postString.c_str());
} else {
// Mutlipart
curl_easy_setopt(curl, CURLOPT_HTTPPOST, httpPostFirst);
}
curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, curlErrorBuffer);
curl_easy_setopt(curl, CURLOPT_FAILONERROR, 1);
curl_easy_setopt(curl, CURLOPT_TIMEOUT, 30);
CURLcode errorCode = curl_easy_perform(curl);
curl_easy_cleanup(curl);
(疑問を解決するために:wiresharkで確認しました...彼はマルチパートポストを使用しています。より頻繁なマルチパートヘッダーを除外することでネットワーク接続を節約できると考えたため、単純なポストを使用するブランチはそこだけです、小さなリクエスト。)
ただし、ここで興味深いのは、サーバー側のスクリプトが json 文字列を受信しないことです。'data' と呼ばれる json 文字列を運ぶフィールドは、PHP の $_POST 構造の一部ではありません! 物事を奇妙にするために、他のすべてのフィールドはとにかくそこにあります。テスト目的で、サーバー上の PHP の $_GET、$_POST、および $_FILES 変数をログ ファイルにダンプしました。問題のリクエストについては、次のようになります。
------
GET
------
array (
)
------
POST
------
array (
'id' => '130',
'nonceid' => '4656',
'authentication' => 'fjOynwtBDE/g/llkQlSgrGUx0ttfJMarExF6E3jg0/QeRgzvp+Chr0XqEIzoK6Rm4/19Q6KIA/Lx32Ti1Y+cQhVdF70AS8GaI2i+0FO3Uj7WfFl4FotUzpbyLpD5/AUe0KOiGA==',
)
------
FILES
------
array (
)
ローカル サーバーを使用している場合、「データ」フィールドは $_POST の一部です。「データ」フィールドは、サーバーに送信される最初のフィールドです。つまり、上記の curl_formadd ループを介して最初に書き込まれ、wireshark でチェックされた TCP ストリームの最初のフィールドであり、$_POST にある最初のフィールドでもあります。私のローカルサーバー上の配列。
サーバーテスト
この問題を発見した後、私はサーバーをテストし、Firefox を使用して WordPress 経由でファイルをアップロードしようとしました。サーバーが大きな $_POST フィールドを拒否するかどうかをテストしました。ただし、アップロードは機能しているようです(アップロードしたいjsonデータよりも大きい大きなPNGをアップロードするようにテストされています)。
次のテストは、「データ」フィールドを小さくすることでした。〜 900 バイトの文字列の繰り返しをアップロードするようにテストしました
"shorter amount of data with special characters +/=?=?$§+#+\'*>< "
これも機能しました(マルチパートポストを使用)。
質問
私の開発マシンのように、長い「データ」フィールドを $_POST 変数の一部として使用できるようにしたいと考えています。何が問題を引き起こしているのかわかりません。私が使用しているマルチパート MIME タイプ (「text/plain」) を使用できますか? Apache/PHP で POST- FIELDのサイズを制限する構成はありますか(全体的な POST サイズの制限についてしか知りません)。
これは、特殊なサーバー構成の問題であると思われます。ただし、長くて (時間を費やさなければ) 複雑な httpd.conf についてはよくわかりません。
この問題の原因と、ローカルサーバーで再現する方法を知っている人はいますか? または、この問題を解決する方法は?
前もって感謝します!