diff --git a/include/benoni/http.h b/include/benoni/http.h index bc7d713..6bb6223 100644 --- a/include/benoni/http.h +++ b/include/benoni/http.h @@ -2,7 +2,7 @@ #define BENONI_HTTP_H_ #include // std::function -#include // std::map +#include // std::multimap #include // std::optional #include // std::string #include // std::variant @@ -27,12 +27,14 @@ class RequestOptions { public: Method method() const { return method_; } const std::string &body() const { return body_; } - const std::map &headers() const { return headers_; } + const std::multimap &headers() const { + return headers_; + } const std::optional &timeout() const { return timeout_; } private: RequestOptions(Method method, std::string body, - std::map headers, + std::multimap headers, std::optional timeout) : method_{method}, body_{std::move(body)}, headers_{std::move(headers)}, timeout_{std::move(timeout)} {} @@ -41,7 +43,7 @@ class RequestOptions { Method method_; std::string body_; - std::map headers_; + std::multimap headers_; std::optional timeout_; }; @@ -58,7 +60,7 @@ class RequestOptionsBuilder { } RequestOptionsBuilder & - set_headers(std::map headers) { + set_headers(std::multimap headers) { headers_ = std::move(headers); return *this; } @@ -76,14 +78,14 @@ class RequestOptionsBuilder { private: Method method_ = Method::GET; std::string body_; - std::map headers_; + std::multimap headers_; std::optional timeout_; }; struct Response { std::string body; uint16_t status; - std::map headers; + std::multimap headers; }; auto request(const std::string &url, RequestOptions options, diff --git a/src/apple/http.mm b/src/apple/http.mm index f65ac3f..e829bcf 100644 --- a/src/apple/http.mm +++ b/src/apple/http.mm @@ -3,6 +3,7 @@ #import #include // std::map +#include // std::istringstream #include // std::string #include // std::variant @@ -11,7 +12,7 @@ struct HTTPTaskContext { std::function)> callback; uint16_t status; - std::map headers; + std::multimap headers; NSMutableData *data; NSStringEncoding encoding; }; @@ -92,8 +93,16 @@ - (void)URLSession:(NSURLSession *)session auto &headers = context->headers; NSDictionary *allHeaderFields = [httpResponse allHeaderFields]; for (NSString *headerField in allHeaderFields) { - headers[[headerField UTF8String]] = + std::string header_key = [headerField UTF8String]; + std::string header_value = [[allHeaderFields objectForKey:headerField] UTF8String]; + + // Splitting the header value by commas (common delimiter) + std::istringstream value_stream(header_value); + std::string single_value; + while (std::getline(value_stream, single_value, ',')) { + headers.emplace(header_key, single_value); + } } } diff --git a/src/linux/http.cc b/src/linux/http.cc index c0f5638..94844ec 100644 --- a/src/linux/http.cc +++ b/src/linux/http.cc @@ -39,13 +39,19 @@ auto stream_close_callback(GObject *source_object, GAsyncResult *res, g_object_unref(stream); - std::map headers; + std::multimap headers; soup_message_headers_foreach( async_http_context->message->response_headers, [](const char *name, const char *value, gpointer user_data) { auto &headers = *static_cast *>(user_data); - headers[name] = value; + + // Splitting the header value by commas (common delimiter) + std::istringstream value_stream(value); + std::string single_value; + while (std::getline(value_stream, single_value, ',')) { + headers.emplace(name, single_value); + } }, &headers); diff --git a/src/win32/http.cc b/src/win32/http.cc index bdfae7f..ae70bef 100644 --- a/src/win32/http.cc +++ b/src/win32/http.cc @@ -336,7 +336,15 @@ class HTTPClient { } for (DWORD i = 0; i < dwHeadersCount; ++i) { - headers_[pHeaders[i].pszName] = pHeaders[i].pszValue; + std::string header_key = pHeaders[i].pszName; + std::string header_value = pHeaders[i].pszValue; + + // Splitting the header value by commas (common delimiter) + std::istringstream value_stream(header_value); + std::string single_value; + while (std::getline(value_stream, single_value, ',')) { + headers_.emplace(header_key, single_value); + } } } @@ -423,7 +431,7 @@ class HTTPClient { Request request_; uint16_t status_; - std::map headers_; + std::multimap headers_; DWORD dwSize_; std::stringstream body_; }; diff --git a/test/unit/postman-echo-get.cc b/test/unit/postman-echo-get.cc index c2b0fda..47ebfd2 100644 --- a/test/unit/postman-echo-get.cc +++ b/test/unit/postman-echo-get.cc @@ -37,8 +37,9 @@ int main() { exit(EXIT_FAILURE); } - if (response.headers["Content-Type"] != - "application/json; charset=utf-8") { + auto content_type = response.headers.find("Content-Type"); + if (content_type == response.headers.end() || + content_type->second != "application/json; charset=utf-8") { std::cout << "unexpected content type in response headers: [" << std::endl; for (const auto &[key, value] : response.headers) {