Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: added support for filters in WebServer library #9842

Merged
merged 11 commits into from
Jun 13, 2024
14 changes: 7 additions & 7 deletions libraries/WebServer/src/Parsing.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ bool WebServer::_parseRequest(NetworkClient &client) {
//attach handler
RequestHandler *handler;
for (handler = _firstHandler; handler; handler = handler->next()) {
if (handler->canHandle(_currentMethod, _currentUri)) {
if (handler->canHandle(*this, _currentMethod, _currentUri)) {
break;
}
}
Expand Down Expand Up @@ -176,7 +176,7 @@ bool WebServer::_parseRequest(NetworkClient &client) {
}
}

if (!isForm && _currentHandler && _currentHandler->canRaw(_currentUri)) {
if (!isForm && _currentHandler && _currentHandler->canRaw(*this, _currentUri)) {
log_v("Parse raw");
_currentRaw.reset(new HTTPRaw());
_currentRaw->status = RAW_START;
Expand Down Expand Up @@ -334,7 +334,7 @@ void WebServer::_parseArguments(String data) {

void WebServer::_uploadWriteByte(uint8_t b) {
if (_currentUpload->currentSize == HTTP_UPLOAD_BUFLEN) {
if (_currentHandler && _currentHandler->canUpload(_currentUri)) {
if (_currentHandler && _currentHandler->canUpload(*this, _currentUri)) {
_currentHandler->upload(*this, _currentUri, *_currentUpload);
}
_currentUpload->totalSize += _currentUpload->currentSize;
Expand Down Expand Up @@ -449,7 +449,7 @@ bool WebServer::_parseForm(NetworkClient &client, String boundary, uint32_t len)
_currentUpload->totalSize = 0;
_currentUpload->currentSize = 0;
log_v("Start File: %s Type: %s", _currentUpload->filename.c_str(), _currentUpload->type.c_str());
if (_currentHandler && _currentHandler->canUpload(_currentUri)) {
if (_currentHandler && _currentHandler->canUpload(*this, _currentUri)) {
_currentHandler->upload(*this, _currentUri, *_currentUpload);
}
_currentUpload->status = UPLOAD_FILE_WRITE;
Expand Down Expand Up @@ -488,12 +488,12 @@ bool WebServer::_parseForm(NetworkClient &client, String boundary, uint32_t len)
}
}
// Found the boundary string, finish processing this file upload
if (_currentHandler && _currentHandler->canUpload(_currentUri)) {
if (_currentHandler && _currentHandler->canUpload(*this, _currentUri)) {
_currentHandler->upload(*this, _currentUri, *_currentUpload);
}
_currentUpload->totalSize += _currentUpload->currentSize;
_currentUpload->status = UPLOAD_FILE_END;
if (_currentHandler && _currentHandler->canUpload(_currentUri)) {
if (_currentHandler && _currentHandler->canUpload(*this, _currentUri)) {
_currentHandler->upload(*this, _currentUri, *_currentUpload);
}
log_v("End File: %s Type: %s Size: %d", _currentUpload->filename.c_str(), _currentUpload->type.c_str(), (int)_currentUpload->totalSize);
Expand Down Expand Up @@ -567,7 +567,7 @@ String WebServer::urlDecode(const String &text) {

bool WebServer::_parseFormUploadAborted() {
_currentUpload->status = UPLOAD_FILE_ABORTED;
if (_currentHandler && _currentHandler->canUpload(_currentUri)) {
if (_currentHandler && _currentHandler->canUpload(*this, _currentUri)) {
_currentHandler->upload(*this, _currentUri, *_currentUpload);
}
return false;
Expand Down
29 changes: 23 additions & 6 deletions libraries/WebServer/src/WebServer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,11 @@
*/

#include <Arduino.h>

#if SOC_WIFI_SUPPORTED
#include "WiFi.h"
#endif

#include <esp32-hal-log.h>
#include <libb64/cdecode.h>
#include <libb64/cencode.h>
Expand Down Expand Up @@ -306,16 +311,18 @@ void WebServer::requestAuthentication(HTTPAuthMethod mode, const char *realm, co
send(401, String(FPSTR(mimeTable[html].mimeType)), authFailMsg);
}

void WebServer::on(const Uri &uri, WebServer::THandlerFunction handler) {
on(uri, HTTP_ANY, handler);
RequestHandler& WebServer::on(const Uri &uri, WebServer::THandlerFunction handler) {
return on(uri, HTTP_ANY, handler);
}

void WebServer::on(const Uri &uri, HTTPMethod method, WebServer::THandlerFunction fn) {
on(uri, method, fn, _fileUploadHandler);
RequestHandler& WebServer::on(const Uri &uri, HTTPMethod method, WebServer::THandlerFunction fn) {
return on(uri, method, fn, _fileUploadHandler);
}

void WebServer::on(const Uri &uri, HTTPMethod method, WebServer::THandlerFunction fn, WebServer::THandlerFunction ufn) {
_addRequestHandler(new FunctionRequestHandler(fn, ufn, uri, method));
RequestHandler& WebServer::on(const Uri &uri, HTTPMethod method, WebServer::THandlerFunction fn, WebServer::THandlerFunction ufn) {
FunctionRequestHandler *handler = new FunctionRequestHandler(fn, ufn, uri, method);
_addRequestHandler(handler);
return *handler;
}

void WebServer::addHandler(RequestHandler *handler) {
Expand Down Expand Up @@ -796,3 +803,13 @@ String WebServer::_responseCodeToString(int code) {
default: return F("");
}
}

me-no-dev marked this conversation as resolved.
Show resolved Hide resolved
#if SOC_WIFI_SUPPORTED
bool ON_STA_FILTER(WebServer &server) {
return WiFi.STA.localIP() == server.client().localIP();
me-no-dev marked this conversation as resolved.
Show resolved Hide resolved
}

bool ON_AP_FILTER(WebServer &server) {
return WiFi.AP.localIP() == server.client().localIP();
me-no-dev marked this conversation as resolved.
Show resolved Hide resolved
}
#endif
15 changes: 12 additions & 3 deletions libraries/WebServer/src/WebServer.h
Original file line number Diff line number Diff line change
Expand Up @@ -144,9 +144,10 @@ class WebServer {
void requestAuthentication(HTTPAuthMethod mode = BASIC_AUTH, const char *realm = NULL, const String &authFailMsg = String(""));

typedef std::function<void(void)> THandlerFunction;
void on(const Uri &uri, THandlerFunction fn);
void on(const Uri &uri, HTTPMethod method, THandlerFunction fn);
void on(const Uri &uri, HTTPMethod method, THandlerFunction fn, THandlerFunction ufn); //ufn handles file uploads
typedef std::function<bool(WebServer &server)> FilterFunction;
RequestHandler& on(const Uri &uri, THandlerFunction fn);
RequestHandler& on(const Uri &uri, HTTPMethod method, THandlerFunction fn);
RequestHandler& on(const Uri &uri, HTTPMethod method, THandlerFunction fn, THandlerFunction ufn); //ufn handles file uploads
void addHandler(RequestHandler *handler);
void serveStatic(const char *uri, fs::FS &fs, const char *path, const char *cache_header = NULL);
void onNotFound(THandlerFunction fn); //called when handler is not assigned
Expand Down Expand Up @@ -292,4 +293,12 @@ class WebServer {
String _srealm; // Store the Auth realm between Calls
};

/*
Request Filters
*/

bool ON_STA_FILTER(WebServer &server);
me-no-dev marked this conversation as resolved.
Show resolved Hide resolved

bool ON_AP_FILTER(WebServer &server);

#endif //ESP8266WEBSERVER_H
31 changes: 31 additions & 0 deletions libraries/WebServer/src/detail/RequestHandler.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@
class RequestHandler {
public:
virtual ~RequestHandler() {}

/*
note: old handler API for backward compatibility
*/

virtual bool canHandle(HTTPMethod method, String uri) {
(void)method;
(void)uri;
Expand All @@ -20,6 +25,27 @@ class RequestHandler {
(void)uri;
return false;
}

/*
note: new handler API with support for filters etc.
*/

virtual bool canHandle(WebServer &server, HTTPMethod method, String uri) {
(void)server;
(void)method;
(void)uri;
return false;
}
virtual bool canUpload(WebServer &server, String uri) {
(void)server;
(void)uri;
return false;
}
virtual bool canRaw(WebServer &server, String uri) {
(void)server;
(void)uri;
return false;
}
virtual bool handle(WebServer &server, HTTPMethod requestMethod, String requestUri) {
(void)server;
(void)requestMethod;
Expand All @@ -37,6 +63,11 @@ class RequestHandler {
(void)raw;
}

virtual RequestHandler& setFilter(std::function<bool(WebServer&)> filter) {
(void)filter;
return *this;
}

RequestHandler *next() {
return _next;
}
Expand Down
68 changes: 61 additions & 7 deletions libraries/WebServer/src/detail/RequestHandlersImpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ class FunctionRequestHandler : public RequestHandler {

return true;
}

bool canRaw(String requestUri) override {
if (!_ufn || _method == HTTP_GET) {
return false;
Expand All @@ -44,9 +45,32 @@ class FunctionRequestHandler : public RequestHandler {
return true;
}

bool canHandle(WebServer &server, HTTPMethod requestMethod, String requestUri) override {
if (_method != HTTP_ANY && _method != requestMethod) {
return false;
}

return _uri->canHandle(requestUri, pathArgs) && (_filter != NULL ? _filter(server) : true);
}

bool canUpload(WebServer &server, String requestUri) override {
if (!_ufn || !canHandle(server, HTTP_POST, requestUri)) {
return false;
}

return true;
}

bool canRaw(WebServer &server, String requestUri) override {
if (!_ufn || _method == HTTP_GET || (_filter != NULL ? _filter(server) == false : false)) {
return false;
}

return true;
}

bool handle(WebServer &server, HTTPMethod requestMethod, String requestUri) override {
(void)server;
if (!canHandle(requestMethod, requestUri)) {
if (!canHandle(server, requestMethod, requestUri)) {
return false;
}

Expand All @@ -55,24 +79,30 @@ class FunctionRequestHandler : public RequestHandler {
}

void upload(WebServer &server, String requestUri, HTTPUpload &upload) override {
(void)server;
(void)upload;
if (canUpload(requestUri)) {
if (canUpload(server, requestUri)) {
_ufn();
}
}

void raw(WebServer &server, String requestUri, HTTPRaw &raw) override {
(void)server;
(void)raw;
if (canRaw(requestUri)) {
if (canRaw(server, requestUri)) {
_ufn();
}
}

FunctionRequestHandler& setFilter(WebServer::FilterFunction filter) {
_filter = filter;
return *this;
}

protected:
WebServer::THandlerFunction _fn;
WebServer::THandlerFunction _ufn;
// _filter should return 'true' when the request should be handled
// and 'false' when the request should be ignored
WebServer::FilterFunction _filter;
Uri *_uri;
HTTPMethod _method;
};
Expand Down Expand Up @@ -100,8 +130,24 @@ class StaticRequestHandler : public RequestHandler {
return true;
}

bool canHandle(WebServer &server, HTTPMethod requestMethod, String requestUri) override {
if (requestMethod != HTTP_GET) {
return false;
}

if ((_isFile && requestUri != _uri) || !requestUri.startsWith(_uri)) {
return false;
}

if (_filter != NULL ? _filter(server) == false : false) {
return false;
}

return true;
}

bool handle(WebServer &server, HTTPMethod requestMethod, String requestUri) override {
if (!canHandle(requestMethod, requestUri)) {
if (!canHandle(server, requestMethod, requestUri)) {
return false;
}

Expand Down Expand Up @@ -197,7 +243,15 @@ class StaticRequestHandler : public RequestHandler {
return (result);
} // calcETag

StaticRequestHandler& setFilter(WebServer::FilterFunction filter) {
_filter = filter;
return *this;
}

protected:
// _filter should return 'true' when the request should be handled
// and 'false' when the request should be ignored
WebServer::FilterFunction _filter;
FS _fs;
String _uri;
String _path;
Expand Down
Loading