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() {
auto pos = path.find('?');
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
return CaseInsensitiveMultimap();
}

View file

@ -122,8 +122,18 @@ int main() {
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";
assert(Percent::encode(percent_decoded)==percent_encoded);
assert(Percent::decode(percent_encoded)==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.io_service=std::make_shared<asio::io_service>();

View file

@ -59,7 +59,7 @@ public:
for(auto &chr : value) {
if(chr == ' ')
result += '+';
else if(chr == '!' || chr == '#' || chr == '$' || (chr >= '&' && chr <= ',') || (chr >= '/' && chr <= ';') || chr == '=' || chr=='?' || chr == '@' || chr == '[' || chr == ']')
else if(chr == '!' || chr == '#' || chr == '$' || (chr >= '&' && chr <= ',') || (chr >= '/' && chr <= ';') || chr == '=' || chr == '?' || chr == '@' || chr == '[' || chr == ']')
result += std::string("%") + hex_chars[chr >> 4] + hex_chars[chr & 15];
else
result += chr;
@ -70,7 +70,7 @@ public:
static std::string decode(const std::string &value) {
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) {
auto &chr = value[i];
@ -90,41 +90,61 @@ public:
}
};
/// Returns query keys with percent-decoded values.
inline CaseInsensitiveMultimap parse_query_string(const std::string &query_string) {
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.
static CaseInsensitiveMultimap parse(const std::string &query_string) {
CaseInsensitiveMultimap result;
if(query_string.empty())
return result;
size_t parameter_pos = 0;
size_t parameter_end_pos = -1;
size_t name_pos = 0;
size_t name_end_pos = -1;
size_t value_pos = -1;
for(size_t c = 0; c < query_string.size(); ++c) {
if(query_string[c] == '&') {
auto parameter = query_string.substr(parameter_pos, (parameter_end_pos == std::string::npos ? c : parameter_end_pos) - parameter_pos);
if(!parameter.empty()) {
auto name = query_string.substr(name_pos, (name_end_pos == std::string::npos ? c : name_end_pos) - name_pos);
if(!name.empty()) {
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;
parameter_end_pos = -1;
name_pos = c + 1;
name_end_pos = -1;
value_pos = -1;
}
else if(query_string[c] == '=') {
parameter_end_pos = c;
name_end_pos = c;
value_pos = c + 1;
}
}
if(parameter_pos < query_string.size()) {
auto parameter = query_string.substr(parameter_pos, parameter_end_pos - parameter_pos);
if(!parameter.empty()) {
if(name_pos < query_string.size()) {
auto name = query_string.substr(name_pos, name_end_pos - name_pos);
if(!name.empty()) {
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;
}
};
/// 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