38 const std::size_t scheme_end = s.find(
"://");
39 if (scheme_end == std::string_view::npos || scheme_end == 0)
return std::nullopt;
40 u.scheme = s.substr(0, scheme_end);
41 std::string_view rest = s.substr(scheme_end + 3);
43 std::size_t authority_end = rest.find_first_of(
"/?");
44 std::string_view authority =
45 authority_end == std::string_view::npos ? rest : rest.substr(0, authority_end);
46 std::string_view tail =
47 authority_end == std::string_view::npos ?
"" : rest.substr(authority_end);
48 if (authority.empty())
return std::nullopt;
50 std::string_view port_str;
51 if (authority.front() ==
'[') {
52 const std::size_t close = authority.find(
']');
53 if (close == std::string_view::npos)
return std::nullopt;
54 u.host = authority.substr(1, close - 1);
55 std::string_view after = authority.substr(close + 1);
57 if (after.front() !=
':')
return std::nullopt;
58 port_str = after.substr(1);
61 const std::size_t colon = authority.rfind(
':');
62 if (colon == std::string_view::npos) {
65 u.host = authority.substr(0, colon);
66 port_str = authority.substr(colon + 1);
69 if (u.host.empty())
return std::nullopt;
71 u.tls = (u.scheme ==
"wss" || u.scheme ==
"https");
72 if (port_str.empty()) {
73 u.port = u.tls ? 443 : 80;
76 for (
char c : port_str) {
77 if (c <
'0' || c >
'9')
return std::nullopt;
78 p = p * 10 +
static_cast<std::uint32_t
>(c -
'0');
79 if (p > 65535)
return std::nullopt;
81 if (p == 0)
return std::nullopt;
82 u.port =
static_cast<std::uint16_t
>(p);
85 if (tail.empty() || tail.front() ==
'?') {
87 u.query = tail.empty() ?
"" : tail.substr(1);
89 const std::size_t q = tail.find(
'?');
90 u.path = q == std::string_view::npos ? tail : tail.substr(0, q);
91 u.query = q == std::string_view::npos ?
"" : tail.substr(q + 1);