diff options
author | Fabio Alessandrelli <fabio.alessandrelli@gmail.com> | 2019-02-20 04:33:31 +0100 |
---|---|---|
committer | Fabio Alessandrelli <fabio.alessandrelli@gmail.com> | 2019-02-20 05:13:51 +0100 |
commit | 0e5655694c844f93e1fdd044d873c2661cb00742 (patch) | |
tree | 855854f43017b6979ae69dd5a4334c8beb79ca29 /core | |
parent | 10e48212608f1fa75fed1dade9551408b30f484e (diff) |
Fix HTTPClient keep alive with chunked encoding.
We need to consume the trailer part and final CRLF after last chunk
as per RFC 7230 section 4.1:
```
chunked-body = *chunk
last-chunk
trailer-part
CRLF
```
We do not return the trailer part, just consume it allowing following
requests to work as expected when using keep alive.
Diffstat (limited to 'core')
-rw-r--r-- | core/io/http_client.cpp | 30 | ||||
-rw-r--r-- | core/io/http_client.h | 1 |
2 files changed, 29 insertions, 2 deletions
diff --git a/core/io/http_client.cpp b/core/io/http_client.cpp index abf4dd200e..e5c6d2a4f2 100644 --- a/core/io/http_client.cpp +++ b/core/io/http_client.cpp @@ -278,6 +278,7 @@ void HTTPClient::close() { body_size = -1; body_left = 0; chunk_left = 0; + chunk_trailer_part = 0; read_until_eof = false; response_num = 0; handshaking = false; @@ -421,6 +422,7 @@ Error HTTPClient::poll() { chunked = false; body_left = 0; chunk_left = 0; + chunk_trailer_part = false; read_until_eof = false; response_str.clear(); response_headers.clear(); @@ -511,7 +513,30 @@ PoolByteArray HTTPClient::read_response_body_chunk() { while (true) { - if (chunk_left == 0) { + if (chunk_trailer_part) { + // We need to consume the trailer part too or keep-alive will break + uint8_t b; + int rec = 0; + err = _get_http_data(&b, 1, rec); + + if (rec == 0) + break; + + chunk.push_back(b); + int cs = chunk.size(); + if ((cs >= 2 && chunk[cs - 2] == '\r' && chunk[cs - 1] == '\n')) { + if (cs == 2) { + // Finally over + chunk_trailer_part = false; + status = STATUS_CONNECTED; + chunk.clear(); + break; + } else { + // We do not process nor return the trailer data + chunk.clear(); + } + } + } else if (chunk_left == 0) { // Reading length uint8_t b; int rec = 0; @@ -556,7 +581,7 @@ PoolByteArray HTTPClient::read_response_body_chunk() { if (len == 0) { // End reached! - status = STATUS_CONNECTED; + chunk_trailer_part = true; chunk.clear(); break; } @@ -695,6 +720,7 @@ HTTPClient::HTTPClient() { body_left = 0; read_until_eof = false; chunk_left = 0; + chunk_trailer_part = false; response_num = 0; ssl = false; blocking = false; diff --git a/core/io/http_client.h b/core/io/http_client.h index 1ad44d5f01..85ee1959a2 100644 --- a/core/io/http_client.h +++ b/core/io/http_client.h @@ -172,6 +172,7 @@ private: bool chunked; Vector<uint8_t> chunk; int chunk_left; + bool chunk_trailer_part; int body_size; int body_left; bool read_until_eof; |