-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
3 changed files
with
104 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
#include "uvio/debug.hpp" | ||
#include "uvio/net/http/http_util.hpp" | ||
|
||
using namespace uvio::net::http; | ||
auto main() -> int { | ||
CaseInsensitiveEqual case_insensitive_equal; | ||
ASSERT(case_insensitive_equal("Test", "tesT")); | ||
ASSERT(case_insensitive_equal("tesT", "test")); | ||
ASSERT(!case_insensitive_equal("test", "tset")); | ||
|
||
CaseInsensitiveHash case_insensitive_hash; | ||
ASSERT(case_insensitive_hash("Test") == case_insensitive_hash("tesT")); | ||
ASSERT(case_insensitive_hash("tesT") == case_insensitive_hash("test")); | ||
ASSERT(case_insensitive_hash("test") != case_insensitive_hash("tset")); | ||
|
||
HttpHeader header; | ||
header.add("Content-Type", "application/json"); | ||
header.add("Set-Cookie", "ID=id"); | ||
header.add("Set-Cookie", "name=name"); | ||
ASSERT(header.find("content-type").has_value()); | ||
ASSERT(!header.find("accept").has_value()); | ||
ASSERT(header.find("Set-Cookie").has_value()); | ||
|
||
auto real_value = *header.find_all("Set-Cookie"); | ||
auto expected = std::vector<std::string>{"ID=id", "name=name"}; | ||
ASSERT(real_value == expected); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
#pragma once | ||
|
||
#include <optional> | ||
#include <string> | ||
#include <unordered_map> | ||
#include <vector> | ||
|
||
namespace uvio::net::http { | ||
|
||
class CaseInsensitiveEqual { | ||
public: | ||
auto operator()(const std::string &left, | ||
const std::string &right) const noexcept -> bool { | ||
return left.size() == right.size() | ||
&& std::equal(left.begin(), | ||
left.end(), | ||
right.begin(), | ||
[](char a, char b) { | ||
return tolower(a) == tolower(b); | ||
}); | ||
} | ||
}; | ||
|
||
// Based on | ||
// https://stackoverflow.com/questions/2590677/how-do-i-combine-hash-values-in-c0x/2595226#2595226 | ||
class CaseInsensitiveHash { | ||
public: | ||
auto operator()(const std::string &str) const noexcept -> std::size_t { | ||
std::size_t seed = 0; | ||
std::hash<int> hash; | ||
for (auto c : str) { | ||
seed ^= hash(tolower(c)) + 0x9e3779b9 + (seed << 6) + (seed >> 2); | ||
} | ||
return seed; | ||
} | ||
}; | ||
|
||
using CaseInsensitiveMultimap = std::unordered_multimap<std::string, | ||
std::string, | ||
CaseInsensitiveHash, | ||
CaseInsensitiveEqual>; | ||
|
||
class HttpHeader { | ||
public: | ||
auto add(const std::string &key, const std::string &value) { | ||
header_multimap_.emplace(key, value); | ||
} | ||
|
||
auto find(const std::string &case_insensitive_key) | ||
-> std::optional<std::string> { | ||
auto range = header_multimap_.equal_range(case_insensitive_key); | ||
if (range.first != header_multimap_.end()) { | ||
return range.first->second; | ||
} else { | ||
return std::nullopt; | ||
} | ||
} | ||
|
||
auto find_all(const std::string &case_insensitive_key) | ||
-> std::optional<std::vector<std::string>> { | ||
auto range = header_multimap_.equal_range(case_insensitive_key); | ||
if (range.first != header_multimap_.end()) { | ||
std::vector<std::string> res; | ||
for (auto it = range.first; it != range.second; ++it) { | ||
res.push_back(it->second); | ||
} | ||
return res; | ||
} else { | ||
return std::nullopt; | ||
} | ||
} | ||
|
||
private: | ||
CaseInsensitiveMultimap header_multimap_; | ||
}; | ||
} // namespace uvio::net::http |