virthttp  0.0
libvirt http interface
urlparser.hpp
Go to the documentation of this file.
1 //
2 // Created by hugo on 07.06.19.
3 //
4 
5 #pragma once
6 
7 #include <algorithm>
8 #include <cstring>
9 #include <string_view>
10 #include <vector>
11 #include <ctll.hpp>
12 #include <ctre.hpp>
13 #include <flatmap.hpp>
14 
15 constexpr auto target_pattern = ctll::fixed_string{R"(^($|/[^#?\s]+)?(.*?)?(#[A-Za-z_\-]+)?$)"};
16 
17 static constexpr auto target_match(std::string_view sv) noexcept { return ctre::match<target_pattern>(sv); }
18 
19 constexpr auto target_queries = ctll::fixed_string{R"([&;]?([^=&;]+)=?([^=&;]*))"};
20 constexpr auto target_path_parts = ctll::fixed_string{R"(/([^/]+))"};
21 
22 #ifndef HE_WA_CTRE_URL_SPLIT
23 constexpr auto url_pattern = ctll::fixed_string{R"(^(?:(http[s]?|ftp)://)?([^/]+?)(?::(\d+))?(?:$|/)([^#?\s]+)?(.*?)?(#[A-Za-z_\-]+)?$)"};
24 
25 static constexpr auto url_match(std::string_view sv) noexcept { return ctre::match<url_pattern>(sv); }
26 
27 #else
28 // https://godbolt.org/#z:OYLghAFBqd5QCxAYwPYBMCmBRdBLAF1QCcAaPECAKxAEZSAbAQwDtRkBSAJgCFufSAZ1QBXYskwgA5NwDMeFsgYisAag6yAwkwbAShBAFsN2DgAYAgnIVKVmdVuQEGDAHQIADh5PmrXeYrKahqaTsSY7l4%2BltaBdg6aggTECsAA%2BgBueJgA7tF%2BAbbBWhmYTiT5sUX2IXioSeFMxrKmMf42QTVaBCIeDJiVliKCqaosTZiCHkwSqknoICAMhJjEOoIafDGWAPQ7qmgsSZgAHh7EqkwiRKrTBASrLA4AIgfODIsAZngnmOhpDVSHAA7DwAErcLgQDgAVmw0NkADFKAh7t4YTwNjDnhpESDNJ8CB4AJQgPbE3HQjGw7A7WE43i44kI5GUWGadAgnj0GEg57EilIlkgAAk%2BJ2zNhfDhclx7KxDJ4gsREFcAComZTZRiLABaABaTF1AC80uzdfT%2BMqRRSuFw%2BZtfIdjmcLlcbncHsQWLQXm8XF8fn8AckgaCIXaqfDcSi0VKFXLgQSiaTyVrqXCdiBLbxma4rTbIQ7ZFsLM6Hq7LtdULcmPdHlw/U4AyBvr9/oC2FyI1CacK2TCOVblcKxUmJVTpaZ/HLBwnc5T1ZqhdqeHrDSazYOLdirbjC3bi6WFARVIYmAoIBTQb5VHfVHsDqgjhXzlWbuFBE3kpIQOeCMgCAhJ6jwmNCdqokSZI7AwqDIDoCD1AQIAABxmChtAwXgABGWTEAQOzoKg54KBsdqCBkgqlvecwEAsICdsAtHEFykKQR4gjQYhSTjIYkgoShAAsgk7HcCA7EQMFwbiACOIirAAnhozysGRABsGRMCxsjPJpDByJ8azAEWwI4iWt73u6Nafr6ylvOEiz/oBwF1l6PpgfMiyMZk2R5KCDR8lRFl3lZ6gYoIaQ6Aw9BzACgGYHxpCxdxBBJRFLCnAQ9J%2BjZjrbBYNGhZ%2BjZ2WEv5OUBWggd69otBA6WZa4RA%2BbkV5BZYNGPqF8aRS4aVxQgCWYP1KX9R4JCpbFYn9XJin9YZTDAHxLBZdiOWTHlBWWdWYWYr1DD9TFEVcP1sj9YJ2V2cVm00Z5KCiKeIQhKoEDYagqAMMS10dfeT1aKoYAyIOLCAwkz0RYI8V8U1qAtTkV7BWD/2A%2ByINSEjmjJUhMNwwjP13n9mMo8DoOE7FtA41krUUvjGMA0Dmho3Tx2U75eNbQTWjPcTjOk1z/0RbIrPU4jZM80zZMRYJwvw8SzN0YsmAsOg%2BnmflfJSMSjDSDCUikCw0hmHrqDSJo/D8HMojiDU/i0HryFSEbAqkAA1iAMJmK4tCCTCgkAJy0LQXC0MCMJcMCana1Igl6wbjvG9IeucWYpAO07pBwLAMCIPdhgeHg/RkBQEBoHnBerCAwAoWd3wMF6nGvYbevYQoWkKdIdukKXy0EAA8iwDDt/HpBYOebD9E3I94OETh4KUnHD6cZTXJIw8npgHzD8s2FrMQCmaBgq%2Bd6GhhN1rzBsCg5u8IwOGcbAvGSGVpClMQIDJCILAu87qAeAQdRHGkLqeYylOCMl4CHVQupe6yCTlbCQdBz461jpPE2UgTgoTUrqNSglVDAGQMgVQKFXCyBergQgJB1C2ySgfMuhcqGyFoHLM24CeD2zPlrN2shPZ%2BzMAHYEftBKML9ihO0fsYRRxjqQU%2BHt9aoMTkIEAKc06awztnCASBS750LuQSgWjy5vyUKwKuZgU613rpQbCk8W7jD3h3PW3clZ9wHkPI2I8ErGInsPfAM9/7z0nkvZAK9J7r03m47eu996H3sanFIp8pB23PsYq%2BrDb7YXvlAR%2BKAfwvwrh/L%2BP8/4AIXsAuioDr7cmBFAmBcCxAIKYVHXWcjh5oIwVgnBBwL5MWIZ7MwZD8BEAuHIGKtDtGrAYVwZhFT2Hx2doNJgWA35XkkXrGRKc45uLQUnJRqcOGuxAFwNSrgBLAjMFwQSKFxE4P4WdTesDmmbIUSorWmcoDqKQA9Dw1xdEl2ImMt%2B9A/gUIBaQHIawPD2KQVIJpGyE4yFtqoHIBhVBtOwbg/BhDiH3OeZwg5XBXB%2BzUsCC5sgRFcBhCIswocVnSPdus%2BRUhtnKLPmo%2BAGiQCfO%2BcXfRhcDmkCBYMugoLwWQsaSglp0g5CNiRQQBAKLMFos6cYohrhekzKdlreZizKBQqkWsh5cKmW7Nmbiu0BKiUkrJRStC1K7niseYy41Gqo5cHtYap1mstavxGM%2BEAgkgA
29 [[deprecated]] constexpr auto url_pat_split1 = ctll::fixed_string{R"(^(?:(http[s]?|ftp)://)?([^/:]+)(.+)$)"};
30 [[deprecated]] constexpr auto url_pat_split2 = ctll::fixed_string{R"(^(?::(\d+))?(?:$|/)([^#?\s]+)?(.*?)?(#[A-Za-z_\-]+)?$)"};
31 
32 [[deprecated]] static constexpr auto url_match_split1(std::string_view sv) noexcept { return ctre::match<url_pat_split1>(sv); }
33 [[deprecated]] static constexpr auto url_match_split2(std::string_view sv) noexcept { return ctre::match<url_pat_split2>(sv); }
34 #endif
35 
36 class TargetParser {
37  protected:
38  std::string_view url{};
39  std::string_view path{};
40 
41  std::vector<std::string_view> path_parts = {};
42  flatmap<std::string_view, std::string_view> queries = {};
43 
44  constexpr std::string_view match() noexcept {
45  auto res = target_match(url);
46  auto [s_all, s_path, s_query, s_fragment] = res;
47  path = s_path;
48  return s_query;
49  }
50 
51  void parse_queries(std::string_view sv_query) noexcept {
52  queries.clear();
53  for (auto [s_match, s_val] : ctre::range<target_path_parts>(path))
54  path_parts.emplace_back(s_val);
55  if (sv_query.length() > 0)
56  sv_query.remove_prefix(1); // strip leading '?'
57  for (auto [s_match, s_name, s_value] : ctre::range<target_queries>(sv_query))
58  queries.emplace(s_name, s_value);
59  }
60 
61  void parse() noexcept { parse_queries(match()); }
62 
63  public:
64  constexpr TargetParser() = default;
65 
66  explicit TargetParser(std::string_view url) : url(url) { parse(); }
67 
68  void setURL(const char* v) {
69  url = v;
70  parse();
71  }
72 
73  void setURL(std::string_view sv) {
74  url = sv;
75  parse();
76  }
77 
78  [[nodiscard]] constexpr std::string_view getPath() const noexcept { return path; }
79 
80  [[nodiscard]] constexpr std::string_view getURL() const noexcept { return url; }
81 
82  [[nodiscard]] constexpr const flatmap<std::string_view, std::string_view>& getQueries() const noexcept { return queries; }
83  [[nodiscard]] constexpr const std::vector<std::string_view>& getPathParts() const noexcept { return path_parts; }
84 
85  [[nodiscard]] constexpr std::string_view operator[](std::string_view key) const noexcept {
86  if (auto it = queries.find(key); it != queries.end())
87  return it->second;
88  return {};
89  }
90 
91  [[nodiscard]] constexpr std::optional<bool> getBool(std::string_view key) const noexcept {
92  const auto val = (*this)[key];
93  if (val.data() == nullptr)
94  return std::nullopt;
95  if (val.empty())
96  return true;
97  if (val == "1" || val == "yes" || val == "true")
98  return true;
99  if (val == "0" || val == "no" || val == "false")
100  return false;
101  return std::nullopt;
102  }
103 };
104 
105 class URLParser : public TargetParser {
106  private:
107  std::string_view scheme;
108  std::string_view host;
109  unsigned short port{0};
110 
111  void parse_all() noexcept {
112  queries.clear();
113 #ifndef HE_WA_CTRE_URL_SPLIT
114  auto [s_all, s_scheme, s_host, s_port, s_path, s_query, s_fragment] = url_match(url);
115 #else
116  auto [s_all1, s_scheme, s_host, s_next] = url_match_split1(url);
117  auto [s_all2, s_port, s_path, s_query, s_fragment] = url_match_split2(s_next.to_view());
118 #endif
119  scheme = s_scheme;
120  host = s_host;
121  if (s_port)
122  port = std::strtoul(s_port.to_view().data(), nullptr, 10);
123  path = s_path;
124  parse_queries(s_query);
125  }
126 
127  public:
128  explicit URLParser(const char* uri) noexcept { setURL(uri); }
129 
130  explicit URLParser(std::string_view uri) noexcept { setURL(uri); }
131 
132  constexpr URLParser() = default;
133 
134  URLParser(const URLParser&) = default;
135 
136  URLParser(URLParser&&) noexcept = default;
137 
138  ~URLParser() noexcept = default;
139 
140  URLParser& operator=(const URLParser&) = default;
141 
142  URLParser& operator=(URLParser&&) = default;
143 
144  void setURL(const char* v) {
145  url = v;
146  parse_all();
147  }
148 
149  void setURL(std::string_view sv) {
150  url = sv;
151  parse_all();
152  }
153 
154  [[nodiscard]] constexpr std::string_view getScheme() const noexcept { return scheme; }
155 
156  [[nodiscard]] constexpr std::string_view getHost() const noexcept { return host; }
157 
161  [[nodiscard]] constexpr unsigned short getPort() const noexcept { return port; }
162 };
163 
164 struct CSVIterator {
165  std::string_view sv;
166 
167  constexpr CSVIterator& operator++() noexcept {
168  const auto it = cexpr::find(sv.begin(), sv.end(), ',');
169  sv.remove_prefix(it != sv.end() ? std::distance(sv.begin(), it) + 1 : sv.size());
170  return *this;
171  }
172  [[nodiscard]] constexpr std::string_view operator*() const noexcept {
173  auto csv = sv;
174  while (!csv.empty() && csv[0] == ',')
175  csv.remove_prefix(1);
176  const auto it = cexpr::find(csv.begin(), csv.end(), ',');
177  return sv.substr(0, std::distance(sv.begin(), it));
178  }
179  [[nodiscard]] constexpr bool operator==(const CSVIterator& oth) const noexcept { return sv == oth.sv; }
180  [[nodiscard]] constexpr bool operator!=(const CSVIterator& oth) const noexcept { return sv != oth.sv; }
181  [[nodiscard]] constexpr CSVIterator end() const noexcept { return {sv.substr(sv.size(), 0)}; }
182 };
URLParser(std::string_view uri) noexcept
Definition: urlparser.hpp:130
std::string_view url
Definition: urlparser.hpp:38
void parse() noexcept
Definition: urlparser.hpp:61
flatmap< std::string_view, std::string_view > queries
Definition: urlparser.hpp:42
constexpr const flatmap< std::string_view, std::string_view > & getQueries() const noexcept
Definition: urlparser.hpp:82
constexpr std::string_view match() noexcept
Definition: urlparser.hpp:44
constexpr std::string_view getPath() const noexcept
Definition: urlparser.hpp:78
Definition: urlparser.hpp:164
Definition: urlparser.hpp:105
static constexpr auto url_match(std::string_view sv) noexcept
Definition: urlparser.hpp:25
TargetParser(std::string_view url)
Definition: urlparser.hpp:66
std::string_view path
Definition: urlparser.hpp:39
constexpr auto url_pattern
Definition: urlparser.hpp:23
URLParser(const char *uri) noexcept
Definition: urlparser.hpp:128
constexpr bool operator!=(const CSVIterator &oth) const noexcept
Definition: urlparser.hpp:180
constexpr std::string_view getScheme() const noexcept
Definition: urlparser.hpp:154
constexpr std::string_view operator[](std::string_view key) const noexcept
Definition: urlparser.hpp:85
void setURL(const char *v)
Definition: urlparser.hpp:68
constexpr std::string_view operator*() const noexcept
Definition: urlparser.hpp:172
constexpr CSVIterator & operator++() noexcept
Definition: urlparser.hpp:167
void parse_queries(std::string_view sv_query) noexcept
Definition: urlparser.hpp:51
constexpr auto target_path_parts
Definition: urlparser.hpp:20
constexpr auto target_queries
Definition: urlparser.hpp:19
std::vector< std::string_view > path_parts
Definition: urlparser.hpp:41
constexpr const std::vector< std::string_view > & getPathParts() const noexcept
Definition: urlparser.hpp:83
constexpr InputIt find(InputIt first, InputIt last, const T &value)
Definition: cexpr_algs.hpp:4
constexpr std::string_view getHost() const noexcept
Definition: urlparser.hpp:156
void setURL(std::string_view sv)
Definition: urlparser.hpp:149
Definition: urlparser.hpp:36
static constexpr auto target_match(std::string_view sv) noexcept
Definition: urlparser.hpp:17
constexpr CSVIterator end() const noexcept
Definition: urlparser.hpp:181
constexpr unsigned short getPort() const noexcept
Definition: urlparser.hpp:161
std::string_view sv
Definition: urlparser.hpp:165
constexpr TargetParser()=default
constexpr auto target_pattern
Definition: urlparser.hpp:15
constexpr bool operator==(const CSVIterator &oth) const noexcept
Definition: urlparser.hpp:179
constexpr std::optional< bool > getBool(std::string_view key) const noexcept
Definition: urlparser.hpp:91
void setURL(std::string_view sv)
Definition: urlparser.hpp:73
constexpr std::string_view getURL() const noexcept
Definition: urlparser.hpp:80
void setURL(const char *v)
Definition: urlparser.hpp:144