Added const char* flavors to reduce heap usage and fragmentation during String objects copy

This commit is contained in:
Mathieu Carbou
2024-08-08 12:23:46 +02:00
parent 843f07334a
commit a9afafb4ad
6 changed files with 155 additions and 144 deletions

View File

@@ -230,18 +230,12 @@ class AsyncWebSocketClient {
size_t queueLen() const; size_t queueLen() const;
size_t printf(const char* format, ...) __attribute__((format(printf, 2, 3))); size_t printf(const char* format, ...) __attribute__((format(printf, 2, 3)));
#ifndef ESP32
size_t printf_P(PGM_P formatP, ...) __attribute__((format(printf, 2, 3)));
#endif
void text(AsyncWebSocketSharedBuffer buffer); void text(AsyncWebSocketSharedBuffer buffer);
void text(const uint8_t* message, size_t len); void text(const uint8_t* message, size_t len);
void text(const char* message, size_t len); void text(const char* message, size_t len);
void text(const char* message); void text(const char* message);
void text(const String& message); void text(const String& message);
#ifndef ESP32
void text(const __FlashStringHelper* message);
#endif // ESP32
void text(AsyncWebSocketMessageBuffer* buffer); void text(AsyncWebSocketMessageBuffer* buffer);
void binary(AsyncWebSocketSharedBuffer buffer); void binary(AsyncWebSocketSharedBuffer buffer);
@@ -249,9 +243,6 @@ class AsyncWebSocketClient {
void binary(const char* message, size_t len); void binary(const char* message, size_t len);
void binary(const char* message); void binary(const char* message);
void binary(const String& message); void binary(const String& message);
#ifndef ESP32
void binary(const __FlashStringHelper* message, size_t len);
#endif // ESP32
void binary(AsyncWebSocketMessageBuffer* buffer); void binary(AsyncWebSocketMessageBuffer* buffer);
bool canSend() const; bool canSend() const;
@@ -263,6 +254,12 @@ class AsyncWebSocketClient {
void _onTimeout(uint32_t time); void _onTimeout(uint32_t time);
void _onDisconnect(); void _onDisconnect();
void _onData(void* pbuf, size_t plen); void _onData(void* pbuf, size_t plen);
#ifdef ESP8266
size_t printf_P(PGM_P formatP, ...) __attribute__((format(printf, 2, 3)));
void text(const __FlashStringHelper* message);
void binary(const __FlashStringHelper* message, size_t len);
#endif
}; };
using AwsHandshakeHandler = std::function<bool(AsyncWebServerRequest* request)>; using AwsHandshakeHandler = std::function<bool(AsyncWebServerRequest* request)>;
@@ -308,17 +305,11 @@ class AsyncWebSocket : public AsyncWebHandler {
void text(uint32_t id, const String& message); void text(uint32_t id, const String& message);
void text(uint32_t id, AsyncWebSocketMessageBuffer* buffer); void text(uint32_t id, AsyncWebSocketMessageBuffer* buffer);
void text(uint32_t id, AsyncWebSocketSharedBuffer buffer); void text(uint32_t id, AsyncWebSocketSharedBuffer buffer);
#ifdef ESP8266
void text(uint32_t id, const __FlashStringHelper* message);
#endif // ESP8266
void textAll(const uint8_t* message, size_t len); void textAll(const uint8_t* message, size_t len);
void textAll(const char* message, size_t len); void textAll(const char* message, size_t len);
void textAll(const char* message); void textAll(const char* message);
void textAll(const String& message); void textAll(const String& message);
#ifdef ESP8266
void textAll(const __FlashStringHelper* message);
#endif // ESP8266
void textAll(AsyncWebSocketMessageBuffer* buffer); void textAll(AsyncWebSocketMessageBuffer* buffer);
void textAll(AsyncWebSocketSharedBuffer buffer); void textAll(AsyncWebSocketSharedBuffer buffer);
@@ -326,9 +317,6 @@ class AsyncWebSocket : public AsyncWebHandler {
void binary(uint32_t id, const char* message, size_t len); void binary(uint32_t id, const char* message, size_t len);
void binary(uint32_t id, const char* message); void binary(uint32_t id, const char* message);
void binary(uint32_t id, const String& message); void binary(uint32_t id, const String& message);
#ifdef ESP8266
void binary(uint32_t id, const __FlashStringHelper* message, size_t len);
#endif // ESP8266
void binary(uint32_t id, AsyncWebSocketMessageBuffer* buffer); void binary(uint32_t id, AsyncWebSocketMessageBuffer* buffer);
void binary(uint32_t id, AsyncWebSocketSharedBuffer buffer); void binary(uint32_t id, AsyncWebSocketSharedBuffer buffer);
@@ -336,9 +324,6 @@ class AsyncWebSocket : public AsyncWebHandler {
void binaryAll(const char* message, size_t len); void binaryAll(const char* message, size_t len);
void binaryAll(const char* message); void binaryAll(const char* message);
void binaryAll(const String& message); void binaryAll(const String& message);
#ifdef ESP8266
void binaryAll(const __FlashStringHelper* message, size_t len);
#endif // ESP8266
void binaryAll(AsyncWebSocketMessageBuffer* buffer); void binaryAll(AsyncWebSocketMessageBuffer* buffer);
void binaryAll(AsyncWebSocketSharedBuffer buffer); void binaryAll(AsyncWebSocketSharedBuffer buffer);
@@ -346,6 +331,10 @@ class AsyncWebSocket : public AsyncWebHandler {
size_t printfAll(const char* format, ...) __attribute__((format(printf, 2, 3))); size_t printfAll(const char* format, ...) __attribute__((format(printf, 2, 3)));
#ifdef ESP8266 #ifdef ESP8266
void text(uint32_t id, const __FlashStringHelper* message);
void textAll(const __FlashStringHelper* message);
void binary(uint32_t id, const __FlashStringHelper* message, size_t len);
void binaryAll(const __FlashStringHelper* message, size_t len);
size_t printf_P(uint32_t id, PGM_P formatP, ...) __attribute__((format(printf, 3, 4))); size_t printf_P(uint32_t id, PGM_P formatP, ...) __attribute__((format(printf, 3, 4)));
size_t printfAll_P(PGM_P formatP, ...) __attribute__((format(printf, 2, 3))); size_t printfAll_P(PGM_P formatP, ...) __attribute__((format(printf, 2, 3)));
#endif #endif

View File

@@ -35,10 +35,10 @@
#include <ESP8266WiFi.h> #include <ESP8266WiFi.h>
#include <ESPAsyncTCP.h> #include <ESPAsyncTCP.h>
#elif defined(TARGET_RP2040) #elif defined(TARGET_RP2040)
#include <WiFi.h>
#include <AsyncTCP_RP2040W.h> #include <AsyncTCP_RP2040W.h>
#include <http_parser.h>
#include <HTTP_Method.h> #include <HTTP_Method.h>
#include <WiFi.h>
#include <http_parser.h>
#else #else
#error Platform not supported #error Platform not supported
#endif #endif
@@ -68,11 +68,11 @@ class AsyncStaticWebHandler;
class AsyncCallbackWebHandler; class AsyncCallbackWebHandler;
class AsyncResponseStream; class AsyncResponseStream;
#if defined (TARGET_RP2040) #if defined(TARGET_RP2040)
typedef enum http_method WebRequestMethod; typedef enum http_method WebRequestMethod;
#else #else
#ifndef WEBSERVER_H #ifndef WEBSERVER_H
typedef enum { typedef enum {
HTTP_GET = 0b00000001, HTTP_GET = 0b00000001,
HTTP_POST = 0b00000010, HTTP_POST = 0b00000010,
HTTP_DELETE = 0b00000100, HTTP_DELETE = 0b00000100,
@@ -81,7 +81,7 @@ class AsyncResponseStream;
HTTP_HEAD = 0b00100000, HTTP_HEAD = 0b00100000,
HTTP_OPTIONS = 0b01000000, HTTP_OPTIONS = 0b01000000,
HTTP_ANY = 0b01111111, HTTP_ANY = 0b01111111,
} WebRequestMethod; } WebRequestMethod;
#endif #endif
#endif #endif
@@ -138,6 +138,7 @@ class AsyncWebHeader {
AsyncWebHeader() = default; AsyncWebHeader() = default;
AsyncWebHeader(const AsyncWebHeader&) = default; AsyncWebHeader(const AsyncWebHeader&) = default;
AsyncWebHeader(const char* name, const char* value) : _name(name), _value(value) {}
AsyncWebHeader(const String& name, const String& value) : _name(name), _value(value) {} AsyncWebHeader(const String& name, const String& value) : _name(name), _value(value) {}
AsyncWebHeader(const String& data) { AsyncWebHeader(const String& data) {
if (!data) if (!data)
@@ -293,14 +294,37 @@ class AsyncWebServerRequest {
void redirect(const String& url) { return redirect(url.c_str()); }; void redirect(const String& url) { return redirect(url.c_str()); };
void send(AsyncWebServerResponse* response); void send(AsyncWebServerResponse* response);
void send(int code, const String& contentType = emptyString, const String& content = emptyString);
void send(int code, const String& contentType, const uint8_t* content, size_t len, AwsTemplateProcessor callback = nullptr); void send(int code, const char* contentType = "", const char* content = "", AwsTemplateProcessor callback = nullptr) { send(beginResponse(code, contentType, content, callback)); }
void send(int code, const String& contentType, PGM_P content, AwsTemplateProcessor callback = nullptr); void send(int code, const String& contentType, const String& content = emptyString, AwsTemplateProcessor callback = nullptr) { send(beginResponse(code, contentType, content, callback)); }
void send(FS& fs, const String& path, const String& contentType = emptyString, bool download = false, AwsTemplateProcessor callback = nullptr);
void send(File content, const String& path, const String& contentType = emptyString, bool download = false, AwsTemplateProcessor callback = nullptr); void send(int code, const char* contentType, const uint8_t* content, size_t len, AwsTemplateProcessor callback = nullptr) { send(beginResponse(code, contentType, content, len, callback)); }
void send(Stream& stream, const String& contentType, size_t len, AwsTemplateProcessor callback = nullptr); void send(int code, const String& contentType, const uint8_t* content, size_t len, AwsTemplateProcessor callback = nullptr) { send(beginResponse(code, contentType, content, len, callback)); }
void send(const String& contentType, size_t len, AwsResponseFiller callback, AwsTemplateProcessor templateCallback = nullptr);
void sendChunked(const String& contentType, AwsResponseFiller callback, AwsTemplateProcessor templateCallback = nullptr); void send(FS& fs, const String& path, const char* contentType = "", bool download = false, AwsTemplateProcessor callback = nullptr) {
if (fs.exists(path) || (!download && fs.exists(path + asyncsrv::T__gz))) {
send(beginResponse(fs, path, contentType, download, callback));
} else
send(404);
}
void send(FS& fs, const String& path, const String& contentType = emptyString, bool download = false, AwsTemplateProcessor callback = nullptr) { send(fs, path, contentType.c_str(), download, callback); }
void send(File content, const String& path, const char* contentType = "", bool download = false, AwsTemplateProcessor callback = nullptr) {
if (content) {
send(beginResponse(content, path, contentType, download, callback));
} else
send(404);
}
void send(File content, const String& path, const String& contentType = emptyString, bool download = false, AwsTemplateProcessor callback = nullptr) { send(content, path, contentType.c_str(), download, callback); }
void send(Stream& stream, const char* contentType, size_t len, AwsTemplateProcessor callback = nullptr) { send(beginResponse(stream, contentType, len, callback)); }
void send(Stream& stream, const String& contentType, size_t len, AwsTemplateProcessor callback = nullptr) { send(beginResponse(stream, contentType, len, callback)); }
void send(const char* contentType, size_t len, AwsResponseFiller callback, AwsTemplateProcessor templateCallback = nullptr) { send(beginResponse(contentType, len, callback, templateCallback)); }
void send(const String& contentType, size_t len, AwsResponseFiller callback, AwsTemplateProcessor templateCallback = nullptr) { send(beginResponse(contentType, len, callback, templateCallback)); }
void sendChunked(const char* contentType, AwsResponseFiller callback, AwsTemplateProcessor templateCallback = nullptr) { send(beginChunkedResponse(contentType, callback, templateCallback)); }
void sendChunked(const String& contentType, AwsResponseFiller callback, AwsTemplateProcessor templateCallback = nullptr) { send(beginChunkedResponse(contentType, callback, templateCallback)); }
[[deprecated("Replaced by send(...)")]] [[deprecated("Replaced by send(...)")]]
void send_P(int code, const String& contentType, const uint8_t* content, size_t len, AwsTemplateProcessor callback = nullptr) { void send_P(int code, const String& contentType, const uint8_t* content, size_t len, AwsTemplateProcessor callback = nullptr) {
@@ -311,16 +335,33 @@ class AsyncWebServerRequest {
send(code, contentType, content, callback); send(code, contentType, content, callback);
} }
AsyncWebServerResponse* beginResponse(int code, const String& contentType = emptyString, const String& content = emptyString); #ifdef ESP8266
AsyncWebServerResponse* beginResponse(int code, const String& contentType, const uint8_t* content, size_t len, AwsTemplateProcessor callback = nullptr); void send(int code, const String& contentType, PGM_P content, AwsTemplateProcessor callback = nullptr) { send(beginResponse(code, contentType, content, callback)); }
AsyncWebServerResponse* beginResponse(int code, const String& contentType, PGM_P content, AwsTemplateProcessor callback = nullptr); #endif
AsyncWebServerResponse* beginResponse(FS& fs, const String& path, const String& contentType = emptyString, bool download = false, AwsTemplateProcessor callback = nullptr);
AsyncWebServerResponse* beginResponse(File content, const String& path, const String& contentType = emptyString, bool download = false, AwsTemplateProcessor callback = nullptr);
AsyncWebServerResponse* beginResponse(Stream& stream, const String& contentType, size_t len, AwsTemplateProcessor callback = nullptr);
AsyncWebServerResponse* beginResponse(const String& contentType, size_t len, AwsResponseFiller callback, AwsTemplateProcessor templateCallback = nullptr);
AsyncWebServerResponse* beginChunkedResponse(const String& contentType, AwsResponseFiller callback, AwsTemplateProcessor templateCallback = nullptr);
AsyncResponseStream* beginResponseStream(const String& contentType, size_t bufferSize = 1460);
AsyncWebServerResponse* beginResponse(int code, const char* contentType = "", const char* content = "", AwsTemplateProcessor callback = nullptr);
AsyncWebServerResponse* beginResponse(int code, const String& contentType, const String& content = emptyString, AwsTemplateProcessor callback = nullptr) { return beginResponse(code, contentType.c_str(), content.c_str(), callback); }
AsyncWebServerResponse* beginResponse(int code, const char* contentType, const uint8_t* content, size_t len, AwsTemplateProcessor callback = nullptr);
AsyncWebServerResponse* beginResponse(int code, const String& contentType, const uint8_t* content, size_t len, AwsTemplateProcessor callback = nullptr) { return beginResponse(code, contentType.c_str(), content, len, callback); }
AsyncWebServerResponse* beginResponse(FS& fs, const String& path, const char* contentType = "", bool download = false, AwsTemplateProcessor callback = nullptr);
AsyncWebServerResponse* beginResponse(FS& fs, const String& path, const String& contentType = emptyString, bool download = false, AwsTemplateProcessor callback = nullptr) { return beginResponse(fs, path, contentType.c_str(), download, callback); }
AsyncWebServerResponse* beginResponse(File content, const String& path, const char* contentType = "", bool download = false, AwsTemplateProcessor callback = nullptr);
AsyncWebServerResponse* beginResponse(File content, const String& path, const String& contentType = emptyString, bool download = false, AwsTemplateProcessor callback = nullptr) { return beginResponse(content, path, contentType.c_str(), download, callback); }
AsyncWebServerResponse* beginResponse(Stream& stream, const char* contentType, size_t len, AwsTemplateProcessor callback = nullptr);
AsyncWebServerResponse* beginResponse(Stream& stream, const String& contentType, size_t len, AwsTemplateProcessor callback = nullptr) { return beginResponse(stream, contentType.c_str(), len, callback); }
AsyncWebServerResponse* beginResponse(const char* contentType, size_t len, AwsResponseFiller callback, AwsTemplateProcessor templateCallback = nullptr);
AsyncWebServerResponse* beginResponse(const String& contentType, size_t len, AwsResponseFiller callback, AwsTemplateProcessor templateCallback = nullptr) { return beginResponse(contentType.c_str(), len, callback, templateCallback); }
AsyncWebServerResponse* beginChunkedResponse(const char* contentType, AwsResponseFiller callback, AwsTemplateProcessor templateCallback = nullptr);
AsyncWebServerResponse* beginChunkedResponse(const String& contentType, AwsResponseFiller callback, AwsTemplateProcessor templateCallback = nullptr);
AsyncResponseStream* beginResponseStream(const char* contentType, size_t bufferSize = 1460);
AsyncResponseStream* beginResponseStream(const String& contentType, size_t bufferSize = 1460) { return beginResponseStream(contentType.c_str(), bufferSize); }
[[deprecated("Replaced by beginResponse(...)")]] [[deprecated("Replaced by beginResponse(...)")]]
AsyncWebServerResponse* beginResponse_P(int code, const String& contentType, const uint8_t* content, size_t len, AwsTemplateProcessor callback = nullptr) { AsyncWebServerResponse* beginResponse_P(int code, const String& contentType, const uint8_t* content, size_t len, AwsTemplateProcessor callback = nullptr) {
@@ -331,6 +372,10 @@ class AsyncWebServerRequest {
return beginResponse(code, contentType, content, callback); return beginResponse(code, contentType, content, callback);
} }
#ifdef ESP8266
AsyncWebServerResponse* beginResponse(int code, const String& contentType, PGM_P content, AwsTemplateProcessor callback = nullptr);
#endif
size_t headers() const; // get header count size_t headers() const; // get header count
// check if header exists // check if header exists
@@ -348,7 +393,8 @@ class AsyncWebServerRequest {
const AsyncWebHeader* getHeader(size_t num) const; const AsyncWebHeader* getHeader(size_t num) const;
size_t params() const; // get arguments count size_t params() const; // get arguments count
bool hasParam(const String& name, bool post = false, bool file = false) const; bool hasParam(const char* name, bool post = false, bool file = false) const;
bool hasParam(const String& name, bool post = false, bool file = false) const { return hasParam(name.c_str(), post, file); };
#ifdef ESP8266 #ifdef ESP8266
bool hasParam(const __FlashStringHelper* data, bool post = false, bool file = false) const { return hasParam(String(data).c_str(), post, file); }; bool hasParam(const __FlashStringHelper* data, bool post = false, bool file = false) const { return hasParam(String(data).c_str(), post, file); };
#endif #endif
@@ -526,8 +572,10 @@ class AsyncWebServerResponse {
virtual ~AsyncWebServerResponse(); virtual ~AsyncWebServerResponse();
virtual void setCode(int code); virtual void setCode(int code);
virtual void setContentLength(size_t len); virtual void setContentLength(size_t len);
virtual void setContentType(const String& type); void setContentType(const String& type) { setContentType(type.c_str()); }
virtual void addHeader(const String& name, const String& value); virtual void setContentType(const char* type);
virtual void addHeader(const char* name, const char* value);
void addHeader(const String& name, const String& value) { addHeader(name.c_str(), value.c_str()); }
virtual String _assembleHead(uint8_t version); virtual String _assembleHead(uint8_t version);
virtual bool _started() const; virtual bool _started() const;
virtual bool _finished() const; virtual bool _finished() const;

View File

@@ -231,16 +231,16 @@ void AsyncStaticWebHandler::handleRequest(AsyncWebServerRequest* request) {
} else if (_cache_control.length() && request->hasHeader(T_INM) && request->header(T_INM).equals(etag)) { } else if (_cache_control.length() && request->hasHeader(T_INM) && request->header(T_INM).equals(etag)) {
request->_tempFile.close(); request->_tempFile.close();
AsyncWebServerResponse* response = new AsyncBasicResponse(304); // Not modified AsyncWebServerResponse* response = new AsyncBasicResponse(304); // Not modified
response->addHeader(T_Cache_Control, _cache_control); response->addHeader(T_Cache_Control, _cache_control.c_str());
response->addHeader(T_ETag, etag); response->addHeader(T_ETag, etag.c_str());
request->send(response); request->send(response);
} else { } else {
AsyncWebServerResponse* response = new AsyncFileResponse(request->_tempFile, filename, String(), false, _callback); AsyncWebServerResponse* response = new AsyncFileResponse(request->_tempFile, filename, String(), false, _callback);
if (_last_modified.length()) if (_last_modified.length())
response->addHeader(T_Last_Modified, _last_modified); response->addHeader(T_Last_Modified, _last_modified.c_str());
if (_cache_control.length()) { if (_cache_control.length()) {
response->addHeader(T_Cache_Control, _cache_control); response->addHeader(T_Cache_Control, _cache_control.c_str());
response->addHeader(T_ETag, etag); response->addHeader(T_ETag, etag.c_str());
} }
request->send(response); request->send(response);
} }

View File

@@ -307,7 +307,7 @@ bool AsyncWebServerRequest::_parseReqHeader() {
if (name.equalsIgnoreCase(T_UPGRADE) && value.equalsIgnoreCase(T_WS)) { if (name.equalsIgnoreCase(T_UPGRADE) && value.equalsIgnoreCase(T_WS)) {
// WebSocket request can be uniquely identified by header: [Upgrade: websocket] // WebSocket request can be uniquely identified by header: [Upgrade: websocket]
_reqconntype = RCT_WS; _reqconntype = RCT_WS;
} else if (name.equalsIgnoreCase(T_ACCEPT)){ } else if (name.equalsIgnoreCase(T_ACCEPT)) {
String lowcase(value); String lowcase(value);
lowcase.toLowerCase(); lowcase.toLowerCase();
#ifndef ESP8266 #ifndef ESP8266
@@ -654,9 +654,9 @@ size_t AsyncWebServerRequest::params() const {
return _params.size(); return _params.size();
} }
bool AsyncWebServerRequest::hasParam(const String& name, bool post, bool file) const { bool AsyncWebServerRequest::hasParam(const char* name, bool post, bool file) const {
for (const auto& p : _params) { for (const auto& p : _params) {
if (p.name() == name && p.isPost() == post && p.isFile() == file) { if (p.name().equals(name) && p.isPost() == post && p.isFile() == file) {
return true; return true;
} }
} }
@@ -689,48 +689,52 @@ void AsyncWebServerRequest::addInterestingHeader(const char* name) {
_interestingHeaders.emplace_back(name); _interestingHeaders.emplace_back(name);
} }
AsyncWebServerResponse* AsyncWebServerRequest::beginResponse(int code, const String& contentType, const String& content) { AsyncWebServerResponse* AsyncWebServerRequest::beginResponse(int code, const char* contentType, const char* content, AwsTemplateProcessor callback) {
if (callback)
return new AsyncProgmemResponse(code, contentType, (const uint8_t*)content, strlen(content), callback);
return new AsyncBasicResponse(code, contentType, content); return new AsyncBasicResponse(code, contentType, content);
} }
AsyncWebServerResponse* AsyncWebServerRequest::beginResponse(int code, const String& contentType, const uint8_t* content, size_t len, AwsTemplateProcessor callback) { AsyncWebServerResponse* AsyncWebServerRequest::beginResponse(int code, const char* contentType, const uint8_t* content, size_t len, AwsTemplateProcessor callback) {
return new AsyncProgmemResponse(code, contentType, content, len, callback); return new AsyncProgmemResponse(code, contentType, content, len, callback);
} }
AsyncWebServerResponse* AsyncWebServerRequest::beginResponse(int code, const String& contentType, PGM_P content, AwsTemplateProcessor callback) { AsyncWebServerResponse* AsyncWebServerRequest::beginResponse(FS& fs, const String& path, const char* contentType, bool download, AwsTemplateProcessor callback) {
return new AsyncProgmemResponse(code, contentType, (const uint8_t*)content, strlen_P(content), callback);
}
AsyncWebServerResponse* AsyncWebServerRequest::beginResponse(FS& fs, const String& path, const String& contentType, bool download, AwsTemplateProcessor callback) {
if (fs.exists(path) || (!download && fs.exists(path + T__gz))) if (fs.exists(path) || (!download && fs.exists(path + T__gz)))
return new AsyncFileResponse(fs, path, contentType, download, callback); return new AsyncFileResponse(fs, path, contentType, download, callback);
return NULL; return NULL;
} }
AsyncWebServerResponse* AsyncWebServerRequest::beginResponse(File content, const String& path, const String& contentType, bool download, AwsTemplateProcessor callback) { AsyncWebServerResponse* AsyncWebServerRequest::beginResponse(File content, const String& path, const char* contentType, bool download, AwsTemplateProcessor callback) {
if (content == true) if (content == true)
return new AsyncFileResponse(content, path, contentType, download, callback); return new AsyncFileResponse(content, path, contentType, download, callback);
return NULL; return NULL;
} }
AsyncWebServerResponse* AsyncWebServerRequest::beginResponse(Stream& stream, const String& contentType, size_t len, AwsTemplateProcessor callback) { AsyncWebServerResponse* AsyncWebServerRequest::beginResponse(Stream& stream, const char* contentType, size_t len, AwsTemplateProcessor callback) {
return new AsyncStreamResponse(stream, contentType, len, callback); return new AsyncStreamResponse(stream, contentType, len, callback);
} }
AsyncWebServerResponse* AsyncWebServerRequest::beginResponse(const String& contentType, size_t len, AwsResponseFiller callback, AwsTemplateProcessor templateCallback) { AsyncWebServerResponse* AsyncWebServerRequest::beginResponse(const char* contentType, size_t len, AwsResponseFiller callback, AwsTemplateProcessor templateCallback) {
return new AsyncCallbackResponse(contentType, len, callback, templateCallback); return new AsyncCallbackResponse(contentType, len, callback, templateCallback);
} }
AsyncWebServerResponse* AsyncWebServerRequest::beginChunkedResponse(const String& contentType, AwsResponseFiller callback, AwsTemplateProcessor templateCallback) { AsyncWebServerResponse* AsyncWebServerRequest::beginChunkedResponse(const char* contentType, AwsResponseFiller callback, AwsTemplateProcessor templateCallback) {
if (_version) if (_version)
return new AsyncChunkedResponse(contentType, callback, templateCallback); return new AsyncChunkedResponse(contentType, callback, templateCallback);
return new AsyncCallbackResponse(contentType, 0, callback, templateCallback); return new AsyncCallbackResponse(contentType, 0, callback, templateCallback);
} }
AsyncResponseStream* AsyncWebServerRequest::beginResponseStream(const String& contentType, size_t bufferSize) { AsyncResponseStream* AsyncWebServerRequest::beginResponseStream(const char* contentType, size_t bufferSize) {
return new AsyncResponseStream(contentType, bufferSize); return new AsyncResponseStream(contentType, bufferSize);
} }
#ifdef ESP8266
AsyncWebServerResponse* AsyncWebServerRequest::beginResponse(int code, const String& contentType, PGM_P content, AwsTemplateProcessor callback) {
return new AsyncProgmemResponse(code, contentType, (const uint8_t*)content, strlen_P(content), callback);
}
#endif
void AsyncWebServerRequest::send(AsyncWebServerResponse* response) { void AsyncWebServerRequest::send(AsyncWebServerResponse* response) {
_response = response; _response = response;
if (_response == NULL) { if (_response == NULL) {
@@ -748,44 +752,6 @@ void AsyncWebServerRequest::send(AsyncWebServerResponse* response) {
} }
} }
void AsyncWebServerRequest::send(int code, const String& contentType, const String& content) {
send(beginResponse(code, contentType, content));
}
void AsyncWebServerRequest::send(int code, const String& contentType, const uint8_t* content, size_t len, AwsTemplateProcessor callback) {
send(beginResponse(code, contentType, content, len, callback));
}
void AsyncWebServerRequest::send(int code, const String& contentType, PGM_P content, AwsTemplateProcessor callback) {
send(beginResponse(code, contentType, content, callback));
}
void AsyncWebServerRequest::send(FS& fs, const String& path, const String& contentType, bool download, AwsTemplateProcessor callback) {
if (fs.exists(path) || (!download && fs.exists(path + T__gz))) {
send(beginResponse(fs, path, contentType, download, callback));
} else
send(404);
}
void AsyncWebServerRequest::send(File content, const String& path, const String& contentType, bool download, AwsTemplateProcessor callback) {
if (content == true) {
send(beginResponse(content, path, contentType, download, callback));
} else
send(404);
}
void AsyncWebServerRequest::send(Stream& stream, const String& contentType, size_t len, AwsTemplateProcessor callback) {
send(beginResponse(stream, contentType, len, callback));
}
void AsyncWebServerRequest::send(const String& contentType, size_t len, AwsResponseFiller callback, AwsTemplateProcessor templateCallback) {
send(beginResponse(contentType, len, callback, templateCallback));
}
void AsyncWebServerRequest::sendChunked(const String& contentType, AwsResponseFiller callback, AwsTemplateProcessor templateCallback) {
send(beginChunkedResponse(contentType, callback, templateCallback));
}
void AsyncWebServerRequest::redirect(const char* url) { void AsyncWebServerRequest::redirect(const char* url) {
AsyncWebServerResponse* response = beginResponse(302); AsyncWebServerResponse* response = beginResponse(302);
response->addHeader(T_LOCATION, url); response->addHeader(T_LOCATION, url);
@@ -834,11 +800,11 @@ void AsyncWebServerRequest::requestAuthentication(const char* realm, bool isDige
String header(T_BASIC_REALM); String header(T_BASIC_REALM);
header.concat(realm); header.concat(realm);
header += '"'; header += '"';
r->addHeader(T_WWW_AUTH, header); r->addHeader(T_WWW_AUTH, header.c_str());
} else { } else {
String header(T_DIGEST_); String header(T_DIGEST_);
header.concat(requestDigestAuthentication(realm)); header.concat(requestDigestAuthentication(realm));
r->addHeader(T_WWW_AUTH, header); r->addHeader(T_WWW_AUTH, header.c_str());
} }
send(r); send(r);
} }

View File

@@ -36,7 +36,8 @@ class AsyncBasicResponse : public AsyncWebServerResponse {
String _content; String _content;
public: public:
AsyncBasicResponse(int code, const String& contentType = emptyString, const String& content = emptyString); AsyncBasicResponse(int code, const char* contentType = "", const char* content = "");
AsyncBasicResponse(int code, const String& contentType, const String& content = emptyString) : AsyncBasicResponse(code, contentType.c_str(), content.c_str()) {}
void _respond(AsyncWebServerRequest* request); void _respond(AsyncWebServerRequest* request);
size_t _ack(AsyncWebServerRequest* request, size_t len, uint32_t time); size_t _ack(AsyncWebServerRequest* request, size_t len, uint32_t time);
bool _sourceValid() const { return true; } bool _sourceValid() const { return true; }
@@ -76,11 +77,13 @@ class AsyncFileResponse : public AsyncAbstractResponse {
private: private:
File _content; File _content;
String _path; String _path;
void _setContentType(const String& path); void _setContentTypeFromPath(const String& path);
public: public:
AsyncFileResponse(FS& fs, const String& path, const String& contentType = emptyString, bool download = false, AwsTemplateProcessor callback = nullptr); AsyncFileResponse(FS& fs, const String& path, const char* contentType = "", bool download = false, AwsTemplateProcessor callback = nullptr);
AsyncFileResponse(File content, const String& path, const String& contentType = emptyString, bool download = false, AwsTemplateProcessor callback = nullptr); AsyncFileResponse(FS& fs, const String& path, const String& contentType, bool download = false, AwsTemplateProcessor callback = nullptr) : AsyncFileResponse(fs, path, contentType.c_str(), download, callback) {}
AsyncFileResponse(File content, const String& path, const char* contentType = "", bool download = false, AwsTemplateProcessor callback = nullptr);
AsyncFileResponse(File content, const String& path, const String& contentType, bool download = false, AwsTemplateProcessor callack = nullptr) : AsyncFileResponse(content, path, contentType.c_str(), download, callack) {}
~AsyncFileResponse(); ~AsyncFileResponse();
bool _sourceValid() const { return !!(_content); } bool _sourceValid() const { return !!(_content); }
virtual size_t _fillBuffer(uint8_t* buf, size_t maxLen) override; virtual size_t _fillBuffer(uint8_t* buf, size_t maxLen) override;
@@ -91,7 +94,8 @@ class AsyncStreamResponse : public AsyncAbstractResponse {
Stream* _content; Stream* _content;
public: public:
AsyncStreamResponse(Stream& stream, const String& contentType, size_t len, AwsTemplateProcessor callback = nullptr); AsyncStreamResponse(Stream& stream, const char* contentType, size_t len, AwsTemplateProcessor callback = nullptr);
AsyncStreamResponse(Stream& stream, const String& contentType, size_t len, AwsTemplateProcessor callback = nullptr) : AsyncStreamResponse(stream, contentType.c_str(), len, callback) {}
bool _sourceValid() const { return !!(_content); } bool _sourceValid() const { return !!(_content); }
virtual size_t _fillBuffer(uint8_t* buf, size_t maxLen) override; virtual size_t _fillBuffer(uint8_t* buf, size_t maxLen) override;
}; };
@@ -102,7 +106,8 @@ class AsyncCallbackResponse : public AsyncAbstractResponse {
size_t _filledLength; size_t _filledLength;
public: public:
AsyncCallbackResponse(const String& contentType, size_t len, AwsResponseFiller callback, AwsTemplateProcessor templateCallback = nullptr); AsyncCallbackResponse(const char* contentType, size_t len, AwsResponseFiller callback, AwsTemplateProcessor templateCallback = nullptr);
AsyncCallbackResponse(const String& contentType, size_t len, AwsResponseFiller callback, AwsTemplateProcessor templateCallback = nullptr) : AsyncCallbackResponse(contentType.c_str(), len, callback, templateCallback) {}
bool _sourceValid() const { return !!(_content); } bool _sourceValid() const { return !!(_content); }
virtual size_t _fillBuffer(uint8_t* buf, size_t maxLen) override; virtual size_t _fillBuffer(uint8_t* buf, size_t maxLen) override;
}; };
@@ -113,7 +118,8 @@ class AsyncChunkedResponse : public AsyncAbstractResponse {
size_t _filledLength; size_t _filledLength;
public: public:
AsyncChunkedResponse(const String& contentType, AwsResponseFiller callback, AwsTemplateProcessor templateCallback = nullptr); AsyncChunkedResponse(const char* contentType, AwsResponseFiller callback, AwsTemplateProcessor templateCallback = nullptr);
AsyncChunkedResponse(const String& contentType, AwsResponseFiller callback, AwsTemplateProcessor templateCallback = nullptr) : AsyncChunkedResponse(contentType.c_str(), callback, templateCallback) {}
bool _sourceValid() const { return !!(_content); } bool _sourceValid() const { return !!(_content); }
virtual size_t _fillBuffer(uint8_t* buf, size_t maxLen) override; virtual size_t _fillBuffer(uint8_t* buf, size_t maxLen) override;
}; };
@@ -124,7 +130,8 @@ class AsyncProgmemResponse : public AsyncAbstractResponse {
size_t _readLength; size_t _readLength;
public: public:
AsyncProgmemResponse(int code, const String& contentType, const uint8_t* content, size_t len, AwsTemplateProcessor callback = nullptr); AsyncProgmemResponse(int code, const char* contentType, const uint8_t* content, size_t len, AwsTemplateProcessor callback = nullptr);
AsyncProgmemResponse(int code, const String& contentType, const uint8_t* content, size_t len, AwsTemplateProcessor callback = nullptr) : AsyncProgmemResponse(code, contentType.c_str(), content, len, callback) {}
bool _sourceValid() const { return true; } bool _sourceValid() const { return true; }
virtual size_t _fillBuffer(uint8_t* buf, size_t maxLen) override; virtual size_t _fillBuffer(uint8_t* buf, size_t maxLen) override;
}; };
@@ -136,7 +143,8 @@ class AsyncResponseStream : public AsyncAbstractResponse, public Print {
std::unique_ptr<cbuf> _content; std::unique_ptr<cbuf> _content;
public: public:
AsyncResponseStream(const String& contentType, size_t bufferSize); AsyncResponseStream(const char* contentType, size_t bufferSize);
AsyncResponseStream(const String& contentType, size_t bufferSize) : AsyncResponseStream(contentType.c_str(), bufferSize) {}
~AsyncResponseStream(); ~AsyncResponseStream();
bool _sourceValid() const { return (_state < RESPONSE_END); } bool _sourceValid() const { return (_state < RESPONSE_END); }
virtual size_t _fillBuffer(uint8_t* buf, size_t maxLen) override; virtual size_t _fillBuffer(uint8_t* buf, size_t maxLen) override;

View File

@@ -234,12 +234,12 @@ void AsyncWebServerResponse::setContentLength(size_t len) {
_contentLength = len; _contentLength = len;
} }
void AsyncWebServerResponse::setContentType(const String& type) { void AsyncWebServerResponse::setContentType(const char* type) {
if (_state == RESPONSE_SETUP) if (_state == RESPONSE_SETUP)
_contentType = type; _contentType = type;
} }
void AsyncWebServerResponse::addHeader(const String& name, const String& value) { void AsyncWebServerResponse::addHeader(const char* name, const char* value) {
_headers.emplace_back(name, value); _headers.emplace_back(name, value);
} }
@@ -298,7 +298,7 @@ size_t AsyncWebServerResponse::_ack(AsyncWebServerRequest* request, size_t len,
/* /*
* String/Code Response * String/Code Response
* */ * */
AsyncBasicResponse::AsyncBasicResponse(int code, const String& contentType, const String& content) { AsyncBasicResponse::AsyncBasicResponse(int code, const char* contentType, const char* content) {
_code = code; _code = code;
_content = content; _content = content;
_contentType = contentType; _contentType = contentType;
@@ -607,7 +607,7 @@ AsyncFileResponse::~AsyncFileResponse() {
_content.close(); _content.close();
} }
void AsyncFileResponse::_setContentType(const String& path) { void AsyncFileResponse::_setContentTypeFromPath(const String& path) {
#if HAVE_EXTERN_GET_Content_Type_FUNCTION #if HAVE_EXTERN_GET_Content_Type_FUNCTION
#ifndef ESP8266 #ifndef ESP8266
extern const char* getContentType(const String& path); extern const char* getContentType(const String& path);
@@ -657,7 +657,7 @@ void AsyncFileResponse::_setContentType(const String& path) {
#endif #endif
} }
AsyncFileResponse::AsyncFileResponse(FS& fs, const String& path, const String& contentType, bool download, AwsTemplateProcessor callback) : AsyncAbstractResponse(callback) { AsyncFileResponse::AsyncFileResponse(FS& fs, const String& path, const char* contentType, bool download, AwsTemplateProcessor callback) : AsyncAbstractResponse(callback) {
_code = 200; _code = 200;
_path = path; _path = path;
@@ -672,8 +672,8 @@ AsyncFileResponse::AsyncFileResponse(FS& fs, const String& path, const String& c
_content = fs.open(_path, fs::FileOpenMode::read); _content = fs.open(_path, fs::FileOpenMode::read);
_contentLength = _content.size(); _contentLength = _content.size();
if (contentType.length() == 0) if (strlen(contentType) == 0)
_setContentType(path); _setContentTypeFromPath(path);
else else
_contentType = contentType; _contentType = contentType;
@@ -691,7 +691,7 @@ AsyncFileResponse::AsyncFileResponse(FS& fs, const String& path, const String& c
addHeader(T_Content_Disposition, buf); addHeader(T_Content_Disposition, buf);
} }
AsyncFileResponse::AsyncFileResponse(File content, const String& path, const String& contentType, bool download, AwsTemplateProcessor callback) : AsyncAbstractResponse(callback) { AsyncFileResponse::AsyncFileResponse(File content, const String& path, const char* contentType, bool download, AwsTemplateProcessor callback) : AsyncAbstractResponse(callback) {
_code = 200; _code = 200;
_path = path; _path = path;
@@ -705,8 +705,8 @@ AsyncFileResponse::AsyncFileResponse(File content, const String& path, const Str
_content = content; _content = content;
_contentLength = _content.size(); _contentLength = _content.size();
if (contentType.length() == 0) if (strlen(contentType) == 0)
_setContentType(path); _setContentTypeFromPath(path);
else else
_contentType = contentType; _contentType = contentType;
@@ -730,7 +730,7 @@ size_t AsyncFileResponse::_fillBuffer(uint8_t* data, size_t len) {
* Stream Response * Stream Response
* */ * */
AsyncStreamResponse::AsyncStreamResponse(Stream& stream, const String& contentType, size_t len, AwsTemplateProcessor callback) : AsyncAbstractResponse(callback) { AsyncStreamResponse::AsyncStreamResponse(Stream& stream, const char* contentType, size_t len, AwsTemplateProcessor callback) : AsyncAbstractResponse(callback) {
_code = 200; _code = 200;
_content = &stream; _content = &stream;
_contentLength = len; _contentLength = len;
@@ -750,7 +750,7 @@ size_t AsyncStreamResponse::_fillBuffer(uint8_t* data, size_t len) {
* Callback Response * Callback Response
* */ * */
AsyncCallbackResponse::AsyncCallbackResponse(const String& contentType, size_t len, AwsResponseFiller callback, AwsTemplateProcessor templateCallback) : AsyncAbstractResponse(templateCallback) { AsyncCallbackResponse::AsyncCallbackResponse(const char* contentType, size_t len, AwsResponseFiller callback, AwsTemplateProcessor templateCallback) : AsyncAbstractResponse(templateCallback) {
_code = 200; _code = 200;
_content = callback; _content = callback;
_contentLength = len; _contentLength = len;
@@ -772,7 +772,7 @@ size_t AsyncCallbackResponse::_fillBuffer(uint8_t* data, size_t len) {
* Chunked Response * Chunked Response
* */ * */
AsyncChunkedResponse::AsyncChunkedResponse(const String& contentType, AwsResponseFiller callback, AwsTemplateProcessor processorCallback) : AsyncAbstractResponse(processorCallback) { AsyncChunkedResponse::AsyncChunkedResponse(const char* contentType, AwsResponseFiller callback, AwsTemplateProcessor processorCallback) : AsyncAbstractResponse(processorCallback) {
_code = 200; _code = 200;
_content = callback; _content = callback;
_contentLength = 0; _contentLength = 0;
@@ -794,7 +794,7 @@ size_t AsyncChunkedResponse::_fillBuffer(uint8_t* data, size_t len) {
* Progmem Response * Progmem Response
* */ * */
AsyncProgmemResponse::AsyncProgmemResponse(int code, const String& contentType, const uint8_t* content, size_t len, AwsTemplateProcessor callback) : AsyncAbstractResponse(callback) { AsyncProgmemResponse::AsyncProgmemResponse(int code, const char* contentType, const uint8_t* content, size_t len, AwsTemplateProcessor callback) : AsyncAbstractResponse(callback) {
_code = code; _code = code;
_content = content; _content = content;
_contentType = contentType; _contentType = contentType;
@@ -818,7 +818,7 @@ size_t AsyncProgmemResponse::_fillBuffer(uint8_t* data, size_t len) {
* Response Stream (You can print/write/printf to it, up to the contentLen bytes) * Response Stream (You can print/write/printf to it, up to the contentLen bytes)
* */ * */
AsyncResponseStream::AsyncResponseStream(const String& contentType, size_t bufferSize) { AsyncResponseStream::AsyncResponseStream(const char* contentType, size_t bufferSize) {
_code = 200; _code = 200;
_contentLength = 0; _contentLength = 0;
_contentType = contentType; _contentType = contentType;