* @brief Append cookies by following the rules specified in the cookies config object. * @param config cookies-related configuration containing information about which cookies need to be appended to the key. * @note Add the cookies to "hier-part" (RFC 3986), always sort them in the cache key. */
| 583 | * @note Add the cookies to "hier-part" (RFC 3986), always sort them in the cache key. |
| 584 | */ |
| 585 | void |
| 586 | CacheKey::appendCookies(const ConfigCookies &config) |
| 587 | { |
| 588 | if (config.toBeRemoved() || config.toBeSkipped()) { |
| 589 | /* Don't append any cookies to the cache key. */ |
| 590 | return; |
| 591 | } |
| 592 | |
| 593 | TSMLoc field; |
| 594 | StringSet cset; /* sort and uniquify the cookies list in the cache key */ |
| 595 | |
| 596 | for (field = TSMimeHdrFieldFind(_buf, _hdrs, TS_MIME_FIELD_COOKIE, TS_MIME_LEN_COOKIE); field != TS_NULL_MLOC; |
| 597 | field = ::nextDuplicate(_buf, _hdrs, field)) { |
| 598 | int count = TSMimeHdrFieldValuesCount(_buf, _hdrs, field); |
| 599 | |
| 600 | for (int i = 0; i < count; ++i) { |
| 601 | const char *value; |
| 602 | int len; |
| 603 | |
| 604 | value = TSMimeHdrFieldValueStringGet(_buf, _hdrs, field, i, &len); |
| 605 | if (value == nullptr || len == 0) { |
| 606 | continue; |
| 607 | } |
| 608 | |
| 609 | std::istringstream istr(String(value, len)); |
| 610 | String cookie; |
| 611 | |
| 612 | while (std::getline(istr, cookie, ';')) { |
| 613 | ::ltrim(cookie); // Trim leading spaces. |
| 614 | |
| 615 | String::size_type pos(cookie.find_first_of('=')); |
| 616 | String name(cookie.substr(0, pos == String::npos ? cookie.size() : pos)); |
| 617 | |
| 618 | /* We only add it to the cache key it is in the cookie set. */ |
| 619 | if (config.toBeAdded(name)) { |
| 620 | cset.insert(cookie); |
| 621 | } |
| 622 | } |
| 623 | } |
| 624 | } |
| 625 | |
| 626 | /* We are iterating over the cookies in client order, |
| 627 | * but the cache key needs a stable ordering, so we sort via std::set. */ |
| 628 | String cookies_keys = containerToString<StringSet, StringSet::const_iterator>(cset, "", ";"); |
| 629 | if (!cookies_keys.empty()) { |
| 630 | append(cookies_keys); |
| 631 | } |
| 632 | } |
| 633 | |
| 634 | /** |
| 635 | * @brief Append query parameters by following the rules specified in the query configuration object. |
no test coverage detected