From ab0e610e86d2e4b8a246ce9628749dd067fc9692 Mon Sep 17 00:00:00 2001 From: Fabio Alessandrelli Date: Tue, 11 Sep 2018 17:46:14 +0200 Subject: [PATCH] Fix non chunked HTTP reading till eof. --- core/io/http_client.cpp | 31 ++++++++++++++++++++++--------- scene/main/http_request.cpp | 17 +++++++++-------- 2 files changed, 31 insertions(+), 17 deletions(-) diff --git a/core/io/http_client.cpp b/core/io/http_client.cpp index bfa2d3b3897..36f5e917c0b 100644 --- a/core/io/http_client.cpp +++ b/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 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; diff --git a/scene/main/http_request.cpp b/scene/main/http_request.cpp index 4750e056333..a9b7fba9c70 100644 --- a/scene/main/http_request.cpp +++ b/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;