ESPHome  2024.4.1
web_server_idf.h
Go to the documentation of this file.
1 #pragma once
2 #ifdef USE_ESP_IDF
3 
4 #include <esp_http_server.h>
5 
6 #include <functional>
7 #include <map>
8 #include <set>
9 #include <string>
10 #include <vector>
11 
12 namespace esphome {
13 namespace web_server_idf {
14 
15 #define F(string_literal) (string_literal)
16 #define PGM_P const char *
17 #define strncpy_P strncpy
18 
19 using String = std::string;
20 
22  public:
23  AsyncWebParameter(std::string value) : value_(std::move(value)) {}
24  const std::string &value() const { return this->value_; }
25 
26  protected:
27  std::string value_;
28 };
29 
31 
33  public:
34  AsyncWebServerResponse(const AsyncWebServerRequest *req) : req_(req) {}
36 
37  // NOLINTNEXTLINE(readability-identifier-naming)
38  void addHeader(const char *name, const char *value);
39 
40  virtual const char *get_content_data() const = 0;
41  virtual size_t get_content_size() const = 0;
42 
43  protected:
45 };
46 
48  public:
50 
51  const char *get_content_data() const override { return nullptr; };
52  size_t get_content_size() const override { return 0; };
53 };
54 
56  public:
57  AsyncWebServerResponseContent(const AsyncWebServerRequest *req, std::string content)
58  : AsyncWebServerResponse(req), content_(std::move(content)) {}
59 
60  const char *get_content_data() const override { return this->content_.c_str(); };
61  size_t get_content_size() const override { return this->content_.size(); };
62 
63  protected:
64  std::string content_;
65 };
66 
68  public:
70 
71  const char *get_content_data() const override { return this->content_.c_str(); };
72  size_t get_content_size() const override { return this->content_.size(); };
73 
74  void print(const char *str) { this->content_.append(str); }
75  void print(const std::string &str) { this->content_.append(str); }
76  void print(float value);
77  void printf(const char *fmt, ...) __attribute__((format(printf, 2, 3)));
78 
79  protected:
80  std::string content_;
81 };
82 
84  public:
85  AsyncWebServerResponseProgmem(const AsyncWebServerRequest *req, const uint8_t *data, const size_t size)
86  : AsyncWebServerResponse(req), data_(data), size_(size) {}
87 
88  const char *get_content_data() const override { return reinterpret_cast<const char *>(this->data_); };
89  size_t get_content_size() const override { return this->size_; };
90 
91  protected:
92  const uint8_t *data_;
93  size_t size_;
94 };
95 
97  friend class AsyncWebServer;
98 
99  public:
101 
102  http_method method() const { return static_cast<http_method>(this->req_->method); }
103  std::string url() const;
104  std::string host() const;
105  // NOLINTNEXTLINE(readability-identifier-naming)
106  size_t contentLength() const { return this->req_->content_len; }
107 
108  bool authenticate(const char *username, const char *password) const;
109  // NOLINTNEXTLINE(readability-identifier-naming)
110  void requestAuthentication(const char *realm = nullptr) const;
111 
112  void redirect(const std::string &url);
113 
114  void send(AsyncWebServerResponse *response);
115  void send(int code, const char *content_type = nullptr, const char *content = nullptr);
116  // NOLINTNEXTLINE(readability-identifier-naming)
117  AsyncWebServerResponse *beginResponse(int code, const char *content_type) {
118  auto *res = new AsyncWebServerResponseEmpty(this); // NOLINT(cppcoreguidelines-owning-memory)
119  this->init_response_(res, code, content_type);
120  return res;
121  }
122  // NOLINTNEXTLINE(readability-identifier-naming)
123  AsyncWebServerResponse *beginResponse(int code, const char *content_type, const std::string &content) {
124  auto *res = new AsyncWebServerResponseContent(this, content); // NOLINT(cppcoreguidelines-owning-memory)
125  this->init_response_(res, code, content_type);
126  return res;
127  }
128  // NOLINTNEXTLINE(readability-identifier-naming)
129  AsyncWebServerResponse *beginResponse_P(int code, const char *content_type, const uint8_t *data,
130  const size_t data_size) {
131  auto *res = new AsyncWebServerResponseProgmem(this, data, data_size); // NOLINT(cppcoreguidelines-owning-memory)
132  this->init_response_(res, code, content_type);
133  return res;
134  }
135  // NOLINTNEXTLINE(readability-identifier-naming)
136  AsyncResponseStream *beginResponseStream(const char *content_type) {
137  auto *res = new AsyncResponseStream(this); // NOLINT(cppcoreguidelines-owning-memory)
138  this->init_response_(res, 200, content_type);
139  return res;
140  }
141 
142  // NOLINTNEXTLINE(readability-identifier-naming)
143  bool hasParam(const std::string &name) { return this->getParam(name) != nullptr; }
144  // NOLINTNEXTLINE(readability-identifier-naming)
145  AsyncWebParameter *getParam(const std::string &name);
146 
147  // NOLINTNEXTLINE(readability-identifier-naming)
148  bool hasArg(const char *name) { return this->hasParam(name); }
149  std::string arg(const std::string &name) {
150  auto *param = this->getParam(name);
151  if (param) {
152  return param->value();
153  }
154  return {};
155  }
156 
157  operator httpd_req_t *() const { return this->req_; }
158  optional<std::string> get_header(const char *name) const;
159  // NOLINTNEXTLINE(readability-identifier-naming)
160  bool hasHeader(const char *name) const;
161 
162  protected:
163  httpd_req_t *req_;
165  std::map<std::string, AsyncWebParameter *> params_;
166  std::string post_query_;
167  AsyncWebServerRequest(httpd_req_t *req) : req_(req) {}
168  AsyncWebServerRequest(httpd_req_t *req, std::string post_query) : req_(req), post_query_(std::move(post_query)) {}
169  void init_response_(AsyncWebServerResponse *rsp, int code, const char *content_type);
170 };
171 
172 class AsyncWebHandler;
173 
175  public:
176  AsyncWebServer(uint16_t port) : port_(port){};
177  ~AsyncWebServer() { this->end(); }
178 
179  // NOLINTNEXTLINE(readability-identifier-naming)
180  void onNotFound(std::function<void(AsyncWebServerRequest *request)> fn) { on_not_found_ = std::move(fn); }
181 
182  void begin();
183  void end();
184 
185  // NOLINTNEXTLINE(readability-identifier-naming)
187  this->handlers_.push_back(handler);
188  return *handler;
189  }
190 
191  protected:
192  uint16_t port_{};
193  httpd_handle_t server_{};
194  static esp_err_t request_handler(httpd_req_t *r);
195  static esp_err_t request_post_handler(httpd_req_t *r);
196  esp_err_t request_handler_(AsyncWebServerRequest *request) const;
197  std::vector<AsyncWebHandler *> handlers_;
198  std::function<void(AsyncWebServerRequest *request)> on_not_found_{};
199 };
200 
202  public:
203  virtual ~AsyncWebHandler() {}
204  // NOLINTNEXTLINE(readability-identifier-naming)
205  virtual bool canHandle(AsyncWebServerRequest *request) { return false; }
206  // NOLINTNEXTLINE(readability-identifier-naming)
207  virtual void handleRequest(AsyncWebServerRequest *request) {}
208  // NOLINTNEXTLINE(readability-identifier-naming)
209  virtual void handleUpload(AsyncWebServerRequest *request, const std::string &filename, size_t index, uint8_t *data,
210  size_t len, bool final) {}
211  // NOLINTNEXTLINE(readability-identifier-naming)
212  virtual void handleBody(AsyncWebServerRequest *request, uint8_t *data, size_t len, size_t index, size_t total) {}
213  // NOLINTNEXTLINE(readability-identifier-naming)
214  virtual bool isRequestHandlerTrivial() { return true; }
215 };
216 
217 class AsyncEventSource;
218 
220  friend class AsyncEventSource;
221 
222  public:
223  void send(const char *message, const char *event = nullptr, uint32_t id = 0, uint32_t reconnect = 0);
224 
225  protected:
227  static void destroy(void *p);
229  httpd_handle_t hd_{};
230  int fd_{};
231 };
232 
234 
237  using connect_handler_t = std::function<void(AsyncEventSourceClient *)>;
238 
239  public:
240  AsyncEventSource(std::string url) : url_(std::move(url)) {}
241  ~AsyncEventSource() override;
242 
243  // NOLINTNEXTLINE(readability-identifier-naming)
244  bool canHandle(AsyncWebServerRequest *request) override {
245  return request->method() == HTTP_GET && request->url() == this->url_;
246  }
247  // NOLINTNEXTLINE(readability-identifier-naming)
248  void handleRequest(AsyncWebServerRequest *request) override;
249  // NOLINTNEXTLINE(readability-identifier-naming)
250  void onConnect(connect_handler_t cb) { this->on_connect_ = std::move(cb); }
251 
252  void send(const char *message, const char *event = nullptr, uint32_t id = 0, uint32_t reconnect = 0);
253 
254  size_t count() const { return this->sessions_.size(); }
255 
256  protected:
257  std::string url_;
258  std::set<AsyncEventSourceResponse *> sessions_;
259  connect_handler_t on_connect_{};
260 };
261 
263  friend class AsyncWebServerRequest;
265 
266  public:
267  // NOLINTNEXTLINE(readability-identifier-naming)
268  void addHeader(const char *name, const char *value) { this->headers_.emplace_back(name, value); }
269 
270  // NOLINTNEXTLINE(readability-identifier-naming)
272  static DefaultHeaders instance;
273  return instance;
274  }
275 
276  protected:
277  std::vector<std::pair<std::string, std::string>> headers_;
278 };
279 
280 } // namespace web_server_idf
281 } // namespace esphome
282 
283 using namespace esphome::web_server_idf; // NOLINT(google-global-names-in-headers)
284 
285 #endif // !defined(USE_ESP_IDF)
const char * name
Definition: stm32flash.h:78
virtual void handleRequest(AsyncWebServerRequest *request)
void addHeader(const char *name, const char *value)
AsyncResponseStream * beginResponseStream(const char *content_type)
AsyncWebHandler & addHandler(AsyncWebHandler *handler)
virtual void handleBody(AsyncWebServerRequest *request, uint8_t *data, size_t len, size_t index, size_t total)
STL namespace.
virtual bool canHandle(AsyncWebServerRequest *request)
const char * get_content_data() const override
static DefaultHeaders & Instance()
AsyncWebServerResponse(const AsyncWebServerRequest *req)
void onConnect(connect_handler_t cb)
AsyncWebServerResponseProgmem(const AsyncWebServerRequest *req, const uint8_t *data, const size_t size)
AsyncWebServerResponse * beginResponse(int code, const char *content_type)
virtual void handleUpload(AsyncWebServerRequest *request, const std::string &filename, size_t index, uint8_t *data, size_t len, bool final)
void onNotFound(std::function< void(AsyncWebServerRequest *request)> fn)
std::vector< AsyncWebHandler * > handlers_
AsyncWebServerResponseContent(const AsyncWebServerRequest *req, std::string content)
AsyncWebServerResponseEmpty(const AsyncWebServerRequest *req)
std::vector< std::pair< std::string, std::string > > headers_
enum esphome::EntityCategory __attribute__
std::string size_t len
Definition: helpers.h:292
std::map< std::string, AsyncWebParameter * > params_
std::string arg(const std::string &name)
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)
This is a workaround until we can figure out a way to get the tflite-micro idf component code availab...
Definition: a01nyub.cpp:7
num_t cb(num_t x)
Definition: sun.cpp:31
std::set< AsyncEventSourceResponse * > sessions_
uint8_t end[39]
Definition: sun_gtil2.cpp:31
AsyncWebServerResponse * beginResponse(int code, const char *content_type, const std::string &content)
bool canHandle(AsyncWebServerRequest *request) override
AsyncResponseStream(const AsyncWebServerRequest *req)