Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit bf6aed6

Browse files
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)

AltStyle によって変換されたページ (->オリジナル) /