2

[来自 lib-curl 邮件列表的交叉发布]

我有一个针对静态 LIBCURL 7.19.4 构建的单线程应用程序(MSVC C++ 2005)

测试应用程序连接到内部服务器并执行定制的身份验证过程,其中包括发布几个表单,当此过程成功时创建新资源 (POST),然后使用 If-Match 更新资源 (PUT)。

我只使用一个到 libcurl 的连接(即只有一个 CURL*)

从一开始就使用 curl_easy_setopt(CURLOPT_COOKIEFILE, "") 启用 cookie 引擎

在身份验证过程结束时使用 curl_easy_setopt(CURLOPT_COOKIELIST, "SESS") 清除 cookie 缓存。这是身份验证过程所必需的。

下一个调用完成了成功的身份验证,导致从服务器返回几个安全 cookie - 它们没有设置到期日期。

服务器(和我)希望随后将安全 cookie 与所有后续请求一起发送到服务器。问题是有时 它们会被发送,有时它们不会。

我不是 CURL 专家,所以我可能做错了什么,但我不知道是什么。在循环结果中运行测试应用程序会显示正确 cookie 处理的随机分布。

作为一种解决方法,我已禁用 cookie 引擎并正在执行基本的手动 cookie 处理。像这样它按预期工作,但如果可能的话,我更喜欢使用该库。

有没有人有任何想法?

谢谢赛博

4

1 回答 1

1

当标头具有特定大小时,我们遇到了 libcurl 丢失“会话”的问题。

我们看到的两个已知案例是 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 回答