ESPHome  2024.4.1
web_server_base.h
Go to the documentation of this file.
1 #pragma once
2 
3 #include <memory>
4 #include <utility>
5 #include <vector>
6 
8 
9 #ifdef USE_ARDUINO
10 #include <ESPAsyncWebServer.h>
11 #elif USE_ESP_IDF
12 #include "esphome/core/hal.h"
14 #endif
15 
16 namespace esphome {
17 namespace web_server_base {
18 
19 namespace internal {
20 
21 class MiddlewareHandler : public AsyncWebHandler {
22  public:
23  MiddlewareHandler(AsyncWebHandler *next) : next_(next) {}
24 
25  bool canHandle(AsyncWebServerRequest *request) override { return next_->canHandle(request); }
26  void handleRequest(AsyncWebServerRequest *request) override { next_->handleRequest(request); }
27  void handleUpload(AsyncWebServerRequest *request, const String &filename, size_t index, uint8_t *data, size_t len,
28  bool final) override {
29  next_->handleUpload(request, filename, index, data, len, final);
30  }
31  void handleBody(AsyncWebServerRequest *request, uint8_t *data, size_t len, size_t index, size_t total) override {
32  next_->handleBody(request, data, len, index, total);
33  }
34  bool isRequestHandlerTrivial() override { return next_->isRequestHandlerTrivial(); }
35 
36  protected:
37  AsyncWebHandler *next_;
38 };
39 
40 struct Credentials {
41  std::string username;
42  std::string password;
43 };
44 
46  public:
47  AuthMiddlewareHandler(AsyncWebHandler *next, Credentials *credentials)
48  : MiddlewareHandler(next), credentials_(credentials) {}
49 
50  bool check_auth(AsyncWebServerRequest *request) {
51  bool success = request->authenticate(credentials_->username.c_str(), credentials_->password.c_str());
52  if (!success) {
53  request->requestAuthentication();
54  }
55  return success;
56  }
57 
58  void handleRequest(AsyncWebServerRequest *request) override {
59  if (!check_auth(request))
60  return;
62  }
63  void handleUpload(AsyncWebServerRequest *request, const String &filename, size_t index, uint8_t *data, size_t len,
64  bool final) override {
65  if (!check_auth(request))
66  return;
67  MiddlewareHandler::handleUpload(request, filename, index, data, len, final);
68  }
69  void handleBody(AsyncWebServerRequest *request, uint8_t *data, size_t len, size_t index, size_t total) override {
70  if (!check_auth(request))
71  return;
72  MiddlewareHandler::handleBody(request, data, len, index, total);
73  }
74 
75  protected:
77 };
78 
79 } // namespace internal
80 
81 class WebServerBase : public Component {
82  public:
83  void init() {
84  if (this->initialized_) {
85  this->initialized_++;
86  return;
87  }
88  this->server_ = std::make_shared<AsyncWebServer>(this->port_);
89  // All content is controlled and created by user - so allowing all origins is fine here.
90  DefaultHeaders::Instance().addHeader("Access-Control-Allow-Origin", "*");
91  this->server_->begin();
92 
93  for (auto *handler : this->handlers_)
94  this->server_->addHandler(handler);
95 
96  this->initialized_++;
97  }
98  void deinit() {
99  this->initialized_--;
100  if (this->initialized_ == 0) {
101  this->server_ = nullptr;
102  }
103  }
104  std::shared_ptr<AsyncWebServer> get_server() const { return server_; }
105  float get_setup_priority() const override;
106 
107  void set_auth_username(std::string auth_username) { credentials_.username = std::move(auth_username); }
108  void set_auth_password(std::string auth_password) { credentials_.password = std::move(auth_password); }
109 
110  void add_handler(AsyncWebHandler *handler);
111 
112  void add_ota_handler();
113 
114  void set_port(uint16_t port) { port_ = port; }
115  uint16_t get_port() const { return port_; }
116 
117  protected:
118  friend class OTARequestHandler;
119 
120  int initialized_{0};
121  uint16_t port_{80};
122  std::shared_ptr<AsyncWebServer> server_{nullptr};
123  std::vector<AsyncWebHandler *> handlers_;
125 };
126 
127 class OTARequestHandler : public AsyncWebHandler {
128  public:
129  OTARequestHandler(WebServerBase *parent) : parent_(parent) {}
130  void handleRequest(AsyncWebServerRequest *request) override;
131  void handleUpload(AsyncWebServerRequest *request, const String &filename, size_t index, uint8_t *data, size_t len,
132  bool final) override;
133  bool canHandle(AsyncWebServerRequest *request) override {
134  return request->url() == "/update" && request->method() == HTTP_POST;
135  }
136 
137  bool isRequestHandlerTrivial() override { return false; }
138 
139  protected:
140  uint32_t last_ota_progress_{0};
141  uint32_t ota_read_length_{0};
143 };
144 
145 } // namespace web_server_base
146 } // namespace esphome
void handleBody(AsyncWebServerRequest *request, uint8_t *data, size_t len, size_t index, size_t total) override
AuthMiddlewareHandler(AsyncWebHandler *next, Credentials *credentials)
bool canHandle(AsyncWebServerRequest *request) override
void set_auth_username(std::string auth_username)
bool canHandle(AsyncWebServerRequest *request) override
void handleBody(AsyncWebServerRequest *request, uint8_t *data, size_t len, size_t index, size_t total) override
void handleRequest(AsyncWebServerRequest *request) override
void handleRequest(AsyncWebServerRequest *request) override
std::string size_t len
Definition: helpers.h:292
std::vector< AsyncWebHandler * > handlers_
void set_auth_password(std::string auth_password)
This is a workaround until we can figure out a way to get the tflite-micro idf component code availab...
Definition: a01nyub.cpp:7
std::shared_ptr< AsyncWebServer > get_server() const
void handleUpload(AsyncWebServerRequest *request, const String &filename, size_t index, uint8_t *data, size_t len, bool final) override
void handleUpload(AsyncWebServerRequest *request, const String &filename, size_t index, uint8_t *data, size_t len, bool final) override