@@ -551,6 +551,76 @@ void WebServer::enableETag(bool enable, ETagFunction fn) {
551
551
_eTagFunction = fn;
552
552
}
553
553
554
+ void WebServer::chunkedResponseModeStart (const char * contentType) {
555
+ if (_chunkedResponseActive) {
556
+ log_e (" Already in chunked response mode" );
557
+ return ;
558
+ }
559
+
560
+ // Validate contentType for CRLF injection
561
+ if (strchr (contentType, ' \r ' ) || strchr (contentType, ' \n ' )) {
562
+ log_e (" Invalid character in content type" );
563
+ return ;
564
+ }
565
+
566
+ // Tell framework response length is unknown (chunked)
567
+ _contentLength = CONTENT_LENGTH_UNKNOWN;
568
+
569
+ // Prepare and send headers properly once
570
+ String header;
571
+ _prepareHeader (header, 200 , contentType, 0 );
572
+ _currentClientWrite (header.c_str (), header.length ());
573
+
574
+ // Activate chunked mode and store client by value (safe)
575
+ _chunkedResponseActive = true ;
576
+ _chunkedClient = _currentClient;
577
+ }
578
+
579
+ void WebServer::sendChunk (const char * data, size_t length) {
580
+ if (!_chunkedResponseActive) return ;
581
+
582
+ char chunkSize[11 ]; // Enough for size_t in hex + CRLF + null
583
+ snprintf (chunkSize, sizeof (chunkSize), " %zx\r\n " , length);
584
+
585
+ if (_chunkedClient.write (chunkSize) != strlen (chunkSize)) {
586
+ log_e (" Failed to write chunk size" );
587
+ _chunkedResponseActive = false ;
588
+ return ;
589
+ }
590
+
591
+ if (_chunkedClient.write ((const uint8_t *)data, length) != length) {
592
+ log_e (" Failed to write chunk data" );
593
+ _chunkedResponseActive = false ;
594
+ return ;
595
+ }
596
+
597
+ if (_chunkedClient.write (" \r\n " ) != 2 ) {
598
+ log_e (" Failed to write chunk terminator" );
599
+ _chunkedResponseActive = false ;
600
+ return ;
601
+ }
602
+
603
+ // Optionally flush here or less frequently for better performance
604
+ // _chunkedClient.flush();
605
+ }
606
+
607
+ void WebServer::chunkedResponseFinalize () {
608
+ if (!_chunkedResponseActive) return ;
609
+
610
+ if (_chunkedClient.write (" 0\r\n\r\n " , 5 ) != 5 ) {
611
+ log_e (" Failed to write terminating chunk" );
612
+ }
613
+
614
+ _chunkedClient.flush ();
615
+
616
+ // Do NOT call stop() to allow framework to handle connection lifetime
617
+ _chunkedResponseActive = false ;
618
+ _chunked = false ;
619
+ _chunkedClient = NetworkClient ();
620
+
621
+ _clearResponseHeaders (); // Clear headers set by sendHeader()
622
+ }
623
+
554
624
void WebServer::_prepareHeader (String &response, int code, const char *content_type, size_t contentLength) {
555
625
_responseCode = code;
556
626
0 commit comments