如何解析cpprestsdk生成的含日期逗号的多个Set-Cookie?
这个问题我太熟了——cpprestsdk生成的Set-Cookie里,Expires日期带逗号的情况确实会坑到不少人,直接按全局逗号分割肯定会把单个Cookie项拆碎。我来给你梳理下正确的解析思路,再附上可用的C++代码。
问题核心
你的Set-Cookie字符串包含两个完整的Cookie项,但Expires字段的日期格式(比如Thu, 03-May-2018...)里的逗号,会干扰常规的“按逗号分割多个Cookie项”的逻辑,导致拆分出错误的片段。
正确解析步骤
要搞定这个,不能粗暴全局分割,得精准识别Cookie项的边界:
- 第一步:区分日期里的逗号和Cookie项之间的逗号。Cookie项之间的分隔是
,(逗号加空格),且空格后的字符是合法的Cookie名称起始字符(字母或下划线);而日期里的逗号后面跟着的是空格加数字/月份缩写,不符合这个特征。 - 第二步:对每个完整提取的Cookie项,只保留
name=value部分——客户端发送Cookie请求头时,不需要携带Expires、HttpOnly、Path这些服务器设置的属性,只需要键值对用分号分隔即可。
C++示例代码(适配cpprestsdk场景)
下面是一个专门处理这种特殊Set-Cookie格式的解析函数,直接用就行:
#include <iostream> #include <string> #include <vector> #include <algorithm> #include <cctype> // 解析带日期逗号的Set-Cookie字符串,生成可直接使用的Cookie头内容 std::string parse_set_cookie(const std::string& set_cookie_str) { std::vector<std::string> cookie_items; size_t start_pos = 0; const size_t str_len = set_cookie_str.size(); // 遍历字符串,精准定位每个Cookie项的结束位置 for (size_t i = 0; i < str_len; ++i) { // 匹配Cookie项之间的分隔符:", " 且后续字符是合法Cookie名开头 if (i + 1 < str_len && set_cookie_str[i] == ',' && set_cookie_str[i+1] == ' ') { if (i + 2 < str_len && (isalpha(static_cast<unsigned char>(set_cookie_str[i+2])) || set_cookie_str[i+2] == '_')) { // 提取当前Cookie项 cookie_items.push_back(set_cookie_str.substr(start_pos, i - start_pos)); // 跳过分隔符,定位到下一个Cookie项的起始位置 start_pos = i + 2; i += 1; // 跳过空格,减少重复遍历 } } } // 添加最后一个Cookie项 if (start_pos < str_len) { cookie_items.push_back(set_cookie_str.substr(start_pos)); } // 从每个Cookie项中提取name=value键值对 std::vector<std::string> cookie_kvs; for (const auto& item : cookie_items) { // 找到第一个分号的位置,分号前就是我们要的键值对 const size_t semicolon_idx = item.find(';'); std::string kv = item.substr(0, semicolon_idx); // 去除键值对前后可能存在的空格,做容错处理 kv.erase(kv.begin(), std::find_if(kv.begin(), kv.end(), [](int ch) { return !std::isspace(ch); })); kv.erase(std::find_if(kv.rbegin(), kv.rend(), [](int ch) { return !std::isspace(ch); }).base(), kv.end()); cookie_kvs.push_back(kv); } // 拼接成标准的Cookie头格式 std::string cookie_header; for (size_t i = 0; i < cookie_kvs.size(); ++i) { if (i != 0) { cookie_header += "; "; } cookie_header += cookie_kvs[i]; } return cookie_header; } int main() { // 你的目标Set-Cookie字符串 const std::string target_set_cookie = "tgw_l7_route=d0bf4a9ab78d53762b596c0a48dabcdf; Expires=Thu, 03-May-2018 11:42:51 GMT; Path=/, session=a1d25e28-0084-421d-ae71-9ae18c7f6b50; Expires=Sun, 03-Jun-2018 10:42:51 GMT; HttpOnly; Path=/"; const std::string result = parse_set_cookie(target_set_cookie); std::cout << "生成的Cookie头内容:\n" << result << std::endl; // 预期输出: // tgw_l7_route=d0bf4a9ab78d53762b596c0a48dabcdf; session=a1d25e28-0084-421d-ae71-9ae18c7f6b50 return 0; }
代码细节说明
- 精准拆分Cookie项:通过判断
,后续字符的类型,完美区分日期逗号和Cookie项分隔逗号,确保每个Cookie项被完整提取。 - 键值对提取:只保留每个Cookie项中第一个分号前的内容,自动过滤掉服务器设置的属性字段,符合Cookie请求头的规范。
- 容错处理:添加了前后空格的清理逻辑,避免因为字符串格式的微小差异(比如多余空格)导致解析失败。
运行验证
运行代码后,会输出符合要求的Cookie头内容,直接把这个值放到请求的Cookie字段里,就能正确发送给服务器了。
内容的提问来源于stack exchange,提问作者user1633272
相关产品推荐
相关产品推荐

