Unverified Commit 01afaa4c authored by Dennis Jenkins's avatar Dennis Jenkins Committed by GitHub

Merge pull request #626 from adamburgess/header-case

Raw and Cookie header case-insensitive
parents e18ed9ba 0bfaa054
...@@ -28,10 +28,15 @@ struct LowercaseHash { ...@@ -28,10 +28,15 @@ struct LowercaseHash {
} }
}; };
bool LowercaseEqualStatic(const std::string& dynamic, const std::string& statik);
struct LowercaseEqual { struct LowercaseEqual {
bool operator()(const std::string& left, const std::string& right) const { bool operator()(const std::string& left, const std::string& right) const {
return toLowercase(left) == toLowercase(right); return std::equal(left.begin(), left.end(), right.begin(), right.end(),
} [] (const char& a, const char& b) {
return std::tolower(a) == std::tolower(b);
});
};
}; };
class Collection { class Collection {
...@@ -109,7 +114,7 @@ public: ...@@ -109,7 +114,7 @@ public:
std::vector<std::shared_ptr<Header>> list() const; std::vector<std::shared_ptr<Header>> list() const;
const std::unordered_map<std::string, Raw>& rawList() const { const std::unordered_map<std::string,Raw,LowercaseHash,LowercaseEqual>& rawList() const {
return rawHeaders; return rawHeaders;
} }
...@@ -126,7 +131,12 @@ private: ...@@ -126,7 +131,12 @@ private:
LowercaseHash, LowercaseHash,
LowercaseEqual LowercaseEqual
> headers; > headers;
std::unordered_map<std::string, Raw> rawHeaders; std::unordered_map<
std::string,
Raw,
LowercaseHash,
LowercaseEqual
> rawHeaders;
}; };
class Registry { class Registry {
......
...@@ -290,11 +290,11 @@ namespace Private { ...@@ -290,11 +290,11 @@ namespace Private {
if (!cursor.advance(1)) return State::Again; if (!cursor.advance(1)) return State::Again;
} }
if (name == "Cookie") { if (Header::LowercaseEqualStatic(name, "cookie")) {
message->cookies_.removeAllCookies(); // removing existing cookies before re-adding them. message->cookies_.removeAllCookies(); // removing existing cookies before re-adding them.
message->cookies_.addFromRaw(cursor.offset(start), cursor.diff(start)); message->cookies_.addFromRaw(cursor.offset(start), cursor.diff(start));
} }
else if (name == "Set-Cookie") { else if (Header::LowercaseEqualStatic(name, "set-cookie")) {
message->cookies_.add(Cookie::fromRaw(cursor.offset(start), cursor.diff(start))); message->cookies_.add(Cookie::fromRaw(cursor.offset(start), cursor.diff(start)));
} }
......
...@@ -41,6 +41,14 @@ toLowercase(std::string str) { ...@@ -41,6 +41,14 @@ toLowercase(std::string str) {
return str; return str;
} }
bool
LowercaseEqualStatic(const std::string& dynamic, const std::string& statik) {
return std::equal(dynamic.begin(), dynamic.end(), statik.begin(), statik.end(),
[] (const char& a, const char& b) {
return std::tolower(a) == b;
});
}
Registry& Registry::instance() { Registry& Registry::instance() {
static Registry instance; static Registry instance;
......
...@@ -700,3 +700,55 @@ TEST(headers_test, registered_header_in_raw_list) ...@@ -700,3 +700,55 @@ TEST(headers_test, registered_header_in_raw_list)
ASSERT_TRUE(foundRawHeader->second.value() == "some data"); ASSERT_TRUE(foundRawHeader->second.value() == "some data");
} }
TEST(headers_test, raw_headers_are_case_insensitive)
{
// no matter the casing of the input header,
std::vector<std::string> test_cases = {
"Custom-Header: x\r\n",
"CUSTOM-HEADER: x\r\n",
"custom-header: x\r\n",
"CuStOm-HeAdEr: x\r\n"
};
for(auto&& test : test_cases) {
Pistache::RawStreamBuf<> buf(&test[0], test.size());
Pistache::StreamCursor cursor(&buf);
Pistache::Http::Request request;
Pistache::Http::Private::HeadersStep step(&request);
step.apply(cursor);
// or the header you try and get, it should work:
ASSERT_FALSE(request.headers().tryGetRaw("Custom-Header").isEmpty());
ASSERT_FALSE(request.headers().tryGetRaw("CUSTOM-HEADER").isEmpty());
ASSERT_FALSE(request.headers().tryGetRaw("custom-header").isEmpty());
ASSERT_FALSE(request.headers().tryGetRaw("CuStOm-HeAdEr").isEmpty());
}
}
TEST(headers_test, cookie_headers_are_case_insensitive)
{
// no matter the casing of the cookie header(s),
std::vector<std::string> test_cases = {
"Cookie: x=y\r\n",
"COOKIE: x=y\r\n",
"cookie: x=y\r\n",
"CoOkIe: x=y\r\n",
"Set-Cookie: x=y\r\n",
"SET-COOKIE: x=y\r\n",
"set-cookie: x=y\r\n",
"SeT-CoOkIe: x=y\r\n",
};
for(auto&& test : test_cases) {
Pistache::RawStreamBuf<> buf(&test[0], test.size());
Pistache::StreamCursor cursor(&buf);
Pistache::Http::Request request;
Pistache::Http::Private::HeadersStep step(&request);
step.apply(cursor);
// the cookies should still exist.
ASSERT_TRUE(request.cookies().has("x"));
ASSERT_TRUE(request.cookies().get("x").value == "y");
}
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment