summaryrefslogtreecommitdiff
path: root/libraries/ESP_Async_WebServer/src/WebResponseImpl.h
diff options
context:
space:
mode:
authorschererleander <leander@schererleander.de>2026-01-20 08:34:54 +0100
committerschererleander <leander@schererleander.de>2026-01-20 08:34:54 +0100
commit85ea4e995a75abe061f6fc375ea0481084dddd43 (patch)
tree7eb5d57653ecd8f041aeac4e68d7d554c1168681 /libraries/ESP_Async_WebServer/src/WebResponseImpl.h
initial commitHEADmain
Diffstat (limited to 'libraries/ESP_Async_WebServer/src/WebResponseImpl.h')
-rw-r--r--libraries/ESP_Async_WebServer/src/WebResponseImpl.h180
1 files changed, 180 insertions, 0 deletions
diff --git a/libraries/ESP_Async_WebServer/src/WebResponseImpl.h b/libraries/ESP_Async_WebServer/src/WebResponseImpl.h
new file mode 100644
index 0000000..6408625
--- /dev/null
+++ b/libraries/ESP_Async_WebServer/src/WebResponseImpl.h
@@ -0,0 +1,180 @@
+// SPDX-License-Identifier: LGPL-3.0-or-later
+// Copyright 2016-2025 Hristo Gochkov, Mathieu Carbou, Emil Muratov
+
+#ifndef ASYNCWEBSERVERRESPONSEIMPL_H_
+#define ASYNCWEBSERVERRESPONSEIMPL_H_
+
+#ifdef Arduino_h
+// arduino is not compatible with std::vector
+#undef min
+#undef max
+#endif
+#include "literals.h"
+#include <cbuf.h>
+#include <memory>
+#include <vector>
+
+// It is possible to restore these defines, but one can use _min and _max instead. Or std::min, std::max.
+
+class AsyncBasicResponse : public AsyncWebServerResponse {
+private:
+ String _content;
+
+public:
+ explicit AsyncBasicResponse(int code, const char *contentType = asyncsrv::empty, const char *content = asyncsrv::empty);
+ AsyncBasicResponse(int code, const String &contentType, const String &content = emptyString)
+ : AsyncBasicResponse(code, contentType.c_str(), content.c_str()) {}
+ void _respond(AsyncWebServerRequest *request) override final;
+ size_t _ack(AsyncWebServerRequest *request, size_t len, uint32_t time) override final;
+ bool _sourceValid() const override final {
+ return true;
+ }
+};
+
+class AsyncAbstractResponse : public AsyncWebServerResponse {
+private:
+#if ASYNCWEBSERVER_USE_CHUNK_INFLIGHT
+ // amount of response data in-flight, i.e. sent, but not acked yet
+ size_t _in_flight{0};
+ // in-flight queue credits
+ size_t _in_flight_credit{2};
+#endif
+ String _head;
+ // Data is inserted into cache at begin().
+ // This is inefficient with vector, but if we use some other container,
+ // we won't be able to access it as contiguous array of bytes when reading from it,
+ // so by gaining performance in one place, we'll lose it in another.
+ std::vector<uint8_t> _cache;
+ size_t _readDataFromCacheOrContent(uint8_t *data, const size_t len);
+ size_t _fillBufferAndProcessTemplates(uint8_t *buf, size_t maxLen);
+
+protected:
+ AwsTemplateProcessor _callback;
+
+public:
+ AsyncAbstractResponse(AwsTemplateProcessor callback = nullptr);
+ virtual ~AsyncAbstractResponse() {}
+ void _respond(AsyncWebServerRequest *request) override final;
+ size_t _ack(AsyncWebServerRequest *request, size_t len, uint32_t time) override final;
+ virtual bool _sourceValid() const {
+ return false;
+ }
+ virtual size_t _fillBuffer(uint8_t *buf __attribute__((unused)), size_t maxLen __attribute__((unused))) {
+ return 0;
+ }
+};
+
+#ifndef TEMPLATE_PLACEHOLDER
+#define TEMPLATE_PLACEHOLDER '%'
+#endif
+
+#define TEMPLATE_PARAM_NAME_LENGTH 32
+class AsyncFileResponse : public AsyncAbstractResponse {
+ using File = fs::File;
+ using FS = fs::FS;
+
+private:
+ File _content;
+ String _path;
+ void _setContentTypeFromPath(const String &path);
+
+public:
+ AsyncFileResponse(FS &fs, const String &path, const char *contentType = asyncsrv::empty, 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 = asyncsrv::empty, bool download = false, AwsTemplateProcessor callback = nullptr
+ );
+ AsyncFileResponse(File content, const String &path, const String &contentType, bool download = false, AwsTemplateProcessor callback = nullptr)
+ : AsyncFileResponse(content, path, contentType.c_str(), download, callback) {}
+ ~AsyncFileResponse() {
+ _content.close();
+ }
+ bool _sourceValid() const override final {
+ return !!(_content);
+ }
+ size_t _fillBuffer(uint8_t *buf, size_t maxLen) override final;
+};
+
+class AsyncStreamResponse : public AsyncAbstractResponse {
+private:
+ Stream *_content;
+
+public:
+ 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 override final {
+ return !!(_content);
+ }
+ size_t _fillBuffer(uint8_t *buf, size_t maxLen) override final;
+};
+
+class AsyncCallbackResponse : public AsyncAbstractResponse {
+private:
+ AwsResponseFiller _content;
+ size_t _filledLength;
+
+public:
+ 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 override final {
+ return !!(_content);
+ }
+ size_t _fillBuffer(uint8_t *buf, size_t maxLen) override final;
+};
+
+class AsyncChunkedResponse : public AsyncAbstractResponse {
+private:
+ AwsResponseFiller _content;
+ size_t _filledLength;
+
+public:
+ 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 override final {
+ return !!(_content);
+ }
+ size_t _fillBuffer(uint8_t *buf, size_t maxLen) override final;
+};
+
+class AsyncProgmemResponse : public AsyncAbstractResponse {
+private:
+ const uint8_t *_content;
+ size_t _readLength;
+
+public:
+ 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 override final {
+ return true;
+ }
+ size_t _fillBuffer(uint8_t *buf, size_t maxLen) override final;
+};
+
+class AsyncResponseStream : public AsyncAbstractResponse, public Print {
+private:
+ std::unique_ptr<cbuf> _content;
+
+public:
+ AsyncResponseStream(const char *contentType, size_t bufferSize);
+ AsyncResponseStream(const String &contentType, size_t bufferSize) : AsyncResponseStream(contentType.c_str(), bufferSize) {}
+ bool _sourceValid() const override final {
+ return (_state < RESPONSE_END);
+ }
+ size_t _fillBuffer(uint8_t *buf, size_t maxLen) override final;
+ size_t write(const uint8_t *data, size_t len);
+ size_t write(uint8_t data);
+ /**
+ * @brief Returns the number of bytes available in the stream.
+ */
+ size_t available() const {
+ return _content->available();
+ }
+ using Print::write;
+};
+
+#endif /* ASYNCWEBSERVERRESPONSEIMPL_H_ */