Added QueryString class with create and parse functions to utility.hpp

This commit is contained in:
eidheim 2017-06-25 16:43:49 +02:00
commit 98d9617244
3 changed files with 61 additions and 31 deletions

View file

@ -165,7 +165,7 @@ namespace SimpleWeb {
CaseInsensitiveMultimap parse_query_string() { CaseInsensitiveMultimap parse_query_string() {
auto pos = path.find('?'); auto pos = path.find('?');
if (pos != std::string::npos && pos + 1 < path.size()) if (pos != std::string::npos && pos + 1 < path.size())
return SimpleWeb::parse_query_string(path.substr(pos + 1)); return SimpleWeb::QueryString::parse(path.substr(pos + 1));
else else
return CaseInsensitiveMultimap(); return CaseInsensitiveMultimap();
} }

View file

@ -122,8 +122,18 @@ int main() {
auto percent_decoded="testing æøå !#$&'()*+,/:;=?@[]"; auto percent_decoded="testing æøå !#$&'()*+,/:;=?@[]";
auto percent_encoded="testing+æøå+%21%23%24%26%27%28%29%2A%2B%2C%2F%3A%3B%3D%3F%40%5B%5D"; auto percent_encoded="testing+æøå+%21%23%24%26%27%28%29%2A%2B%2C%2F%3A%3B%3D%3F%40%5B%5D";
assert(Percent::encode(percent_decoded)==percent_encoded); assert(Percent::encode(percent_decoded)==percent_encoded);
assert(Percent::decode(percent_encoded)==percent_decoded);
assert(Percent::decode(Percent::encode(percent_decoded))==percent_decoded); assert(Percent::decode(Percent::encode(percent_decoded))==percent_decoded);
SimpleWeb::CaseInsensitiveMultimap fields={{"test1", "æøå"}, {"test2", "!#$&'()*+,/:;=?@[]"}};
auto query_string1="test1=æøå&test2=%21%23%24%26%27%28%29%2A%2B%2C%2F%3A%3B%3D%3F%40%5B%5D";
auto query_string2="test2=%21%23%24%26%27%28%29%2A%2B%2C%2F%3A%3B%3D%3F%40%5B%5D&test1=æøå";
auto query_string_result=QueryString::create(fields);
assert(query_string_result==query_string1 || query_string_result==query_string2);
auto fields_result1=QueryString::parse(query_string1);
auto fields_result2=QueryString::parse(query_string2);
assert(fields_result1==fields_result2 && fields_result1==fields);
ServerTest serverTest; ServerTest serverTest;
serverTest.io_service=std::make_shared<asio::io_service>(); serverTest.io_service=std::make_shared<asio::io_service>();

View file

@ -70,7 +70,7 @@ public:
static std::string decode(const std::string &value) { static std::string decode(const std::string &value) {
std::string result; std::string result;
result.reserve((value.size() + 2) / 3); // minimum size of result result.reserve(value.size() / 3 + (value.size() % 3)); // minimum size of result
for(size_t i = 0; i < value.size(); ++i) { for(size_t i = 0; i < value.size(); ++i) {
auto &chr = value[i]; auto &chr = value[i];
@ -90,42 +90,62 @@ public:
} }
}; };
class QueryString {
public:
static std::string create(const CaseInsensitiveMultimap &fields) {
std::string result;
bool first = true;
for(auto &field : fields) {
result += (!first ? "&" : "") + field.first + '=' + Percent::encode(field.second);
first = false;
}
return result;
}
/// Returns query keys with percent-decoded values. /// Returns query keys with percent-decoded values.
inline CaseInsensitiveMultimap parse_query_string(const std::string &query_string) { static CaseInsensitiveMultimap parse(const std::string &query_string) {
CaseInsensitiveMultimap result; CaseInsensitiveMultimap result;
if(query_string.empty()) if(query_string.empty())
return result; return result;
size_t parameter_pos = 0; size_t name_pos = 0;
size_t parameter_end_pos = -1; size_t name_end_pos = -1;
size_t value_pos = -1; size_t value_pos = -1;
for(size_t c = 0; c < query_string.size(); ++c) { for(size_t c = 0; c < query_string.size(); ++c) {
if(query_string[c] == '&') { if(query_string[c] == '&') {
auto parameter = query_string.substr(parameter_pos, (parameter_end_pos == std::string::npos ? c : parameter_end_pos) - parameter_pos); auto name = query_string.substr(name_pos, (name_end_pos == std::string::npos ? c : name_end_pos) - name_pos);
if(!parameter.empty()) { if(!name.empty()) {
auto value = value_pos == std::string::npos ? std::string() : query_string.substr(value_pos, c - value_pos); auto value = value_pos == std::string::npos ? std::string() : query_string.substr(value_pos, c - value_pos);
result.emplace(std::move(parameter), Percent::decode(value)); result.emplace(std::move(name), Percent::decode(value));
} }
parameter_pos = c + 1; name_pos = c + 1;
parameter_end_pos = -1; name_end_pos = -1;
value_pos = -1; value_pos = -1;
} }
else if(query_string[c] == '=') { else if(query_string[c] == '=') {
parameter_end_pos = c; name_end_pos = c;
value_pos = c + 1; value_pos = c + 1;
} }
} }
if(parameter_pos < query_string.size()) { if(name_pos < query_string.size()) {
auto parameter = query_string.substr(parameter_pos, parameter_end_pos - parameter_pos); auto name = query_string.substr(name_pos, name_end_pos - name_pos);
if(!parameter.empty()) { if(!name.empty()) {
auto value = value_pos >= query_string.size() ? std::string() : query_string.substr(value_pos); auto value = value_pos >= query_string.size() ? std::string() : query_string.substr(value_pos);
result.emplace(std::move(parameter), Percent::decode(value)); result.emplace(std::move(name), Percent::decode(value));
} }
} }
return result; return result;
} }
};
/// Returns query keys with percent-decoded values.
DEPRECATED inline CaseInsensitiveMultimap parse_query_string(const std::string &query_string) {
return QueryString::parse(query_string);
}
} // namespace SimpleWeb } // namespace SimpleWeb
#endif // SIMPLE_WEB_SERVER_UTILITY_HPP #endif // SIMPLE_WEB_SERVER_UTILITY_HPP