libcurl cookie引擎的问题

时间:2009-06-25 15:59:36

标签: libcurl

[从lib-curl邮件列表交叉发布]

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

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

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

Cookie引擎从一开始就启用了 curl_easy_setopt(CURLOPT_COOKIEFILE,“”)

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

完成成功身份验证的下一个调用将导致 从服务器返回几个安全cookie - 他们 没有设定失效日期。

服务器(和我)希望随后发送安全cookie 所有后续的服务器请求。问题是有时候 他们被发送,有时他们不是。

我不是CURL专家,所以我可能做错了什么,但我 无法弄清楚是什么。在循环结果中运行测试应用程序显示了一个 随机分配正确的cookie处理。

作为一种解决方法,我已禁用cookie引擎并且正在执行基本操作 手动cookie处理。像这样按预期工作,但我更喜欢 尽可能使用图书馆。

有没有人有任何想法?

由于 SEB

1 个答案:

答案 0 :(得分:1)

当标题是特定大小时,我们遇到了libcurl丢失“session”的问题。

我们见过的两个已知病例是1425和2885。

发送的标头是这个特定大小时,服务器似乎没有收到正确的cookie。我们实际上没有针对受控服务器进行测试,以查看服务器实际收到的内容。

我们提出的解决方法是通过在末尾添加空格来稍微改变用户代理以更改标题大小。

以下是在发送请求之前预测标头大小的一些代码

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;
}