Merge pull request #92237 from timothyqiu/url-fragment
String: Parse fragment from URL
This commit is contained in:
commit
cf1d910e10
9 changed files with 74 additions and 13 deletions
|
@ -221,18 +221,35 @@ void CharString::copy_from(const char *p_cstr) {
|
||||||
/* String */
|
/* String */
|
||||||
/*************************************************************************/
|
/*************************************************************************/
|
||||||
|
|
||||||
Error String::parse_url(String &r_scheme, String &r_host, int &r_port, String &r_path) const {
|
Error String::parse_url(String &r_scheme, String &r_host, int &r_port, String &r_path, String &r_fragment) const {
|
||||||
// Splits the URL into scheme, host, port, path. Strip credentials when present.
|
// Splits the URL into scheme, host, port, path, fragment. Strip credentials when present.
|
||||||
String base = *this;
|
String base = *this;
|
||||||
r_scheme = "";
|
r_scheme = "";
|
||||||
r_host = "";
|
r_host = "";
|
||||||
r_port = 0;
|
r_port = 0;
|
||||||
r_path = "";
|
r_path = "";
|
||||||
|
r_fragment = "";
|
||||||
|
|
||||||
int pos = base.find("://");
|
int pos = base.find("://");
|
||||||
// Scheme
|
// Scheme
|
||||||
if (pos != -1) {
|
if (pos != -1) {
|
||||||
r_scheme = base.substr(0, pos + 3).to_lower();
|
bool is_scheme_valid = true;
|
||||||
base = base.substr(pos + 3, base.length() - pos - 3);
|
for (int i = 0; i < pos; i++) {
|
||||||
|
if (!is_ascii_alphanumeric_char(base[i]) && base[i] != '+' && base[i] != '-' && base[i] != '.') {
|
||||||
|
is_scheme_valid = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (is_scheme_valid) {
|
||||||
|
r_scheme = base.substr(0, pos + 3).to_lower();
|
||||||
|
base = base.substr(pos + 3, base.length() - pos - 3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pos = base.find("#");
|
||||||
|
// Fragment
|
||||||
|
if (pos != -1) {
|
||||||
|
r_fragment = base.substr(pos + 1);
|
||||||
|
base = base.substr(0, pos);
|
||||||
}
|
}
|
||||||
pos = base.find("/");
|
pos = base.find("/");
|
||||||
// Path
|
// Path
|
||||||
|
|
|
@ -452,7 +452,7 @@ public:
|
||||||
String c_escape_multiline() const;
|
String c_escape_multiline() const;
|
||||||
String c_unescape() const;
|
String c_unescape() const;
|
||||||
String json_escape() const;
|
String json_escape() const;
|
||||||
Error parse_url(String &r_scheme, String &r_host, int &r_port, String &r_path) const;
|
Error parse_url(String &r_scheme, String &r_host, int &r_port, String &r_path, String &r_fragment) const;
|
||||||
|
|
||||||
String property_name_encode() const;
|
String property_name_encode() const;
|
||||||
|
|
||||||
|
|
|
@ -77,8 +77,8 @@ Error EditorDebuggerServerTCP::start(const String &p_uri) {
|
||||||
|
|
||||||
// Optionally override
|
// Optionally override
|
||||||
if (!p_uri.is_empty() && p_uri != "tcp://") {
|
if (!p_uri.is_empty() && p_uri != "tcp://") {
|
||||||
String scheme, path;
|
String scheme, path, fragment;
|
||||||
Error err = p_uri.parse_url(scheme, bind_host, bind_port, path);
|
Error err = p_uri.parse_url(scheme, bind_host, bind_port, path, fragment);
|
||||||
ERR_FAIL_COND_V(err != OK, ERR_INVALID_PARAMETER);
|
ERR_FAIL_COND_V(err != OK, ERR_INVALID_PARAMETER);
|
||||||
ERR_FAIL_COND_V(!bind_host.is_valid_ip_address() && bind_host != "*", ERR_INVALID_PARAMETER);
|
ERR_FAIL_COND_V(!bind_host.is_valid_ip_address() && bind_host != "*", ERR_INVALID_PARAMETER);
|
||||||
}
|
}
|
||||||
|
|
|
@ -993,7 +993,8 @@ void EditorAssetLibrary::_request_image(ObjectID p_for, int p_asset_id, String p
|
||||||
String url_host;
|
String url_host;
|
||||||
int url_port;
|
int url_port;
|
||||||
String url_path;
|
String url_path;
|
||||||
Error err = trimmed_url.parse_url(url_scheme, url_host, url_port, url_path);
|
String url_fragment;
|
||||||
|
Error err = trimmed_url.parse_url(url_scheme, url_host, url_port, url_path, url_fragment);
|
||||||
if (err != OK) {
|
if (err != OK) {
|
||||||
if (is_print_verbose_enabled()) {
|
if (is_print_verbose_enabled()) {
|
||||||
ERR_PRINT(vformat("Asset Library: Invalid image URL '%s' for asset # %d.", trimmed_url, p_asset_id));
|
ERR_PRINT(vformat("Asset Library: Invalid image URL '%s' for asset # %d.", trimmed_url, p_asset_id));
|
||||||
|
|
|
@ -77,8 +77,8 @@ Error EditorDebuggerServerWebSocket::start(const String &p_uri) {
|
||||||
|
|
||||||
// Optionally override
|
// Optionally override
|
||||||
if (!p_uri.is_empty() && p_uri != "ws://") {
|
if (!p_uri.is_empty() && p_uri != "ws://") {
|
||||||
String scheme, path;
|
String scheme, path, fragment;
|
||||||
Error err = p_uri.parse_url(scheme, bind_host, bind_port, path);
|
Error err = p_uri.parse_url(scheme, bind_host, bind_port, path, fragment);
|
||||||
ERR_FAIL_COND_V(err != OK, ERR_INVALID_PARAMETER);
|
ERR_FAIL_COND_V(err != OK, ERR_INVALID_PARAMETER);
|
||||||
ERR_FAIL_COND_V(!bind_host.is_valid_ip_address() && bind_host != "*", ERR_INVALID_PARAMETER);
|
ERR_FAIL_COND_V(!bind_host.is_valid_ip_address() && bind_host != "*", ERR_INVALID_PARAMETER);
|
||||||
}
|
}
|
||||||
|
|
|
@ -68,8 +68,9 @@ Error EMWSPeer::connect_to_url(const String &p_url, Ref<TLSOptions> p_tls_option
|
||||||
String host;
|
String host;
|
||||||
String path;
|
String path;
|
||||||
String scheme;
|
String scheme;
|
||||||
|
String fragment;
|
||||||
int port = 0;
|
int port = 0;
|
||||||
Error err = p_url.parse_url(scheme, host, port, path);
|
Error err = p_url.parse_url(scheme, host, port, path, fragment);
|
||||||
ERR_FAIL_COND_V_MSG(err != OK, err, "Invalid URL: " + p_url);
|
ERR_FAIL_COND_V_MSG(err != OK, err, "Invalid URL: " + p_url);
|
||||||
|
|
||||||
if (scheme.is_empty()) {
|
if (scheme.is_empty()) {
|
||||||
|
|
|
@ -482,8 +482,9 @@ Error WSLPeer::connect_to_url(const String &p_url, Ref<TLSOptions> p_options) {
|
||||||
String host;
|
String host;
|
||||||
String path;
|
String path;
|
||||||
String scheme;
|
String scheme;
|
||||||
|
String fragment;
|
||||||
int port = 0;
|
int port = 0;
|
||||||
Error err = p_url.parse_url(scheme, host, port, path);
|
Error err = p_url.parse_url(scheme, host, port, path, fragment);
|
||||||
ERR_FAIL_COND_V_MSG(err != OK, err, "Invalid URL: " + p_url);
|
ERR_FAIL_COND_V_MSG(err != OK, err, "Invalid URL: " + p_url);
|
||||||
if (scheme.is_empty()) {
|
if (scheme.is_empty()) {
|
||||||
scheme = "ws://";
|
scheme = "ws://";
|
||||||
|
|
|
@ -49,7 +49,8 @@ Error HTTPRequest::_parse_url(const String &p_url) {
|
||||||
redirections = 0;
|
redirections = 0;
|
||||||
|
|
||||||
String scheme;
|
String scheme;
|
||||||
Error err = p_url.parse_url(scheme, url, port, request_string);
|
String fragment;
|
||||||
|
Error err = p_url.parse_url(scheme, url, port, request_string, fragment);
|
||||||
ERR_FAIL_COND_V_MSG(err != OK, err, vformat("Error parsing URL: '%s'.", p_url));
|
ERR_FAIL_COND_V_MSG(err != OK, err, vformat("Error parsing URL: '%s'.", p_url));
|
||||||
|
|
||||||
if (scheme == "https://") {
|
if (scheme == "https://") {
|
||||||
|
|
|
@ -1988,6 +1988,46 @@ TEST_CASE("[String] Variant ptr indexed set") {
|
||||||
CHECK_EQ(s, String("azcd"));
|
CHECK_EQ(s, String("azcd"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE("[String] parse_url") {
|
||||||
|
String scheme, host, path, fragment;
|
||||||
|
int port;
|
||||||
|
|
||||||
|
SUBCASE("Typical URL") {
|
||||||
|
Error err = String("https://docs.godotengine.org/en/stable/").parse_url(scheme, host, port, path, fragment);
|
||||||
|
REQUIRE(err == OK);
|
||||||
|
CHECK_EQ(scheme, "https://");
|
||||||
|
CHECK_EQ(host, "docs.godotengine.org");
|
||||||
|
CHECK_EQ(port, 0);
|
||||||
|
CHECK_EQ(path, "/en/stable/");
|
||||||
|
CHECK_EQ(fragment, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
SUBCASE("All Elements") {
|
||||||
|
Error err = String("https://www.example.com:8080/path/to/file.html#fragment").parse_url(scheme, host, port, path, fragment);
|
||||||
|
REQUIRE(err == OK);
|
||||||
|
CHECK_EQ(scheme, "https://");
|
||||||
|
CHECK_EQ(host, "www.example.com");
|
||||||
|
CHECK_EQ(port, 8080);
|
||||||
|
CHECK_EQ(path, "/path/to/file.html");
|
||||||
|
CHECK_EQ(fragment, "fragment");
|
||||||
|
}
|
||||||
|
|
||||||
|
SUBCASE("Invalid Scheme") {
|
||||||
|
Error err = String("http_://example.com").parse_url(scheme, host, port, path, fragment);
|
||||||
|
REQUIRE(err == ERR_INVALID_PARAMETER); // Host being empty is an error.
|
||||||
|
}
|
||||||
|
|
||||||
|
SUBCASE("Scheme vs Fragment") {
|
||||||
|
Error err = String("google.com/#goto=http://redirect_url/").parse_url(scheme, host, port, path, fragment);
|
||||||
|
REQUIRE(err == OK);
|
||||||
|
CHECK_EQ(scheme, "");
|
||||||
|
CHECK_EQ(host, "google.com");
|
||||||
|
CHECK_EQ(port, 0);
|
||||||
|
CHECK_EQ(path, "/");
|
||||||
|
CHECK_EQ(fragment, "goto=http://redirect_url/");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
TEST_CASE("[Stress][String] Empty via ' == String()'") {
|
TEST_CASE("[Stress][String] Empty via ' == String()'") {
|
||||||
for (int i = 0; i < 100000; ++i) {
|
for (int i = 0; i < 100000; ++i) {
|
||||||
String str = "Hello World!";
|
String str = "Hello World!";
|
||||||
|
|
Loading…
Reference in a new issue