ESPHome 2025.6.3
Loading...
Searching...
No Matches
web_server_idf.h
Go to the documentation of this file.
1#pragma once
2#ifdef USE_ESP_IDF
5#include <esp_http_server.h>
6
7#include <functional>
8#include <list>
9#include <map>
10#include <set>
11#include <string>
12#include <utility>
13#include <vector>
14
15namespace esphome {
16#ifdef USE_WEBSERVER
17namespace web_server {
18class WebServer;
19class ListEntitiesIterator;
20}; // namespace web_server
21#endif
22namespace web_server_idf {
23
24#define F(string_literal) (string_literal)
25#define PGM_P const char *
26#define strncpy_P strncpy
27
28using String = std::string;
29
31 public:
32 AsyncWebParameter(std::string value) : value_(std::move(value)) {}
33 const std::string &value() const { return this->value_; }
34
35 protected:
36 std::string value_;
37};
38
40
42 public:
45
46 // NOLINTNEXTLINE(readability-identifier-naming)
47 void addHeader(const char *name, const char *value);
48
49 virtual const char *get_content_data() const = 0;
50 virtual size_t get_content_size() const = 0;
51
52 protected:
54};
55
57 public:
59
60 const char *get_content_data() const override { return nullptr; };
61 size_t get_content_size() const override { return 0; };
62};
63
65 public:
67 : AsyncWebServerResponse(req), content_(std::move(content)) {}
68
69 const char *get_content_data() const override { return this->content_.c_str(); };
70 size_t get_content_size() const override { return this->content_.size(); };
71
72 protected:
73 std::string content_;
74};
75
77 public:
79
80 const char *get_content_data() const override { return this->content_.c_str(); };
81 size_t get_content_size() const override { return this->content_.size(); };
82
83 void print(const char *str) { this->content_.append(str); }
84 void print(const std::string &str) { this->content_.append(str); }
85 void print(float value);
86 void printf(const char *fmt, ...) __attribute__((format(printf, 2, 3)));
87
88 protected:
89 std::string content_;
90};
91
93 public:
94 AsyncWebServerResponseProgmem(const AsyncWebServerRequest *req, const uint8_t *data, const size_t size)
95 : AsyncWebServerResponse(req), data_(data), size_(size) {}
96
97 const char *get_content_data() const override { return reinterpret_cast<const char *>(this->data_); };
98 size_t get_content_size() const override { return this->size_; };
99
100 protected:
101 const uint8_t *data_;
102 size_t size_;
103};
104
106 friend class AsyncWebServer;
107
108 public:
110
111 http_method method() const { return static_cast<http_method>(this->req_->method); }
112 std::string url() const;
113 std::string host() const;
114 // NOLINTNEXTLINE(readability-identifier-naming)
115 size_t contentLength() const { return this->req_->content_len; }
116
117 bool authenticate(const char *username, const char *password) const;
118 // NOLINTNEXTLINE(readability-identifier-naming)
119 void requestAuthentication(const char *realm = nullptr) const;
120
121 void redirect(const std::string &url);
122
123 void send(AsyncWebServerResponse *response);
124 void send(int code, const char *content_type = nullptr, const char *content = nullptr);
125 // NOLINTNEXTLINE(readability-identifier-naming)
126 AsyncWebServerResponse *beginResponse(int code, const char *content_type) {
127 auto *res = new AsyncWebServerResponseEmpty(this); // NOLINT(cppcoreguidelines-owning-memory)
128 this->init_response_(res, code, content_type);
129 return res;
130 }
131 // NOLINTNEXTLINE(readability-identifier-naming)
132 AsyncWebServerResponse *beginResponse(int code, const char *content_type, const std::string &content) {
133 auto *res = new AsyncWebServerResponseContent(this, content); // NOLINT(cppcoreguidelines-owning-memory)
134 this->init_response_(res, code, content_type);
135 return res;
136 }
137 // NOLINTNEXTLINE(readability-identifier-naming)
138 AsyncWebServerResponse *beginResponse_P(int code, const char *content_type, const uint8_t *data,
139 const size_t data_size) {
140 auto *res = new AsyncWebServerResponseProgmem(this, data, data_size); // NOLINT(cppcoreguidelines-owning-memory)
141 this->init_response_(res, code, content_type);
142 return res;
143 }
144 // NOLINTNEXTLINE(readability-identifier-naming)
145 AsyncResponseStream *beginResponseStream(const char *content_type) {
146 auto *res = new AsyncResponseStream(this); // NOLINT(cppcoreguidelines-owning-memory)
147 this->init_response_(res, 200, content_type);
148 return res;
149 }
150
151 // NOLINTNEXTLINE(readability-identifier-naming)
152 bool hasParam(const std::string &name) { return this->getParam(name) != nullptr; }
153 // NOLINTNEXTLINE(readability-identifier-naming)
154 AsyncWebParameter *getParam(const std::string &name);
155
156 // NOLINTNEXTLINE(readability-identifier-naming)
157 bool hasArg(const char *name) { return this->hasParam(name); }
158 std::string arg(const std::string &name) {
159 auto *param = this->getParam(name);
160 if (param) {
161 return param->value();
162 }
163 return {};
164 }
165
166 operator httpd_req_t *() const { return this->req_; }
167 optional<std::string> get_header(const char *name) const;
168 // NOLINTNEXTLINE(readability-identifier-naming)
169 bool hasHeader(const char *name) const;
170
171 protected:
172 httpd_req_t *req_;
174 std::map<std::string, AsyncWebParameter *> params_;
175 std::string post_query_;
176 AsyncWebServerRequest(httpd_req_t *req) : req_(req) {}
177 AsyncWebServerRequest(httpd_req_t *req, std::string post_query) : req_(req), post_query_(std::move(post_query)) {}
178 void init_response_(AsyncWebServerResponse *rsp, int code, const char *content_type);
179};
180
181class AsyncWebHandler;
182
184 public:
185 AsyncWebServer(uint16_t port) : port_(port){};
186 ~AsyncWebServer() { this->end(); }
187
188 // NOLINTNEXTLINE(readability-identifier-naming)
189 void onNotFound(std::function<void(AsyncWebServerRequest *request)> fn) { on_not_found_ = std::move(fn); }
190
191 void begin();
192 void end();
193
194 // NOLINTNEXTLINE(readability-identifier-naming)
196 this->handlers_.push_back(handler);
197 return *handler;
198 }
199
200 protected:
201 uint16_t port_{};
202 httpd_handle_t server_{};
203 static esp_err_t request_handler(httpd_req_t *r);
204 static esp_err_t request_post_handler(httpd_req_t *r);
205 esp_err_t request_handler_(AsyncWebServerRequest *request) const;
206 std::vector<AsyncWebHandler *> handlers_;
207 std::function<void(AsyncWebServerRequest *request)> on_not_found_{};
208};
209
211 public:
212 virtual ~AsyncWebHandler() {}
213 // NOLINTNEXTLINE(readability-identifier-naming)
214 virtual bool canHandle(AsyncWebServerRequest *request) { return false; }
215 // NOLINTNEXTLINE(readability-identifier-naming)
216 virtual void handleRequest(AsyncWebServerRequest *request) {}
217 // NOLINTNEXTLINE(readability-identifier-naming)
218 virtual void handleUpload(AsyncWebServerRequest *request, const std::string &filename, size_t index, uint8_t *data,
219 size_t len, bool final) {}
220 // NOLINTNEXTLINE(readability-identifier-naming)
221 virtual void handleBody(AsyncWebServerRequest *request, uint8_t *data, size_t len, size_t index, size_t total) {}
222 // NOLINTNEXTLINE(readability-identifier-naming)
223 virtual bool isRequestHandlerTrivial() { return true; }
224};
225
226#ifdef USE_WEBSERVER
227class AsyncEventSource;
229
231
232/*
233 This class holds a pointer to the source component that wants to publish a state event, and a pointer to a function
234 that will lazily generate that event. The two pointers allow dedup in the deferred queue if multiple publishes for
235 the same component are backed up, and take up only 8 bytes of memory. The entry in the deferred queue (a
236 std::vector) is the DeferredEvent instance itself (not a pointer to one elsewhere in heap) so still only 8 bytes per
237 entry (and no heap fragmentation). Even 100 backed up events (you'd have to have at least 100 sensors publishing
238 because of dedup) would take up only 0.8 kB.
239*/
242
243 protected:
244 void *source_;
246
247 public:
248 DeferredEvent(void *source, message_generator_t *message_generator)
249 : source_(source), message_generator_(message_generator) {}
250 bool operator==(const DeferredEvent &test) const {
251 return (source_ == test.source_ && message_generator_ == test.message_generator_);
252 }
253} __attribute__((packed));
254
256 friend class AsyncEventSource;
257
258 public:
259 bool try_send_nodefer(const char *message, const char *event = nullptr, uint32_t id = 0, uint32_t reconnect = 0);
260 void deferrable_send_state(void *source, const char *event_type, message_generator_t *message_generator);
261 void loop();
262
263 protected:
266
267 void deq_push_back_with_dedup_(void *source, message_generator_t *message_generator);
268 void process_deferred_queue_();
269 void process_buffer_();
270
271 static void destroy(void *p);
273 httpd_handle_t hd_{};
274 int fd_{};
275 std::vector<DeferredEvent> deferred_queue_;
277 std::unique_ptr<esphome::web_server::ListEntitiesIterator> entities_iterator_;
278 std::string event_buffer_{""};
281
283
286 using connect_handler_t = std::function<void(AsyncEventSourceClient *)>;
287
288 public:
289 AsyncEventSource(std::string url, esphome::web_server::WebServer *ws) : url_(std::move(url)), web_server_(ws) {}
290 ~AsyncEventSource() override;
291
292 // NOLINTNEXTLINE(readability-identifier-naming)
293 bool canHandle(AsyncWebServerRequest *request) override {
294 return request->method() == HTTP_GET && request->url() == this->url_;
295 }
296 // NOLINTNEXTLINE(readability-identifier-naming)
297 void handleRequest(AsyncWebServerRequest *request) override;
298 // NOLINTNEXTLINE(readability-identifier-naming)
299 void onConnect(connect_handler_t cb) { this->on_connect_ = std::move(cb); }
300
301 void try_send_nodefer(const char *message, const char *event = nullptr, uint32_t id = 0, uint32_t reconnect = 0);
302 void deferrable_send_state(void *source, const char *event_type, message_generator_t *message_generator);
303 void loop();
304 bool empty() { return this->count() == 0; }
305
306 size_t count() const { return this->sessions_.size(); }
307
308 protected:
309 std::string url_;
310 std::set<AsyncEventSourceResponse *> sessions_;
311 connect_handler_t on_connect_{};
313};
314#endif // USE_WEBSERVER
315
318#ifdef USE_WEBSERVER
320#endif
321
322 public:
323 // NOLINTNEXTLINE(readability-identifier-naming)
324 void addHeader(const char *name, const char *value) { this->headers_.emplace_back(name, value); }
325
326 // NOLINTNEXTLINE(readability-identifier-naming)
328 static DefaultHeaders instance;
329 return instance;
330 }
331
332 protected:
333 std::vector<std::pair<std::string, std::string>> headers_;
334};
335
336} // namespace web_server_idf
337} // namespace esphome
338
339using namespace esphome::web_server_idf; // NOLINT(google-global-names-in-headers)
340
341#endif // !defined(USE_ESP_IDF)
This class allows users to create a web server with their ESP nodes.
Definition web_server.h:149
AsyncEventSource(std::string url, esphome::web_server::WebServer *ws)
bool canHandle(AsyncWebServerRequest *request) override
std::set< AsyncEventSourceResponse * > sessions_
esphome::web_server::WebServer * web_server_
esphome::web_server::WebServer * web_server_
std::unique_ptr< esphome::web_server::ListEntitiesIterator > entities_iterator_
AsyncResponseStream(const AsyncWebServerRequest *req)
void printf(const char *fmt,...) __attribute__((format(printf
const char * get_content_data() const override
virtual bool canHandle(AsyncWebServerRequest *request)
virtual void handleRequest(AsyncWebServerRequest *request)
virtual void handleUpload(AsyncWebServerRequest *request, const std::string &filename, size_t index, uint8_t *data, size_t len, bool final)
virtual void handleBody(AsyncWebServerRequest *request, uint8_t *data, size_t len, size_t index, size_t total)
std::vector< AsyncWebHandler * > handlers_
AsyncWebHandler & addHandler(AsyncWebHandler *handler)
void onNotFound(std::function< void(AsyncWebServerRequest *request)> fn)
std::map< std::string, AsyncWebParameter * > params_
AsyncWebServerResponse * beginResponse(int code, const char *content_type, const std::string &content)
std::string arg(const std::string &name)
AsyncWebServerResponse * beginResponse(int code, const char *content_type)
AsyncResponseStream * beginResponseStream(const char *content_type)
AsyncWebServerResponse * beginResponse_P(int code, const char *content_type, const uint8_t *data, const size_t data_size)
AsyncWebServerRequest(httpd_req_t *req, std::string post_query)
AsyncWebServerResponseContent(const AsyncWebServerRequest *req, std::string content)
AsyncWebServerResponseEmpty(const AsyncWebServerRequest *req)
virtual const char * get_content_data() const =0
AsyncWebServerResponse(const AsyncWebServerRequest *req)
void addHeader(const char *name, const char *value)
AsyncWebServerResponseProgmem(const AsyncWebServerRequest *req, const uint8_t *data, const size_t size)
std::vector< std::pair< std::string, std::string > > headers_
void addHeader(const char *name, const char *value)
void loop()
std::string(esphome::web_server::WebServer *, void *) message_generator_t
class esphome::web_server_idf::AsyncEventSourceResponse __attribute__
Providing packet encoding functions for exchanging data with a remote host.
Definition a01nyub.cpp:7
bool operator==(const DeferredEvent &test) const
DeferredEvent(void *source, message_generator_t *message_generator)
uint8_t end[39]
Definition sun_gtil2.cpp:17
uint32_t len
std::string print()
message_generator_t * message_generator_
Definition web_server.h:4
void * source_
Definition web_server.h:3
friend class AsyncEventSourceResponse