Skip to content

Commit bf6aed6

Browse files
committed
Add chunkedResponseModeStart, sendChunk, chunkedResponseFinalize
to WebServer library for chunked HTTP responses
1 parent ea382df commit bf6aed6

File tree

2 files changed

+77
-0
lines changed

2 files changed

+77
-0
lines changed

libraries/WebServer/src/WebServer.cpp

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -551,6 +551,75 @@ void WebServer::enableETag(bool enable, ETagFunction fn) {
551551
_eTagFunction = fn;
552552
}
553553

554+
void WebServer::chunkResponseBegin(const char* contentType) {
555+
if (_chunkedResponseActive) {
556+
log_e("Already in chunked response mode");
557+
return;
558+
}
559+
560+
if (strchr(contentType, '\r') || strchr(contentType, '\n')) {
561+
log_e("Invalid character in content type");
562+
return;
563+
}
564+
565+
_contentLength = CONTENT_LENGTH_UNKNOWN;
566+
567+
String header;
568+
_prepareHeader(header, 200, contentType, 0);
569+
_currentClientWrite(header.c_str(), header.length());
570+
571+
_chunkedResponseActive = true;
572+
_chunkedClient = _currentClient;
573+
}
574+
575+
void WebServer::chunkWrite(const char* data, size_t length) {
576+
if (!_chunkedResponseActive)
577+
{
578+
log_e("Chunked response has not been started");
579+
return;
580+
}
581+
582+
char chunkSize[11];
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+
604+
void WebServer::chunkResponseEnd() {
605+
if (!_chunkedResponseActive)
606+
{
607+
log_e("Chunked response has not been started");
608+
return;
609+
}
610+
611+
if (_chunkedClient.write("0\r\n\r\n", 5) != 5) {
612+
log_e("Failed to write terminating chunk");
613+
}
614+
615+
_chunkedClient.flush();
616+
_chunkedResponseActive = false;
617+
_chunked = false;
618+
_chunkedClient = NetworkClient();
619+
620+
_clearResponseHeaders();
621+
}
622+
554623
void WebServer::_prepareHeader(String &response, int code, const char *content_type, size_t contentLength) {
555624
_responseCode = code;
556625

libraries/WebServer/src/WebServer.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,10 @@ class WebServer {
115115
const String AuthTypeDigest = F("Digest");
116116
const String AuthTypeBasic = F("Basic");
117117

118+
void chunkResponseBegin(const char* contentType = "text/plain");
119+
void chunkWrite(const char* data, size_t length);
120+
void chunkResponseEnd();
121+
118122
/* Callbackhandler for authentication. The extra parameters depend on the
119123
* HTTPAuthMethod mode:
120124
*
@@ -241,6 +245,10 @@ class WebServer {
241245

242246
static String responseCodeToString(int code);
243247

248+
private:
249+
bool _chunkedResponseActive = false;
250+
NetworkClient _chunkedClient; // Store by value, no dangling pointer
251+
244252
protected:
245253
virtual size_t _currentClientWrite(const char *b, size_t l) {
246254
return _currentClient.write(b, l);

0 commit comments

Comments
 (0)