diff options
Diffstat (limited to 'scene/main/http_request.cpp')
-rw-r--r-- | scene/main/http_request.cpp | 114 |
1 files changed, 52 insertions, 62 deletions
diff --git a/scene/main/http_request.cpp b/scene/main/http_request.cpp index ce7d6ef13c..f649380afa 100644 --- a/scene/main/http_request.cpp +++ b/scene/main/http_request.cpp @@ -40,9 +40,7 @@ Error HTTPRequest::_request() { } Error HTTPRequest::_parse_url(const String &p_url) { - url = p_url; use_ssl = false; - request_string = ""; port = 80; request_sent = false; @@ -52,35 +50,20 @@ Error HTTPRequest::_parse_url(const String &p_url) { downloaded.set(0); redirections = 0; - String url_lower = url.to_lower(); - if (url_lower.begins_with("http://")) { - url = url.substr(7, url.length() - 7); - } else if (url_lower.begins_with("https://")) { - url = url.substr(8, url.length() - 8); + String scheme; + Error err = p_url.parse_url(scheme, url, port, request_string); + ERR_FAIL_COND_V_MSG(err != OK, err, "Error parsing URL: " + p_url + "."); + if (scheme == "https://") { use_ssl = true; - port = 443; - } else { - ERR_FAIL_V_MSG(ERR_INVALID_PARAMETER, "Malformed URL: " + url + "."); + } else if (scheme != "http://") { + ERR_FAIL_V_MSG(ERR_INVALID_PARAMETER, "Invalid URL scheme: " + scheme + "."); } - - ERR_FAIL_COND_V_MSG(url.length() < 1, ERR_INVALID_PARAMETER, "URL too short: " + url + "."); - - int slash_pos = url.find("/"); - - if (slash_pos != -1) { - request_string = url.substr(slash_pos, url.length()); - url = url.substr(0, slash_pos); - } else { - request_string = "/"; + if (port == 0) { + port = use_ssl ? 443 : 80; } - - 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); + if (request_string.is_empty()) { + request_string = "/"; } - return OK; } @@ -123,7 +106,7 @@ Error HTTPRequest::request(const String &p_url, const Vector<String> &p_custom_h size_t len = charstr.length(); raw_data.resize(len); uint8_t *w = raw_data.ptrw(); - copymem(w, charstr.ptr(), len); + memcpy(w, charstr.ptr(), len); return request_raw(p_url, p_custom_headers, p_ssl_validate_domain, p_method, raw_data); } @@ -168,7 +151,7 @@ Error HTTPRequest::request_raw(const String &p_url, const Vector<String> &p_cust client->set_blocking_mode(false); err = _request(); if (err != OK) { - call_deferred("_request_done", RESULT_CANT_CONNECT, 0, PackedStringArray(), PackedByteArray()); + call_deferred(SNAME("_request_done"), RESULT_CANT_CONNECT, 0, PackedStringArray(), PackedByteArray()); return ERR_CANT_CONNECT; } @@ -184,7 +167,7 @@ void HTTPRequest::_thread_func(void *p_userdata) { Error err = hr->_request(); if (err != OK) { - hr->call_deferred("_request_done", RESULT_CANT_CONNECT, 0, PackedStringArray(), PackedByteArray()); + hr->call_deferred(SNAME("_request_done"), RESULT_CANT_CONNECT, 0, PackedStringArray(), PackedByteArray()); } else { while (!hr->thread_request_quit.is_set()) { bool exit = hr->_update_connection(); @@ -226,7 +209,7 @@ void HTTPRequest::cancel_request() { bool HTTPRequest::_handle_response(bool *ret_value) { if (!client->has_response()) { - call_deferred("_request_done", RESULT_NO_RESPONSE, 0, PackedStringArray(), PackedByteArray()); + call_deferred(SNAME("_request_done"), RESULT_NO_RESPONSE, 0, PackedStringArray(), PackedByteArray()); *ret_value = true; return true; } @@ -245,7 +228,7 @@ bool HTTPRequest::_handle_response(bool *ret_value) { // Handle redirect if (max_redirects >= 0 && redirections >= max_redirects) { - call_deferred("_request_done", RESULT_REDIRECT_LIMIT_REACHED, response_code, response_headers, PackedByteArray()); + call_deferred(SNAME("_request_done"), RESULT_REDIRECT_LIMIT_REACHED, response_code, response_headers, PackedByteArray()); *ret_value = true; return true; } @@ -290,7 +273,7 @@ bool HTTPRequest::_handle_response(bool *ret_value) { bool HTTPRequest::_update_connection() { switch (client->get_status()) { case HTTPClient::STATUS_DISCONNECTED: { - call_deferred("_request_done", RESULT_CANT_CONNECT, 0, PackedStringArray(), PackedByteArray()); + call_deferred(SNAME("_request_done"), RESULT_CANT_CONNECT, 0, PackedStringArray(), PackedByteArray()); return true; // End it, since it's doing something } break; case HTTPClient::STATUS_RESOLVING: { @@ -299,7 +282,7 @@ bool HTTPRequest::_update_connection() { return false; } break; case HTTPClient::STATUS_CANT_RESOLVE: { - call_deferred("_request_done", RESULT_CANT_RESOLVE, 0, PackedStringArray(), PackedByteArray()); + call_deferred(SNAME("_request_done"), RESULT_CANT_RESOLVE, 0, PackedStringArray(), PackedByteArray()); return true; } break; @@ -309,7 +292,7 @@ bool HTTPRequest::_update_connection() { return false; } break; // Connecting to IP case HTTPClient::STATUS_CANT_CONNECT: { - call_deferred("_request_done", RESULT_CANT_CONNECT, 0, PackedStringArray(), PackedByteArray()); + call_deferred(SNAME("_request_done"), RESULT_CANT_CONNECT, 0, PackedStringArray(), PackedByteArray()); return true; } break; @@ -324,24 +307,25 @@ bool HTTPRequest::_update_connection() { return ret_value; } - call_deferred("_request_done", RESULT_SUCCESS, response_code, response_headers, PackedByteArray()); + call_deferred(SNAME("_request_done"), RESULT_SUCCESS, response_code, response_headers, PackedByteArray()); return true; } if (body_len < 0) { // Chunked transfer is done - call_deferred("_request_done", RESULT_SUCCESS, response_code, response_headers, body); + call_deferred(SNAME("_request_done"), RESULT_SUCCESS, response_code, response_headers, body); return true; } - call_deferred("_request_done", RESULT_CHUNKED_BODY_SIZE_MISMATCH, response_code, response_headers, PackedByteArray()); + call_deferred(SNAME("_request_done"), RESULT_CHUNKED_BODY_SIZE_MISMATCH, response_code, response_headers, PackedByteArray()); return true; - // Request migh have been done + // Request might have been done } else { // Did not request yet, do request - Error err = client->request_raw(method, request_string, headers, request_data); + int size = request_data.size(); + Error err = client->request(method, request_string, headers, size > 0 ? request_data.ptr() : nullptr, size); if (err != OK) { - call_deferred("_request_done", RESULT_CONNECTION_ERROR, 0, PackedStringArray(), PackedByteArray()); + call_deferred(SNAME("_request_done"), RESULT_CONNECTION_ERROR, 0, PackedStringArray(), PackedByteArray()); return true; } @@ -364,7 +348,7 @@ bool HTTPRequest::_update_connection() { } if (!client->is_response_chunked() && client->get_response_body_length() == 0) { - call_deferred("_request_done", RESULT_SUCCESS, response_code, response_headers, PackedByteArray()); + call_deferred(SNAME("_request_done"), RESULT_SUCCESS, response_code, response_headers, PackedByteArray()); return true; } @@ -373,59 +357,65 @@ bool HTTPRequest::_update_connection() { body_len = client->get_response_body_length(); if (body_size_limit >= 0 && body_len > body_size_limit) { - call_deferred("_request_done", RESULT_BODY_SIZE_LIMIT_EXCEEDED, response_code, response_headers, PackedByteArray()); + call_deferred(SNAME("_request_done"), RESULT_BODY_SIZE_LIMIT_EXCEEDED, response_code, response_headers, PackedByteArray()); return true; } if (download_to_file != String()) { file = FileAccess::open(download_to_file, FileAccess::WRITE); if (!file) { - call_deferred("_request_done", RESULT_DOWNLOAD_FILE_CANT_OPEN, response_code, response_headers, PackedByteArray()); + call_deferred(SNAME("_request_done"), RESULT_DOWNLOAD_FILE_CANT_OPEN, response_code, response_headers, PackedByteArray()); return true; } } } client->poll(); + if (client->get_status() != HTTPClient::STATUS_BODY) { + return false; + } PackedByteArray chunk = client->read_response_body_chunk(); - downloaded.add(chunk.size()); - if (file) { - const uint8_t *r = chunk.ptr(); - file->store_buffer(r, chunk.size()); - if (file->get_error() != OK) { - call_deferred("_request_done", RESULT_DOWNLOAD_FILE_WRITE_ERROR, response_code, response_headers, PackedByteArray()); - return true; + if (chunk.size()) { + downloaded.add(chunk.size()); + if (file) { + const uint8_t *r = chunk.ptr(); + file->store_buffer(r, chunk.size()); + if (file->get_error() != OK) { + call_deferred(SNAME("_request_done"), RESULT_DOWNLOAD_FILE_WRITE_ERROR, response_code, response_headers, PackedByteArray()); + return true; + } + } else { + body.append_array(chunk); } - } else { - body.append_array(chunk); } if (body_size_limit >= 0 && downloaded.get() > body_size_limit) { - call_deferred("_request_done", RESULT_BODY_SIZE_LIMIT_EXCEEDED, response_code, response_headers, PackedByteArray()); + call_deferred(SNAME("_request_done"), RESULT_BODY_SIZE_LIMIT_EXCEEDED, response_code, response_headers, PackedByteArray()); return true; } if (body_len >= 0) { if (downloaded.get() == body_len) { - call_deferred("_request_done", RESULT_SUCCESS, response_code, response_headers, body); + call_deferred(SNAME("_request_done"), RESULT_SUCCESS, response_code, response_headers, body); return true; } } else if (client->get_status() == HTTPClient::STATUS_DISCONNECTED) { // We read till EOF, with no errors. Request is done. - call_deferred("_request_done", RESULT_SUCCESS, response_code, response_headers, body); + call_deferred(SNAME("_request_done"), RESULT_SUCCESS, response_code, response_headers, body); + return true; } return false; } break; // Request resulted in body: break which must be read case HTTPClient::STATUS_CONNECTION_ERROR: { - call_deferred("_request_done", RESULT_CONNECTION_ERROR, 0, PackedStringArray(), PackedByteArray()); + call_deferred(SNAME("_request_done"), RESULT_CONNECTION_ERROR, 0, PackedStringArray(), PackedByteArray()); return true; } break; case HTTPClient::STATUS_SSL_HANDSHAKE_ERROR: { - call_deferred("_request_done", RESULT_SSL_HANDSHAKE_ERROR, 0, PackedStringArray(), PackedByteArray()); + call_deferred(SNAME("_request_done"), RESULT_SSL_HANDSHAKE_ERROR, 0, PackedStringArray(), PackedByteArray()); return true; } break; } @@ -450,7 +440,7 @@ void HTTPRequest::_request_done(int p_status, int p_code, const PackedStringArra is_compressed = false; } - const PackedByteArray *data = NULL; + const PackedByteArray *data = nullptr; if (accept_gzip && is_compressed && p_data.size() > 0) { // Decompress request body @@ -473,7 +463,7 @@ void HTTPRequest::_request_done(int p_status, int p_code, const PackedStringArra data = &p_data; } - emit_signal("request_completed", p_status, p_code, p_headers, *data); + emit_signal(SNAME("request_completed"), p_status, p_code, p_headers, *data); } void HTTPRequest::_notification(int p_what) { @@ -573,7 +563,7 @@ int HTTPRequest::get_timeout() { void HTTPRequest::_timeout() { cancel_request(); - call_deferred("_request_done", RESULT_TIMEOUT, 0, PackedStringArray(), PackedByteArray()); + call_deferred(SNAME("_request_done"), RESULT_TIMEOUT, 0, PackedStringArray(), PackedByteArray()); } void HTTPRequest::_bind_methods() { @@ -638,7 +628,7 @@ void HTTPRequest::_bind_methods() { } HTTPRequest::HTTPRequest() { - client.instance(); + client = Ref<HTTPClient>(HTTPClient::create()); timer = memnew(Timer); timer->set_one_shot(true); timer->connect("timeout", callable_mp(this, &HTTPRequest::_timeout)); |