18 std::ostringstream escaped;
22 for (
const unsigned char c : input) {
23 if (std::isalnum(c) || c ==
'-' || c ==
'_' || c ==
'.' || c ==
'~') {
26 escaped << '%' << std::uppercase << std::setw(2) << static_cast<int>(c) << std::nouppercase;
36 decoded.reserve(input.size());
38 for (
size_t i = 0; i < input.size(); ++i) {
39 if (input[i] ==
'%' && i + 2 < input.size()) {
40 const auto hex = input.substr(i + 1, 2);
41 const char ch =
static_cast<char>(std::stoi(hex,
nullptr, 16));
44 }
else if (input[i] ==
'+') {
58 std::optional<std::string>
host;
59 std::optional<std::string>
path;
61 std::optional<std::string>
query;
68 throw std::invalid_argument(
"Can't have 'scheme' or 'authority' and 'host' or 'hostpath' option");
72 throw std::invalid_argument(
"Can't have 'host' and 'hostpath' option");
76 throw std::invalid_argument(
"Can't have 'path' and 'hostpath' option");
81 result += *options.
scheme +
":";
87 result += *options.
host;
90 result += *options.
path;
96 result +=
"?" + *options.
query;
108 explicit URI(
const std::string& uri)
110 static const std::regex regex(R
"(^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?)");
112 std::regex_match(uri, match, regex);
115 path = match[5].str();
116 query = match[7].str();
130 if (!
query.empty()) {
131 result +=
"?" +
query;
139 [[nodiscard]] std::map<std::string, std::string>
getQuery()
const
141 std::map<std::string, std::string> result;
148 while (std::getline(stream, kv,
'&')) {
149 const size_t sep = kv.find(
'=');
150 if (sep == std::string::npos) {
153 result[kv.substr(0, sep)] = kv.substr(sep + 1);
160 void setQuery(
const std::map<std::string, std::string>& params)
163 for (
const auto& [key, value] : params) {
std::string toString() const
std::map< std::string, std::string > getQuery() const
URI(const std::string &uri)
void setQuery(const std::map< std::string, std::string > ¶ms)
std::string createURI(const URIOptions &options)
std::string decodeURIComponent(const std::string &input)
std::string encodeURIComponent(const std::string &input)
std::optional< std::string > hostpath
std::optional< std::string > authority
std::optional< std::string > scheme
std::optional< std::string > path
std::optional< std::string > query
std::optional< std::string > host
std::optional< std::string > fragment