# UNDF: UNDF-2026-000001162 --- a/src/HttpHeader.cc +++ b/src/HttpHeader.cc @@ -1859,16 +1859,24 @@ void HttpHeader::removeConnectionHeaderEntries() { if (has(Http::HdrType::CONNECTION)) { - /* anything that matches Connection list member will be deleted */ + // Build a case-insensitive set of Connection header tokens for O(1) + // lookup instead of O(C) strListIsMember scan per header entry. + // Without this, removal is O(H * C) per response hop where H is + // the number of HTTP headers and C is the Connection token count. + // A response with 50 headers and Connection: with 10 tokens costs + // 500 string comparisons; with a set it costs 10 inserts + 50 probes. String strConnection; - (void) getList(Http::HdrType::CONNECTION, &strConnection); + + std::unordered_set connTokens; + const char *item = nullptr; + int ilen = 0; + const char *pos = nullptr; + while (strListGetItem(&strConnection, ',', &item, &ilen, &pos)) + connTokens.emplace(item, ilen); + const HttpHeaderEntry *e; HttpHeaderPos pos = HttpHeaderInitPos; - /* - * think: on-average-best nesting of the two loops (hdrEntry - * and strListItem) @?@ - */ - /* - * maybe we should delete standard stuff ("keep-alive","close") - * from strConnection first? - */ - int headers_deleted = 0; while ((e = getEntry(&pos))) { - if (strListIsMember(&strConnection, e->name, ',')) + if (connTokens.count(e->name)) delAt(pos, headers_deleted); } if (headers_deleted)