Prechádzať zdrojové kódy

Merge pull request #21976 from Faless/http_client_eof_fix

Fix non chunked HTTP reading till eof.
Rémi Verschelde 7 rokov pred
rodič
commit
1259cbf13c
2 zmenil súbory, kde vykonal 31 pridanie a 17 odobranie
  1. 22 9
      core/io/http_client.cpp
  2. 9 8
      scene/main/http_request.cpp

+ 22 - 9
core/io/http_client.cpp

@@ -275,7 +275,7 @@ void HTTPClient::close() {
 
 	response_headers.clear();
 	response_str.clear();
-	body_size = 0;
+	body_size = -1;
 	body_left = 0;
 	chunk_left = 0;
 	read_until_eof = false;
@@ -404,7 +404,7 @@ Error HTTPClient::poll() {
 					String response;
 					response.parse_utf8((const char *)response_str.ptr());
 					Vector<String> responses = response.split("\n");
-					body_size = 0;
+					body_size = -1;
 					chunked = false;
 					body_left = 0;
 					chunk_left = 0;
@@ -448,7 +448,7 @@ Error HTTPClient::poll() {
 						}
 					}
 
-					if (body_size || chunked) {
+					if (body_size != -1 || chunked) {
 
 						status = STATUS_BODY;
 					} else if (!keep_alive) {
@@ -665,11 +665,24 @@ Error HTTPClient::_get_http_data(uint8_t *p_buffer, int p_bytes, int &r_received
 
 	if (blocking) {
 
-		Error err = connection->get_data(p_buffer, p_bytes);
-		if (err == OK)
-			r_received = p_bytes;
-		else
-			r_received = 0;
+		// We can't use StreamPeer.get_data, since when reaching EOF we will get an
+		// error without knowing how many bytes we received.
+		Error err = ERR_FILE_EOF;
+		int read;
+		int left = p_bytes;
+		r_received = 0;
+		while (left > 0) {
+			err = connection->get_partial_data(p_buffer, left, read);
+			if (err == OK) {
+				r_received += read;
+			} else if (err == ERR_FILE_EOF) {
+				r_received += read;
+				return err;
+			} else {
+				return err;
+			}
+			left -= read;
+		}
 		return err;
 	} else {
 		return connection->get_partial_data(p_buffer, p_bytes, r_received);
@@ -687,7 +700,7 @@ HTTPClient::HTTPClient() {
 	resolving = IP::RESOLVER_INVALID_ID;
 	status = STATUS_DISCONNECTED;
 	conn_port = -1;
-	body_size = 0;
+	body_size = -1;
 	chunked = false;
 	body_left = 0;
 	read_until_eof = false;

+ 9 - 8
scene/main/http_request.cpp

@@ -330,15 +330,13 @@ bool HTTPRequest::_update_connection() {
 					return true;
 				}
 
-				if (client->is_response_chunked()) {
-					body_len = -1; // No body len because chunked, change your webserver configuration if you want body len
-				} else {
-					body_len = client->get_response_body_length();
+				// No body len (-1) if chunked or no content-length header was provided.
+				// Change your webserver configuration if you want body len.
+				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, PoolByteArray());
-						return true;
-					}
+				if (body_size_limit >= 0 && body_len > body_size_limit) {
+					call_deferred("_request_done", RESULT_BODY_SIZE_LIMIT_EXCEEDED, response_code, response_headers, PoolByteArray());
+					return true;
 				}
 
 				if (download_to_file != String()) {
@@ -378,6 +376,9 @@ bool HTTPRequest::_update_connection() {
 					call_deferred("_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);
 			}
 
 			return false;