@@ -139,6 +139,8 @@ void HTTPClient::clear()
139
139
_size = -1 ;
140
140
_headers.clear ();
141
141
_location.clear ();
142
+ _chunkHeader.clear ();
143
+ _chunkLen = 0 ;
142
144
_payload.reset ();
143
145
}
144
146
@@ -956,22 +958,15 @@ int HTTPClient::writeToStream(Stream * stream)
956
958
if (!connected ()) {
957
959
return returnError (HTTPC_ERROR_CONNECTION_LOST);
958
960
}
959
- String chunkHeader = _client->readStringUntil (' \n ' );
960
-
961
- if (chunkHeader.length () <= 0 ) {
961
+ if (!readChunkHeader ()) {
962
962
return returnError (HTTPC_ERROR_READ_TIMEOUT);
963
963
}
964
-
965
- chunkHeader.trim (); // remove \r
966
-
967
- // read size of chunk
968
- len = (uint32_t ) strtol ((const char *) chunkHeader.c_str (), NULL , 16 );
969
- size += len;
970
- DEBUG_HTTPCLIENT (" [HTTP-Client] read chunk len: %d\n " , len);
964
+ size += _chunkLen;
965
+ DEBUG_HTTPCLIENT (" [HTTP-Client] read chunk len: %d\n " , _chunkLen);
971
966
972
967
// data left?
973
- if (len > 0 ) {
974
- int r = writeToStreamDataBlock (stream, len );
968
+ if (_chunkLen > 0 ) {
969
+ int r = writeToStreamDataBlock (stream, _chunkLen );
975
970
if (r < 0 ) {
976
971
// error in writeToStreamDataBlock
977
972
return returnError (r);
@@ -992,9 +987,7 @@ int HTTPClient::writeToStream(Stream * stream)
992
987
}
993
988
994
989
// read trailing \r\n at the end of the chunk
995
- char buf[2 ];
996
- auto trailing_seq_len = _client->readBytes ((uint8_t *)buf, 2 );
997
- if (trailing_seq_len != 2 || buf[0 ] != ' \r ' || buf[1 ] != ' \n ' ) {
990
+ if (!readChunkTrailer ()) {
998
991
return returnError (HTTPC_ERROR_READ_TIMEOUT);
999
992
}
1000
993
@@ -1496,6 +1489,61 @@ int HTTPClient::writeToStreamDataBlock(Stream * stream, int size)
1496
1489
return bytesWritten;
1497
1490
}
1498
1491
1492
+ /* *
1493
+ * Read header of next chunk in HTTP response using chunked encoding
1494
+ * @param blocking bool whether this method is allowed to block
1495
+ * @return boolean value indicating whether a complete header could be read
1496
+ */
1497
+ bool HTTPClient::readChunkHeader (bool blocking)
1498
+ {
1499
+ if (blocking) {
1500
+ _chunkHeader += _client->readStringUntil (' \n ' );
1501
+ if (_chunkHeader.length () == 0 ) {
1502
+ return false ;
1503
+ }
1504
+ } else {
1505
+ while (_client->available () && !_chunkHeader.endsWith (" \n " )) {
1506
+ _chunkHeader += (char ) _client->read ();
1507
+ }
1508
+ if (!_chunkHeader.endsWith (" \n " )) {
1509
+ return false ;
1510
+ }
1511
+ }
1512
+
1513
+ // read size of chunk
1514
+ _chunkLen = (uint32_t ) strtol ((const char *) _chunkHeader.c_str (), NULL ,
1515
+ 16 );
1516
+
1517
+ return true ;
1518
+ }
1519
+
1520
+ /* *
1521
+ * Read trailer of current chunk in HTTP response using chunked encoding
1522
+ * @param blocking bool whether this method is allowed to block
1523
+ * @return boolean value indicating whether the complete trailer could be read
1524
+ */
1525
+ bool HTTPClient::readChunkTrailer (bool blocking)
1526
+ {
1527
+ uint8_t buf[2 ];
1528
+
1529
+ if (blocking || (_client->available () >= 2 )) {
1530
+ auto trailing_seq_len = _client->readBytes ((uint8_t *) buf, 2 );
1531
+
1532
+ if (trailing_seq_len != 2 || buf[0 ] != ' \r ' || buf[1 ] != ' \n ' ) {
1533
+ return false ;
1534
+ } else {
1535
+ /* Clear _chunkHeader to indicate that the current chunk has been
1536
+ * completely read, and reset _chunkLen to indicate that the next
1537
+ * chunk header has not been read yet. */
1538
+ _chunkHeader.clear ();
1539
+ _chunkLen = 0 ;
1540
+ return true ;
1541
+ }
1542
+ } else {
1543
+ return false ;
1544
+ }
1545
+ }
1546
+
1499
1547
/* *
1500
1548
* called to handle error return, may disconnect the connection if still exists
1501
1549
* @param error
0 commit comments