@@ -40,6 +40,8 @@ HTTPClient::HTTPClient() {
40
40
_port = 0 ;
41
41
42
42
_reuse = false ;
43
+ _tcpTimeout = HTTPCLIENT_DEFAULT_TCP_TIMEOUT;
44
+
43
45
_https = false ;
44
46
45
47
_userAgent = " ESP8266HTTPClient" ;
@@ -50,7 +52,7 @@ HTTPClient::HTTPClient() {
50
52
_returnCode = 0 ;
51
53
_size = -1 ;
52
54
_canReuse = false ;
53
- _tcpTimeout = HTTPCLIENT_DEFAULT_TCP_TIMEOUT ;
55
+ _transferEncoding = HTTPC_TE_IDENTITY ;
54
56
55
57
}
56
58
@@ -468,61 +470,36 @@ int HTTPClient::writeToStream(Stream * stream) {
468
470
469
471
// get length of document (is -1 when Server sends no Content-Length header)
470
472
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;
503
490
}
504
-
505
- delay (0 );
491
+ ret += r;
506
492
} else {
507
- delay ( 1 ) ;
493
+ break ;
508
494
}
495
+ delay (0 );
509
496
}
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
-
519
497
} 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;
522
499
}
523
500
524
501
end ();
525
- return bytesWritten ;
502
+ return ret ;
526
503
}
527
504
528
505
/* *
@@ -567,6 +544,8 @@ String HTTPClient::errorToString(int error) {
567
544
return String (" no HTTP server" );
568
545
case HTTPC_ERROR_TOO_LESS_RAM:
569
546
return String (" too less ram" );
547
+ case HTTPC_ERROR_ENCODING:
548
+ return String (" Transfer-Encoding not supported" );
570
549
default :
571
550
return String ();
572
551
}
@@ -706,6 +685,7 @@ bool HTTPClient::sendHeader(const char * type) {
706
685
String header = String (type) + " " + _url + " HTTP/1.1\r\n "
707
686
" Host: " + _host + " \r\n "
708
687
" User-Agent: " + _userAgent + " \r\n "
688
+ " Accept-Encoding: identity;q=1 chunked;q=0.1 *;q=0\r\n "
709
689
" Connection: " ;
710
690
711
691
if (_reuse) {
@@ -733,9 +713,10 @@ int HTTPClient::handleHeaderResponse() {
733
713
if (!connected ()) {
734
714
return HTTPC_ERROR_NOT_CONNECTED;
735
715
}
736
-
716
+ String transferEncoding;
737
717
_returnCode = -1 ;
738
718
_size = -1 ;
719
+ _transferEncoding = HTTPC_TE_IDENTITY;
739
720
740
721
while (connected ()) {
741
722
size_t len = _tcp->available ();
@@ -759,6 +740,10 @@ int HTTPClient::handleHeaderResponse() {
759
740
_canReuse = headerValue.equalsIgnoreCase (" keep-alive" );
760
741
}
761
742
743
+ if (headerName.equalsIgnoreCase (" Transfer-Encoding" )) {
744
+ transferEncoding = headerValue;
745
+ }
746
+
762
747
for (size_t i = 0 ; i < _headerKeysCount; i++) {
763
748
if (_currentHeaders[i].key .equalsIgnoreCase (headerName)) {
764
749
_currentHeaders[i].value = headerValue;
@@ -769,9 +754,22 @@ int HTTPClient::handleHeaderResponse() {
769
754
770
755
if (headerLine == " " ) {
771
756
DEBUG_HTTPCLIENT (" [HTTP-Client][handleHeaderResponse] code: %d\n " , _returnCode);
772
- if (_size) {
757
+
758
+ if (_size > 0 ) {
773
759
DEBUG_HTTPCLIENT (" [HTTP-Client][handleHeaderResponse] size: %d\n " , _size);
774
760
}
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
+
775
773
if (_returnCode) {
776
774
return _returnCode;
777
775
} else {
@@ -787,3 +785,87 @@ int HTTPClient::handleHeaderResponse() {
787
785
788
786
return HTTPC_ERROR_CONNECTION_LOST;
789
787
}
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