mirror of
https://github.com/esphome/esphome.git
synced 2026-10-27 08:22:25 +00:00
Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e14a918218 |
No files matched your search
@@ -92,5 +92,9 @@ async def to_code(config: ConfigType) -> None:
|
||||
await ota_to_code(var, config)
|
||||
await cg.register_component(var, config)
|
||||
cg.add_define("USE_WEBSERVER_OTA")
|
||||
# web_server and prometheus create the server in an earlier setup(); without them
|
||||
# the handler waits until captive_portal starts it
|
||||
if not {"web_server", "prometheus"} & CORE.config.keys():
|
||||
cg.add_define("USE_WEBSERVER_BASE_PENDING_HANDLER")
|
||||
if CORE.is_esp32:
|
||||
add_idf_component(name="zorxx/multipart-parser", ref="1.0.1")
|
||||
@@ -72,7 +72,7 @@ async def to_code(config: ConfigType) -> None:
|
||||
cg.add(cg.RawExpression(f"{web_server_base_ns}::global_web_server_base = {var}"))
|
||||
|
||||
if CORE.is_esp32:
|
||||
# Count for StaticVector in web_server_idf - matches headers added in init()
|
||||
# Count for StaticVector in web_server_idf - matches headers added in create_server_()
|
||||
cg.add_define("WEB_SERVER_DEFAULT_HEADERS_COUNT", 1)
|
||||
return
|
||||
|
||||
|
||||
@@ -15,10 +15,29 @@ void WebServerBase::add_handler(AsyncWebHandler *handler) {
|
||||
}
|
||||
|
||||
void WebServerBase::add_handler_without_auth(AsyncWebHandler *handler) {
|
||||
this->handlers_.push_back(handler);
|
||||
if (this->server_ != nullptr) {
|
||||
this->server_->addHandler(handler);
|
||||
if (this->server_ == nullptr) {
|
||||
#ifdef USE_WEBSERVER_BASE_PENDING_HANDLER
|
||||
if (this->pending_handler_ == nullptr) {
|
||||
this->pending_handler_ = handler;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
// Nowhere for it to wait: create the server now, after the waiting handler to keep the order
|
||||
this->create_server_();
|
||||
}
|
||||
this->server_->addHandler(handler);
|
||||
}
|
||||
|
||||
void WebServerBase::create_server_() {
|
||||
this->server_ = new AsyncWebServer(this->port_);
|
||||
// All content is controlled and created by user - so allowing all origins is fine here.
|
||||
// NOTE: Currently 1 header. If more are added, update in __init__.py:
|
||||
// cg.add_define("WEB_SERVER_DEFAULT_HEADERS_COUNT", 1)
|
||||
DefaultHeaders::Instance().addHeader(ESPHOME_F("Access-Control-Allow-Origin"), ESPHOME_F("*"));
|
||||
#ifdef USE_WEBSERVER_BASE_PENDING_HANDLER
|
||||
if (this->pending_handler_ != nullptr)
|
||||
this->server_->addHandler(this->pending_handler_);
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace esphome::web_server_base
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
#pragma once
|
||||
#include "esphome/core/defines.h"
|
||||
#if defined(USE_NETWORK) && !defined(USE_ZEPHYR) && !defined(USE_HOST)
|
||||
#include <vector>
|
||||
|
||||
#include "esphome/core/progmem.h"
|
||||
|
||||
#if USE_ESP32
|
||||
@@ -115,26 +113,14 @@ class WebServerBase final {
|
||||
// The AsyncWebServer is created once and intentionally never deleted: on Arduino
|
||||
// platforms ESPAsyncWebServer owns its registered handlers, so destroying it would
|
||||
// also destroy live components (e.g. the captive portal) out from under us.
|
||||
// init()/deinit() refcount users and start/stop the listener; handlers are
|
||||
// registered once at creation and survive listener restarts.
|
||||
// init()/deinit() refcount users and start/stop the listener; handlers stay
|
||||
// registered across listener restarts.
|
||||
void init() {
|
||||
this->initialized_++;
|
||||
if (this->server_ != nullptr) {
|
||||
if (this->initialized_ == 1) {
|
||||
// Restart the listener after a previous deinit()
|
||||
this->server_->begin();
|
||||
}
|
||||
if (++this->initialized_ != 1)
|
||||
return;
|
||||
}
|
||||
this->server_ = new AsyncWebServer(this->port_);
|
||||
// All content is controlled and created by user - so allowing all origins is fine here.
|
||||
// NOTE: Currently 1 header. If more are added, update in __init__.py:
|
||||
// cg.add_define("WEB_SERVER_DEFAULT_HEADERS_COUNT", 1)
|
||||
DefaultHeaders::Instance().addHeader(ESPHOME_F("Access-Control-Allow-Origin"), ESPHOME_F("*"));
|
||||
if (this->server_ == nullptr)
|
||||
this->create_server_();
|
||||
this->server_->begin();
|
||||
|
||||
for (auto *handler : this->handlers_)
|
||||
this->server_->addHandler(handler);
|
||||
}
|
||||
void deinit() {
|
||||
if (this->initialized_ == 0)
|
||||
@@ -169,10 +155,15 @@ class WebServerBase final {
|
||||
uint16_t get_port() const { return port_; }
|
||||
|
||||
protected:
|
||||
void create_server_();
|
||||
|
||||
uint8_t initialized_{0};
|
||||
uint16_t port_{80}; // Keep in sync with DEFAULT_PORT in web_server/__init__.py
|
||||
AsyncWebServer *server_{nullptr};
|
||||
std::vector<AsyncWebHandler *> handlers_;
|
||||
#ifdef USE_WEBSERVER_BASE_PENDING_HANDLER
|
||||
// Web OTA's handler when it is added before any component created the server
|
||||
AsyncWebHandler *pending_handler_{nullptr};
|
||||
#endif
|
||||
#ifdef USE_WEBSERVER_AUTH
|
||||
internal::Credentials credentials_;
|
||||
#endif
|
||||
|
||||
@@ -561,6 +561,7 @@
|
||||
#define USE_WEBSERVER_PRIVATE_NETWORK_ACCESS
|
||||
#define USE_WEBSERVER_VERSION 3
|
||||
#define WEB_SERVER_DEFAULT_HEADERS_COUNT 1
|
||||
#define USE_WEBSERVER_BASE_PENDING_HANDLER
|
||||
#define USE_CAPTIVE_PORTAL_GZIP
|
||||
#endif
|
||||
#define USE_WIFI_11KV_SUPPORT
|
||||
@@ -740,6 +741,7 @@
|
||||
#define USE_WEBSERVER_VERSION 2
|
||||
#define USE_WEBSERVER_LOCAL
|
||||
#define USE_WEBSERVER_OTA
|
||||
#define USE_WEBSERVER_BASE_PENDING_HANDLER
|
||||
#define USE_WEBSERVER_OTA_DISABLED
|
||||
#endif
|
||||
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
---
|
||||
esphome:
|
||||
name: test
|
||||
|
||||
esp8266:
|
||||
board: d1_mini
|
||||
|
||||
wifi:
|
||||
ssid: test
|
||||
password: testtest
|
||||
ap:
|
||||
password: testtest
|
||||
|
||||
captive_portal:
|
||||
@@ -0,0 +1,16 @@
|
||||
---
|
||||
esphome:
|
||||
name: test
|
||||
|
||||
esp8266:
|
||||
board: d1_mini
|
||||
|
||||
wifi:
|
||||
ssid: test
|
||||
password: testtest
|
||||
ap:
|
||||
password: testtest
|
||||
|
||||
captive_portal:
|
||||
|
||||
prometheus:
|
||||
@@ -0,0 +1,16 @@
|
||||
---
|
||||
esphome:
|
||||
name: test
|
||||
|
||||
esp8266:
|
||||
board: d1_mini
|
||||
|
||||
wifi:
|
||||
ssid: test
|
||||
password: testtest
|
||||
ap:
|
||||
password: testtest
|
||||
|
||||
captive_portal:
|
||||
|
||||
web_server:
|
||||
@@ -0,0 +1,34 @@
|
||||
"""Tests for when web OTA's handler waits in WebServerBase for the server to be created."""
|
||||
|
||||
from collections.abc import Callable
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
|
||||
from esphome.core import CORE
|
||||
|
||||
_PENDING = "USE_WEBSERVER_BASE_PENDING_HANDLER"
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("config_file", "pending"),
|
||||
[
|
||||
# captive_portal loads web OTA, and with it the web_server package, but only
|
||||
# creates the server when the AP starts
|
||||
("pending_handler_captive_portal.yaml", True),
|
||||
("pending_handler_web_server.yaml", False),
|
||||
("pending_handler_prometheus.yaml", False),
|
||||
],
|
||||
)
|
||||
def test_pending_handler_define(
|
||||
generate_main: Callable[[str | Path], str],
|
||||
component_config_path: Callable[[str], Path],
|
||||
config_file: str,
|
||||
pending: bool,
|
||||
) -> None:
|
||||
"""Only configs where nothing creates the server before web OTA's setup() keep the pointer."""
|
||||
generate_main(component_config_path(config_file))
|
||||
defines = {define.name for define in CORE.defines}
|
||||
|
||||
assert "USE_WEBSERVER_OTA" in defines
|
||||
assert (_PENDING in defines) is pending
|
||||
Reference in new issue
Block a user