Проблема с файлом cookie libcurl - PullRequest
1 голос
/ 25 июня 2009

[Перекрестная публикация из списка рассылки 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. Как это работает, как и ожидалось, но я бы предпочел по возможности использовать библиотеку.

У кого-нибудь есть идеи?

Спасибо Себ

1 Ответ

1 голос
/ 03 апреля 2010

У нас возникли проблемы с потерей 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;
}
...