Files
EMS-ESP32/src/ESP32React/ESP32React.cpp
2025-11-01 16:04:47 +01:00

88 lines
3.8 KiB
C++

#include "ESP32React.h"
#include "WWWData.h" // include auto-generated static web resources
ESP32React::ESP32React(AsyncWebServer * server, FS * fs)
: _securitySettingsService(server, fs)
, _networkSettingsService(server, fs, &_securitySettingsService)
, _wifiScanner(server, &_securitySettingsService)
, _networkStatus(server, &_securitySettingsService)
, _apSettingsService(server, fs, &_securitySettingsService)
, _apStatus(server, &_securitySettingsService, &_apSettingsService)
, _ntpSettingsService(server, fs, &_securitySettingsService)
, _ntpStatus(server, &_securitySettingsService)
, _uploadFileService(server, &_securitySettingsService)
, _mqttSettingsService(server, fs, &_securitySettingsService)
, _mqttStatus(server, &_mqttSettingsService, &_securitySettingsService)
, _authenticationService(server, &_securitySettingsService) {
//
// Serve static web resources
//
ArRequestHandlerFunction indexHtmlHandler = nullptr;
WWWData::registerRoutes([server, &indexHtmlHandler](const char * uri, const String & contentType, const uint8_t * content, size_t len, const String & hash) {
ArRequestHandlerFunction requestHandler = [contentType, content, len, hash](AsyncWebServerRequest * request) {
AsyncWebServerResponse * response;
// Check if the client already has the same version and respond with a 304 (Not modified)
if (request->header("If-None-Match").equals(hash)) {
response = request->beginResponse(304);
} else {
response = request->beginResponse(200, contentType, content, len);
response->addHeader("Content-Encoding", "gzip"); // not br for brotlin only works over HTTPS
}
// always send these headers - see https://datatracker.ietf.org/doc/html/rfc7232#section-4.1
response->addHeader("ETag", hash);
response->addHeader("Cache-Control", "no-cache"); // Requires revalidation before using cached content (ETags enable 304 responses)
request->send(response);
};
server->on(uri, HTTP_GET, requestHandler);
// Capture index.html handler to set onNotFound once after all routes are registered
if (strcmp(uri, "/index.html") == 0) {
indexHtmlHandler = requestHandler;
}
});
// Set onNotFound handler once after all routes are registered
// Serving non matching get requests with "/index.html"
// OPTIONS get a straight up 200 response
if (indexHtmlHandler != nullptr) {
server->onNotFound([indexHtmlHandler](AsyncWebServerRequest * request) {
if (request->method() == HTTP_GET) {
indexHtmlHandler(request);
} else if (request->method() == HTTP_OPTIONS) {
request->send(200);
} else {
request->send(404); // not found
}
});
}
}
void ESP32React::begin() {
_networkSettingsService.begin();
_networkSettingsService.read([&](NetworkSettings & networkSettings) {
DefaultHeaders & defaultHeaders = DefaultHeaders::Instance();
if (networkSettings.enableCORS) {
defaultHeaders.addHeader("Access-Control-Allow-Origin", networkSettings.CORSOrigin);
defaultHeaders.addHeader("Access-Control-Allow-Headers", "Accept, Content-Type, Authorization");
defaultHeaders.addHeader("Access-Control-Allow-Credentials", "true");
}
defaultHeaders.addHeader("Server", networkSettings.hostname);
});
_apSettingsService.begin();
_ntpSettingsService.begin();
_mqttSettingsService.begin();
_securitySettingsService.begin();
}
void ESP32React::loop() {
_networkSettingsService.loop();
_apSettingsService.loop();
_mqttSettingsService.loop();
}