Skip to content

Commit cc0a790

Browse files
authored
Use multimap instead of map for headers (#7)
Signed-off-by: Darshan Sen <raisinten@gmail.com>
1 parent 4738ba6 commit cc0a790

File tree

5 files changed

+41
-15
lines changed

5 files changed

+41
-15
lines changed

include/benoni/http.h

+9-7
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
#define BENONI_HTTP_H_
33

44
#include <functional> // std::function
5-
#include <map> // std::map
5+
#include <map> // std::multimap
66
#include <optional> // std::optional
77
#include <string> // std::string
88
#include <variant> // std::variant
@@ -27,12 +27,14 @@ class RequestOptions {
2727
public:
2828
Method method() const { return method_; }
2929
const std::string &body() const { return body_; }
30-
const std::map<std::string, std::string> &headers() const { return headers_; }
30+
const std::multimap<std::string, std::string> &headers() const {
31+
return headers_;
32+
}
3133
const std::optional<int> &timeout() const { return timeout_; }
3234

3335
private:
3436
RequestOptions(Method method, std::string body,
35-
std::map<std::string, std::string> headers,
37+
std::multimap<std::string, std::string> headers,
3638
std::optional<int> timeout)
3739
: method_{method}, body_{std::move(body)}, headers_{std::move(headers)},
3840
timeout_{std::move(timeout)} {}
@@ -41,7 +43,7 @@ class RequestOptions {
4143

4244
Method method_;
4345
std::string body_;
44-
std::map<std::string, std::string> headers_;
46+
std::multimap<std::string, std::string> headers_;
4547
std::optional<int> timeout_;
4648
};
4749

@@ -58,7 +60,7 @@ class RequestOptionsBuilder {
5860
}
5961

6062
RequestOptionsBuilder &
61-
set_headers(std::map<std::string, std::string> headers) {
63+
set_headers(std::multimap<std::string, std::string> headers) {
6264
headers_ = std::move(headers);
6365
return *this;
6466
}
@@ -76,14 +78,14 @@ class RequestOptionsBuilder {
7678
private:
7779
Method method_ = Method::GET;
7880
std::string body_;
79-
std::map<std::string, std::string> headers_;
81+
std::multimap<std::string, std::string> headers_;
8082
std::optional<int> timeout_;
8183
};
8284

8385
struct Response {
8486
std::string body;
8587
uint16_t status;
86-
std::map<std::string, std::string> headers;
88+
std::multimap<std::string, std::string> headers;
8789
};
8890

8991
auto request(const std::string &url, RequestOptions options,

src/apple/http.mm

+11-2
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#import <Foundation/Foundation.h>
44

55
#include <map> // std::map
6+
#include <sstream> // std::istringstream
67
#include <string> // std::string
78
#include <variant> // std::variant
89

@@ -11,7 +12,7 @@
1112
struct HTTPTaskContext {
1213
std::function<void(std::variant<std::string, benoni::Response>)> callback;
1314
uint16_t status;
14-
std::map<std::string, std::string> headers;
15+
std::multimap<std::string, std::string> headers;
1516
NSMutableData *data;
1617
NSStringEncoding encoding;
1718
};
@@ -92,8 +93,16 @@ - (void)URLSession:(NSURLSession *)session
9293
auto &headers = context->headers;
9394
NSDictionary *allHeaderFields = [httpResponse allHeaderFields];
9495
for (NSString *headerField in allHeaderFields) {
95-
headers[[headerField UTF8String]] =
96+
std::string header_key = [headerField UTF8String];
97+
std::string header_value =
9698
[[allHeaderFields objectForKey:headerField] UTF8String];
99+
100+
// Splitting the header value by commas (common delimiter)
101+
std::istringstream value_stream(header_value);
102+
std::string single_value;
103+
while (std::getline(value_stream, single_value, ',')) {
104+
headers.emplace(header_key, single_value);
105+
}
97106
}
98107
}
99108

src/linux/http.cc

+8-2
Original file line numberDiff line numberDiff line change
@@ -39,13 +39,19 @@ auto stream_close_callback(GObject *source_object, GAsyncResult *res,
3939

4040
g_object_unref(stream);
4141

42-
std::map<std::string, std::string> headers;
42+
std::multimap<std::string, std::string> headers;
4343
soup_message_headers_foreach(
4444
async_http_context->message->response_headers,
4545
[](const char *name, const char *value, gpointer user_data) {
4646
auto &headers =
4747
*static_cast<std::map<std::string, std::string> *>(user_data);
48-
headers[name] = value;
48+
49+
// Splitting the header value by commas (common delimiter)
50+
std::istringstream value_stream(value);
51+
std::string single_value;
52+
while (std::getline(value_stream, single_value, ',')) {
53+
headers.emplace(name, single_value);
54+
}
4955
},
5056
&headers);
5157

src/win32/http.cc

+10-2
Original file line numberDiff line numberDiff line change
@@ -336,7 +336,15 @@ class HTTPClient {
336336
}
337337

338338
for (DWORD i = 0; i < dwHeadersCount; ++i) {
339-
headers_[pHeaders[i].pszName] = pHeaders[i].pszValue;
339+
std::string header_key = pHeaders[i].pszName;
340+
std::string header_value = pHeaders[i].pszValue;
341+
342+
// Splitting the header value by commas (common delimiter)
343+
std::istringstream value_stream(header_value);
344+
std::string single_value;
345+
while (std::getline(value_stream, single_value, ',')) {
346+
headers_.emplace(header_key, single_value);
347+
}
340348
}
341349
}
342350

@@ -423,7 +431,7 @@ class HTTPClient {
423431
Request request_;
424432

425433
uint16_t status_;
426-
std::map<std::string, std::string> headers_;
434+
std::multimap<std::string, std::string> headers_;
427435
DWORD dwSize_;
428436
std::stringstream body_;
429437
};

test/unit/postman-echo-get.cc

+3-2
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,9 @@ int main() {
3737
exit(EXIT_FAILURE);
3838
}
3939

40-
if (response.headers["Content-Type"] !=
41-
"application/json; charset=utf-8") {
40+
auto content_type = response.headers.find("Content-Type");
41+
if (content_type == response.headers.end() ||
42+
content_type->second != "application/json; charset=utf-8") {
4243
std::cout << "unexpected content type in response headers: ["
4344
<< std::endl;
4445
for (const auto &[key, value] : response.headers) {

0 commit comments

Comments
 (0)