mirror of
https://github.com/emsesp/EMS-ESP32.git
synced 2025-12-07 00:09:51 +03:00
some standalone compile updates for testing
This commit is contained in:
@@ -68,7 +68,7 @@
|
|||||||
"eslint-plugin-react-hooks": "^4.6.0",
|
"eslint-plugin-react-hooks": "^4.6.0",
|
||||||
"preact": "^10.19.3",
|
"preact": "^10.19.3",
|
||||||
"prettier": "^3.1.1",
|
"prettier": "^3.1.1",
|
||||||
"rollup-plugin-visualizer": "^5.11.0",
|
"rollup-plugin-visualizer": "^5.12.0",
|
||||||
"terser": "^5.26.0",
|
"terser": "^5.26.0",
|
||||||
"vite": "^5.0.10",
|
"vite": "^5.0.10",
|
||||||
"vite-plugin-imagemin": "^0.6.1",
|
"vite-plugin-imagemin": "^0.6.1",
|
||||||
|
|||||||
@@ -1866,7 +1866,7 @@ __metadata:
|
|||||||
react-icons: "npm:^4.12.0"
|
react-icons: "npm:^4.12.0"
|
||||||
react-router-dom: "npm:^6.21.1"
|
react-router-dom: "npm:^6.21.1"
|
||||||
react-toastify: "npm:^9.1.3"
|
react-toastify: "npm:^9.1.3"
|
||||||
rollup-plugin-visualizer: "npm:^5.11.0"
|
rollup-plugin-visualizer: "npm:^5.12.0"
|
||||||
sockette: "npm:^2.0.6"
|
sockette: "npm:^2.0.6"
|
||||||
terser: "npm:^5.26.0"
|
terser: "npm:^5.26.0"
|
||||||
typesafe-i18n: "npm:^5.26.2"
|
typesafe-i18n: "npm:^5.26.2"
|
||||||
@@ -7450,9 +7450,9 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"rollup-plugin-visualizer@npm:^5.11.0":
|
"rollup-plugin-visualizer@npm:^5.12.0":
|
||||||
version: 5.11.0
|
version: 5.12.0
|
||||||
resolution: "rollup-plugin-visualizer@npm:5.11.0"
|
resolution: "rollup-plugin-visualizer@npm:5.12.0"
|
||||||
dependencies:
|
dependencies:
|
||||||
open: "npm:^8.4.0"
|
open: "npm:^8.4.0"
|
||||||
picomatch: "npm:^2.3.1"
|
picomatch: "npm:^2.3.1"
|
||||||
@@ -7465,7 +7465,7 @@ __metadata:
|
|||||||
optional: true
|
optional: true
|
||||||
bin:
|
bin:
|
||||||
rollup-plugin-visualizer: dist/bin/cli.js
|
rollup-plugin-visualizer: dist/bin/cli.js
|
||||||
checksum: 947238aa22706a47a4d3e8ce616855f0e5cb969ed9f61b9a268eaede0a86f461ecb38e27b4e6bf00f4b5e3f63677667f65e0d4af89a659a5160f74add1f192bb
|
checksum: 47358feb672291d6edcfd94197577c192a84c24cb644119425dae8241fb6f5a52556efd0c501f38b276c07534642a80c0885ef681babb474e83c7b5a3b475b84
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
|||||||
@@ -82,7 +82,7 @@ class DummySettings {
|
|||||||
|
|
||||||
class DummySettingsService : public StatefulService<DummySettings> {
|
class DummySettingsService : public StatefulService<DummySettings> {
|
||||||
public:
|
public:
|
||||||
DummySettingsService(AsyncWebServer * server, FS * fs, SecurityManager * securityManager){};
|
DummySettingsService(PsychicHttpServer * server, FS * fs, SecurityManager * securityManager){};
|
||||||
|
|
||||||
void begin();
|
void begin();
|
||||||
void loop();
|
void loop();
|
||||||
@@ -95,16 +95,17 @@ class DummySettingsService : public StatefulService<DummySettings> {
|
|||||||
|
|
||||||
class ESP8266React {
|
class ESP8266React {
|
||||||
public:
|
public:
|
||||||
ESP8266React(AsyncWebServer * server, FS * fs)
|
ESP8266React(PsychicHttpServer * server, FS * fs)
|
||||||
: _settings(server, fs, nullptr)
|
: _settings(server, fs, nullptr)
|
||||||
, _securitySettingsService(server, fs){};
|
, _securitySettingsService(server, fs){};
|
||||||
|
|
||||||
void begin() {
|
void begin() {
|
||||||
// initialize mqtt
|
|
||||||
_mqttClient = new espMqttClient();
|
_mqttClient = new espMqttClient();
|
||||||
};
|
};
|
||||||
void loop(){};
|
void loop(){};
|
||||||
|
|
||||||
|
void registerURI(){};
|
||||||
|
|
||||||
SecurityManager * getSecurityManager() {
|
SecurityManager * getSecurityManager() {
|
||||||
return &_securitySettingsService;
|
return &_securitySettingsService;
|
||||||
}
|
}
|
||||||
|
|||||||
505
lib_standalone/PsychicHttp.h
Normal file
505
lib_standalone/PsychicHttp.h
Normal file
@@ -0,0 +1,505 @@
|
|||||||
|
/*
|
||||||
|
* PsychicHttp.h
|
||||||
|
* Standalone hacky version
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef PsychicHttp_h
|
||||||
|
#define PsychicHttp_h
|
||||||
|
|
||||||
|
#include "Arduino.h"
|
||||||
|
#include <ArduinoJson.h>
|
||||||
|
#include <functional>
|
||||||
|
#include <map>
|
||||||
|
#include <list>
|
||||||
|
|
||||||
|
#define esp_err_t uint8_t
|
||||||
|
|
||||||
|
class PsychicHttpServer;
|
||||||
|
class PsychicHttpsServer;
|
||||||
|
class PsychicEndpoint;
|
||||||
|
class PsychicHandler;
|
||||||
|
class PsychicStaticFileHandler;
|
||||||
|
class PsychicClient;
|
||||||
|
class PsychicRequest;
|
||||||
|
class PsychicResponse;
|
||||||
|
class PsychicEventSource;
|
||||||
|
class PsychicEventSourceResponse;
|
||||||
|
class PsychicEventSourceClient;
|
||||||
|
class PsychicResponse;
|
||||||
|
|
||||||
|
typedef std::function<void(PsychicEventSourceClient * client)> PsychicEventSourceClientCallback;
|
||||||
|
typedef std::function<esp_err_t(PsychicRequest * request, JsonVariant & json)> PsychicJsonRequestCallback;
|
||||||
|
typedef std::function<bool(PsychicRequest * request)> PsychicRequestFilterFunction;
|
||||||
|
typedef std::function<void(PsychicClient * client)> PsychicClientCallback;
|
||||||
|
typedef std::function<esp_err_t(PsychicRequest * request)> PsychicHttpRequestCallback;
|
||||||
|
typedef std::function<esp_err_t(PsychicRequest * request, JsonVariant & json)> PsychicJsonRequestCallback; // added by proddy
|
||||||
|
|
||||||
|
/* Request Methods */
|
||||||
|
#define HTTP_METHOD_MAP(XX) \
|
||||||
|
XX(1, GET, GET) \
|
||||||
|
XX(3, POST, POST)
|
||||||
|
|
||||||
|
enum http_method {
|
||||||
|
#define XX(num, name, string) HTTP_##name = num,
|
||||||
|
HTTP_METHOD_MAP(XX)
|
||||||
|
#undef XX
|
||||||
|
};
|
||||||
|
|
||||||
|
constexpr const char * JSON_MIMETYPE = "application/json";
|
||||||
|
|
||||||
|
enum HTTPAuthMethod { BASIC_AUTH, DIGEST_AUTH };
|
||||||
|
|
||||||
|
typedef void * httpd_handle_t;
|
||||||
|
|
||||||
|
typedef struct httpd_req {
|
||||||
|
httpd_handle_t handle; /*!< Handle to server instance */
|
||||||
|
int method; /*!< The type of HTTP request, -1 if unsupported method */
|
||||||
|
const char uri[513]; /*!< The URI of this request (1 byte extra for null termination) */
|
||||||
|
size_t content_len; /*!< Length of the request body */
|
||||||
|
void * aux; /*!< Internally used members */
|
||||||
|
|
||||||
|
} httpd_req_t;
|
||||||
|
|
||||||
|
typedef std::map<String, String> SessionData;
|
||||||
|
enum Disposition { NONE, INLINE, ATTACHMENT, FORM_DATA };
|
||||||
|
|
||||||
|
struct ContentDisposition {
|
||||||
|
Disposition disposition;
|
||||||
|
String filename;
|
||||||
|
String name;
|
||||||
|
};
|
||||||
|
|
||||||
|
class PsychicWebParameter {
|
||||||
|
private:
|
||||||
|
String _name;
|
||||||
|
String _value;
|
||||||
|
size_t _size;
|
||||||
|
bool _isForm;
|
||||||
|
bool _isFile;
|
||||||
|
|
||||||
|
public:
|
||||||
|
PsychicWebParameter(const String & name, const String & value, bool form = false, bool file = false, size_t size = 0)
|
||||||
|
: _name(name)
|
||||||
|
, _value(value)
|
||||||
|
, _size(size)
|
||||||
|
, _isForm(form)
|
||||||
|
, _isFile(file) {
|
||||||
|
}
|
||||||
|
const String & name() const {
|
||||||
|
return _name;
|
||||||
|
}
|
||||||
|
const String & value() const {
|
||||||
|
return _value;
|
||||||
|
}
|
||||||
|
size_t size() const {
|
||||||
|
return _size;
|
||||||
|
}
|
||||||
|
bool isPost() const {
|
||||||
|
return _isForm;
|
||||||
|
}
|
||||||
|
bool isFile() const {
|
||||||
|
return _isFile;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class PsychicRequest {
|
||||||
|
protected:
|
||||||
|
PsychicHttpServer * _server;
|
||||||
|
httpd_req_t * _req;
|
||||||
|
SessionData * _session;
|
||||||
|
PsychicClient * _client;
|
||||||
|
|
||||||
|
http_method _method;
|
||||||
|
String _uri;
|
||||||
|
String _query;
|
||||||
|
String _body;
|
||||||
|
|
||||||
|
std::list<PsychicWebParameter *> _params;
|
||||||
|
|
||||||
|
void _addParams(const String & params);
|
||||||
|
void _parseGETParams();
|
||||||
|
void _parsePOSTParams();
|
||||||
|
|
||||||
|
const String _extractParam(const String & authReq, const String & param, const char delimit);
|
||||||
|
const String _getRandomHexString();
|
||||||
|
|
||||||
|
public:
|
||||||
|
PsychicRequest(PsychicHttpServer * server, httpd_req_t * req);
|
||||||
|
virtual ~PsychicRequest();
|
||||||
|
|
||||||
|
void * _tempObject;
|
||||||
|
|
||||||
|
PsychicHttpServer * server();
|
||||||
|
httpd_req_t * request();
|
||||||
|
virtual PsychicClient * client();
|
||||||
|
|
||||||
|
bool isMultipart();
|
||||||
|
esp_err_t loadBody();
|
||||||
|
|
||||||
|
const String header(const char * name);
|
||||||
|
bool hasHeader(const char * name);
|
||||||
|
|
||||||
|
static void freeSession(void * ctx);
|
||||||
|
bool hasSessionKey(const String & key);
|
||||||
|
const String getSessionKey(const String & key);
|
||||||
|
void setSessionKey(const String & key, const String & value);
|
||||||
|
|
||||||
|
bool hasCookie(const char * key);
|
||||||
|
const String getCookie(const char * key);
|
||||||
|
|
||||||
|
http_method method() {
|
||||||
|
return HTTP_GET;
|
||||||
|
} // returns the HTTP method used as enum value (eg. HTTP_GET)
|
||||||
|
const String methodStr(); // returns the HTTP method used as a string (eg. "GET")
|
||||||
|
const String path(); // returns the request path (eg /page?foo=bar returns "/page")
|
||||||
|
const String & uri(); // returns the full request uri (eg /page?foo=bar)
|
||||||
|
const String & query(); // returns the request query data (eg /page?foo=bar returns "foo=bar")
|
||||||
|
const String host(); // returns the requested host (request to http://psychic.local/foo will return "psychic.local")
|
||||||
|
const String contentType(); // returns the Content-Type header value
|
||||||
|
size_t contentLength(); // returns the Content-Length header value
|
||||||
|
const String & body(); // returns the body of the request
|
||||||
|
const ContentDisposition getContentDisposition();
|
||||||
|
|
||||||
|
const String & queryString() {
|
||||||
|
return query();
|
||||||
|
} //compatability function. same as query()
|
||||||
|
const String & url() {
|
||||||
|
return uri();
|
||||||
|
} //compatability function. same as uri()
|
||||||
|
|
||||||
|
void loadParams();
|
||||||
|
PsychicWebParameter * addParam(PsychicWebParameter * param);
|
||||||
|
PsychicWebParameter * addParam(const String & name, const String & value, bool decode = true);
|
||||||
|
bool hasParam(const char * key);
|
||||||
|
PsychicWebParameter * getParam(const char * name);
|
||||||
|
|
||||||
|
const String getFilename();
|
||||||
|
|
||||||
|
bool authenticate(const char * username, const char * password);
|
||||||
|
esp_err_t requestAuthentication(HTTPAuthMethod mode, const char * realm, const char * authFailMsg);
|
||||||
|
|
||||||
|
esp_err_t redirect(const char * url);
|
||||||
|
esp_err_t reply(int code);
|
||||||
|
esp_err_t reply(const char * content);
|
||||||
|
esp_err_t reply(int code, const char * contentType, const char * content);
|
||||||
|
};
|
||||||
|
|
||||||
|
class PsychicHandler {
|
||||||
|
protected:
|
||||||
|
PsychicRequestFilterFunction _filter;
|
||||||
|
PsychicHttpServer * _server;
|
||||||
|
|
||||||
|
String _username;
|
||||||
|
String _password;
|
||||||
|
HTTPAuthMethod _method;
|
||||||
|
String _realm;
|
||||||
|
String _authFailMsg;
|
||||||
|
|
||||||
|
std::list<PsychicClient *> _clients;
|
||||||
|
|
||||||
|
public:
|
||||||
|
PsychicHandler();
|
||||||
|
~PsychicHandler();
|
||||||
|
|
||||||
|
PsychicHandler * setFilter(PsychicRequestFilterFunction fn);
|
||||||
|
bool filter(PsychicRequest * request);
|
||||||
|
|
||||||
|
PsychicHandler *
|
||||||
|
setAuthentication(const char * username, const char * password, HTTPAuthMethod method = BASIC_AUTH, const char * realm = "", const char * authFailMsg = "");
|
||||||
|
bool needsAuthentication(PsychicRequest * request);
|
||||||
|
esp_err_t authenticate(PsychicRequest * request);
|
||||||
|
|
||||||
|
virtual bool isWebSocket() {
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
PsychicClient * checkForNewClient(PsychicClient * client);
|
||||||
|
void checkForClosedClient(PsychicClient * client);
|
||||||
|
|
||||||
|
virtual void addClient(PsychicClient * client);
|
||||||
|
virtual void removeClient(PsychicClient * client);
|
||||||
|
virtual PsychicClient * getClient(int socket);
|
||||||
|
virtual PsychicClient * getClient(PsychicClient * client);
|
||||||
|
virtual void openCallback(PsychicClient * client){};
|
||||||
|
virtual void closeCallback(PsychicClient * client){};
|
||||||
|
|
||||||
|
bool hasClient(PsychicClient * client);
|
||||||
|
int count() {
|
||||||
|
return _clients.size();
|
||||||
|
};
|
||||||
|
const std::list<PsychicClient *> & getClientList();
|
||||||
|
|
||||||
|
virtual bool canHandle(PsychicRequest * request) {
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
virtual esp_err_t handleRequest(PsychicRequest * request) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
class PsychicEndpoint {
|
||||||
|
friend PsychicHttpServer;
|
||||||
|
|
||||||
|
private:
|
||||||
|
PsychicHttpServer * _server;
|
||||||
|
String _uri;
|
||||||
|
http_method _method;
|
||||||
|
PsychicHandler * _handler;
|
||||||
|
|
||||||
|
public:
|
||||||
|
PsychicEndpoint();
|
||||||
|
PsychicEndpoint(PsychicHttpServer * server, http_method method, const char * uri);
|
||||||
|
|
||||||
|
PsychicEndpoint * setHandler(PsychicHandler * handler);
|
||||||
|
PsychicHandler * handler();
|
||||||
|
|
||||||
|
PsychicEndpoint * setFilter(PsychicRequestFilterFunction fn);
|
||||||
|
PsychicEndpoint *
|
||||||
|
setAuthentication(const char * username, const char * password, HTTPAuthMethod method = BASIC_AUTH, const char * realm = "", const char * authFailMsg = "");
|
||||||
|
|
||||||
|
String uri();
|
||||||
|
|
||||||
|
static esp_err_t requestCallback(httpd_req_t * req);
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct httpd_config {
|
||||||
|
uint16_t max_uri_handlers; /*!< Maximum allowed uri handlers */
|
||||||
|
} httpd_config_t;
|
||||||
|
|
||||||
|
httpd_config_t config;
|
||||||
|
|
||||||
|
class PsychicHttpServer {
|
||||||
|
public:
|
||||||
|
PsychicHttpServer();
|
||||||
|
~PsychicHttpServer();
|
||||||
|
|
||||||
|
httpd_handle_t server;
|
||||||
|
httpd_config_t config;
|
||||||
|
|
||||||
|
unsigned long maxUploadSize;
|
||||||
|
unsigned long maxRequestBodySize;
|
||||||
|
|
||||||
|
PsychicEndpoint * defaultEndpoint;
|
||||||
|
PsychicHandler & addHandler(PsychicHandler * handler);
|
||||||
|
|
||||||
|
esp_err_t listen(uint16_t port);
|
||||||
|
|
||||||
|
PsychicEndpoint * on(const char * uri);
|
||||||
|
PsychicEndpoint * on(const char * uri, http_method method);
|
||||||
|
PsychicEndpoint * on(const char * uri, PsychicHttpRequestCallback onRequest);
|
||||||
|
PsychicEndpoint * on(const char * uri, http_method method, PsychicHttpRequestCallback onRequest);
|
||||||
|
PsychicEndpoint * on(const char * uri, PsychicHandler * handler);
|
||||||
|
PsychicEndpoint * on(const char * uri, http_method method, PsychicHandler * handler);
|
||||||
|
PsychicEndpoint * on(const char * uri, http_method method, PsychicJsonRequestCallback onRequest); // added proddy
|
||||||
|
|
||||||
|
void onNotFound(PsychicHttpRequestCallback fn);
|
||||||
|
|
||||||
|
void onOpen(PsychicClientCallback handler);
|
||||||
|
void onClose(PsychicClientCallback handler);
|
||||||
|
static esp_err_t openCallback(httpd_handle_t hd, int sockfd);
|
||||||
|
static void closeCallback(httpd_handle_t hd, int sockfd);
|
||||||
|
};
|
||||||
|
|
||||||
|
class PsychicHttpsServer : public PsychicHttpServer {
|
||||||
|
public:
|
||||||
|
PsychicHttpsServer();
|
||||||
|
~PsychicHttpsServer();
|
||||||
|
|
||||||
|
uint8_t listen(uint16_t port, const char * cert, const char * private_key);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct HTTPHeader {
|
||||||
|
char * field;
|
||||||
|
char * value;
|
||||||
|
};
|
||||||
|
|
||||||
|
class DefaultHeaders {
|
||||||
|
std::list<HTTPHeader> _headers;
|
||||||
|
|
||||||
|
public:
|
||||||
|
DefaultHeaders() {
|
||||||
|
}
|
||||||
|
|
||||||
|
void addHeader(const String & field, const String & value) {
|
||||||
|
addHeader(field.c_str(), value.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
void addHeader(const char * field, const char * value) {
|
||||||
|
HTTPHeader header;
|
||||||
|
_headers.push_back(header);
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::list<HTTPHeader> & getHeaders() {
|
||||||
|
return _headers;
|
||||||
|
}
|
||||||
|
|
||||||
|
DefaultHeaders(DefaultHeaders const &) = delete;
|
||||||
|
DefaultHeaders & operator=(DefaultHeaders const &) = delete;
|
||||||
|
|
||||||
|
static DefaultHeaders & Instance() {
|
||||||
|
static DefaultHeaders instance;
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class PsychicWebHandler : public PsychicHandler {
|
||||||
|
protected:
|
||||||
|
PsychicHttpRequestCallback _requestCallback;
|
||||||
|
|
||||||
|
public:
|
||||||
|
PsychicWebHandler();
|
||||||
|
~PsychicWebHandler();
|
||||||
|
|
||||||
|
virtual bool canHandle(PsychicRequest * request) override;
|
||||||
|
virtual esp_err_t handleRequest(PsychicRequest * request) override;
|
||||||
|
PsychicWebHandler * onRequest(PsychicHttpRequestCallback fn);
|
||||||
|
};
|
||||||
|
|
||||||
|
class PsychicResponse {
|
||||||
|
protected:
|
||||||
|
PsychicRequest * _request;
|
||||||
|
|
||||||
|
int _code;
|
||||||
|
char _status[60];
|
||||||
|
std::list<HTTPHeader> _headers;
|
||||||
|
int64_t _contentLength;
|
||||||
|
const char * _body;
|
||||||
|
|
||||||
|
public:
|
||||||
|
PsychicResponse(PsychicRequest * request);
|
||||||
|
virtual ~PsychicResponse();
|
||||||
|
|
||||||
|
void setCode(int code);
|
||||||
|
|
||||||
|
void setContentType(const char * contentType);
|
||||||
|
void setContentLength(int64_t contentLength) {
|
||||||
|
_contentLength = contentLength;
|
||||||
|
}
|
||||||
|
int64_t getContentLength(int64_t contentLength) {
|
||||||
|
return _contentLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
void addHeader(const char * field, const char * value);
|
||||||
|
void setCookie(const char * key, const char * value, unsigned long max_age = 60 * 60 * 24 * 30, const char * extras = "");
|
||||||
|
void setContent(const char * content);
|
||||||
|
void setContent(const uint8_t * content, size_t len);
|
||||||
|
const char * getContent();
|
||||||
|
size_t getContentLength();
|
||||||
|
esp_err_t send();
|
||||||
|
void sendHeaders();
|
||||||
|
esp_err_t sendChunk(uint8_t * chunk, size_t chunksize);
|
||||||
|
esp_err_t finishChunking();
|
||||||
|
};
|
||||||
|
|
||||||
|
class PsychicJsonResponse : public PsychicResponse {
|
||||||
|
protected:
|
||||||
|
#ifdef ARDUINOJSON_5_COMPATIBILITY
|
||||||
|
DynamicJsonBuffer _jsonBuffer;
|
||||||
|
#else
|
||||||
|
DynamicJsonDocument _jsonBuffer;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
JsonVariant _root;
|
||||||
|
size_t _contentLength;
|
||||||
|
bool _msgPack; // added by proddy
|
||||||
|
|
||||||
|
public:
|
||||||
|
PsychicJsonResponse(PsychicRequest * request, bool isArray = false, size_t maxJsonBufferSize = 4096, bool msgPack = false) // added by proddy
|
||||||
|
: PsychicResponse(request)
|
||||||
|
, _jsonBuffer(maxJsonBufferSize)
|
||||||
|
, _msgPack(msgPack) // added by proddy
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
~PsychicJsonResponse() {
|
||||||
|
}
|
||||||
|
|
||||||
|
JsonVariant & getRoot() {
|
||||||
|
return _root;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t getLength() {
|
||||||
|
// return measureJson(_root);
|
||||||
|
return (_msgPack) ? measureMsgPack(_root) : measureJson(_root); // added by proddy
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_err_t send() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class PsychicClient {
|
||||||
|
protected:
|
||||||
|
httpd_handle_t _server;
|
||||||
|
int _socket;
|
||||||
|
|
||||||
|
public:
|
||||||
|
PsychicClient(httpd_handle_t server, int socket);
|
||||||
|
~PsychicClient();
|
||||||
|
|
||||||
|
//no idea if this is the right way to do it or not, but lets see.
|
||||||
|
//pointer to our derived class (eg. PsychicWebSocketConnection)
|
||||||
|
void * _friend;
|
||||||
|
|
||||||
|
bool isNew = false;
|
||||||
|
|
||||||
|
bool operator==(PsychicClient & rhs) const {
|
||||||
|
return _socket == rhs.socket();
|
||||||
|
}
|
||||||
|
|
||||||
|
httpd_handle_t server();
|
||||||
|
int socket();
|
||||||
|
esp_err_t close();
|
||||||
|
|
||||||
|
IPAddress localIP();
|
||||||
|
IPAddress remoteIP();
|
||||||
|
};
|
||||||
|
|
||||||
|
class PsychicEventSourceClient : public PsychicClient {
|
||||||
|
protected:
|
||||||
|
uint32_t _lastId;
|
||||||
|
|
||||||
|
public:
|
||||||
|
PsychicEventSourceClient(PsychicClient * client);
|
||||||
|
~PsychicEventSourceClient();
|
||||||
|
|
||||||
|
uint32_t lastId() const {
|
||||||
|
return _lastId;
|
||||||
|
}
|
||||||
|
void send(const char * message, const char * event = NULL, uint32_t id = 0, uint32_t reconnect = 0);
|
||||||
|
void sendEvent(const char * event);
|
||||||
|
};
|
||||||
|
|
||||||
|
class PsychicEventSource : public PsychicHandler {
|
||||||
|
private:
|
||||||
|
PsychicEventSourceClientCallback _onOpen;
|
||||||
|
PsychicEventSourceClientCallback _onClose;
|
||||||
|
|
||||||
|
public:
|
||||||
|
PsychicEventSource();
|
||||||
|
~PsychicEventSource();
|
||||||
|
|
||||||
|
PsychicEventSourceClient * getClient(int socket) override;
|
||||||
|
PsychicEventSourceClient * getClient(PsychicClient * client) override;
|
||||||
|
void addClient(PsychicClient * client) override;
|
||||||
|
void removeClient(PsychicClient * client) override;
|
||||||
|
void openCallback(PsychicClient * client) override;
|
||||||
|
void closeCallback(PsychicClient * client) override;
|
||||||
|
|
||||||
|
PsychicEventSource * onOpen(PsychicEventSourceClientCallback fn);
|
||||||
|
PsychicEventSource * onClose(PsychicEventSourceClientCallback fn);
|
||||||
|
|
||||||
|
esp_err_t handleRequest(PsychicRequest * request) override final;
|
||||||
|
|
||||||
|
void send(const char * message, const char * event = NULL, uint32_t id = 0, uint32_t reconnect = 0);
|
||||||
|
};
|
||||||
|
|
||||||
|
class PsychicEventSourceResponse : public PsychicResponse {
|
||||||
|
public:
|
||||||
|
PsychicEventSourceResponse(PsychicRequest * request);
|
||||||
|
esp_err_t send();
|
||||||
|
};
|
||||||
|
|
||||||
|
String generateEventMessage(const char * message, const char * event, uint32_t id, uint32_t reconnect);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -2,15 +2,12 @@
|
|||||||
#define SecurityManager_h
|
#define SecurityManager_h
|
||||||
|
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
|
#include <PsychicHttp.h>
|
||||||
#include <Features.h>
|
#include <Features.h>
|
||||||
#include <list>
|
#include <list>
|
||||||
|
|
||||||
#ifndef FACTORY_JWT_SECRET
|
#define FACTORY_JWT_SECRET "secret"
|
||||||
#define FACTORY_JWT_SECRET ESPUtils::defaultDeviceValue()
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define ACCESS_TOKEN_PARAMATER "access_token"
|
#define ACCESS_TOKEN_PARAMATER "access_token"
|
||||||
|
|
||||||
#define AUTHORIZATION_HEADER "Authorization"
|
#define AUTHORIZATION_HEADER "Authorization"
|
||||||
#define AUTHORIZATION_HEADER_PREFIX "Bearer "
|
#define AUTHORIZATION_HEADER_PREFIX "Bearer "
|
||||||
#define AUTHORIZATION_HEADER_PREFIX_LEN 7
|
#define AUTHORIZATION_HEADER_PREFIX_LEN 7
|
||||||
@@ -67,10 +64,35 @@ class AuthenticationPredicates {
|
|||||||
|
|
||||||
class SecurityManager {
|
class SecurityManager {
|
||||||
public:
|
public:
|
||||||
#if FT_ENABLED(FT_SECURITY)
|
/*
|
||||||
|
* Authenticate, returning the user if found
|
||||||
|
*/
|
||||||
virtual Authentication authenticate(const String & username, const String & password) = 0;
|
virtual Authentication authenticate(const String & username, const String & password) = 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Generate a JWT for the user provided
|
||||||
|
*/
|
||||||
virtual String generateJWT(User * user) = 0;
|
virtual String generateJWT(User * user) = 0;
|
||||||
#endif
|
|
||||||
|
/*
|
||||||
|
* Check the request header for the Authorization token
|
||||||
|
*/
|
||||||
|
virtual Authentication authenticateRequest(PsychicRequest * request) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Filter a request with the provided predicate, only returning true if the predicate matches.
|
||||||
|
*/
|
||||||
|
virtual PsychicRequestFilterFunction filterRequest(AuthenticationPredicate predicate) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wrap the provided request to provide validation against an AuthenticationPredicate.
|
||||||
|
*/
|
||||||
|
virtual PsychicHttpRequestCallback wrapRequest(PsychicHttpRequestCallback onRequest, AuthenticationPredicate predicate) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wrap the provided json request callback to provide validation against an AuthenticationPredicate.
|
||||||
|
*/
|
||||||
|
virtual PsychicJsonRequestCallback wrapCallback(PsychicJsonRequestCallback onRequest, AuthenticationPredicate predicate) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -4,12 +4,13 @@
|
|||||||
|
|
||||||
#if FT_ENABLED(FT_SECURITY)
|
#if FT_ENABLED(FT_SECURITY)
|
||||||
|
|
||||||
#include "../../src/emsesp_stub.h
|
#include "../../src/emsesp_stub.h" // proddy added
|
||||||
|
|
||||||
SecuritySettingsService::SecuritySettingsService(AsyncWebServer * server, FS * fs)
|
SecuritySettingsService::SecuritySettingsService(AsyncWebServer * server, FS * fs)
|
||||||
: _httpEndpoint(SecuritySettings::read, SecuritySettings::update, this, server, SECURITY_SETTINGS_PATH, this)
|
: _httpEndpoint(SecuritySettings::read, SecuritySettings::update, this, server, SECURITY_SETTINGS_PATH, this)
|
||||||
, _fsPersistence(SecuritySettings::read, SecuritySettings::update, this, fs, SECURITY_SETTINGS_FILE)
|
, _fsPersistence(SecuritySettings::read, SecuritySettings::update, this, fs, SECURITY_SETTINGS_FILE)
|
||||||
, _jwtHandler(FACTORY_JWT_SECRET) {
|
// , _jwtHandler(FACTORY_JWT_SECRET) {
|
||||||
|
{
|
||||||
addUpdateHandler([&](const String & originId) { configureJWTHandler(); }, false);
|
addUpdateHandler([&](const String & originId) { configureJWTHandler(); }, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -18,29 +19,32 @@ void SecuritySettingsService::begin() {
|
|||||||
configureJWTHandler();
|
configureJWTHandler();
|
||||||
}
|
}
|
||||||
|
|
||||||
Authentication SecuritySettingsService::authenticateRequest(AsyncWebServerRequest * request) {
|
void SecuritySettingsService::registerURI() {
|
||||||
AsyncWebHeader * authorizationHeader = request->getHeader(AUTHORIZATION_HEADER);
|
_httpEndpoint.registerURI();
|
||||||
if (authorizationHeader) {
|
_server->on(GENERATE_TOKEN_PATH, HTTP_GET, wrapRequest(std::bind(&SecuritySettingsService::generateToken, this, _1), AuthenticationPredicates::IS_ADMIN));
|
||||||
String value = authorizationHeader->value();
|
}
|
||||||
|
|
||||||
|
Authentication SecuritySettingsService::authenticateRequest(PsychicRequest * request) {
|
||||||
|
if (request->hasHeader(AUTHORIZATION_HEADER)) {
|
||||||
|
auto value = request->header(AUTHORIZATION_HEADER);
|
||||||
if (value.startsWith(AUTHORIZATION_HEADER_PREFIX)) {
|
if (value.startsWith(AUTHORIZATION_HEADER_PREFIX)) {
|
||||||
value = value.substring(AUTHORIZATION_HEADER_PREFIX_LEN);
|
value = value.substring(AUTHORIZATION_HEADER_PREFIX_LEN);
|
||||||
return authenticateJWT(value);
|
return authenticateJWT(value);
|
||||||
}
|
}
|
||||||
} else if (request->hasParam(ACCESS_TOKEN_PARAMATER)) {
|
} else if (request->hasParam(ACCESS_TOKEN_PARAMATER)) {
|
||||||
AsyncWebParameter * tokenParamater = request->getParam(ACCESS_TOKEN_PARAMATER);
|
String value = request->getParam(ACCESS_TOKEN_PARAMATER)->value();
|
||||||
String value = tokenParamater->value();
|
|
||||||
return authenticateJWT(value);
|
return authenticateJWT(value);
|
||||||
}
|
}
|
||||||
return Authentication();
|
return Authentication();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SecuritySettingsService::configureJWTHandler() {
|
void SecuritySettingsService::configureJWTHandler() {
|
||||||
_jwtHandler.setSecret(_state.jwtSecret);
|
// _jwtHandler.setSecret(_state.jwtSecret);
|
||||||
}
|
}
|
||||||
|
|
||||||
Authentication SecuritySettingsService::authenticateJWT(String & jwt) {
|
Authentication SecuritySettingsService::authenticateJWT(String & jwt) {
|
||||||
DynamicJsonDocument payloadDocument(MAX_JWT_SIZE);
|
DynamicJsonDocument payloadDocument(MAX_JWT_SIZE);
|
||||||
_jwtHandler.parseJWT(jwt, payloadDocument);
|
// _jwtHandler.parseJWT(jwt, payloadDocument);
|
||||||
if (payloadDocument.is<JsonObject>()) {
|
if (payloadDocument.is<JsonObject>()) {
|
||||||
JsonObject parsedPayload = payloadDocument.as<JsonObject>();
|
JsonObject parsedPayload = payloadDocument.as<JsonObject>();
|
||||||
String username = parsedPayload["username"];
|
String username = parsedPayload["username"];
|
||||||
@@ -78,7 +82,7 @@ String SecuritySettingsService::generateJWT(User * user) {
|
|||||||
DynamicJsonDocument jsonDocument(MAX_JWT_SIZE);
|
DynamicJsonDocument jsonDocument(MAX_JWT_SIZE);
|
||||||
JsonObject payload = jsonDocument.to<JsonObject>();
|
JsonObject payload = jsonDocument.to<JsonObject>();
|
||||||
populateJWTPayload(payload, user);
|
populateJWTPayload(payload, user);
|
||||||
return _jwtHandler.buildJWT(payload);
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
ArRequestFilterFunction SecuritySettingsService::filterRequest(AuthenticationPredicate predicate) {
|
ArRequestFilterFunction SecuritySettingsService::filterRequest(AuthenticationPredicate predicate) {
|
||||||
@@ -88,56 +92,26 @@ ArRequestFilterFunction SecuritySettingsService::filterRequest(AuthenticationPre
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
ArRequestHandlerFunction SecuritySettingsService::wrapRequest(ArRequestHandlerFunction onRequest, AuthenticationPredicate predicate) {
|
PsychicHttpRequestCallback SecuritySettingsService::wrapRequest(PsychicHttpRequestCallback onRequest, AuthenticationPredicate predicate) {
|
||||||
return [this, onRequest, predicate](AsyncWebServerRequest * request) {
|
return [this, onRequest, predicate](PsychicRequest * request) {
|
||||||
Authentication authentication = authenticateRequest(request);
|
Authentication authentication = authenticateRequest(request);
|
||||||
if (!predicate(authentication)) {
|
if (!predicate(authentication)) {
|
||||||
request->send(401);
|
return request->reply(401);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
onRequest(request);
|
return onRequest(request);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
ArJsonRequestHandlerFunction SecuritySettingsService::wrapCallback(ArJsonRequestHandlerFunction onRequest, AuthenticationPredicate predicate) {
|
PsychicJsonRequestCallback SecuritySettingsService::wrapCallback(PsychicJsonRequestCallback onRequest, AuthenticationPredicate predicate) {
|
||||||
return [this, onRequest, predicate](AsyncWebServerRequest * request, JsonVariant & json) {
|
return [this, onRequest, predicate](PsychicRequest * request, JsonVariant & json) {
|
||||||
Authentication authentication = authenticateRequest(request);
|
Authentication authentication = authenticateRequest(request);
|
||||||
if (!predicate(authentication)) {
|
if (!predicate(authentication)) {
|
||||||
request->send(401);
|
return request->reply(401);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
onRequest(request, json);
|
return onRequest(request, json);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
User ADMIN_USER = User(FACTORY_ADMIN_USERNAME, FACTORY_ADMIN_PASSWORD, true);
|
|
||||||
|
|
||||||
SecuritySettingsService::SecuritySettingsService(AsyncWebServer * server, FS * fs)
|
|
||||||
: SecurityManager() {
|
|
||||||
}
|
|
||||||
SecuritySettingsService::~SecuritySettingsService() {
|
|
||||||
}
|
|
||||||
|
|
||||||
ArRequestFilterFunction SecuritySettingsService::filterRequest(AuthenticationPredicate predicate) {
|
|
||||||
return [this, predicate](AsyncWebServerRequest * request) { return true; };
|
|
||||||
}
|
|
||||||
|
|
||||||
// Return the admin user on all request - disabling security features
|
|
||||||
Authentication SecuritySettingsService::authenticateRequest(AsyncWebServerRequest * request) {
|
|
||||||
return Authentication(ADMIN_USER);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Return the function unwrapped
|
|
||||||
ArRequestHandlerFunction SecuritySettingsService::wrapRequest(ArRequestHandlerFunction onRequest, AuthenticationPredicate predicate) {
|
|
||||||
return onRequest;
|
|
||||||
}
|
|
||||||
|
|
||||||
ArJsonRequestHandlerFunction SecuritySettingsService::wrapCallback(ArJsonRequestHandlerFunction onRequest, AuthenticationPredicate predicate) {
|
|
||||||
return onRequest;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -25,7 +25,8 @@
|
|||||||
#define SECURITY_SETTINGS_FILE "/config/securitySettings.json"
|
#define SECURITY_SETTINGS_FILE "/config/securitySettings.json"
|
||||||
#define SECURITY_SETTINGS_PATH "/rest/securitySettings"
|
#define SECURITY_SETTINGS_PATH "/rest/securitySettings"
|
||||||
|
|
||||||
#if FT_ENABLED(FT_SECURITY)
|
#define GENERATE_TOKEN_SIZE 512
|
||||||
|
#define GENERATE_TOKEN_PATH "/rest/generateToken"
|
||||||
|
|
||||||
class SecuritySettings {
|
class SecuritySettings {
|
||||||
public:
|
public:
|
||||||
@@ -66,41 +67,32 @@ class SecuritySettings {
|
|||||||
|
|
||||||
class SecuritySettingsService : public StatefulService<SecuritySettings>, public SecurityManager {
|
class SecuritySettingsService : public StatefulService<SecuritySettings>, public SecurityManager {
|
||||||
public:
|
public:
|
||||||
SecuritySettingsService(AsyncWebServer * server, FS * fs);
|
SecuritySettingsService(PsychicHttpServer * server, FS * fs);
|
||||||
|
|
||||||
void begin();
|
void begin();
|
||||||
|
void registerURI();
|
||||||
|
|
||||||
// Functions to implement SecurityManager
|
// Functions to implement SecurityManager
|
||||||
Authentication authenticate(const String & username, const String & password);
|
Authentication authenticate(const String & username, const String & password);
|
||||||
Authentication authenticateRequest(AsyncWebServerRequest * request);
|
Authentication authenticateRequest(PsychicRequest * request);
|
||||||
String generateJWT(User * user);
|
String generateJWT(User * user);
|
||||||
ArRequestFilterFunction filterRequest(AuthenticationPredicate predicate);
|
|
||||||
ArRequestHandlerFunction wrapRequest(ArRequestHandlerFunction onRequest, AuthenticationPredicate predicate);
|
PsychicRequestFilterFunction filterRequest(AuthenticationPredicate predicate);
|
||||||
ArJsonRequestHandlerFunction wrapCallback(ArJsonRequestHandlerFunction callback, AuthenticationPredicate predicate);
|
PsychicHttpRequestCallback wrapRequest(PsychicHttpRequestCallback onRequest, AuthenticationPredicate predicate);
|
||||||
|
PsychicJsonRequestCallback wrapCallback(PsychicJsonRequestCallback onRequest, AuthenticationPredicate predicate);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
PsychicHttpServer * _server;
|
||||||
|
|
||||||
HttpEndpoint<SecuritySettings> _httpEndpoint;
|
HttpEndpoint<SecuritySettings> _httpEndpoint;
|
||||||
FSPersistence<SecuritySettings> _fsPersistence;
|
FSPersistence<SecuritySettings> _fsPersistence;
|
||||||
ArduinoJsonJWT _jwtHandler;
|
// ArduinoJsonJWT _jwtHandler;
|
||||||
|
|
||||||
|
esp_err_t generateToken(PsychicRequest * request);
|
||||||
|
|
||||||
void configureJWTHandler();
|
void configureJWTHandler();
|
||||||
Authentication authenticateJWT(String & jwt);
|
Authentication authenticateJWT(String & jwt); // Lookup the user by JWT
|
||||||
boolean validatePayload(JsonObject & parsedPayload, User * user);
|
boolean validatePayload(JsonObject & parsedPayload, User * user); // Verify the payload is correct
|
||||||
};
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
class SecuritySettingsService : public SecurityManager {
|
|
||||||
public:
|
|
||||||
SecuritySettingsService(AsyncWebServer * server, FS * fs);
|
|
||||||
~SecuritySettingsService();
|
|
||||||
|
|
||||||
// minimal set of functions to support framework with security settings disabled
|
|
||||||
Authentication authenticateRequest(AsyncWebServerRequest * request);
|
|
||||||
ArRequestFilterFunction filterRequest(AuthenticationPredicate predicate);
|
|
||||||
ArRequestHandlerFunction wrapRequest(ArRequestHandlerFunction onRequest, AuthenticationPredicate predicate);
|
|
||||||
ArJsonRequestHandlerFunction wrapCallback(ArJsonRequestHandlerFunction onRequest, AuthenticationPredicate predicate);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
#endif
|
|
||||||
|
|||||||
@@ -185,7 +185,7 @@ build_flags =
|
|||||||
; platform = https://github.com/Jason2866/platform-espressif32.git#Arduino/IDF5
|
; platform = https://github.com/Jason2866/platform-espressif32.git#Arduino/IDF5
|
||||||
; platform_packages = https://github.com/espressif/arduino-esp32.git#3.0.0-alpha2
|
; platform_packages = https://github.com/espressif/arduino-esp32.git#3.0.0-alpha2
|
||||||
|
|
||||||
platform = espressif32
|
platform = espressif32@6.4.0
|
||||||
framework = arduino
|
framework = arduino
|
||||||
board = esp32dev
|
board = esp32dev
|
||||||
board_build.filesystem = littlefs
|
board_build.filesystem = littlefs
|
||||||
@@ -219,7 +219,8 @@ build_flags =
|
|||||||
-lpthread
|
-lpthread
|
||||||
-std=gnu++11 -Og -ggdb
|
-std=gnu++11 -Og -ggdb
|
||||||
build_src_flags =
|
build_src_flags =
|
||||||
-Wall -Wextra -Werror -Wswitch-enum -Wno-unused-parameter -Wno-inconsistent-missing-override -Wno-unused-lambda-capture -Wno-sign-compare
|
; -Wall -Wextra -Werror -Wswitch-enum -Wno-unused-parameter -Wno-inconsistent-missing-override -Wno-unused-lambda-capture -Wno-sign-compare
|
||||||
|
; -Wall -Wextra -Werror
|
||||||
-Wno-missing-braces
|
-Wno-missing-braces
|
||||||
-I./lib_standalone
|
-I./lib_standalone
|
||||||
-I./lib/ArduinoJson/src
|
-I./lib/ArduinoJson/src
|
||||||
@@ -230,7 +231,6 @@ build_src_flags =
|
|||||||
-I./lib/PButton
|
-I./lib/PButton
|
||||||
-I./lib/espMqttClient/src
|
-I./lib/espMqttClient/src
|
||||||
-I./lib/espMqttClient/src/Transport
|
-I./lib/espMqttClient/src/Transport
|
||||||
-I./lib/PsychicHttp
|
|
||||||
build_src_filter =
|
build_src_filter =
|
||||||
+<*>
|
+<*>
|
||||||
-<.git/>
|
-<.git/>
|
||||||
@@ -242,6 +242,5 @@ build_src_filter =
|
|||||||
+<../lib/PButton>
|
+<../lib/PButton>
|
||||||
+<../lib/espMqttClient/src>
|
+<../lib/espMqttClient/src>
|
||||||
+<../lib/espMqttClient/src/Transport>
|
+<../lib/espMqttClient/src/Transport>
|
||||||
+<../lib/PsychicHttp>
|
|
||||||
lib_compat_mode = off
|
lib_compat_mode = off
|
||||||
lib_ldf_mode = off
|
lib_ldf_mode = off
|
||||||
@@ -22,7 +22,9 @@ static_assert(uuid::thread_safe, "uuid-common must be thread-safe");
|
|||||||
static_assert(uuid::log::thread_safe, "uuid-log must be thread-safe");
|
static_assert(uuid::log::thread_safe, "uuid-log must be thread-safe");
|
||||||
static_assert(uuid::console::thread_safe, "uuid-console must be thread-safe");
|
static_assert(uuid::console::thread_safe, "uuid-console must be thread-safe");
|
||||||
|
|
||||||
|
#ifndef EMSESP_STANDALONE
|
||||||
#include <WWWData.h>
|
#include <WWWData.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace emsesp {
|
namespace emsesp {
|
||||||
|
|
||||||
@@ -1439,7 +1441,9 @@ void EMSESP::setupWeb() {
|
|||||||
|
|
||||||
DefaultHeaders::Instance().addHeader("Server", "EMS-ESP");
|
DefaultHeaders::Instance().addHeader("Server", "EMS-ESP");
|
||||||
|
|
||||||
|
#ifndef EMSESP_STANDALONE
|
||||||
WWWData::registerRoutes(handler); // add webServer.on() endpoints from the generated web code
|
WWWData::registerRoutes(handler); // add webServer.on() endpoints from the generated web code
|
||||||
|
#endif
|
||||||
|
|
||||||
esp8266React.registerURI(); // load up the core system web endpoints
|
esp8266React.registerURI(); // load up the core system web endpoints
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user