Skip to content

Commit 3428eb6

Browse files
feat: added support for filters in WebServer library (#9842)
* feat: added support for filters in webserver * feat: add setFilter function in StaticRequestHandler * fix: ON_STA_FILTER & ON_AP_FILTER * fix: make request handlers backward compatible * fix: ON_STA_FILTER & ON_AP_FILTER * fix: more filters to their own example * chore: grammar * fix: remove filters from header file * fix: use same root route for both interfaces * ci(pre-commit): Apply automatic fixes --------- Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com>
1 parent 1d895e5 commit 3428eb6

File tree

7 files changed

+226
-23
lines changed

7 files changed

+226
-23
lines changed

Diff for: libraries/WebServer/examples/Filters/Filters.ino

+110
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
#include <WiFi.h>
2+
#include <NetworkClient.h>
3+
#include <WebServer.h>
4+
#include <ESPmDNS.h>
5+
6+
// Your STA WiFi Credentials
7+
// ( This is the AP your ESP will connect to )
8+
const char *ssid = "........";
9+
const char *password = "........";
10+
11+
// Your AP WiFi Credentials
12+
// ( This is the AP your ESP will broadcast )
13+
const char *ap_ssid = "ESP32_Demo";
14+
const char *ap_password = "";
15+
16+
WebServer server(80);
17+
18+
const int led = 13;
19+
20+
// ON_STA_FILTER - Only accept requests coming from STA interface
21+
bool ON_STA_FILTER(WebServer &server) {
22+
return WiFi.STA.hasIP() && WiFi.STA.localIP() == server.client().localIP();
23+
}
24+
25+
// ON_AP_FILTER - Only accept requests coming from AP interface
26+
bool ON_AP_FILTER(WebServer &server) {
27+
return WiFi.AP.hasIP() && WiFi.AP.localIP() == server.client().localIP();
28+
}
29+
30+
void handleNotFound() {
31+
digitalWrite(led, 1);
32+
String message = "File Not Found\n\n";
33+
message += "URI: ";
34+
message += server.uri();
35+
message += "\nMethod: ";
36+
message += (server.method() == HTTP_GET) ? "GET" : "POST";
37+
message += "\nArguments: ";
38+
message += server.args();
39+
message += "\n";
40+
for (uint8_t i = 0; i < server.args(); i++) {
41+
message += " " + server.argName(i) + ": " + server.arg(i) + "\n";
42+
}
43+
server.send(404, "text/plain", message);
44+
digitalWrite(led, 0);
45+
}
46+
47+
void setup(void) {
48+
pinMode(led, OUTPUT);
49+
digitalWrite(led, 0);
50+
Serial.begin(115200);
51+
WiFi.mode(WIFI_AP_STA);
52+
// Connect to STA
53+
WiFi.begin(ssid, password);
54+
// Start AP
55+
WiFi.softAP(ap_ssid, ap_password);
56+
Serial.println("");
57+
58+
// Wait for connection
59+
while (WiFi.status() != WL_CONNECTED) {
60+
delay(500);
61+
Serial.print(".");
62+
}
63+
Serial.println("");
64+
Serial.print("Connected to ");
65+
Serial.println(ssid);
66+
Serial.print("IP address: ");
67+
Serial.println(WiFi.localIP());
68+
69+
if (MDNS.begin("esp32")) {
70+
Serial.println("MDNS responder started");
71+
}
72+
73+
// This route will be accessible by STA clients only
74+
server
75+
.on(
76+
"/",
77+
[&]() {
78+
digitalWrite(led, 1);
79+
server.send(200, "text/plain", "Hi!, This route is accessible for STA clients only");
80+
digitalWrite(led, 0);
81+
}
82+
)
83+
.setFilter(ON_STA_FILTER);
84+
85+
// This route will be accessible by AP clients only
86+
server
87+
.on(
88+
"/",
89+
[&]() {
90+
digitalWrite(led, 1);
91+
server.send(200, "text/plain", "Hi!, This route is accessible for AP clients only");
92+
digitalWrite(led, 0);
93+
}
94+
)
95+
.setFilter(ON_AP_FILTER);
96+
97+
server.on("/inline", []() {
98+
server.send(200, "text/plain", "this works as well");
99+
});
100+
101+
server.onNotFound(handleNotFound);
102+
103+
server.begin();
104+
Serial.println("HTTP server started");
105+
}
106+
107+
void loop(void) {
108+
server.handleClient();
109+
delay(2); //allow the cpu to switch to other tasks
110+
}

Diff for: libraries/WebServer/examples/Filters/ci.json

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"targets": {
3+
"esp32h2": false
4+
}
5+
}

Diff for: libraries/WebServer/src/Parsing.cpp

+7-7
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ bool WebServer::_parseRequest(NetworkClient &client) {
124124
//attach handler
125125
RequestHandler *handler;
126126
for (handler = _firstHandler; handler; handler = handler->next()) {
127-
if (handler->canHandle(_currentMethod, _currentUri)) {
127+
if (handler->canHandle(*this, _currentMethod, _currentUri)) {
128128
break;
129129
}
130130
}
@@ -176,7 +176,7 @@ bool WebServer::_parseRequest(NetworkClient &client) {
176176
}
177177
}
178178

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

335335
void WebServer::_uploadWriteByte(uint8_t b) {
336336
if (_currentUpload->currentSize == HTTP_UPLOAD_BUFLEN) {
337-
if (_currentHandler && _currentHandler->canUpload(_currentUri)) {
337+
if (_currentHandler && _currentHandler->canUpload(*this, _currentUri)) {
338338
_currentHandler->upload(*this, _currentUri, *_currentUpload);
339339
}
340340
_currentUpload->totalSize += _currentUpload->currentSize;
@@ -449,7 +449,7 @@ bool WebServer::_parseForm(NetworkClient &client, String boundary, uint32_t len)
449449
_currentUpload->totalSize = 0;
450450
_currentUpload->currentSize = 0;
451451
log_v("Start File: %s Type: %s", _currentUpload->filename.c_str(), _currentUpload->type.c_str());
452-
if (_currentHandler && _currentHandler->canUpload(_currentUri)) {
452+
if (_currentHandler && _currentHandler->canUpload(*this, _currentUri)) {
453453
_currentHandler->upload(*this, _currentUri, *_currentUpload);
454454
}
455455
_currentUpload->status = UPLOAD_FILE_WRITE;
@@ -488,12 +488,12 @@ bool WebServer::_parseForm(NetworkClient &client, String boundary, uint32_t len)
488488
}
489489
}
490490
// Found the boundary string, finish processing this file upload
491-
if (_currentHandler && _currentHandler->canUpload(_currentUri)) {
491+
if (_currentHandler && _currentHandler->canUpload(*this, _currentUri)) {
492492
_currentHandler->upload(*this, _currentUri, *_currentUpload);
493493
}
494494
_currentUpload->totalSize += _currentUpload->currentSize;
495495
_currentUpload->status = UPLOAD_FILE_END;
496-
if (_currentHandler && _currentHandler->canUpload(_currentUri)) {
496+
if (_currentHandler && _currentHandler->canUpload(*this, _currentUri)) {
497497
_currentHandler->upload(*this, _currentUri, *_currentUpload);
498498
}
499499
log_v("End File: %s Type: %s Size: %d", _currentUpload->filename.c_str(), _currentUpload->type.c_str(), (int)_currentUpload->totalSize);
@@ -567,7 +567,7 @@ String WebServer::urlDecode(const String &text) {
567567

568568
bool WebServer::_parseFormUploadAborted() {
569569
_currentUpload->status = UPLOAD_FILE_ABORTED;
570-
if (_currentHandler && _currentHandler->canUpload(_currentUri)) {
570+
if (_currentHandler && _currentHandler->canUpload(*this, _currentUri)) {
571571
_currentHandler->upload(*this, _currentUri, *_currentUpload);
572572
}
573573
return false;

Diff for: libraries/WebServer/src/WebServer.cpp

+8-6
Original file line numberDiff line numberDiff line change
@@ -306,16 +306,18 @@ void WebServer::requestAuthentication(HTTPAuthMethod mode, const char *realm, co
306306
send(401, String(FPSTR(mimeTable[html].mimeType)), authFailMsg);
307307
}
308308

309-
void WebServer::on(const Uri &uri, WebServer::THandlerFunction handler) {
310-
on(uri, HTTP_ANY, handler);
309+
RequestHandler &WebServer::on(const Uri &uri, WebServer::THandlerFunction handler) {
310+
return on(uri, HTTP_ANY, handler);
311311
}
312312

313-
void WebServer::on(const Uri &uri, HTTPMethod method, WebServer::THandlerFunction fn) {
314-
on(uri, method, fn, _fileUploadHandler);
313+
RequestHandler &WebServer::on(const Uri &uri, HTTPMethod method, WebServer::THandlerFunction fn) {
314+
return on(uri, method, fn, _fileUploadHandler);
315315
}
316316

317-
void WebServer::on(const Uri &uri, HTTPMethod method, WebServer::THandlerFunction fn, WebServer::THandlerFunction ufn) {
318-
_addRequestHandler(new FunctionRequestHandler(fn, ufn, uri, method));
317+
RequestHandler &WebServer::on(const Uri &uri, HTTPMethod method, WebServer::THandlerFunction fn, WebServer::THandlerFunction ufn) {
318+
FunctionRequestHandler *handler = new FunctionRequestHandler(fn, ufn, uri, method);
319+
_addRequestHandler(handler);
320+
return *handler;
319321
}
320322

321323
bool WebServer::removeRoute(const char *uri) {

Diff for: libraries/WebServer/src/WebServer.h

+4-3
Original file line numberDiff line numberDiff line change
@@ -144,9 +144,10 @@ class WebServer {
144144
void requestAuthentication(HTTPAuthMethod mode = BASIC_AUTH, const char *realm = NULL, const String &authFailMsg = String(""));
145145

146146
typedef std::function<void(void)> THandlerFunction;
147-
void on(const Uri &uri, THandlerFunction fn);
148-
void on(const Uri &uri, HTTPMethod method, THandlerFunction fn);
149-
void on(const Uri &uri, HTTPMethod method, THandlerFunction fn, THandlerFunction ufn); //ufn handles file uploads
147+
typedef std::function<bool(WebServer &server)> FilterFunction;
148+
RequestHandler &on(const Uri &uri, THandlerFunction fn);
149+
RequestHandler &on(const Uri &uri, HTTPMethod method, THandlerFunction fn);
150+
RequestHandler &on(const Uri &uri, HTTPMethod method, THandlerFunction fn, THandlerFunction ufn); //ufn handles file uploads
150151
bool removeRoute(const char *uri);
151152
bool removeRoute(const char *uri, HTTPMethod method);
152153
bool removeRoute(const String &uri);

Diff for: libraries/WebServer/src/detail/RequestHandler.h

+31
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,11 @@
77
class RequestHandler {
88
public:
99
virtual ~RequestHandler() {}
10+
11+
/*
12+
note: old handler API for backward compatibility
13+
*/
14+
1015
virtual bool canHandle(HTTPMethod method, String uri) {
1116
(void)method;
1217
(void)uri;
@@ -20,6 +25,27 @@ class RequestHandler {
2025
(void)uri;
2126
return false;
2227
}
28+
29+
/*
30+
note: new handler API with support for filters etc.
31+
*/
32+
33+
virtual bool canHandle(WebServer &server, HTTPMethod method, String uri) {
34+
(void)server;
35+
(void)method;
36+
(void)uri;
37+
return false;
38+
}
39+
virtual bool canUpload(WebServer &server, String uri) {
40+
(void)server;
41+
(void)uri;
42+
return false;
43+
}
44+
virtual bool canRaw(WebServer &server, String uri) {
45+
(void)server;
46+
(void)uri;
47+
return false;
48+
}
2349
virtual bool handle(WebServer &server, HTTPMethod requestMethod, String requestUri) {
2450
(void)server;
2551
(void)requestMethod;
@@ -37,6 +63,11 @@ class RequestHandler {
3763
(void)raw;
3864
}
3965

66+
virtual RequestHandler &setFilter(std::function<bool(WebServer &)> filter) {
67+
(void)filter;
68+
return *this;
69+
}
70+
4071
RequestHandler *next() {
4172
return _next;
4273
}

Diff for: libraries/WebServer/src/detail/RequestHandlersImpl.h

+61-7
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ class FunctionRequestHandler : public RequestHandler {
3636

3737
return true;
3838
}
39+
3940
bool canRaw(String requestUri) override {
4041
if (!_ufn || _method == HTTP_GET) {
4142
return false;
@@ -44,9 +45,32 @@ class FunctionRequestHandler : public RequestHandler {
4445
return true;
4546
}
4647

48+
bool canHandle(WebServer &server, HTTPMethod requestMethod, String requestUri) override {
49+
if (_method != HTTP_ANY && _method != requestMethod) {
50+
return false;
51+
}
52+
53+
return _uri->canHandle(requestUri, pathArgs) && (_filter != NULL ? _filter(server) : true);
54+
}
55+
56+
bool canUpload(WebServer &server, String requestUri) override {
57+
if (!_ufn || !canHandle(server, HTTP_POST, requestUri)) {
58+
return false;
59+
}
60+
61+
return true;
62+
}
63+
64+
bool canRaw(WebServer &server, String requestUri) override {
65+
if (!_ufn || _method == HTTP_GET || (_filter != NULL ? _filter(server) == false : false)) {
66+
return false;
67+
}
68+
69+
return true;
70+
}
71+
4772
bool handle(WebServer &server, HTTPMethod requestMethod, String requestUri) override {
48-
(void)server;
49-
if (!canHandle(requestMethod, requestUri)) {
73+
if (!canHandle(server, requestMethod, requestUri)) {
5074
return false;
5175
}
5276

@@ -55,24 +79,30 @@ class FunctionRequestHandler : public RequestHandler {
5579
}
5680

5781
void upload(WebServer &server, String requestUri, HTTPUpload &upload) override {
58-
(void)server;
5982
(void)upload;
60-
if (canUpload(requestUri)) {
83+
if (canUpload(server, requestUri)) {
6184
_ufn();
6285
}
6386
}
6487

6588
void raw(WebServer &server, String requestUri, HTTPRaw &raw) override {
66-
(void)server;
6789
(void)raw;
68-
if (canRaw(requestUri)) {
90+
if (canRaw(server, requestUri)) {
6991
_ufn();
7092
}
7193
}
7294

95+
FunctionRequestHandler &setFilter(WebServer::FilterFunction filter) {
96+
_filter = filter;
97+
return *this;
98+
}
99+
73100
protected:
74101
WebServer::THandlerFunction _fn;
75102
WebServer::THandlerFunction _ufn;
103+
// _filter should return 'true' when the request should be handled
104+
// and 'false' when the request should be ignored
105+
WebServer::FilterFunction _filter;
76106
Uri *_uri;
77107
HTTPMethod _method;
78108
};
@@ -100,8 +130,24 @@ class StaticRequestHandler : public RequestHandler {
100130
return true;
101131
}
102132

133+
bool canHandle(WebServer &server, HTTPMethod requestMethod, String requestUri) override {
134+
if (requestMethod != HTTP_GET) {
135+
return false;
136+
}
137+
138+
if ((_isFile && requestUri != _uri) || !requestUri.startsWith(_uri)) {
139+
return false;
140+
}
141+
142+
if (_filter != NULL ? _filter(server) == false : false) {
143+
return false;
144+
}
145+
146+
return true;
147+
}
148+
103149
bool handle(WebServer &server, HTTPMethod requestMethod, String requestUri) override {
104-
if (!canHandle(requestMethod, requestUri)) {
150+
if (!canHandle(server, requestMethod, requestUri)) {
105151
return false;
106152
}
107153

@@ -197,7 +243,15 @@ class StaticRequestHandler : public RequestHandler {
197243
return (result);
198244
} // calcETag
199245

246+
StaticRequestHandler &setFilter(WebServer::FilterFunction filter) {
247+
_filter = filter;
248+
return *this;
249+
}
250+
200251
protected:
252+
// _filter should return 'true' when the request should be handled
253+
// and 'false' when the request should be ignored
254+
WebServer::FilterFunction _filter;
201255
FS _fs;
202256
String _uri;
203257
String _path;

0 commit comments

Comments
 (0)