1
0
mirror of https://github.com/esp8266/Arduino.git synced 2025-04-19 23:22:16 +03:00

Expose webserver's chunk api (#7134)

* expose hidden WebServer's chunked API
This commit is contained in:
david gauchard 2020-04-07 02:49:34 +02:00 committed by GitHub
parent 3db610f6d0
commit d600cc7fa6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 42 additions and 7 deletions

View File

@ -186,12 +186,27 @@ void handleFileList() {
Dir dir = filesystem->openDir(path); Dir dir = filesystem->openDir(path);
path.clear(); 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()) { while (dir.next()) {
File entry = dir.openFile("r");
if (output != "[") { if (output.length()) {
output += ','; // send string from previous iteration
// as an HTTP chunk
server.sendContent(output);
output = ',';
} else {
output = '[';
} }
File entry = dir.openFile("r");
bool isDir = false; bool isDir = false;
output += "{\"type\":\""; output += "{\"type\":\"";
output += (isDir) ? "dir" : "file"; output += (isDir) ? "dir" : "file";
@ -205,8 +220,10 @@ void handleFileList() {
entry.close(); entry.close();
} }
// send last string
output += "]"; output += "]";
server.send(200, "text/json", output); server.sendContent(output);
server.chunkedResponseFinalize();
} }
void setup(void) { void setup(void) {

View File

@ -149,18 +149,36 @@ public:
void sendContent(const char *content) { sendContent_P(content); } void sendContent(const char *content) { sendContent_P(content); }
void sendContent(const char *content, size_t size) { sendContent_P(content, size); } 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 credentialHash(const String& username, const String& realm, const String& password);
static String urlDecode(const String& text); 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> template<typename T>
size_t streamFile(T &file, const String& contentType) { size_t streamFile(T &file, const String& contentType) {
return streamFile(file, contentType, HTTP_GET); return streamFile(file, contentType, HTTP_GET);
} }
// Implement GET and HEAD requests for files. // 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> template<typename T>
size_t streamFile(T &file, const String& contentType, HTTPMethod requestMethod) { size_t streamFile(T &file, const String& contentType, HTTPMethod requestMethod) {
size_t contentLength = 0; size_t contentLength = 0;