Merge pull request #48205 from Faless/net/4.x_url_parsing
[Net] Implement String::parse_url for parsing URLs.
This commit is contained in:
commit
015fc2ad4f
4 changed files with 84 additions and 51 deletions
|
@ -240,6 +240,71 @@ String String::word_wrap(int p_chars_per_line) const {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Error String::parse_url(String &r_scheme, String &r_host, int &r_port, String &r_path) const {
|
||||||
|
// Splits the URL into scheme, host, port, path. Strip credentials when present.
|
||||||
|
String base = *this;
|
||||||
|
r_scheme = "";
|
||||||
|
r_host = "";
|
||||||
|
r_port = 0;
|
||||||
|
r_path = "";
|
||||||
|
int pos = base.find("://");
|
||||||
|
// Scheme
|
||||||
|
if (pos != -1) {
|
||||||
|
r_scheme = base.substr(0, pos + 3).to_lower();
|
||||||
|
base = base.substr(pos + 3, base.length() - pos - 3);
|
||||||
|
}
|
||||||
|
pos = base.find("/");
|
||||||
|
// Path
|
||||||
|
if (pos != -1) {
|
||||||
|
r_path = base.substr(pos, base.length() - pos);
|
||||||
|
base = base.substr(0, pos);
|
||||||
|
}
|
||||||
|
// Host
|
||||||
|
pos = base.find("@");
|
||||||
|
if (pos != -1) {
|
||||||
|
// Strip credentials
|
||||||
|
base = base.substr(pos + 1, base.length() - pos - 1);
|
||||||
|
}
|
||||||
|
if (base.begins_with("[")) {
|
||||||
|
// Literal IPv6
|
||||||
|
pos = base.rfind("]");
|
||||||
|
if (pos == -1) {
|
||||||
|
return ERR_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
r_host = base.substr(1, pos - 1);
|
||||||
|
base = base.substr(pos + 1, base.length() - pos - 1);
|
||||||
|
} else {
|
||||||
|
// Anything else
|
||||||
|
if (base.get_slice_count(":") > 1) {
|
||||||
|
return ERR_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
pos = base.rfind(":");
|
||||||
|
if (pos == -1) {
|
||||||
|
r_host = base;
|
||||||
|
base = "";
|
||||||
|
} else {
|
||||||
|
r_host = base.substr(0, pos);
|
||||||
|
base = base.substr(pos, base.length() - pos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (r_host.is_empty()) {
|
||||||
|
return ERR_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
r_host = r_host.to_lower();
|
||||||
|
// Port
|
||||||
|
if (base.begins_with(":")) {
|
||||||
|
base = base.substr(1, base.length() - 1);
|
||||||
|
if (!base.is_valid_integer()) {
|
||||||
|
return ERR_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
r_port = base.to_int();
|
||||||
|
if (r_port < 1 || r_port > 65535) {
|
||||||
|
return ERR_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
void String::copy_from(const char *p_cstr) {
|
void String::copy_from(const char *p_cstr) {
|
||||||
// copy Latin-1 encoded c-string directly
|
// copy Latin-1 encoded c-string directly
|
||||||
if (!p_cstr) {
|
if (!p_cstr) {
|
||||||
|
|
|
@ -416,6 +416,7 @@ public:
|
||||||
String c_unescape() const;
|
String c_unescape() const;
|
||||||
String json_escape() const;
|
String json_escape() const;
|
||||||
String word_wrap(int p_chars_per_line) const;
|
String word_wrap(int p_chars_per_line) const;
|
||||||
|
Error parse_url(String &r_scheme, String &r_host, int &r_port, String &r_path) const;
|
||||||
|
|
||||||
String property_name_encode() const;
|
String property_name_encode() const;
|
||||||
|
|
||||||
|
|
|
@ -43,34 +43,18 @@ Error WebSocketClient::connect_to_url(String p_url, const Vector<String> p_proto
|
||||||
|
|
||||||
String host = p_url;
|
String host = p_url;
|
||||||
String path = "/";
|
String path = "/";
|
||||||
int p_len = -1;
|
String scheme = "";
|
||||||
int port = 80;
|
int port = 80;
|
||||||
|
Error err = p_url.parse_url(scheme, host, port, path);
|
||||||
|
ERR_FAIL_COND_V_MSG(err != OK, err, "Invalid URL: " + p_url);
|
||||||
|
|
||||||
bool ssl = false;
|
bool ssl = false;
|
||||||
if (host.begins_with("wss://")) {
|
if (scheme == "wss://") {
|
||||||
ssl = true; // we should implement this
|
ssl = true;
|
||||||
host = host.substr(6, host.length() - 6);
|
|
||||||
port = 443;
|
|
||||||
} else {
|
|
||||||
ssl = false;
|
|
||||||
if (host.begins_with("ws://")) {
|
|
||||||
host = host.substr(5, host.length() - 5);
|
|
||||||
}
|
}
|
||||||
|
if (port == 0) {
|
||||||
|
port = ssl ? 443 : 80;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Path
|
|
||||||
p_len = host.find("/");
|
|
||||||
if (p_len != -1) {
|
|
||||||
path = host.substr(p_len, host.length() - p_len);
|
|
||||||
host = host.substr(0, p_len);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Port
|
|
||||||
p_len = host.rfind(":");
|
|
||||||
if (p_len != -1 && p_len == host.find(":")) {
|
|
||||||
port = host.substr(p_len, host.length() - p_len).to_int();
|
|
||||||
host = host.substr(0, p_len);
|
|
||||||
}
|
|
||||||
|
|
||||||
return connect_to_host(host, path, port, ssl, p_protocols, p_custom_headers);
|
return connect_to_host(host, path, port, ssl, p_protocols, p_custom_headers);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -40,9 +40,7 @@ Error HTTPRequest::_request() {
|
||||||
}
|
}
|
||||||
|
|
||||||
Error HTTPRequest::_parse_url(const String &p_url) {
|
Error HTTPRequest::_parse_url(const String &p_url) {
|
||||||
url = p_url;
|
|
||||||
use_ssl = false;
|
use_ssl = false;
|
||||||
|
|
||||||
request_string = "";
|
request_string = "";
|
||||||
port = 80;
|
port = 80;
|
||||||
request_sent = false;
|
request_sent = false;
|
||||||
|
@ -52,35 +50,20 @@ Error HTTPRequest::_parse_url(const String &p_url) {
|
||||||
downloaded.set(0);
|
downloaded.set(0);
|
||||||
redirections = 0;
|
redirections = 0;
|
||||||
|
|
||||||
String url_lower = url.to_lower();
|
String scheme;
|
||||||
if (url_lower.begins_with("http://")) {
|
Error err = p_url.parse_url(scheme, url, port, request_string);
|
||||||
url = url.substr(7, url.length() - 7);
|
ERR_FAIL_COND_V_MSG(err != OK, err, "Error parsing URL: " + p_url + ".");
|
||||||
} else if (url_lower.begins_with("https://")) {
|
if (scheme == "https://") {
|
||||||
url = url.substr(8, url.length() - 8);
|
|
||||||
use_ssl = true;
|
use_ssl = true;
|
||||||
port = 443;
|
} else if (scheme != "http://") {
|
||||||
} else {
|
ERR_FAIL_V_MSG(ERR_INVALID_PARAMETER, "Invalid URL scheme: " + scheme + ".");
|
||||||
ERR_FAIL_V_MSG(ERR_INVALID_PARAMETER, "Malformed URL: " + url + ".");
|
|
||||||
}
|
}
|
||||||
|
if (port == 0) {
|
||||||
ERR_FAIL_COND_V_MSG(url.length() < 1, ERR_INVALID_PARAMETER, "URL too short: " + url + ".");
|
port = use_ssl ? 443 : 80;
|
||||||
|
}
|
||||||
int slash_pos = url.find("/");
|
if (request_string.is_empty()) {
|
||||||
|
|
||||||
if (slash_pos != -1) {
|
|
||||||
request_string = url.substr(slash_pos, url.length());
|
|
||||||
url = url.substr(0, slash_pos);
|
|
||||||
} else {
|
|
||||||
request_string = "/";
|
request_string = "/";
|
||||||
}
|
}
|
||||||
|
|
||||||
int colon_pos = url.find(":");
|
|
||||||
if (colon_pos != -1) {
|
|
||||||
port = url.substr(colon_pos + 1, url.length()).to_int();
|
|
||||||
url = url.substr(0, colon_pos);
|
|
||||||
ERR_FAIL_COND_V(port < 1 || port > 65535, ERR_INVALID_PARAMETER);
|
|
||||||
}
|
|
||||||
|
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue