Skip to content

Commit d600cc7

Browse files
authored
Expose webserver's chunk api (#7134)
* expose hidden WebServer's chunked API
1 parent 3db610f commit d600cc7

File tree

2 files changed

+42
-7
lines changed

2 files changed

+42
-7
lines changed

Diff for: libraries/ESP8266WebServer/examples/FSBrowser/FSBrowser.ino

+22-5
Original file line numberDiff line numberDiff line change
@@ -186,12 +186,27 @@ void handleFileList() {
186186
Dir dir = filesystem->openDir(path);
187187
path.clear();
188188

189-
String output = "[";
189+
// use HTTP/1.1 Chunked response to avoid building a huge temporary string
190+
if (!server.chunkedResponseModeStart(200, "text/json")) {
191+
server.send(505, FPSTR("text/html"), FPSTR("HTTP1.1 required"));
192+
return;
193+
}
194+
195+
// use the same string for every line
196+
String output;
197+
output.reserve(64);
190198
while (dir.next()) {
191-
File entry = dir.openFile("r");
192-
if (output != "[") {
193-
output += ',';
199+
200+
if (output.length()) {
201+
// send string from previous iteration
202+
// as an HTTP chunk
203+
server.sendContent(output);
204+
output = ',';
205+
} else {
206+
output = '[';
194207
}
208+
209+
File entry = dir.openFile("r");
195210
bool isDir = false;
196211
output += "{\"type\":\"";
197212
output += (isDir) ? "dir" : "file";
@@ -205,8 +220,10 @@ void handleFileList() {
205220
entry.close();
206221
}
207222

223+
// send last string
208224
output += "]";
209-
server.send(200, "text/json", output);
225+
server.sendContent(output);
226+
server.chunkedResponseFinalize();
210227
}
211228

212229
void setup(void) {

Diff for: libraries/ESP8266WebServer/src/ESP8266WebServer.h

+20-2
Original file line numberDiff line numberDiff line change
@@ -149,18 +149,36 @@ class ESP8266WebServerTemplate
149149
void sendContent(const char *content) { sendContent_P(content); }
150150
void sendContent(const char *content, size_t size) { sendContent_P(content, size); }
151151

152+
bool chunkedResponseModeStart_P (int code, PGM_P content_type) {
153+
if (_currentVersion == 0)
154+
// no chunk mode in HTTP/1.0
155+
return false;
156+
setContentLength(CONTENT_LENGTH_UNKNOWN);
157+
send_P(code, content_type, "");
158+
return true;
159+
}
160+
bool chunkedResponseModeStart (int code, const char* content_type) {
161+
return chunkedResponseModeStart_P(code, content_type);
162+
}
163+
bool chunkedResponseModeStart (int code, const String& content_type) {
164+
return chunkedResponseModeStart_P(code, content_type.c_str());
165+
}
166+
void chunkedResponseFinalize () {
167+
sendContent(emptyString);
168+
}
169+
152170
static String credentialHash(const String& username, const String& realm, const String& password);
153171

154172
static String urlDecode(const String& text);
155173

156-
// Handle a GET request by sending a response header and stream file content to response body
174+
// Handle a GET request by sending a response header and stream file content to response body
157175
template<typename T>
158176
size_t streamFile(T &file, const String& contentType) {
159177
return streamFile(file, contentType, HTTP_GET);
160178
}
161179

162180
// Implement GET and HEAD requests for files.
163-
// Stream body on HTTP_GET but not on HTTP_HEAD requests.
181+
// Stream body on HTTP_GET but not on HTTP_HEAD requests.
164182
template<typename T>
165183
size_t streamFile(T &file, const String& contentType, HTTPMethod requestMethod) {
166184
size_t contentLength = 0;

0 commit comments

Comments
 (0)