Skip to content

Commit

Permalink
Expose webserver's chunk api (#7134)
Browse files Browse the repository at this point in the history
* expose hidden WebServer's chunked API
  • Loading branch information
d-a-v committed Apr 7, 2020
1 parent 3db610f commit d600cc7
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 7 deletions.
27 changes: 22 additions & 5 deletions libraries/ESP8266WebServer/examples/FSBrowser/FSBrowser.ino
Original file line number Diff line number Diff line change
Expand Up @@ -186,12 +186,27 @@ void handleFileList() {
Dir dir = filesystem->openDir(path);
path.clear();

String output = "[";
// use HTTP/1.1 Chunked response to avoid building a huge temporary string
if (!server.chunkedResponseModeStart(200, "text/json")) {
server.send(505, FPSTR("text/html"), FPSTR("HTTP1.1 required"));
return;
}

// use the same string for every line
String output;
output.reserve(64);
while (dir.next()) {
File entry = dir.openFile("r");
if (output != "[") {
output += ',';

if (output.length()) {
// send string from previous iteration
// as an HTTP chunk
server.sendContent(output);
output = ',';
} else {
output = '[';
}

File entry = dir.openFile("r");
bool isDir = false;
output += "{\"type\":\"";
output += (isDir) ? "dir" : "file";
Expand All @@ -205,8 +220,10 @@ void handleFileList() {
entry.close();
}

// send last string
output += "]";
server.send(200, "text/json", output);
server.sendContent(output);
server.chunkedResponseFinalize();
}

void setup(void) {
Expand Down
22 changes: 20 additions & 2 deletions libraries/ESP8266WebServer/src/ESP8266WebServer.h
Original file line number Diff line number Diff line change
Expand Up @@ -149,18 +149,36 @@ class ESP8266WebServerTemplate
void sendContent(const char *content) { sendContent_P(content); }
void sendContent(const char *content, size_t size) { sendContent_P(content, size); }

bool chunkedResponseModeStart_P (int code, PGM_P content_type) {
if (_currentVersion == 0)
// no chunk mode in HTTP/1.0
return false;
setContentLength(CONTENT_LENGTH_UNKNOWN);
send_P(code, content_type, "");
return true;
}
bool chunkedResponseModeStart (int code, const char* content_type) {
return chunkedResponseModeStart_P(code, content_type);
}
bool chunkedResponseModeStart (int code, const String& content_type) {
return chunkedResponseModeStart_P(code, content_type.c_str());
}
void chunkedResponseFinalize () {
sendContent(emptyString);
}

static String credentialHash(const String& username, const String& realm, const String& password);

static String urlDecode(const String& text);

// Handle a GET request by sending a response header and stream file content to response body
// Handle a GET request by sending a response header and stream file content to response body
template<typename T>
size_t streamFile(T &file, const String& contentType) {
return streamFile(file, contentType, HTTP_GET);
}

// Implement GET and HEAD requests for files.
// Stream body on HTTP_GET but not on HTTP_HEAD requests.
// Stream body on HTTP_GET but not on HTTP_HEAD requests.
template<typename T>
size_t streamFile(T &file, const String& contentType, HTTPMethod requestMethod) {
size_t contentLength = 0;
Expand Down

0 comments on commit d600cc7

Please sign in to comment.