2

[lib-curlメーリングリストからクロスポスト]

静的 LIBCURL 7.19.4 に対してシングル スレッド アプリ (MSVC C++ 2005) をビルドしています。

テスト アプリケーションは社内サーバーに接続し、いくつかのフォームの投稿を含む特注の認証プロセスを実行します。これが成功すると、新しいリソースが作成され (POST)、If-Match を使用してリソースが更新されます (PUT)。

libcurl への接続は 1 つしか使用しません (つまり、CURL* は 1 つだけです)。

curl_easy_setopt(CURLOPT_COOKIEFILE, "") を使用して、Cookie エンジンを最初から有効にします。

cookie キャッシュは、認証プロセスの最後に curl_easy_setopt(CURLOPT_COOKIELIST, "SESS") を使用してクリアされます。これは、認証プロセスで必要です。

次の呼び出しで認証が成功すると、サーバーからいくつかのセキュリティ Cookie が返されます。有効期限は設定されていません。

サーバー (および私) は、サーバーへの後続のすべての要求と共にセキュリティ Cookie が送信されることを期待しています。問題は、送信される場合 と送信されない場合があることです。

私は CURL の専門家ではないので、おそらく何か間違ったことをしているのでしょうが、何が原因なのかわかりません。ループ結果でテスト アプリを実行すると、正しい Cookie 処理のランダムな分布が示されます。

回避策として、Cookie エンジンを無効にし、基本的な手動の Cookie 処理を行っています。このように期待どおりに動作しますが、可能であればライブラリを使用したいと思います。

誰にもアイデアはありますか?

ありがとうセブ

4

1 に答える 1

1

ヘッダーが特定のサイズの場合、libcurl が「セッション」を失うという問題が発生しました。

私たちが確認した 2 つの既知のケースは、1425 と 2885 です。

送信されたヘッダーがこの特定のサイズの場合、サーバーは適切な Cookie を受信して​​いないように見えます。サーバーが実際に受信するものを確認するために、制御されたサーバーに対して実際にテストしていません。

私たちが思いついた回避策は、最後にスペースを追加してヘッダー サイズを変更することで、User-Agent をわずかに変更することでした。

リクエストが送信される前にヘッダー サイズを予測するコードを次に示します。

size_t PredictHeaderOutSize(CURL *curl, bool doPost, const char* request, char* userAgent, const char* host, const char* form)
{
    size_t predictedHeaderOutSize = 0;

    // Note, so far predicting 1 byte per newline, fix the hard coded #'s below if that turns out to be wrong

    // POST/GET line
    predictedHeaderOutSize += (doPost ? 4 : 3); // POST vs GET
    predictedHeaderOutSize += strlen(request);
    predictedHeaderOutSize += 11; // Extra characters in 'POST <request> HTTP/1.1' not accounted for above

    // User-Agent line
    predictedHeaderOutSize += strlen(userAgent);
    predictedHeaderOutSize += 13;

    // Host: header
    predictedHeaderOutSize += strlen(host);
    predictedHeaderOutSize += 7;

    // Accept: */*
    predictedHeaderOutSize += 12;

    // Cookie:
    struct curl_slist *cookies=NULL;
    struct curl_slist *next_cookie;
    int num_cookies = 0;
    CURLcode res = curl_easy_getinfo(curl, CURLINFO_COOKIELIST, &cookies);
    if (res == CURLE_OK)
    {
        if (cookies != NULL)
        {
            // At least 1 cookie so add the extra space taken on cookie line
            predictedHeaderOutSize += 7;
            next_cookie = cookies;
            num_cookies = 1;
            while (next_cookie)
            {
                std::vector<std::string> cookie = QueueHelper::Split("\t", next_cookie->data, 7);
                if (cookie.size() != 7)
                {
                    // wtf?
                }
                else
                {
                    // For each cookie we add length of key + value + 3 (for the = ; and extra space)
                    predictedHeaderOutSize += cookie[5].length() + cookie[6].length() + 3;
                }
                next_cookie = next_cookie->next;
                num_cookies++;
            }
            curl_slist_free_all(cookies);
        }
    }
    else
    {
        printf("curl_easy_getinfo failed: %s\n", curl_easy_strerror(res));
    }

    if (doPost)
    {
        // Content-Length:
        size_t formLength = strlen(form);
        if (formLength < 10)
            predictedHeaderOutSize += 1;
        if (formLength >= 10 && formLength < 100)
            predictedHeaderOutSize += 2;
        if (formLength >= 100 && formLength < 1000)
            predictedHeaderOutSize += 3;
        if (formLength >= 1000 && formLength < 10000)
            predictedHeaderOutSize += 4;
        predictedHeaderOutSize += 17;

        // Content-Type: application/x-www-form-urlencoded
        predictedHeaderOutSize += 48;
    }

    predictedHeaderOutSize += 2; // 2 newlines at the end? something else? not sure

    return predictedHeaderOutSize;
}
于 2010-04-03T01:26:37.410 に答える