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
fix #292 change get_args to return mutliple values per key #293
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -105,20 +105,31 @@ const http::header_view_map http_request::get_cookies() const { | |
} | ||
|
||
std::string_view http_request::get_arg(std::string_view key) const { | ||
std::map<std::string, std::string>::const_iterator it = cache->unescaped_args.find(std::string(key)); | ||
auto const it = cache->unescaped_args.find(std::string(key)); | ||
|
||
if (it != cache->unescaped_args.end()) { | ||
return it->second; | ||
return it->second.front(); | ||
} | ||
|
||
return get_connection_value(key, MHD_GET_ARGUMENT_KIND); | ||
} | ||
|
||
static void fill_arg_view_map(http::arg_view_map *arguments, const http::arg_map& cached_map) { | ||
for (const auto& kv : cached_map) { | ||
std::vector<std::string_view> vec; | ||
vec.reserve(kv.second.size()); | ||
for (const auto& value : kv.second) { | ||
vec.push_back(value); | ||
} | ||
arguments->emplace(std::string_view(kv.first), std::move(vec)); | ||
} | ||
} | ||
|
||
const http::arg_view_map http_request::get_args() const { | ||
http::arg_view_map arguments; | ||
|
||
if (!cache->unescaped_args.empty()) { | ||
arguments.insert(cache->unescaped_args.begin(), cache->unescaped_args.end()); | ||
fill_arg_view_map(&arguments, cache->unescaped_args); | ||
return arguments; | ||
} | ||
|
||
|
@@ -128,7 +139,7 @@ const http::arg_view_map http_request::get_args() const { | |
|
||
MHD_get_connection_values(underlying_connection, MHD_GET_ARGUMENT_KIND, &build_request_args, reinterpret_cast<void*>(&aa)); | ||
|
||
arguments.insert(cache->unescaped_args.begin(), cache->unescaped_args.end()); | ||
fill_arg_view_map(&arguments, cache->unescaped_args); | ||
|
||
return arguments; | ||
} | ||
|
@@ -155,7 +166,13 @@ MHD_Result http_request::build_request_args(void *cls, enum MHD_ValueKind kind, | |
std::string value = ((arg_value == nullptr) ? "" : arg_value); | ||
|
||
http::base_unescaper(&value, aa->unescaper); | ||
(*aa->arguments)[key] = value; | ||
auto existing_iter = aa->arguments->find(key); | ||
if (existing_iter != aa->arguments->end()) { | ||
// Key exists, add value to collection instead of overwriting previous value. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Whether the key exists or not, I think this if/else equivalent to just:
|
||
existing_iter->second.push_back(value); | ||
} else { | ||
(*aa->arguments)[key] = {value}; | ||
} | ||
return MHD_YES; | ||
} | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -173,8 +173,8 @@ class http_request { | |
|
||
/** | ||
* Method used to get a specific argument passed with the request. | ||
* @param ket the specific argument to get the value from | ||
* @return the value of the arg. | ||
* @param key the specific argument to get the value from | ||
* @return the value of the first arg matching the key. | ||
**/ | ||
std::string_view get_arg(std::string_view key) const; | ||
|
||
|
@@ -298,7 +298,12 @@ class http_request { | |
* @param value The value assumed by the argument | ||
**/ | ||
void set_arg(const std::string& key, const std::string& value) { | ||
cache->unescaped_args[key] = value.substr(0, content_size_limit); | ||
auto existing_iter = cache->unescaped_args.find(key); | ||
if (existing_iter != cache->unescaped_args.end()) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Similarly I think this is also just |
||
existing_iter->second.push_back(value.substr(0, content_size_limit)); | ||
} else { | ||
cache->unescaped_args[key] = {value.substr(0, content_size_limit)}; | ||
} | ||
} | ||
|
||
/** | ||
|
@@ -308,7 +313,13 @@ class http_request { | |
* @param size The size in number of char of the value parameter. | ||
**/ | ||
void set_arg(const char* key, const char* value, size_t size) { | ||
cache->unescaped_args[key] = std::string(value, std::min(size, content_size_limit)); | ||
auto value_str = std::string(value, std::min(size, content_size_limit)); | ||
auto existing_iter = cache->unescaped_args.find(key); | ||
if (existing_iter != cache->unescaped_args.end()) { | ||
existing_iter->second.push_back(value_str); | ||
} else { | ||
cache->unescaped_args[key] = {value_str}; | ||
} | ||
} | ||
|
||
/** | ||
|
@@ -365,10 +376,13 @@ class http_request { | |
* Method used to set all arguments of the request. | ||
* @param args The args key-value map to set for the request. | ||
**/ | ||
void set_args(const std::map<std::string, std::string>& args) { | ||
std::map<std::string, std::string>::const_iterator it; | ||
for (it = args.begin(); it != args.end(); ++it) { | ||
this->cache->unescaped_args[it->first] = it->second.substr(0, content_size_limit); | ||
void set_args(const std::map<std::string, std::vector<std::string>>& args) { | ||
for (auto it = args.begin(); it != args.end(); ++it) { | ||
auto value_vec = it->second; | ||
std::transform(value_vec.begin(), value_vec.end(), value_vec.begin(), [this](const std::string& s) { | ||
return s.substr(0, content_size_limit); | ||
}); | ||
this->cache->unescaped_args[it->first] = std::move(value_vec); | ||
} | ||
} | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since get_arg() now returns only the first matching item (which does keep the API the same), should there also be a get_args() method that returns a
std::span<const std::string>
or whatever type makes the least memory allocations? IIRC aspan<const T>
can be made from avector<T>
implicitly.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
afaik span is C++20, so this would require bumping the min version from 17.