Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use multimap instead of map for headers #7

Merged
merged 1 commit into from
Apr 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 9 additions & 7 deletions include/benoni/http.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
#define BENONI_HTTP_H_

#include <functional> // std::function
#include <map> // std::map
#include <map> // std::multimap
#include <optional> // std::optional
#include <string> // std::string
#include <variant> // std::variant
Expand All @@ -27,12 +27,14 @@ class RequestOptions {
public:
Method method() const { return method_; }
const std::string &body() const { return body_; }
const std::map<std::string, std::string> &headers() const { return headers_; }
const std::multimap<std::string, std::string> &headers() const {
return headers_;
}
const std::optional<int> &timeout() const { return timeout_; }

private:
RequestOptions(Method method, std::string body,
std::map<std::string, std::string> headers,
std::multimap<std::string, std::string> headers,
std::optional<int> timeout)
: method_{method}, body_{std::move(body)}, headers_{std::move(headers)},
timeout_{std::move(timeout)} {}
Expand All @@ -41,7 +43,7 @@ class RequestOptions {

Method method_;
std::string body_;
std::map<std::string, std::string> headers_;
std::multimap<std::string, std::string> headers_;
std::optional<int> timeout_;
};

Expand All @@ -58,7 +60,7 @@ class RequestOptionsBuilder {
}

RequestOptionsBuilder &
set_headers(std::map<std::string, std::string> headers) {
set_headers(std::multimap<std::string, std::string> headers) {
headers_ = std::move(headers);
return *this;
}
Expand All @@ -76,14 +78,14 @@ class RequestOptionsBuilder {
private:
Method method_ = Method::GET;
std::string body_;
std::map<std::string, std::string> headers_;
std::multimap<std::string, std::string> headers_;
std::optional<int> timeout_;
};

struct Response {
std::string body;
uint16_t status;
std::map<std::string, std::string> headers;
std::multimap<std::string, std::string> headers;
};

auto request(const std::string &url, RequestOptions options,
Expand Down
13 changes: 11 additions & 2 deletions src/apple/http.mm
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#import <Foundation/Foundation.h>

#include <map> // std::map
#include <sstream> // std::istringstream
#include <string> // std::string
#include <variant> // std::variant

Expand All @@ -11,7 +12,7 @@
struct HTTPTaskContext {
std::function<void(std::variant<std::string, benoni::Response>)> callback;
uint16_t status;
std::map<std::string, std::string> headers;
std::multimap<std::string, std::string> headers;
NSMutableData *data;
NSStringEncoding encoding;
};
Expand Down Expand Up @@ -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);
}
}
}

Expand Down
10 changes: 8 additions & 2 deletions src/linux/http.cc
Original file line number Diff line number Diff line change
Expand Up @@ -39,13 +39,19 @@ auto stream_close_callback(GObject *source_object, GAsyncResult *res,

g_object_unref(stream);

std::map<std::string, std::string> headers;
std::multimap<std::string, std::string> headers;
soup_message_headers_foreach(
async_http_context->message->response_headers,
[](const char *name, const char *value, gpointer user_data) {
auto &headers =
*static_cast<std::map<std::string, std::string> *>(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);

Expand Down
12 changes: 10 additions & 2 deletions src/win32/http.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}
}

Expand Down Expand Up @@ -423,7 +431,7 @@ class HTTPClient {
Request request_;

uint16_t status_;
std::map<std::string, std::string> headers_;
std::multimap<std::string, std::string> headers_;
DWORD dwSize_;
std::stringstream body_;
};
Expand Down
5 changes: 3 additions & 2 deletions test/unit/postman-echo-get.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down