Skip to content

Commit 31e53d2

Browse files
committed
Fixed yhirose#32
1 parent 459f197 commit 31e53d2

File tree

4 files changed

+55
-19
lines changed

4 files changed

+55
-19
lines changed

example/server.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313

1414
using namespace httplib;
1515

16-
std::string dump_headers(const MultiMap& headers)
16+
std::string dump_headers(const Headers& headers)
1717
{
1818
std::string s;
1919
char buf[BUFSIZ];

example/simplesvr.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
using namespace httplib;
1616
using namespace std;
1717

18-
string dump_headers(const MultiMap& headers)
18+
string dump_headers(const Headers& headers)
1919
{
2020
string s;
2121
char buf[BUFSIZ];

httplib.h

Lines changed: 37 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -73,9 +73,25 @@ typedef int socket_t;
7373
namespace httplib
7474
{
7575

76+
namespace detail {
77+
78+
struct ci {
79+
bool operator() (const std::string & s1, const std::string & s2) const {
80+
return std::lexicographical_compare(
81+
s1.begin(), s1.end(),
82+
s2.begin(), s2.end(),
83+
[](char c1, char c2) {
84+
return std::tolower(c1) < std::tolower(c2);
85+
});
86+
}
87+
};
88+
89+
} // namespace detail
90+
7691
enum class HttpVersion { v1_0 = 0, v1_1 };
7792

78-
typedef std::multimap<std::string, std::string> MultiMap;
93+
typedef std::multimap<std::string, std::string, detail::ci> Headers;
94+
typedef std::multimap<std::string, std::string> Params;
7995
typedef std::smatch Match;
8096
typedef std::function<void (int64_t current, int64_t total)> Progress;
8197

@@ -90,9 +106,9 @@ typedef std::multimap<std::string, MultipartFile> MultipartFiles;
90106
struct Request {
91107
std::string method;
92108
std::string path;
93-
MultiMap headers;
109+
Headers headers;
94110
std::string body;
95-
MultiMap params;
111+
Params params;
96112
MultipartFiles files;
97113
Match matches;
98114
Progress progress;
@@ -110,7 +126,7 @@ struct Request {
110126

111127
struct Response {
112128
int status;
113-
MultiMap headers;
129+
Headers headers;
114130
std::string body;
115131

116132
bool has_header(const char* key) const;
@@ -198,7 +214,7 @@ class Client {
198214
std::shared_ptr<Response> get(const char* path, Progress callback = [](int64_t,int64_t){});
199215
std::shared_ptr<Response> head(const char* path);
200216
std::shared_ptr<Response> post(const char* path, const std::string& body, const char* content_type);
201-
std::shared_ptr<Response> post(const char* path, const MultiMap& params);
217+
std::shared_ptr<Response> post(const char* path, const Params& params);
202218

203219
bool send(const Request& req, Response& res);
204220

@@ -562,7 +578,7 @@ inline const char* status_message(int status)
562578
}
563579
}
564580

565-
inline const char* get_header_value(const MultiMap& headers, const char* key, const char* def)
581+
inline const char* get_header_value(const Headers& headers, const char* key, const char* def)
566582
{
567583
auto it = headers.find(key);
568584
if (it != headers.end()) {
@@ -571,7 +587,7 @@ inline const char* get_header_value(const MultiMap& headers, const char* key, co
571587
return def;
572588
}
573589

574-
inline int get_header_value_int(const MultiMap& headers, const char* key, int def)
590+
inline int get_header_value_int(const Headers& headers, const char* key, int def)
575591
{
576592
auto it = headers.find(key);
577593
if (it != headers.end()) {
@@ -580,7 +596,7 @@ inline int get_header_value_int(const MultiMap& headers, const char* key, int de
580596
return def;
581597
}
582598

583-
inline bool read_headers(Stream& strm, MultiMap& headers)
599+
inline bool read_headers(Stream& strm, Headers& headers)
584600
{
585601
static std::regex re("(.+?): (.+?)\r\n");
586602

@@ -853,7 +869,7 @@ inline std::string decode_url(const std::string& s)
853869
return result;
854870
}
855871

856-
inline void parse_query_text(const std::string& s, MultiMap& params)
872+
inline void parse_query_text(const std::string& s, Params& params)
857873
{
858874
split(&s[0], &s[s.size()], '&', [&](const char* b, const char* e) {
859875
std::string key;
@@ -980,6 +996,17 @@ class WSInit {
980996
static WSInit wsinit_;
981997
#endif
982998

999+
inline std::string to_lower(const char* beg, const char* end)
1000+
{
1001+
std::string out;
1002+
auto it = beg;
1003+
while (it != end) {
1004+
out += ::tolower(*it);
1005+
it++;
1006+
}
1007+
return out;
1008+
}
1009+
9831010
} // namespace detail
9841011

9851012
// Request implementation
@@ -1497,7 +1524,7 @@ inline std::shared_ptr<Response> Client::post(
14971524
}
14981525

14991526
inline std::shared_ptr<Response> Client::post(
1500-
const char* path, const MultiMap& params)
1527+
const char* path, const Params& params)
15011528
{
15021529
std::string query;
15031530
for (auto it = params.begin(); it != params.end(); ++it) {

test/test.cc

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ TEST(StartupTest, WSAStartup)
3232
TEST(SplitTest, ParseQueryString)
3333
{
3434
string s = "key1=val1&key2=val2&key3=val3";
35-
MultiMap dic;
35+
Params dic;
3636

3737
detail::split(s.c_str(), s.c_str() + s.size(), '&', [&](const char* b, const char* e) {
3838
string key, val;
@@ -54,7 +54,7 @@ TEST(SplitTest, ParseQueryString)
5454
TEST(ParseQueryTest, ParseQueryString)
5555
{
5656
string s = "key1=val1&key2=val2&key3=val3";
57-
MultiMap dic;
57+
Params dic;
5858

5959
detail::parse_query_text(s, dic);
6060

@@ -83,28 +83,28 @@ TEST(SocketTest, OpenCloseWithAI_PASSIVE)
8383

8484
TEST(GetHeaderValueTest, DefaultValue)
8585
{
86-
MultiMap map = {{"Dummy","Dummy"}};
86+
Headers map = {{"Dummy","Dummy"}};
8787
auto val = detail::get_header_value(map, "Content-Type", "text/plain");
8888
ASSERT_STREQ("text/plain", val);
8989
}
9090

9191
TEST(GetHeaderValueTest, DefaultValueInt)
9292
{
93-
MultiMap map = {{"Dummy","Dummy"}};
93+
Headers map = {{"Dummy","Dummy"}};
9494
auto val = detail::get_header_value_int(map, "Content-Length", 100);
9595
EXPECT_EQ(100, val);
9696
}
9797

9898
TEST(GetHeaderValueTest, RegularValue)
9999
{
100-
MultiMap map = {{"Content-Type", "text/html"}, {"Dummy", "Dummy"}};
100+
Headers map = {{"Content-Type", "text/html"}, {"Dummy", "Dummy"}};
101101
auto val = detail::get_header_value(map, "Content-Type", "text/plain");
102102
ASSERT_STREQ("text/html", val);
103103
}
104104

105105
TEST(GetHeaderValueTest, RegularValueInt)
106106
{
107-
MultiMap map = {{"Content-Length", "100"}, {"Dummy", "Dummy"}};
107+
Headers map = {{"Content-Length", "100"}, {"Dummy", "Dummy"}};
108108
auto val = detail::get_header_value_int(map, "Content-Length", 0);
109109
EXPECT_EQ(100, val);
110110
}
@@ -310,7 +310,7 @@ TEST_F(ServerTest, PostMethod2)
310310
ASSERT_TRUE(res != nullptr);
311311
ASSERT_EQ(404, res->status);
312312

313-
MultiMap params;
313+
Params params;
314314
params.emplace("name", "john2");
315315
params.emplace("note", "coder");
316316

@@ -512,6 +512,15 @@ TEST_F(ServerTest, MultipartFormData)
512512
EXPECT_EQ(200, res->status);
513513
}
514514

515+
TEST_F(ServerTest, CaseInsensitiveHeaderName)
516+
{
517+
auto res = cli_.get("/hi");
518+
ASSERT_TRUE(res != nullptr);
519+
EXPECT_EQ(200, res->status);
520+
EXPECT_EQ("text/plain", res->get_header_value("content-type"));
521+
EXPECT_EQ("Hello World!", res->body);
522+
}
523+
515524
class ServerTestWithAI_PASSIVE : public ::testing::Test {
516525
protected:
517526
ServerTestWithAI_PASSIVE()

0 commit comments

Comments
 (0)