@@ -40,6 +40,8 @@ HTTPClient::HTTPClient() {
4040 _port = 0 ;
4141
4242 _reuse = false ;
43+ _tcpTimeout = HTTPCLIENT_DEFAULT_TCP_TIMEOUT;
44+
4345 _https = false ;
4446
4547 _userAgent = " ESP8266HTTPClient" ;
@@ -50,7 +52,7 @@ HTTPClient::HTTPClient() {
5052 _returnCode = 0 ;
5153 _size = -1 ;
5254 _canReuse = false ;
53- _tcpTimeout = HTTPCLIENT_DEFAULT_TCP_TIMEOUT ;
55+ _transferEncoding = HTTPC_TE_IDENTITY ;
5456
5557}
5658
@@ -468,61 +470,36 @@ int HTTPClient::writeToStream(Stream * stream) {
468470
469471 // get length of document (is -1 when Server sends no Content-Length header)
470472 int len = _size;
471- int bytesWritten = 0 ;
472-
473- size_t buff_size = HTTP_TCP_BUFFER_SIZE;
474-
475- // if possible create smaller buffer then HTTP_TCP_BUFFER_SIZE
476- if ((len > 0 ) && (len < HTTP_TCP_BUFFER_SIZE)) {
477- buff_size = len;
478- }
479-
480- // create buffer for read
481- uint8_t * buff = (uint8_t *) malloc (buff_size);
482-
483- if (buff) {
484- // read all data from server
485- while (connected () && (len > 0 || len == -1 )) {
486-
487- // get available data size
488- size_t size = _tcp->available ();
489-
490- if (size) {
491- int c = _tcp->readBytes (buff, ((size > buff_size) ? buff_size : size));
492-
493- // write it to Stream
494- int w = stream->write (buff, c);
495- bytesWritten += w;
496- if (w != c) {
497- DEBUG_HTTPCLIENT (" [HTTP-Client][writeToStream] short write asked for %d but got %d\n " , c, w);
498- break ;
499- }
500-
501- if (len > 0 ) {
502- len -= c;
473+ int ret = 0 ;
474+
475+ if (_transferEncoding == HTTPC_TE_IDENTITY) {
476+ ret = writeToStreamDataBlock (stream, len);
477+ } else if (_transferEncoding == HTTPC_TE_CHUNKED) {
478+ while (1 ) {
479+ String chunkHeader = _tcp->readStringUntil (' \n ' );
480+ chunkHeader.trim (); // remove \r
481+
482+ // read size of chunk
483+ len = (uint32_t ) strtol ((const char *) chunkHeader.c_str (), NULL , 16 );
484+ DEBUG_HTTPCLIENT (" [HTTP-Client] read chunk len: %d\n " , len);
485+ if (len > 0 ) {
486+ int r = writeToStreamDataBlock (stream, len);
487+ if (r < 0 ) {
488+ // error in writeToStreamDataBlock
489+ return r;
503490 }
504-
505- delay (0 );
491+ ret += r;
506492 } else {
507- delay ( 1 ) ;
493+ break ;
508494 }
495+ delay (0 );
509496 }
510-
511- free (buff);
512-
513- DEBUG_HTTPCLIENT (" [HTTP-Client][writeToStream] connection closed or file end (written: %d).\n " , bytesWritten);
514-
515- if (_size && _size != bytesWritten) {
516- DEBUG_HTTPCLIENT (" [HTTP-Client][writeToStream] bytesWritten %d and size %d mismatch!.\n " , bytesWritten, _size);
517- }
518-
519497 } else {
520- DEBUG_HTTPCLIENT (" [HTTP-Client][writeToStream] too less ram! need %d\n " , HTTP_TCP_BUFFER_SIZE);
521- return HTTPC_ERROR_TOO_LESS_RAM;
498+ return HTTPC_ERROR_ENCODING;
522499 }
523500
524501 end ();
525- return bytesWritten ;
502+ return ret ;
526503}
527504
528505/* *
@@ -567,6 +544,8 @@ String HTTPClient::errorToString(int error) {
567544 return String (" no HTTP server" );
568545 case HTTPC_ERROR_TOO_LESS_RAM:
569546 return String (" too less ram" );
547+ case HTTPC_ERROR_ENCODING:
548+ return String (" Transfer-Encoding not supported" );
570549 default :
571550 return String ();
572551 }
@@ -706,6 +685,7 @@ bool HTTPClient::sendHeader(const char * type) {
706685 String header = String (type) + " " + _url + " HTTP/1.1\r\n "
707686 " Host: " + _host + " \r\n "
708687 " User-Agent: " + _userAgent + " \r\n "
688+ " Accept-Encoding: identity;q=1 chunked;q=0.1 *;q=0\r\n "
709689 " Connection: " ;
710690
711691 if (_reuse) {
@@ -733,9 +713,10 @@ int HTTPClient::handleHeaderResponse() {
733713 if (!connected ()) {
734714 return HTTPC_ERROR_NOT_CONNECTED;
735715 }
736-
716+ String transferEncoding;
737717 _returnCode = -1 ;
738718 _size = -1 ;
719+ _transferEncoding = HTTPC_TE_IDENTITY;
739720
740721 while (connected ()) {
741722 size_t len = _tcp->available ();
@@ -759,6 +740,10 @@ int HTTPClient::handleHeaderResponse() {
759740 _canReuse = headerValue.equalsIgnoreCase (" keep-alive" );
760741 }
761742
743+ if (headerName.equalsIgnoreCase (" Transfer-Encoding" )) {
744+ transferEncoding = headerValue;
745+ }
746+
762747 for (size_t i = 0 ; i < _headerKeysCount; i++) {
763748 if (_currentHeaders[i].key .equalsIgnoreCase (headerName)) {
764749 _currentHeaders[i].value = headerValue;
@@ -769,9 +754,22 @@ int HTTPClient::handleHeaderResponse() {
769754
770755 if (headerLine == " " ) {
771756 DEBUG_HTTPCLIENT (" [HTTP-Client][handleHeaderResponse] code: %d\n " , _returnCode);
772- if (_size) {
757+
758+ if (_size > 0 ) {
773759 DEBUG_HTTPCLIENT (" [HTTP-Client][handleHeaderResponse] size: %d\n " , _size);
774760 }
761+
762+ if (transferEncoding.length () > 0 ) {
763+ DEBUG_HTTPCLIENT (" [HTTP-Client][handleHeaderResponse] Transfer-Encoding: %s\n " , transferEncoding.c_str ());
764+ if (transferEncoding.equalsIgnoreCase (" chunked" )) {
765+ _transferEncoding = HTTPC_TE_CHUNKED;
766+ } else {
767+ return HTTPC_ERROR_ENCODING;
768+ }
769+ } else {
770+ _transferEncoding = HTTPC_TE_IDENTITY;
771+ }
772+
775773 if (_returnCode) {
776774 return _returnCode;
777775 } else {
@@ -787,3 +785,87 @@ int HTTPClient::handleHeaderResponse() {
787785
788786 return HTTPC_ERROR_CONNECTION_LOST;
789787}
788+
789+
790+
791+ /* *
792+ *
793+ * @param stream
794+ * @param len
795+ * @return
796+ */
797+ int HTTPClient::writeToStreamDataBlock (Stream * stream, int size) {
798+ int buff_size = HTTP_TCP_BUFFER_SIZE;
799+ int len = size;
800+ int bytesWritten = 0 ;
801+
802+ // if possible create smaller buffer then HTTP_TCP_BUFFER_SIZE
803+ if ((len > 0 ) && (len < HTTP_TCP_BUFFER_SIZE)) {
804+ buff_size = len;
805+ }
806+
807+ // create buffer for read
808+ uint8_t * buff = (uint8_t *) malloc (buff_size);
809+
810+ if (buff) {
811+ // read all data from server
812+ while (connected () && (len > 0 || len == -1 )) {
813+
814+ // get available data size
815+ size_t sizeAvailable = _tcp->available ();
816+
817+ if (sizeAvailable) {
818+
819+ int readBytes = sizeAvailable;
820+
821+ // read only the asked bytes
822+ if (readBytes > len) {
823+ readBytes = len;
824+ }
825+
826+ // not read more the buffer can handle
827+ if (readBytes > buff_size) {
828+ readBytes = buff_size;
829+ }
830+
831+ // read data
832+ int c = _tcp->readBytes (buff, readBytes);
833+
834+ // write it to Stream
835+ int w = stream->write (buff, c);
836+ bytesWritten += w;
837+ if (w != c) {
838+ DEBUG_HTTPCLIENT (" [HTTP-Client][writeToStreamDataBlock] short write asked for %d but got %d\n " , c, w);
839+ break ;
840+ }
841+
842+ if (stream->getWriteError ()) {
843+ DEBUG_HTTPCLIENT (" [HTTP-Client][writeToStreamDataBlock] stream write error %d\n " , stream->getWriteError ());
844+ break ;
845+ }
846+
847+ if (len > 0 ) {
848+ len -= c;
849+ }
850+
851+ delay (0 );
852+ } else {
853+ delay (1 );
854+ }
855+ }
856+
857+ free (buff);
858+
859+ DEBUG_HTTPCLIENT (" [HTTP-Client][writeToStreamDataBlock] connection closed or file end (written: %d).\n " , bytesWritten);
860+
861+ if ((size > 0 ) && (size != bytesWritten)) {
862+ DEBUG_HTTPCLIENT (" [HTTP-Client][writeToStreamDataBlock] bytesWritten %d and size %d mismatch!.\n " , bytesWritten, size);
863+ }
864+
865+ } else {
866+ DEBUG_HTTPCLIENT (" [HTTP-Client][writeToStreamDataBlock] too less ram! need %d\n " , HTTP_TCP_BUFFER_SIZE);
867+ return HTTPC_ERROR_TOO_LESS_RAM;
868+ }
869+
870+ return bytesWritten;
871+ }
0 commit comments