当标头具有特定大小时,我们遇到了 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;
}