diff -U2 -r /var/lib/copr-rpmbuild/results/i2pd-git/upstream-unpacked/Source0/i2pd-openssl/libi2pd/HTTP.cpp /var/lib/copr-rpmbuild/results/i2pd-git/srpm-unpacked/i2pd-openssl.tar.gz-extract/i2pd-openssl/libi2pd/HTTP.cpp --- /var/lib/copr-rpmbuild/results/i2pd-git/upstream-unpacked/Source0/i2pd-openssl/libi2pd/HTTP.cpp 2026-03-27 11:42:26.000000000 +0000 +++ /var/lib/copr-rpmbuild/results/i2pd-git/srpm-unpacked/i2pd-openssl.tar.gz-extract/i2pd-openssl/libi2pd/HTTP.cpp 2026-03-27 01:09:41.000000000 +0000 @@ -373,5 +373,5 @@ { for (auto& it : headers) - if (boost::iequals(it.first, name)) + if (it.first == name) { it.second = value; @@ -384,5 +384,5 @@ for (auto it = headers.begin (); it != headers.end ();) { - if (boost::istarts_with(it->first, name) && !boost::iequals(it->first, exempt)) + if (!it->first.compare(0, name.length (), name) && it->first != exempt) it = headers.erase (it); else @@ -394,5 +394,5 @@ { for (auto& it : headers) - if (boost::iequals(it.first, name)) + if (it.first == name) return it.second; return ""; @@ -403,5 +403,5 @@ size_t num = 0; for (auto& it : headers) - if (boost::iequals(it.first, name)) num++; + if (it.first == name) num++; return num; } diff -U2 -r /var/lib/copr-rpmbuild/results/i2pd-git/upstream-unpacked/Source0/i2pd-openssl/libi2pd/HTTP.h /var/lib/copr-rpmbuild/results/i2pd-git/srpm-unpacked/i2pd-openssl.tar.gz-extract/i2pd-openssl/libi2pd/HTTP.h --- /var/lib/copr-rpmbuild/results/i2pd-git/upstream-unpacked/Source0/i2pd-openssl/libi2pd/HTTP.h 2026-03-27 11:42:26.000000000 +0000 +++ /var/lib/copr-rpmbuild/results/i2pd-git/srpm-unpacked/i2pd-openssl.tar.gz-extract/i2pd-openssl/libi2pd/HTTP.h 2026-03-27 01:09:41.000000000 +0000 @@ -17,5 +17,4 @@ #include #include -#include namespace i2p @@ -26,15 +25,4 @@ constexpr std::string_view HTTP_EOH = "\r\n\r\n"; /**< HTTP end-of-headers mark */ - // case-insensitive comparator for HTTP header names (RFC 7230) - struct CaseInsensitiveLess - { - using is_transparent = void; - - bool operator() (std::string_view a, std::string_view b) const - { - return boost::ilexicographical_compare(a, b); - } - }; - struct URL { @@ -79,5 +67,5 @@ struct HTTPMsg { - std::map headers; + std::map headers; void add_header(const char *name, const std::string & value, bool replace = false); diff -U2 -r /var/lib/copr-rpmbuild/results/i2pd-git/upstream-unpacked/Source0/i2pd-openssl/tests/test-http-req.cpp /var/lib/copr-rpmbuild/results/i2pd-git/srpm-unpacked/i2pd-openssl.tar.gz-extract/i2pd-openssl/tests/test-http-req.cpp --- /var/lib/copr-rpmbuild/results/i2pd-git/upstream-unpacked/Source0/i2pd-openssl/tests/test-http-req.cpp 2026-03-27 11:42:26.000000000 +0000 +++ /var/lib/copr-rpmbuild/results/i2pd-git/srpm-unpacked/i2pd-openssl.tar.gz-extract/i2pd-openssl/tests/test-http-req.cpp 2026-03-27 01:09:41.000000000 +0000 @@ -84,57 +84,4 @@ delete req; - /* test: case-insensitive header matching (RFC 7230) */ - buf = - "GET / HTTP/1.1\r\n" - "HOST: example.i2p\r\n" - "content-type: text/html\r\n" - "Content-Length: 100\r\n" - "X-Custom-Header: value\r\n" - "\r\n"; - len = strlen(buf); - req = new HTTPReq; - assert((ret = req->parse(buf, len)) == len); - /* GetHeader should be case-insensitive */ - assert(req->GetHeader("Host") == "example.i2p"); - assert(req->GetHeader("host") == "example.i2p"); - assert(req->GetHeader("HOST") == "example.i2p"); - assert(req->GetHeader("Content-Type") == "text/html"); - assert(req->GetHeader("content-type") == "text/html"); - assert(req->GetHeader("CONTENT-TYPE") == "text/html"); - assert(req->GetHeader("Content-Length") == "100"); - assert(req->GetHeader("content-length") == "100"); - assert(req->GetHeader("x-custom-header") == "value"); - assert(req->GetHeader("X-CUSTOM-HEADER") == "value"); - /* GetNumHeaders should be case-insensitive */ - assert(req->GetNumHeaders("Host") == 1); - assert(req->GetNumHeaders("host") == 1); - assert(req->GetNumHeaders("HOST") == 1); - assert(req->GetNumHeaders("content-type") == 1); - delete req; - - /* test: UpdateHeader case-insensitivity */ - req = new HTTPReq; - req->AddHeader("Content-Type", "text/plain"); - assert(req->GetHeader("Content-Type") == "text/plain"); - req->UpdateHeader("content-type", "application/json"); - assert(req->GetHeader("Content-Type") == "application/json"); - assert(req->GetHeader("CONTENT-TYPE") == "application/json"); - req->UpdateHeader("CONTENT-TYPE", "text/html"); - assert(req->GetHeader("content-type") == "text/html"); - delete req; - - /* test: RemoveHeader case-insensitivity */ - req = new HTTPReq; - req->AddHeader("X-Forwarded-For", "1.2.3.4"); - req->AddHeader("X-Forwarded-Host", "proxy.i2p"); - req->AddHeader("Accept", "*/*"); - assert(req->GetNumHeaders() == 3); - /* remove headers starting with "x-forwarded" (case-insensitive), exempt "X-Forwarded-Host" */ - req->RemoveHeader("X-Forwarded", "x-forwarded-host"); - assert(req->GetNumHeaders() == 2); - assert(req->GetHeader("X-Forwarded-Host") == "proxy.i2p"); - assert(req->GetHeader("X-Forwarded-For") == ""); - delete req; - return 0; } diff -U2 -r /var/lib/copr-rpmbuild/results/i2pd-git/upstream-unpacked/Source0/i2pd-openssl/tests/test-http-res.cpp /var/lib/copr-rpmbuild/results/i2pd-git/srpm-unpacked/i2pd-openssl.tar.gz-extract/i2pd-openssl/tests/test-http-res.cpp --- /var/lib/copr-rpmbuild/results/i2pd-git/upstream-unpacked/Source0/i2pd-openssl/tests/test-http-res.cpp 2026-03-27 11:42:26.000000000 +0000 +++ /var/lib/copr-rpmbuild/results/i2pd-git/srpm-unpacked/i2pd-openssl.tar.gz-extract/i2pd-openssl/tests/test-http-res.cpp 2026-03-27 01:09:41.000000000 +0000 @@ -45,72 +45,4 @@ assert(res->to_string() == buf); - /* test: case-insensitive header parsing (RFC 7230) */ - buf = - "HTTP/1.1 200 OK\r\n" - "content-type: text/html\r\n" - "CONTENT-LENGTH: 42\r\n" - "transfer-encoding: chunked\r\n" - "content-encoding: gzip\r\n" - "\r\n"; - len = strlen(buf); - res = new HTTPRes; - assert((ret = res->parse(buf, len)) == len); - assert(res->code == 200); - /* content_length() should work with any case */ - assert(res->content_length() == 42); - /* is_chunked() should work with any case */ - assert(res->is_chunked() == true); - /* is_gzipped() should work with any case */ - assert(res->is_gzipped() == true); - delete res; - - /* test: add_header case-insensitivity (no duplicates) */ - res = new HTTPRes; - res->add_header("Content-Type", "text/plain"); - res->add_header("content-type", "text/html"); /* should not add duplicate */ - assert(res->headers.size() == 1); - res->add_header("content-type", "application/json", true); /* replace=true */ - assert(res->headers.size() == 1); - delete res; - - /* test: del_header case-insensitivity */ - res = new HTTPRes; - res->add_header("X-Custom-Header", "value"); - assert(res->headers.size() == 1); - res->del_header("x-custom-header"); - assert(res->headers.size() == 0); - delete res; - - /* test: to_string() doesn't add duplicate Date/Content-Length with different case */ - res = new HTTPRes; - res->version = "HTTP/1.1"; - res->code = 200; - res->status = "OK"; - res->add_header("date", "Thu, 01 Jan 1970 00:00:00 GMT"); - res->add_header("content-length", "0"); - res->body = ""; - std::string response = res->to_string(); - /* should not have duplicate headers */ - size_t date_count = 0, pos = 0; - while ((pos = response.find("ate:", pos)) != std::string::npos) { - date_count++; - pos++; - } - assert(date_count == 1); /* only one Date header */ - delete res; - - /* test: get_header case-insensitivity (used by Reseed for Location redirect) */ - buf = - "HTTP/1.1 302 Found\r\n" - "location: https://example.com/new\r\n" - "\r\n"; - len = strlen(buf); - res = new HTTPRes; - assert((ret = res->parse(buf, len)) == len); - assert(res->get_header("Location") == "https://example.com/new"); - assert(res->get_header("location") == "https://example.com/new"); - assert(res->get_header("LOCATION") == "https://example.com/new"); - delete res; - return 0; }