@@ -139,6 +139,8 @@ void HTTPClient::clear()
139139 _size = -1 ;
140140 _headers.clear ();
141141 _location.clear ();
142+ _chunkHeader.clear ();
143+ _chunkLen = 0 ;
142144 _payload.reset ();
143145}
144146
@@ -956,22 +958,15 @@ int HTTPClient::writeToStream(Stream * stream)
956958 if (!connected ()) {
957959 return returnError (HTTPC_ERROR_CONNECTION_LOST);
958960 }
959- String chunkHeader = _client->readStringUntil (' \n ' );
960-
961- if (chunkHeader.length () <= 0 ) {
961+ if (!readChunkHeader ()) {
962962 return returnError (HTTPC_ERROR_READ_TIMEOUT);
963963 }
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);
971966
972967 // data left?
973- if (len > 0 ) {
974- int r = writeToStreamDataBlock (stream, len );
968+ if (_chunkLen > 0 ) {
969+ int r = writeToStreamDataBlock (stream, _chunkLen );
975970 if (r < 0 ) {
976971 // error in writeToStreamDataBlock
977972 return returnError (r);
@@ -992,9 +987,7 @@ int HTTPClient::writeToStream(Stream * stream)
992987 }
993988
994989 // 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 ()) {
998991 return returnError (HTTPC_ERROR_READ_TIMEOUT);
999992 }
1000993
@@ -1496,6 +1489,61 @@ int HTTPClient::writeToStreamDataBlock(Stream * stream, int size)
14961489 return bytesWritten;
14971490}
14981491
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+
14991547/* *
15001548 * called to handle error return, may disconnect the connection if still exists
15011549 * @param error
0 commit comments