Browse Source

Merge pull request #16781 from eska014/html5-httpc

HTML5 HTTPClient fixes
Rémi Verschelde 7 years ago
parent
commit
df522cf4e1
2 changed files with 37 additions and 15 deletions
  1. 5 0
      platform/javascript/http_client.h.inc
  2. 32 15
      platform/javascript/http_client_javascript.cpp

+ 5 - 0
platform/javascript/http_client.h.inc

@@ -46,3 +46,8 @@ String password;
 int polled_response_code;
 String polled_response_header;
 PoolByteArray polled_response;
+
+#ifdef DEBUG_ENABLED
+bool has_polled;
+uint64_t last_polling_frame;
+#endif

+ 32 - 15
platform/javascript/http_client_javascript.cpp

@@ -81,6 +81,8 @@ Ref<StreamPeer> HTTPClient::get_connection() const {
 Error HTTPClient::prepare_request(Method p_method, const String &p_url, const Vector<String> &p_headers) {
 
 	ERR_FAIL_INDEX_V(p_method, METHOD_MAX, ERR_INVALID_PARAMETER);
+	ERR_EXPLAIN("HTTP methods TRACE and CONNECT are not supported for the HTML5 platform");
+	ERR_FAIL_COND_V(p_method == METHOD_TRACE || p_method == METHOD_CONNECT, ERR_UNAVAILABLE);
 	ERR_FAIL_COND_V(status != STATUS_CONNECTED, ERR_INVALID_PARAMETER);
 	ERR_FAIL_COND_V(host.empty(), ERR_UNCONFIGURED);
 	ERR_FAIL_COND_V(port < 0, ERR_UNCONFIGURED);
@@ -158,7 +160,7 @@ int HTTPClient::get_response_code() const {
 
 Error HTTPClient::get_response_headers(List<String> *r_response) {
 
-	if (!polled_response_header.size())
+	if (polled_response_header.empty())
 		return ERR_INVALID_PARAMETER;
 
 	Vector<String> header_lines = polled_response_header.split("\r\n", false);
@@ -191,8 +193,6 @@ PoolByteArray HTTPClient::read_response_body_chunk() {
 	if (response_read_offset == polled_response.size()) {
 		status = STATUS_CONNECTED;
 		polled_response.resize(0);
-		polled_response_code = 0;
-		polled_response_header = String();
 		godot_xhr_reset(xhr_id);
 	}
 
@@ -238,34 +238,47 @@ Error HTTPClient::poll() {
 			return ERR_CONNECTION_ERROR;
 
 		case STATUS_REQUESTING:
-			polled_response_code = godot_xhr_get_status(xhr_id);
-			int response_length = godot_xhr_get_response_length(xhr_id);
-			if (response_length == 0) {
-				godot_xhr_ready_state_t ready_state = godot_xhr_get_ready_state(xhr_id);
-				if (ready_state == XHR_READY_STATE_HEADERS_RECEIVED || ready_state == XHR_READY_STATE_LOADING) {
-					return OK;
-				} else {
-					status = STATUS_CONNECTION_ERROR;
-					return ERR_CONNECTION_ERROR;
+
+#ifdef DEBUG_ENABLED
+			if (!has_polled) {
+				has_polled = true;
+			} else {
+				// forcing synchronous requests is not possible on the web
+				if (last_polling_frame == Engine::get_singleton()->get_idle_frames()) {
+					WARN_PRINT("HTTPClient polled multiple times in one frame, "
+							   "but request cannot progress more than once per "
+							   "frame on the HTML5 platform.");
 				}
 			}
+			last_polling_frame = Engine::get_singleton()->get_idle_frames();
+#endif
+
+			polled_response_code = godot_xhr_get_status(xhr_id);
+			if (godot_xhr_get_ready_state(xhr_id) != XHR_READY_STATE_DONE) {
+				return OK;
+			} else if (!polled_response_code) {
+				status = STATUS_CONNECTION_ERROR;
+				return ERR_CONNECTION_ERROR;
+			}
 
 			status = STATUS_BODY;
 
 			PoolByteArray bytes;
 			int len = godot_xhr_get_response_headers_length(xhr_id);
-			bytes.resize(len);
+			bytes.resize(len + 1);
+
 			PoolByteArray::Write write = bytes.write();
 			godot_xhr_get_response_headers(xhr_id, reinterpret_cast<char *>(write.ptr()), len);
+			write[len] = 0;
 			write = PoolByteArray::Write();
 
 			PoolByteArray::Read read = bytes.read();
 			polled_response_header = String::utf8(reinterpret_cast<const char *>(read.ptr()));
 			read = PoolByteArray::Read();
 
-			polled_response.resize(response_length);
+			polled_response.resize(godot_xhr_get_response_length(xhr_id));
 			write = polled_response.write();
-			godot_xhr_get_response(xhr_id, write.ptr(), response_length);
+			godot_xhr_get_response(xhr_id, write.ptr(), polled_response.size());
 			write = PoolByteArray::Write();
 			break;
 	}
@@ -280,6 +293,10 @@ HTTPClient::HTTPClient() {
 	port = -1;
 	use_tls = false;
 	polled_response_code = 0;
+#ifdef DEBUG_ENABLED
+	has_polled = false;
+	last_polling_frame = 0;
+#endif
 }
 
 HTTPClient::~HTTPClient() {