16 if (a_Scheme ==
"http")
20 else if (a_Scheme ==
"https")
24 else if (a_Scheme ==
"ftp")
28 else if (a_Scheme ==
"mailto")
40 const AString & a_AuthorityPart,
55 auto idxLastAtSign = a_AuthorityPart.find_last_of(
'@');
56 auto credPart = (idxLastAtSign == AString::npos) ?
AString() : a_AuthorityPart.substr(0, idxLastAtSign);
57 auto srvrPart = (idxLastAtSign == AString::npos) ? a_AuthorityPart : a_AuthorityPart.substr(idxLastAtSign + 1);
60 auto idxCredColon = credPart.find(
':');
61 a_Username = credPart.substr(0, idxCredColon);
62 a_Password = (idxCredColon == AString::npos) ?
AString() : credPart.substr(idxCredColon + 1);
69 return std::make_pair(
true,
AString());
71 if (srvrPart[0] ==
'[')
74 auto idxClosingBracket = srvrPart.find(
']');
75 if (idxClosingBracket == AString::npos)
77 return std::make_pair(
false,
"Invalid IPv6-like address, missing closing bracket");
79 a_Host = srvrPart.substr(0, idxClosingBracket);
80 auto portPart = srvrPart.substr(idxClosingBracket + 1);
84 return std::make_pair(
true,
AString());
86 if (portPart[0] !=
':')
88 return std::make_pair(
false,
"Invalid port format after IPv6 address, mising colon");
92 return std::make_pair(
false,
"Failed to parse port number after IPv6 address");
94 return std::make_pair(
true,
AString());
98 auto idxLastColon = srvrPart.find_last_of(
':');
99 a_Host = srvrPart.substr(0, idxLastColon);
100 if (idxLastColon == AString::npos)
103 return std::make_pair(
true,
AString());
105 auto portPart = srvrPart.substr(idxLastColon + 1);
108 return std::make_pair(
false,
"Failed to parse port number after hostname");
110 return std::make_pair(
true,
AString());
130 auto idxColon = a_Url.find(
':');
131 if (idxColon == AString::npos)
133 return std::make_pair(
false,
"Cannot parse the Scheme part of the URL");
135 a_Scheme =
StrToLower(a_Url.substr(0, idxColon));
139 return std::make_pair(
false, fmt::format(FMT_STRING(
"Unknown URL scheme: \"{}\""), a_Scheme));
143 auto authStart = idxColon + 1;
144 if (a_Url.substr(authStart, 2) ==
"//")
150 auto idxFirstSlash = a_Url.find(
'/', authStart + 1);
151 if (idxFirstSlash == AString::npos)
154 idxFirstSlash = a_Url.size();
159 a_Url.substr(authStart, idxFirstSlash - authStart),
160 a_Username, a_Password,
172 if (idxFirstSlash == a_Url.size())
175 return std::make_pair(
true,
AString());
177 auto idxPathEnd = a_Url.find_first_of(
"?#", idxFirstSlash + 1);
178 if (idxPathEnd == AString::npos)
180 a_Path = a_Url.substr(idxFirstSlash);
181 return std::make_pair(
true,
AString());
183 a_Path = a_Url.substr(idxFirstSlash, idxPathEnd - idxFirstSlash);
184 auto idxHash = a_Url.find(
'#', idxPathEnd);
185 if (idxHash == AString::npos)
187 a_Query = a_Url.substr(idxPathEnd + 1);
188 return std::make_pair(
true,
AString());
190 if (idxHash > idxPathEnd)
192 a_Query = a_Url.substr(idxPathEnd + 1, idxHash - idxPathEnd - 1);
194 a_Fragment = a_Url.substr(idxHash + 1);
195 return std::make_pair(
true,
AString());
204 AString UrlScheme, UrlUsername, UrlPassword, UrlHost, UrlPath, UrlQuery, UrlFragment;
206 return Parse(a_Url, UrlScheme, UrlUsername, UrlPassword, UrlHost, Port, UrlPath, UrlQuery, UrlFragment);
AString StrToLower(const AString &s)
Returns a lower-cased copy of the string.
bool StringToInteger(const AString &a_str, T &a_Num)
Parses any integer type.
static std::pair< bool, AString > Parse(const AString &a_Url, AString &a_Scheme, AString &a_Username, AString &a_Password, AString &a_Host, UInt16 &a_Port, AString &a_Path, AString &a_Query, AString &a_Fragment)
Parses the given URL into individual components.
static std::pair< bool, AString > ParseAuthorityPart(const AString &a_AuthorityPart, AString &a_Username, AString &a_Password, AString &a_Host, UInt16 &a_Port)
Parses the given Authority part of an URL into individual components.
static std::pair< bool, AString > Validate(const AString &a_Url)
Checks if the supplied URL is valid.
static UInt16 GetDefaultPort(const AString &a_Scheme)
Returns the default port used by the specified scheme / protocol.