ESPHome  2024.2.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 <string>
7 #include <functional>
8 #include <vector>
9 #include <map>
10 #include <set>
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  const size_t size_;
94 };
95 
97  // FIXME friend class AsyncWebServerResponse;
98  friend class AsyncWebServer;
99 
100  public:
102 
103  http_method method() const { return static_cast<http_method>(this->req_->method); }
104  std::string url() const;
105  std::string host() const;
106  // NOLINTNEXTLINE(readability-identifier-naming)
107  size_t contentLength() const { return this->req_->content_len; }
108 
109  bool authenticate(const char *username, const char *password) const;
110  // NOLINTNEXTLINE(readability-identifier-naming)
111  void requestAuthentication(const char *realm = nullptr) const;
112 
113  void redirect(const std::string &url);
114 
115  void send(AsyncWebServerResponse *response);
116  void send(int code, const char *content_type = nullptr, const char *content = nullptr);
117  // NOLINTNEXTLINE(readability-identifier-naming)
118  AsyncWebServerResponse *beginResponse(int code, const char *content_type) {
119  auto *res = new AsyncWebServerResponseEmpty(this); // NOLINT(cppcoreguidelines-owning-memory)
120  this->init_response_(res, code, content_type);
121  return res;
122  }
123  // NOLINTNEXTLINE(readability-identifier-naming)
124  AsyncWebServerResponse *beginResponse(int code, const char *content_type, const std::string &content) {
125  auto *res = new AsyncWebServerResponseContent(this, content); // NOLINT(cppcoreguidelines-owning-memory)
126  this->init_response_(res, code, content_type);
127  return res;
128  }
129  // NOLINTNEXTLINE(readability-identifier-naming)
130  AsyncWebServerResponse *beginResponse_P(int code, const char *content_type, const uint8_t *data,
131  const size_t data_size) {
132  auto *res = new AsyncWebServerResponseProgmem(this, data, data_size); // NOLINT(cppcoreguidelines-owning-memory)
133  this->init_response_(res, code, content_type);
134  return res;
135  }
136  // NOLINTNEXTLINE(readability-identifier-naming)
137  AsyncResponseStream *beginResponseStream(const char *content_type) {
138  auto *res = new AsyncResponseStream(this); // NOLINT(cppcoreguidelines-owning-memory)
139  this->init_response_(res, 200, content_type);
140  return res;
141  }
142 
143  // NOLINTNEXTLINE(readability-identifier-naming)
144  bool hasParam(const std::string &name) { return this->getParam(name) != nullptr; }
145  // NOLINTNEXTLINE(readability-identifier-naming)
146  AsyncWebParameter *getParam(const std::string &name);
147 
148  // NOLINTNEXTLINE(readability-identifier-naming)
149  bool hasArg(const char *name) { return this->hasParam(name); }
150  std::string arg(const std::string &name) {
151  auto *param = this->getParam(name);
152  if (param) {
153  return param->value();
154  }
155  return {};
156  }
157 
158  operator httpd_req_t *() const { return this->req_; }
159  optional<std::string> get_header(const char *name) const;
160  // NOLINTNEXTLINE(readability-identifier-naming)
161  bool hasHeader(const char *name) const;
162 
163  protected:
164  httpd_req_t *req_;
166  std::map<std::string, AsyncWebParameter *> params_;
167  AsyncWebServerRequest(httpd_req_t *req) : req_(req) {}
168  void init_response_(AsyncWebServerResponse *rsp, int code, const char *content_type);
169 };
170 
171 class AsyncWebHandler;
172 
174  public:
175  AsyncWebServer(uint16_t port) : port_(port){};
176  ~AsyncWebServer() { this->end(); }
177 
178  // NOLINTNEXTLINE(readability-identifier-naming)
179  void onNotFound(std::function<void(AsyncWebServerRequest *request)> fn) { on_not_found_ = std::move(fn); }
180 
181  void begin();
182  void end();
183 
184  // NOLINTNEXTLINE(readability-identifier-naming)
186  this->handlers_.push_back(handler);
187  return *handler;
188  }
189 
190  protected:
191  uint16_t port_{};
192  httpd_handle_t server_{};
193  static esp_err_t request_handler(httpd_req_t *r);
194  std::vector<AsyncWebHandler *> handlers_;
195  std::function<void(AsyncWebServerRequest *request)> on_not_found_{};
196 };
197 
199  public:
200  virtual ~AsyncWebHandler() {}
201  // NOLINTNEXTLINE(readability-identifier-naming)
202  virtual bool canHandle(AsyncWebServerRequest *request) { return false; }
203  // NOLINTNEXTLINE(readability-identifier-naming)
204  virtual void handleRequest(AsyncWebServerRequest *request) {}
205  // NOLINTNEXTLINE(readability-identifier-naming)
206  virtual void handleUpload(AsyncWebServerRequest *request, const std::string &filename, size_t index, uint8_t *data,
207  size_t len, bool final) {}
208  // NOLINTNEXTLINE(readability-identifier-naming)
209  virtual void handleBody(AsyncWebServerRequest *request, uint8_t *data, size_t len, size_t index, size_t total) {}
210  // NOLINTNEXTLINE(readability-identifier-naming)
211  virtual bool isRequestHandlerTrivial() { return true; }
212 };
213 
214 class AsyncEventSource;
215 
217  friend class AsyncEventSource;
218 
219  public:
220  void send(const char *message, const char *event = nullptr, uint32_t id = 0, uint32_t reconnect = 0);
221 
222  protected:
224  static void destroy(void *p);
226  httpd_handle_t hd_{};
227  int fd_{};
228 };
229 
231 
234  using connect_handler_t = std::function<void(AsyncEventSourceClient *)>;
235 
236  public:
237  AsyncEventSource(std::string url) : url_(std::move(url)) {}
238  ~AsyncEventSource() override;
239 
240  // NOLINTNEXTLINE(readability-identifier-naming)
241  bool canHandle(AsyncWebServerRequest *request) override {
242  return request->method() == HTTP_GET && request->url() == this->url_;
243  }
244  // NOLINTNEXTLINE(readability-identifier-naming)
245  void handleRequest(AsyncWebServerRequest *request) override;
246  // NOLINTNEXTLINE(readability-identifier-naming)
247  void onConnect(connect_handler_t cb) { this->on_connect_ = std::move(cb); }
248 
249  void send(const char *message, const char *event = nullptr, uint32_t id = 0, uint32_t reconnect = 0);
250 
251  protected:
252  std::string url_;
253  std::set<AsyncEventSourceResponse *> sessions_;
254  connect_handler_t on_connect_{};
255 };
256 
258  friend class AsyncWebServerRequest;
260 
261  public:
262  // NOLINTNEXTLINE(readability-identifier-naming)
263  void addHeader(const char *name, const char *value) { this->headers_.emplace_back(name, value); }
264 
265  // NOLINTNEXTLINE(readability-identifier-naming)
267  static DefaultHeaders instance;
268  return instance;
269  }
270 
271  protected:
272  std::vector<std::pair<std::string, std::string>> headers_;
273 };
274 
275 } // namespace web_server_idf
276 } // namespace esphome
277 
278 using namespace esphome::web_server_idf; // NOLINT(google-global-names-in-headers)
279 
280 #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)
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_
AsyncWebServerResponse * beginResponse(int code, const char *content_type, const std::string &content)
bool canHandle(AsyncWebServerRequest *request) override
AsyncResponseStream(const AsyncWebServerRequest *req)