mirror of
https://github.com/esphome/esphome.git
synced 2026-02-08 00:31:58 +00:00
[captive_portal] Allow web_server access while captive portal is active
This commit is contained in:
@@ -43,7 +43,11 @@ void CaptivePortal::handle_config(AsyncWebServerRequest *request) {
|
||||
scan.get_with_auth());
|
||||
#endif
|
||||
}
|
||||
#ifdef USE_WEBSERVER
|
||||
stream->print(ESPHOME_F("],\"web_server\":true}"));
|
||||
#else
|
||||
stream->print(ESPHOME_F("]}"));
|
||||
#endif
|
||||
request->send(stream);
|
||||
}
|
||||
void CaptivePortal::handle_wifisave(AsyncWebServerRequest *request) {
|
||||
@@ -71,7 +75,8 @@ void CaptivePortal::setup() {
|
||||
void CaptivePortal::start() {
|
||||
this->base_->init();
|
||||
if (!this->initialized_) {
|
||||
this->base_->add_handler(this);
|
||||
// Use fallback position so web_server handlers are checked first
|
||||
this->base_->add_handler(this, web_server_base::HandlerPosition::FALLBACK);
|
||||
}
|
||||
|
||||
network::IPAddress ip = wifi::global_wifi_component->wifi_soft_ap_ip();
|
||||
|
||||
@@ -46,9 +46,10 @@ class CaptivePortal : public AsyncWebHandler, public Component {
|
||||
}
|
||||
|
||||
bool canHandle(AsyncWebServerRequest *request) const override {
|
||||
// Handle all GET requests when captive portal is active
|
||||
// Handle all GET requests when captive portal is active.
|
||||
// This allows us to respond with the portal page for any URL,
|
||||
// triggering OS captive portal detection
|
||||
// triggering OS captive portal detection.
|
||||
// We use add_fallback_handler() so web_server handlers are checked first.
|
||||
return this->active_ && request->method() == HTTP_GET;
|
||||
}
|
||||
|
||||
|
||||
@@ -28,6 +28,10 @@
|
||||
#include "esphome/components/climate/climate.h"
|
||||
#endif
|
||||
|
||||
#ifdef USE_CAPTIVE_PORTAL
|
||||
#include "esphome/components/captive_portal/captive_portal.h"
|
||||
#endif
|
||||
|
||||
#ifdef USE_WEBSERVER_LOCAL
|
||||
#if USE_WEBSERVER_VERSION == 2
|
||||
#include "server_index_v2.h"
|
||||
@@ -1957,9 +1961,19 @@ bool WebServer::canHandle(AsyncWebServerRequest *request) const {
|
||||
const auto &url = request->url();
|
||||
const auto method = request->method();
|
||||
|
||||
// Static URL checks
|
||||
// Handle root URL
|
||||
if (url == ESPHOME_F("/")) {
|
||||
#ifdef USE_CAPTIVE_PORTAL
|
||||
// When captive portal is active, only handle "/" if ?web_server param is present
|
||||
if (captive_portal::global_captive_portal != nullptr && captive_portal::global_captive_portal->is_active()) {
|
||||
return request->hasParam(ESPHOME_F("web_server"));
|
||||
}
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
// Other static URL checks
|
||||
static const char *const STATIC_URLS[] = {
|
||||
"/",
|
||||
#if !defined(USE_ESP32) && defined(USE_ARDUINO)
|
||||
"/events",
|
||||
#endif
|
||||
|
||||
@@ -11,15 +11,18 @@ static const char *const TAG = "web_server_base";
|
||||
|
||||
WebServerBase *global_web_server_base = nullptr; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
|
||||
|
||||
void WebServerBase::add_handler(AsyncWebHandler *handler) {
|
||||
// remove all handlers
|
||||
|
||||
void WebServerBase::add_handler(AsyncWebHandler *handler, HandlerPosition position) {
|
||||
#ifdef USE_WEBSERVER_AUTH
|
||||
if (!credentials_.username.empty()) {
|
||||
if (position != HandlerPosition::FALLBACK && !credentials_.username.empty()) {
|
||||
handler = new internal::AuthMiddlewareHandler(handler, &credentials_);
|
||||
}
|
||||
#endif
|
||||
this->handlers_.push_back(handler);
|
||||
if (position == HandlerPosition::FALLBACK) {
|
||||
this->handlers_.push_back(handler);
|
||||
} else {
|
||||
this->handlers_.insert(this->handlers_.begin() + this->fallback_start_, handler);
|
||||
this->fallback_start_++;
|
||||
}
|
||||
if (this->server_ != nullptr) {
|
||||
this->server_->addHandler(handler);
|
||||
}
|
||||
|
||||
@@ -91,6 +91,11 @@ class AuthMiddlewareHandler : public MiddlewareHandler {
|
||||
|
||||
} // namespace internal
|
||||
|
||||
enum class HandlerPosition : uint8_t {
|
||||
NORMAL, ///< Before fallback handlers (default)
|
||||
FALLBACK ///< After normal handlers (catch-all)
|
||||
};
|
||||
|
||||
class WebServerBase : public Component {
|
||||
public:
|
||||
void init() {
|
||||
@@ -122,7 +127,7 @@ class WebServerBase : public Component {
|
||||
void set_auth_password(std::string auth_password) { credentials_.password = std::move(auth_password); }
|
||||
#endif
|
||||
|
||||
void add_handler(AsyncWebHandler *handler);
|
||||
void add_handler(AsyncWebHandler *handler, HandlerPosition position = HandlerPosition::NORMAL);
|
||||
|
||||
void set_port(uint16_t port) { port_ = port; }
|
||||
uint16_t get_port() const { return port_; }
|
||||
@@ -132,6 +137,7 @@ class WebServerBase : public Component {
|
||||
uint16_t port_{80};
|
||||
std::unique_ptr<AsyncWebServer> server_{nullptr};
|
||||
std::vector<AsyncWebHandler *> handlers_;
|
||||
size_t fallback_start_{0}; ///< Index where fallback handlers begin
|
||||
#ifdef USE_WEBSERVER_AUTH
|
||||
internal::Credentials credentials_;
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user