ESPHome 2026.8.0
Loading...
Searching...
No Matches
web_server_base.h
Go to the documentation of this file.
1#pragma once
3#if defined(USE_NETWORK) && !defined(USE_ZEPHYR)
4#include <vector>
5
7
8#if USE_ESP32
9#include "esphome/core/hal.h"
11#else
12#include <ESPAsyncWebServer.h>
13#endif
14
15#if USE_ESP32
16using PlatformString = std::string;
17#elif USE_ARDUINO
18using PlatformString = String;
19#endif
20
22
23class WebServerBase;
24extern WebServerBase *global_web_server_base; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
25
26namespace internal {
27
28class MiddlewareHandler : public AsyncWebHandler {
29 public:
30 MiddlewareHandler(AsyncWebHandler *next) : next_(next) {}
31
32 bool canHandle(AsyncWebServerRequest *request) const override { return next_->canHandle(request); }
33 void handleRequest(AsyncWebServerRequest *request) override { next_->handleRequest(request); }
34 void handleUpload(AsyncWebServerRequest *request, const PlatformString &filename, size_t index, uint8_t *data,
35 size_t len, bool final) override {
36 next_->handleUpload(request, filename, index, data, len, final);
37 }
38 void handleBody(AsyncWebServerRequest *request, uint8_t *data, size_t len, size_t index, size_t total) override {
39 next_->handleBody(request, data, len, index, total);
40 }
41 bool isRequestHandlerTrivial() const override { return next_->isRequestHandlerTrivial(); }
42
43 protected:
44 AsyncWebHandler *next_;
45};
46
47#ifdef USE_WEBSERVER_AUTH
48// All fields point to string literals in generated code; nothing is copied.
50#if USE_ESP32 || defined(USE_WEBSERVER_AUTH_DIGEST)
51 const char *username{nullptr};
52 const char *password{nullptr};
53 bool is_set() const { return username != nullptr; }
54#else
55 // base64("username:password"), precomputed at codegen time. Used by every non-ESP32 basic
56 // auth build. The ESP8266 and RP2040 core libb64 wraps base64 output every 72 chars, so
57 // letting the library encode and compare fails for long credentials; instead the header
58 // payload is compared against this hash.
59 const char *basic_auth_hash{nullptr};
60 bool is_set() const { return basic_auth_hash != nullptr; }
61#endif
62};
63
65 public:
66 AuthMiddlewareHandler(AsyncWebHandler *next, Credentials *credentials)
67 : MiddlewareHandler(next), credentials_(credentials) {}
68
69 bool check_auth(AsyncWebServerRequest *request) {
70 // The scheme is chosen at build time (USE_WEBSERVER_AUTH_DIGEST); the unused path is
71 // compiled out. On ESP32 our own server picks the scheme internally.
72#if USE_ESP32 || defined(USE_WEBSERVER_AUTH_DIGEST)
73 bool success = request->authenticate(credentials_->username, credentials_->password);
74#else
75 bool success = request->authenticate(credentials_->basic_auth_hash);
76#endif
77 if (!success) {
78#if USE_ESP32
79 request->requestAuthentication();
80#elif defined(USE_WEBSERVER_AUTH_DIGEST)
81 request->requestAuthentication(nullptr, true);
82#else
83 request->requestAuthentication(nullptr, false);
84#endif
85 }
86 return success;
87 }
88
89 void handleRequest(AsyncWebServerRequest *request) override {
90 if (!check_auth(request))
91 return;
93 }
94 void handleUpload(AsyncWebServerRequest *request, const PlatformString &filename, size_t index, uint8_t *data,
95 size_t len, bool final) override {
96 if (!check_auth(request))
97 return;
98 MiddlewareHandler::handleUpload(request, filename, index, data, len, final);
99 }
100 void handleBody(AsyncWebServerRequest *request, uint8_t *data, size_t len, size_t index, size_t total) override {
101 if (!check_auth(request))
102 return;
103 MiddlewareHandler::handleBody(request, data, len, index, total);
104 }
105
106 protected:
108};
109#endif
110
111} // namespace internal
112
113class WebServerBase final {
114 public:
115 // The AsyncWebServer is created once and intentionally never deleted: on Arduino
116 // platforms ESPAsyncWebServer owns its registered handlers, so destroying it would
117 // also destroy live components (e.g. the captive portal) out from under us.
118 // init()/deinit() refcount users and start/stop the listener; handlers are
119 // registered once at creation and survive listener restarts.
120 void init() {
121 this->initialized_++;
122 if (this->server_ != nullptr) {
123 if (this->initialized_ == 1) {
124 // Restart the listener after a previous deinit()
125 this->server_->begin();
126 }
127 return;
128 }
129 this->server_ = new AsyncWebServer(this->port_);
130 // All content is controlled and created by user - so allowing all origins is fine here.
131 // NOTE: Currently 1 header. If more are added, update in __init__.py:
132 // cg.add_define("WEB_SERVER_DEFAULT_HEADERS_COUNT", 1)
133 DefaultHeaders::Instance().addHeader(ESPHOME_F("Access-Control-Allow-Origin"), ESPHOME_F("*"));
134 this->server_->begin();
135
136 for (auto *handler : this->handlers_)
137 this->server_->addHandler(handler);
138 }
139 void deinit() {
140 if (this->initialized_ == 0)
141 return; // unbalanced deinit()
142 this->initialized_--;
143 if (this->initialized_ == 0) {
144 this->server_->end();
145 }
146 }
147 AsyncWebServer *get_server() const { return this->server_; }
148
149#ifdef USE_WEBSERVER_AUTH
150#if USE_ESP32 || defined(USE_WEBSERVER_AUTH_DIGEST)
151 void set_auth_username(const char *auth_username) { credentials_.username = auth_username; }
152 void set_auth_password(const char *auth_password) { credentials_.password = auth_password; }
153#else
154 void set_auth_basic_hash(const char *hash) { credentials_.basic_auth_hash = hash; }
155#endif
156#endif
157
158 void add_handler(AsyncWebHandler *handler);
166 void add_handler_without_auth(AsyncWebHandler *handler);
167
168 void set_port(uint16_t port) { port_ = port; }
169 uint16_t get_port() const { return port_; }
170
171 protected:
172 uint8_t initialized_{0};
173 uint16_t port_{80};
174 AsyncWebServer *server_{nullptr};
175 std::vector<AsyncWebHandler *> handlers_;
176#ifdef USE_WEBSERVER_AUTH
178#endif
179};
180
181} // namespace esphome::web_server_base
182#endif // USE_NETWORK && !USE_ZEPHYR
void add_handler_without_auth(AsyncWebHandler *handler)
WARNING: Registers a handler that bypasses the USE_WEBSERVER_AUTH middleware.
void set_auth_username(const char *auth_username)
void set_auth_password(const char *auth_password)
void add_handler(AsyncWebHandler *handler)
std::vector< AsyncWebHandler * > handlers_
void handleUpload(AsyncWebServerRequest *request, const PlatformString &filename, size_t index, uint8_t *data, size_t len, bool final) override
void handleRequest(AsyncWebServerRequest *request) override
AuthMiddlewareHandler(AsyncWebHandler *next, Credentials *credentials)
void handleBody(AsyncWebServerRequest *request, uint8_t *data, size_t len, size_t index, size_t total) override
bool canHandle(AsyncWebServerRequest *request) const override
void handleUpload(AsyncWebServerRequest *request, const PlatformString &filename, size_t index, uint8_t *data, size_t len, bool final) override
void handleRequest(AsyncWebServerRequest *request) override
void handleBody(AsyncWebServerRequest *request, uint8_t *data, size_t len, size_t index, size_t total) override
WebServerBase * global_web_server_base
const void size_t len
Definition hal.h:64
std::string PlatformString