Add parse_url_query.

This commit is contained in:
levlam 2021-05-24 23:47:18 +03:00
parent 4cc60bbc25
commit 200da2c684
6 changed files with 79 additions and 2 deletions

View File

@ -173,6 +173,40 @@ StringBuilder &operator<<(StringBuilder &sb, const HttpUrl &url) {
return sb;
}
HttpUrlQuery parse_url_query(Slice query) {
size_t path_size = 0;
while (path_size < query.size() && query[path_size] != '?' && query[path_size] != '#') {
path_size++;
}
HttpUrlQuery result;
result.path_ = url_decode(query.substr(0, path_size), false);
if (path_size < query.size() && query[path_size] == '?') {
query = query.substr(path_size + 1);
query.truncate(query.find('#'));
ConstParser parser(query);
while (!parser.data().empty()) {
auto key_value = split(parser.read_till_nofail('&'), '=');
parser.skip_nofail('&');
auto key = url_decode(key_value.first, true);
if (!key.empty()) {
result.args_.emplace_back(std::move(key), url_decode(key_value.second, true));
}
}
CHECK(parser.status().is_ok());
}
return result;
}
Slice HttpUrlQuery::get_arg(Slice key) const {
auto it =
std::find_if(args_.begin(), args_.end(), [&key](const std::pair<string, string> &s) { return s.first == key; });
return it == args_.end() ? Slice() : it->second;
}
string get_url_query_file_name(const string &query) {
Slice query_slice = query;
query_slice.truncate(query.find_first_of("?#"));

View File

@ -11,6 +11,8 @@
#include "td/utils/Status.h"
#include "td/utils/StringBuilder.h"
#include <utility>
namespace td {
class HttpUrl {
@ -41,6 +43,16 @@ Result<HttpUrl> parse_url(Slice url,
StringBuilder &operator<<(StringBuilder &sb, const HttpUrl &url);
class HttpUrlQuery {
public:
string path_;
vector<std::pair<string, string>> args_;
Slice get_arg(Slice key) const;
};
HttpUrlQuery parse_url_query(Slice query);
string get_url_query_file_name(const string &query);
string get_url_file_name(Slice url);

View File

@ -166,6 +166,13 @@ size_t url_decode(Slice from, MutableSlice to, bool decode_plus_sign_as_space) {
return to_i;
}
string url_decode(Slice from, bool decode_plus_sign_as_space) {
string to;
to.resize(from.size());
to.resize(url_decode(from, to, decode_plus_sign_as_space));
return to;
}
MutableSlice url_decode_inplace(MutableSlice str, bool decode_plus_sign_as_space) {
size_t result_size = url_decode(str, str, decode_plus_sign_as_space);
str.truncate(result_size);

View File

@ -263,6 +263,8 @@ string url_encode(Slice data);
size_t url_decode(Slice from, MutableSlice to, bool decode_plus_sign_as_space);
string url_decode(Slice from, bool decode_plus_sign_as_space);
MutableSlice url_decode_inplace(MutableSlice str, bool decode_plus_sign_as_space);
// run-time checked narrowing cast (type conversion):

View File

@ -8,6 +8,8 @@
#include "td/utils/HttpUrl.h"
#include "td/utils/tests.h"
#include <utility>
static void test_get_url_query_file_name(const char *prefix, const char *suffix, const char *file_name) {
auto path = td::string(prefix) + td::string(file_name) + td::string(suffix);
ASSERT_STREQ(file_name, td::get_url_query_file_name(path));
@ -26,3 +28,24 @@ TEST(HttpUrl, get_url_query_file_name) {
test_get_url_query_file_name("/", suffix, "\\a\\1\\2\\3\\a\\s\\a\\das");
}
}
static void test_parse_url_query(const td::string &query, const td::string &path,
const td::vector<std::pair<td::string, td::string>> &args) {
for (auto hash : {"", "#", "#?t=1", "#t=1&a=b"}) {
auto url_query = td::parse_url_query(query + hash);
ASSERT_STREQ(path, url_query.path_);
ASSERT_EQ(args, url_query.args_);
}
}
TEST(HttpUrl, parce_url_query) {
test_parse_url_query("", "", {});
test_parse_url_query("a", "a", {});
test_parse_url_query("/a/b/c/", "/a/b/c/", {});
test_parse_url_query("/a/b/?c/", "/a/b/", {{"c/", ""}});
test_parse_url_query("?", "", {});
test_parse_url_query("???", "", {{"??", ""}});
test_parse_url_query("?a=b=c=d?e=f=g=h&x=y=z?d=3&", "", {{"a", "b=c=d?e=f=g=h"}, {"x", "y=z?d=3"}});
test_parse_url_query("c?&&&a=b", "c", {{"a", "b"}});
test_parse_url_query("c?&&&=b", "c", {});
}

View File

@ -4,12 +4,11 @@
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#include "td/utils/tests.h"
#include "td/utils/JsonBuilder.h"
#include "td/utils/logging.h"
#include "td/utils/Slice.h"
#include "td/utils/StringBuilder.h"
#include "td/utils/tests.h"
#include <utility>