From b80ea9021b59583469499573aed564b3ce80ea1c Mon Sep 17 00:00:00 2001 From: Bob Mooij Date: Sat, 6 Oct 2018 22:17:57 +0200 Subject: [PATCH 01/25] Add path args --- .../src/ESP8266WebServer-impl.h | 5 ++ .../ESP8266WebServer/src/ESP8266WebServer.h | 1 + .../src/detail/RequestHandler.h | 10 ++++ .../src/detail/RequestHandlersImpl.h | 50 +++++++++++++++++-- 4 files changed, 63 insertions(+), 3 deletions(-) diff --git a/libraries/ESP8266WebServer/src/ESP8266WebServer-impl.h b/libraries/ESP8266WebServer/src/ESP8266WebServer-impl.h index 1efcf92e5e..6acfff2cb3 100644 --- a/libraries/ESP8266WebServer/src/ESP8266WebServer-impl.h +++ b/libraries/ESP8266WebServer/src/ESP8266WebServer-impl.h @@ -542,6 +542,11 @@ void ESP8266WebServerTemplate::_streamFileCore(const size_t fileSize send(200, contentType, emptyString); } +String ESP8266WebServer::pathArg(int i) { + if (_currentHandler != nullptr) + return _currentHandler->pathArg(i); + return ""; +} template const String& ESP8266WebServerTemplate::arg(const String& name) const { diff --git a/libraries/ESP8266WebServer/src/ESP8266WebServer.h b/libraries/ESP8266WebServer/src/ESP8266WebServer.h index 4281ce8636..bb550bc315 100644 --- a/libraries/ESP8266WebServer/src/ESP8266WebServer.h +++ b/libraries/ESP8266WebServer/src/ESP8266WebServer.h @@ -107,6 +107,7 @@ class ESP8266WebServerTemplate // Allows setting server options (i.e. SSL keys) by the instantiator ServerType &getServer() { return _server; } + String pathArg(int i); // get request path argument by number const String& arg(const String& name) const; // get request argument value by name const String& arg(int i) const; // get request argument value by number const String& argName(int i) const; // get request argument name by number diff --git a/libraries/ESP8266WebServer/src/detail/RequestHandler.h b/libraries/ESP8266WebServer/src/detail/RequestHandler.h index db840af2a1..1848479040 100644 --- a/libraries/ESP8266WebServer/src/detail/RequestHandler.h +++ b/libraries/ESP8266WebServer/src/detail/RequestHandler.h @@ -18,6 +18,16 @@ class RequestHandler { private: RequestHandler* _next = nullptr; + +protected: + std::vector pathArgs; + +public: + String pathArg(int i) { + if (i < pathArgs.size()) + return pathArgs[i]; + return ""; + } }; #endif //REQUESTHANDLER_H diff --git a/libraries/ESP8266WebServer/src/detail/RequestHandlersImpl.h b/libraries/ESP8266WebServer/src/detail/RequestHandlersImpl.h index e9b8689c04..31d5cef4de 100644 --- a/libraries/ESP8266WebServer/src/detail/RequestHandlersImpl.h +++ b/libraries/ESP8266WebServer/src/detail/RequestHandlersImpl.h @@ -18,16 +18,60 @@ class FunctionRequestHandler : public RequestHandler { , _uri(uri) , _method(method) { + int numParams = 0, start = 0; + do + { + start = _uri.indexOf("{}", start); + if (start > 0) + { + numParams++; + start += 2; + } + } while (start > 0); + pathArgs = std::vector(numParams); } bool canHandle(HTTPMethod requestMethod, String requestUri) override { if (_method != HTTP_ANY && _method != requestMethod) return false; - if (requestUri != _uri) - return false; + if (_uri == requestUri) + return true; + + int listIndex = 0; + int length = _uri.length(); + int j = 0; + for (int i = 0; i < length; i++, j++) + { + char uriChar = _uri[i]; + char requestUriChar = requestUri[j]; + + if (uriChar == requestUriChar) + continue; + + if (uriChar != '{') + return false; + + i += 2; // index of char after '}' + if (i >= length) + { + // there is no char after '}' + pathArgs[listIndex] = requestUri.substring(j); + return true; + } + else + { + char charEnd = _uri[i]; + int uriIndex = requestUri.indexOf(charEnd, j); + if (uriIndex < 0) + return false; + pathArgs[listIndex] = requestUri.substring(j, uriIndex); + j = uriIndex; + } + listIndex++; + } - return true; + return j >= requestUri.length(); } bool canUpload(String requestUri) override { From 37f3d59c5e02e24f62313a0da9ce7706c4862c8c Mon Sep 17 00:00:00 2001 From: Bob Mooij Date: Sat, 6 Oct 2018 22:35:54 +0200 Subject: [PATCH 02/25] Add example --- .../examples/PathArgServer/PathArgServer.ino | 70 +++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100644 libraries/ESP8266WebServer/examples/PathArgServer/PathArgServer.ino diff --git a/libraries/ESP8266WebServer/examples/PathArgServer/PathArgServer.ino b/libraries/ESP8266WebServer/examples/PathArgServer/PathArgServer.ino new file mode 100644 index 0000000000..1a2917dfaa --- /dev/null +++ b/libraries/ESP8266WebServer/examples/PathArgServer/PathArgServer.ino @@ -0,0 +1,70 @@ +#include +#include +#include +#include + +const char *ssid = "........"; +const char *password = "........"; + +ESP8266WebServer server(80); + +const int led = 2; + +void setup(void) +{ + pinMode(led, OUTPUT); + digitalWrite(led, 0); + Serial.begin(9600); + WiFi.mode(WIFI_STA); + WiFi.begin(ssid, password); + Serial.println(""); + + // Wait for connection + while (WiFi.status() != WL_CONNECTED) + { + delay(500); + Serial.print("."); + } + Serial.println(""); + Serial.print("Connected to "); + Serial.println(ssid); + Serial.print("IP address: "); + Serial.println(WiFi.localIP()); + + if (MDNS.begin("esp8266")) + { + Serial.println("MDNS responder started"); + } + + server.on("/", []() { + server.send(200, "text/plain", "hello from esp8266!"); + }); + + server.on("/led/2/actions/{}", []() { + String action = server.pathArg(0); + if (action == "on") + { + // /led/2/actions/on + digitalWrite(led, 1); + server.send(200, "text/plain", "Led 2 on"); + } + else if (action == "off") + { + // /led/2/actions/off + digitalWrite(led, 0); + server.send(200, "text/plain", "Led 2 off"); + } + else + { + server.send(404, "text/plain", "Action '" + action + "' was not found"); + } + }); + + server.begin(); + Serial.println("HTTP server started"); +} + +void loop(void) +{ + server.handleClient(); +} From 41695e6298618cf000450f61b018ec0f21b88ac5 Mon Sep 17 00:00:00 2001 From: Bob Mooij Date: Sat, 6 Oct 2018 23:04:22 +0200 Subject: [PATCH 03/25] Update code format --- .../examples/PathArgServer/PathArgServer.ino | 23 ++++++------------- .../src/detail/RequestHandlersImpl.h | 16 ++++--------- 2 files changed, 12 insertions(+), 27 deletions(-) diff --git a/libraries/ESP8266WebServer/examples/PathArgServer/PathArgServer.ino b/libraries/ESP8266WebServer/examples/PathArgServer/PathArgServer.ino index 1a2917dfaa..c7086c0080 100644 --- a/libraries/ESP8266WebServer/examples/PathArgServer/PathArgServer.ino +++ b/libraries/ESP8266WebServer/examples/PathArgServer/PathArgServer.ino @@ -10,8 +10,7 @@ ESP8266WebServer server(80); const int led = 2; -void setup(void) -{ +void setup(void) { pinMode(led, OUTPUT); digitalWrite(led, 0); Serial.begin(9600); @@ -20,8 +19,7 @@ void setup(void) Serial.println(""); // Wait for connection - while (WiFi.status() != WL_CONNECTED) - { + while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); } @@ -31,8 +29,7 @@ void setup(void) Serial.print("IP address: "); Serial.println(WiFi.localIP()); - if (MDNS.begin("esp8266")) - { + if (MDNS.begin("esp8266")) { Serial.println("MDNS responder started"); } @@ -42,20 +39,15 @@ void setup(void) server.on("/led/2/actions/{}", []() { String action = server.pathArg(0); - if (action == "on") - { + if (action == "on") { // /led/2/actions/on digitalWrite(led, 1); server.send(200, "text/plain", "Led 2 on"); - } - else if (action == "off") - { + } else if (action == "off") { // /led/2/actions/off digitalWrite(led, 0); server.send(200, "text/plain", "Led 2 off"); - } - else - { + } else { server.send(404, "text/plain", "Action '" + action + "' was not found"); } }); @@ -64,7 +56,6 @@ void setup(void) Serial.println("HTTP server started"); } -void loop(void) -{ +void loop(void) { server.handleClient(); } diff --git a/libraries/ESP8266WebServer/src/detail/RequestHandlersImpl.h b/libraries/ESP8266WebServer/src/detail/RequestHandlersImpl.h index 31d5cef4de..93707f42c1 100644 --- a/libraries/ESP8266WebServer/src/detail/RequestHandlersImpl.h +++ b/libraries/ESP8266WebServer/src/detail/RequestHandlersImpl.h @@ -19,11 +19,9 @@ class FunctionRequestHandler : public RequestHandler { , _method(method) { int numParams = 0, start = 0; - do - { + do { start = _uri.indexOf("{}", start); - if (start > 0) - { + if (start > 0) { numParams++; start += 2; } @@ -41,8 +39,7 @@ class FunctionRequestHandler : public RequestHandler { int listIndex = 0; int length = _uri.length(); int j = 0; - for (int i = 0; i < length; i++, j++) - { + for (int i = 0; i < length; i++, j++) { char uriChar = _uri[i]; char requestUriChar = requestUri[j]; @@ -53,14 +50,11 @@ class FunctionRequestHandler : public RequestHandler { return false; i += 2; // index of char after '}' - if (i >= length) - { + if (i >= length) { // there is no char after '}' pathArgs[listIndex] = requestUri.substring(j); return true; - } - else - { + } else { char charEnd = _uri[i]; int uriIndex = requestUri.indexOf(charEnd, j); if (uriIndex < 0) From 5dfa3f1bc650137504e42040d93cb6856570e787 Mon Sep 17 00:00:00 2001 From: Bob Mooij Date: Sat, 6 Oct 2018 23:07:09 +0200 Subject: [PATCH 04/25] Add missing include --- libraries/ESP8266WebServer/src/detail/RequestHandler.h | 1 + 1 file changed, 1 insertion(+) diff --git a/libraries/ESP8266WebServer/src/detail/RequestHandler.h b/libraries/ESP8266WebServer/src/detail/RequestHandler.h index 1848479040..c60a40b10a 100644 --- a/libraries/ESP8266WebServer/src/detail/RequestHandler.h +++ b/libraries/ESP8266WebServer/src/detail/RequestHandler.h @@ -2,6 +2,7 @@ #define REQUESTHANDLER_H #include +#include template class RequestHandler { From ddb0f6fa43accf484b1080958ebad0c3d640abbe Mon Sep 17 00:00:00 2001 From: Bob Mooij Date: Sat, 6 Oct 2018 23:36:04 +0200 Subject: [PATCH 05/25] Fix codestyle and unsigned int --- .../examples/PathArgServer/PathArgServer.ino | 84 +++++++++---------- .../src/ESP8266WebServer-impl.h | 2 +- .../ESP8266WebServer/src/ESP8266WebServer.h | 2 +- .../src/detail/RequestHandler.h | 2 +- 4 files changed, 45 insertions(+), 45 deletions(-) diff --git a/libraries/ESP8266WebServer/examples/PathArgServer/PathArgServer.ino b/libraries/ESP8266WebServer/examples/PathArgServer/PathArgServer.ino index c7086c0080..13108d6a2e 100644 --- a/libraries/ESP8266WebServer/examples/PathArgServer/PathArgServer.ino +++ b/libraries/ESP8266WebServer/examples/PathArgServer/PathArgServer.ino @@ -11,51 +11,51 @@ ESP8266WebServer server(80); const int led = 2; void setup(void) { - pinMode(led, OUTPUT); - digitalWrite(led, 0); - Serial.begin(9600); - WiFi.mode(WIFI_STA); - WiFi.begin(ssid, password); - Serial.println(""); - - // Wait for connection - while (WiFi.status() != WL_CONNECTED) { - delay(500); - Serial.print("."); - } - Serial.println(""); - Serial.print("Connected to "); - Serial.println(ssid); - Serial.print("IP address: "); - Serial.println(WiFi.localIP()); - - if (MDNS.begin("esp8266")) { - Serial.println("MDNS responder started"); + pinMode(led, OUTPUT); + digitalWrite(led, 0); + Serial.begin(9600); + WiFi.mode(WIFI_STA); + WiFi.begin(ssid, password); + Serial.println(""); + + // Wait for connection + while (WiFi.status() != WL_CONNECTED) { + delay(500); + Serial.print("."); + } + Serial.println(""); + Serial.print("Connected to "); + Serial.println(ssid); + Serial.print("IP address: "); + Serial.println(WiFi.localIP()); + + if (MDNS.begin("esp8266")) { + Serial.println("MDNS responder started"); + } + + server.on("/", []() { + server.send(200, "text/plain", "hello from esp8266!"); + }); + + server.on("/led/2/actions/{}", []() { + String action = server.pathArg(0); + if (action == "on") { + // /led/2/actions/on + digitalWrite(led, 1); + server.send(200, "text/plain", "Led 2 on"); + } else if (action == "off") { + // /led/2/actions/off + digitalWrite(led, 0); + server.send(200, "text/plain", "Led 2 off"); + } else { + server.send(404, "text/plain", "Action '" + action + "' was not found"); } + }); - server.on("/", []() { - server.send(200, "text/plain", "hello from esp8266!"); - }); - - server.on("/led/2/actions/{}", []() { - String action = server.pathArg(0); - if (action == "on") { - // /led/2/actions/on - digitalWrite(led, 1); - server.send(200, "text/plain", "Led 2 on"); - } else if (action == "off") { - // /led/2/actions/off - digitalWrite(led, 0); - server.send(200, "text/plain", "Led 2 off"); - } else { - server.send(404, "text/plain", "Action '" + action + "' was not found"); - } - }); - - server.begin(); - Serial.println("HTTP server started"); + server.begin(); + Serial.println("HTTP server started"); } void loop(void) { - server.handleClient(); + server.handleClient(); } diff --git a/libraries/ESP8266WebServer/src/ESP8266WebServer-impl.h b/libraries/ESP8266WebServer/src/ESP8266WebServer-impl.h index 6acfff2cb3..4d93e18ad5 100644 --- a/libraries/ESP8266WebServer/src/ESP8266WebServer-impl.h +++ b/libraries/ESP8266WebServer/src/ESP8266WebServer-impl.h @@ -542,7 +542,7 @@ void ESP8266WebServerTemplate::_streamFileCore(const size_t fileSize send(200, contentType, emptyString); } -String ESP8266WebServer::pathArg(int i) { +String ESP8266WebServer::pathArg(unsigned int i) { if (_currentHandler != nullptr) return _currentHandler->pathArg(i); return ""; diff --git a/libraries/ESP8266WebServer/src/ESP8266WebServer.h b/libraries/ESP8266WebServer/src/ESP8266WebServer.h index bb550bc315..dffa470a7f 100644 --- a/libraries/ESP8266WebServer/src/ESP8266WebServer.h +++ b/libraries/ESP8266WebServer/src/ESP8266WebServer.h @@ -107,7 +107,7 @@ class ESP8266WebServerTemplate // Allows setting server options (i.e. SSL keys) by the instantiator ServerType &getServer() { return _server; } - String pathArg(int i); // get request path argument by number + String pathArg(unsigned int i); // get request path argument by number const String& arg(const String& name) const; // get request argument value by name const String& arg(int i) const; // get request argument value by number const String& argName(int i) const; // get request argument name by number diff --git a/libraries/ESP8266WebServer/src/detail/RequestHandler.h b/libraries/ESP8266WebServer/src/detail/RequestHandler.h index c60a40b10a..d0ed402f6e 100644 --- a/libraries/ESP8266WebServer/src/detail/RequestHandler.h +++ b/libraries/ESP8266WebServer/src/detail/RequestHandler.h @@ -24,7 +24,7 @@ class RequestHandler { std::vector pathArgs; public: - String pathArg(int i) { + String pathArg(unsigned int i) { if (i < pathArgs.size()) return pathArgs[i]; return ""; From 4e49e29e305e91196ae046aa2ca96c9654e1f284 Mon Sep 17 00:00:00 2001 From: Bob Mooij Date: Sun, 7 Oct 2018 00:01:11 +0200 Subject: [PATCH 06/25] fix unsigned int --- .../src/detail/RequestHandlersImpl.h | 23 ++++++++++--------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/libraries/ESP8266WebServer/src/detail/RequestHandlersImpl.h b/libraries/ESP8266WebServer/src/detail/RequestHandlersImpl.h index 93707f42c1..f67c81cb69 100644 --- a/libraries/ESP8266WebServer/src/detail/RequestHandlersImpl.h +++ b/libraries/ESP8266WebServer/src/detail/RequestHandlersImpl.h @@ -36,33 +36,34 @@ class FunctionRequestHandler : public RequestHandler { if (_uri == requestUri) return true; - int listIndex = 0; - int length = _uri.length(); - int j = 0; - for (int i = 0; i < length; i++, j++) { + size_t uriLength = _uri.length(); + unsigned int pathArgIndex = 0; + unsigned int j = 0; + for (unsigned int i = 0; i < uriLength; i++, j++) { char uriChar = _uri[i]; char requestUriChar = requestUri[j]; if (uriChar == requestUriChar) continue; - if (uriChar != '{') return false; i += 2; // index of char after '}' - if (i >= length) { + if (i >= uriLength) { // there is no char after '}' - pathArgs[listIndex] = requestUri.substring(j); + pathArgs[pathArgIndex] = requestUri.substring(j); return true; - } else { + } + else + { char charEnd = _uri[i]; int uriIndex = requestUri.indexOf(charEnd, j); if (uriIndex < 0) return false; - pathArgs[listIndex] = requestUri.substring(j, uriIndex); - j = uriIndex; + pathArgs[pathArgIndex] = requestUri.substring(j, uriIndex); + j = (unsigned int) uriIndex; } - listIndex++; + pathArgIndex++; } return j >= requestUri.length(); From 15848597fd6866b1d7433e958df932d1e7b6c464 Mon Sep 17 00:00:00 2001 From: Bob Mooij Date: Mon, 8 Oct 2018 14:10:37 +0200 Subject: [PATCH 07/25] Remove tabs --- libraries/ESP8266WebServer/src/detail/RequestHandlersImpl.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/ESP8266WebServer/src/detail/RequestHandlersImpl.h b/libraries/ESP8266WebServer/src/detail/RequestHandlersImpl.h index f67c81cb69..ac47beb198 100644 --- a/libraries/ESP8266WebServer/src/detail/RequestHandlersImpl.h +++ b/libraries/ESP8266WebServer/src/detail/RequestHandlersImpl.h @@ -18,7 +18,7 @@ class FunctionRequestHandler : public RequestHandler { , _uri(uri) , _method(method) { - int numParams = 0, start = 0; + int numParams = 0, start = 0; do { start = _uri.indexOf("{}", start); if (start > 0) { From da189bad18b1391077bc3d1b4b49c97b98184756 Mon Sep 17 00:00:00 2001 From: Bob Mooij Date: Mon, 8 Oct 2018 14:11:16 +0200 Subject: [PATCH 08/25] use vector<>.resize --- libraries/ESP8266WebServer/src/detail/RequestHandlersImpl.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/ESP8266WebServer/src/detail/RequestHandlersImpl.h b/libraries/ESP8266WebServer/src/detail/RequestHandlersImpl.h index ac47beb198..61d42f3836 100644 --- a/libraries/ESP8266WebServer/src/detail/RequestHandlersImpl.h +++ b/libraries/ESP8266WebServer/src/detail/RequestHandlersImpl.h @@ -26,7 +26,7 @@ class FunctionRequestHandler : public RequestHandler { start += 2; } } while (start > 0); - pathArgs = std::vector(numParams); + pathArgs.resize(numParams); } bool canHandle(HTTPMethod requestMethod, String requestUri) override { From cabf6200e9324727429a990f9ea5096952c0c787 Mon Sep 17 00:00:00 2001 From: Bob Mooij Date: Mon, 8 Oct 2018 14:12:32 +0200 Subject: [PATCH 09/25] rename j to requestUriIndex --- .../src/detail/RequestHandlersImpl.h | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/libraries/ESP8266WebServer/src/detail/RequestHandlersImpl.h b/libraries/ESP8266WebServer/src/detail/RequestHandlersImpl.h index 61d42f3836..ba47a971c6 100644 --- a/libraries/ESP8266WebServer/src/detail/RequestHandlersImpl.h +++ b/libraries/ESP8266WebServer/src/detail/RequestHandlersImpl.h @@ -38,10 +38,10 @@ class FunctionRequestHandler : public RequestHandler { size_t uriLength = _uri.length(); unsigned int pathArgIndex = 0; - unsigned int j = 0; - for (unsigned int i = 0; i < uriLength; i++, j++) { + unsigned int requestUriIndex = 0; + for (unsigned int i = 0; i < uriLength; i++, requestUriIndex++) { char uriChar = _uri[i]; - char requestUriChar = requestUri[j]; + char requestUriChar = requestUri[requestUriIndex]; if (uriChar == requestUriChar) continue; @@ -51,22 +51,22 @@ class FunctionRequestHandler : public RequestHandler { i += 2; // index of char after '}' if (i >= uriLength) { // there is no char after '}' - pathArgs[pathArgIndex] = requestUri.substring(j); + pathArgs[pathArgIndex] = requestUri.substring(requestUriIndex); return true; } else { char charEnd = _uri[i]; - int uriIndex = requestUri.indexOf(charEnd, j); + int uriIndex = requestUri.indexOf(charEnd, requestUriIndex); if (uriIndex < 0) return false; - pathArgs[pathArgIndex] = requestUri.substring(j, uriIndex); - j = (unsigned int) uriIndex; + pathArgs[pathArgIndex] = requestUri.substring(requestUriIndex, uriIndex); + requestUriIndex = (unsigned int) uriIndex; } pathArgIndex++; } - return j >= requestUri.length(); + return requestUriIndex >= requestUri.length(); } bool canUpload(String requestUri) override { From 7cd3468b80aa0903885eab06baaed44b4390f90e Mon Sep 17 00:00:00 2001 From: Bob Mooij Date: Tue, 9 Oct 2018 13:23:14 +0200 Subject: [PATCH 10/25] using assert checking the path argument index --- libraries/ESP8266WebServer/src/detail/RequestHandler.h | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/libraries/ESP8266WebServer/src/detail/RequestHandler.h b/libraries/ESP8266WebServer/src/detail/RequestHandler.h index d0ed402f6e..e37c5a5cf9 100644 --- a/libraries/ESP8266WebServer/src/detail/RequestHandler.h +++ b/libraries/ESP8266WebServer/src/detail/RequestHandler.h @@ -25,9 +25,8 @@ class RequestHandler { public: String pathArg(unsigned int i) { - if (i < pathArgs.size()) - return pathArgs[i]; - return ""; + assert(i < pathArgs.size()); + return pathArgs[i]; } }; From 637b9cb6fc1dbf68be48c5696612b933b828a66a Mon Sep 17 00:00:00 2001 From: Bob Mooij Date: Tue, 9 Oct 2018 15:05:17 +0200 Subject: [PATCH 11/25] Add missing include "assert.h" --- libraries/ESP8266WebServer/src/detail/RequestHandler.h | 1 + 1 file changed, 1 insertion(+) diff --git a/libraries/ESP8266WebServer/src/detail/RequestHandler.h b/libraries/ESP8266WebServer/src/detail/RequestHandler.h index e37c5a5cf9..5384a5f305 100644 --- a/libraries/ESP8266WebServer/src/detail/RequestHandler.h +++ b/libraries/ESP8266WebServer/src/detail/RequestHandler.h @@ -3,6 +3,7 @@ #include #include +#include template class RequestHandler { From 63163d7af6a9601e7fca6a56f71837e6ef2871ca Mon Sep 17 00:00:00 2001 From: Bob Mooij Date: Tue, 9 Oct 2018 15:38:14 +0200 Subject: [PATCH 12/25] The order no longer matters. Path arguments may not contain the value '/' Updated the example --- .../examples/PathArgServer/PathArgServer.ino | 26 +++++++------------ .../src/detail/RequestHandlersImpl.h | 2 +- 2 files changed, 10 insertions(+), 18 deletions(-) diff --git a/libraries/ESP8266WebServer/examples/PathArgServer/PathArgServer.ino b/libraries/ESP8266WebServer/examples/PathArgServer/PathArgServer.ino index 13108d6a2e..5f8ae8ea9c 100644 --- a/libraries/ESP8266WebServer/examples/PathArgServer/PathArgServer.ino +++ b/libraries/ESP8266WebServer/examples/PathArgServer/PathArgServer.ino @@ -8,11 +8,7 @@ const char *password = "........"; ESP8266WebServer server(80); -const int led = 2; - void setup(void) { - pinMode(led, OUTPUT); - digitalWrite(led, 0); Serial.begin(9600); WiFi.mode(WIFI_STA); WiFi.begin(ssid, password); @@ -37,19 +33,15 @@ void setup(void) { server.send(200, "text/plain", "hello from esp8266!"); }); - server.on("/led/2/actions/{}", []() { - String action = server.pathArg(0); - if (action == "on") { - // /led/2/actions/on - digitalWrite(led, 1); - server.send(200, "text/plain", "Led 2 on"); - } else if (action == "off") { - // /led/2/actions/off - digitalWrite(led, 0); - server.send(200, "text/plain", "Led 2 off"); - } else { - server.send(404, "text/plain", "Action '" + action + "' was not found"); - } + server.on("/users/{}", []() { + String user = server.pathArg(0); + server.send(200, "text/plain", "User: '" + user + "'"); + }); + + server.on("/users/{}/devices/{}", []() { + String user = server.pathArg(0); + String device = server.pathArg(1); + server.send(200, "text/plain", "User: '" + user + "' and Device: '" + device + "'"); }); server.begin(); diff --git a/libraries/ESP8266WebServer/src/detail/RequestHandlersImpl.h b/libraries/ESP8266WebServer/src/detail/RequestHandlersImpl.h index ba47a971c6..1fcf9a970f 100644 --- a/libraries/ESP8266WebServer/src/detail/RequestHandlersImpl.h +++ b/libraries/ESP8266WebServer/src/detail/RequestHandlersImpl.h @@ -52,7 +52,7 @@ class FunctionRequestHandler : public RequestHandler { if (i >= uriLength) { // there is no char after '}' pathArgs[pathArgIndex] = requestUri.substring(requestUriIndex); - return true; + return pathArgs[pathArgIndex].indexOf("/") == -1; // path argument may not contain a '/' } else { From a626c5fd9b21bd44bd76e703c77d44ccfce88d62 Mon Sep 17 00:00:00 2001 From: Bob Mooij Date: Tue, 9 Oct 2018 15:39:31 +0200 Subject: [PATCH 13/25] make pathArg return a const --- libraries/ESP8266WebServer/src/detail/RequestHandler.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/ESP8266WebServer/src/detail/RequestHandler.h b/libraries/ESP8266WebServer/src/detail/RequestHandler.h index 5384a5f305..9202f623b3 100644 --- a/libraries/ESP8266WebServer/src/detail/RequestHandler.h +++ b/libraries/ESP8266WebServer/src/detail/RequestHandler.h @@ -25,7 +25,7 @@ class RequestHandler { std::vector pathArgs; public: - String pathArg(unsigned int i) { + const String& pathArg(unsigned int i) { assert(i < pathArgs.size()); return pathArgs[i]; } From 977120c4c614c0913264e28448360b5c0aad6809 Mon Sep 17 00:00:00 2001 From: david gauchard Date: Thu, 11 Oct 2018 00:39:41 +0200 Subject: [PATCH 14/25] Update PathArgServer.ino fix trailing space --- .../ESP8266WebServer/examples/PathArgServer/PathArgServer.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/ESP8266WebServer/examples/PathArgServer/PathArgServer.ino b/libraries/ESP8266WebServer/examples/PathArgServer/PathArgServer.ino index 5f8ae8ea9c..e100290f61 100644 --- a/libraries/ESP8266WebServer/examples/PathArgServer/PathArgServer.ino +++ b/libraries/ESP8266WebServer/examples/PathArgServer/PathArgServer.ino @@ -37,7 +37,7 @@ void setup(void) { String user = server.pathArg(0); server.send(200, "text/plain", "User: '" + user + "'"); }); - + server.on("/users/{}/devices/{}", []() { String user = server.pathArg(0); String device = server.pathArg(1); From de7b504564c5fa61281396cf2da4cef549c26fb4 Mon Sep 17 00:00:00 2001 From: david gauchard Date: Fri, 30 Nov 2018 01:03:24 +0100 Subject: [PATCH 15/25] const String& --- libraries/ESP8266WebServer/src/ESP8266WebServer-impl.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/ESP8266WebServer/src/ESP8266WebServer-impl.h b/libraries/ESP8266WebServer/src/ESP8266WebServer-impl.h index 4d93e18ad5..0532455e4d 100644 --- a/libraries/ESP8266WebServer/src/ESP8266WebServer-impl.h +++ b/libraries/ESP8266WebServer/src/ESP8266WebServer-impl.h @@ -542,10 +542,10 @@ void ESP8266WebServerTemplate::_streamFileCore(const size_t fileSize send(200, contentType, emptyString); } -String ESP8266WebServer::pathArg(unsigned int i) { +const String& ESP8266WebServer::pathArg(unsigned int i) { if (_currentHandler != nullptr) return _currentHandler->pathArg(i); - return ""; + return emptyString; } template From 879e076dd774f9afb791c350a50f284ebef83bfa Mon Sep 17 00:00:00 2001 From: Bob Mooij Date: Mon, 24 Dec 2018 11:29:17 +0100 Subject: [PATCH 16/25] Add regex support --- .../examples/PathArgServer/PathArgServer.ino | 2 +- .../src/detail/RequestHandler.h | 1 + .../src/detail/RequestHandlersImpl.h | 61 ++++++++----------- 3 files changed, 26 insertions(+), 38 deletions(-) diff --git a/libraries/ESP8266WebServer/examples/PathArgServer/PathArgServer.ino b/libraries/ESP8266WebServer/examples/PathArgServer/PathArgServer.ino index e100290f61..db8bcfe039 100644 --- a/libraries/ESP8266WebServer/examples/PathArgServer/PathArgServer.ino +++ b/libraries/ESP8266WebServer/examples/PathArgServer/PathArgServer.ino @@ -38,7 +38,7 @@ void setup(void) { server.send(200, "text/plain", "User: '" + user + "'"); }); - server.on("/users/{}/devices/{}", []() { + server.on("^\\/users\\/([0-9]+)\\/devices\\/([0-9]+)$", []() { String user = server.pathArg(0); String device = server.pathArg(1); server.send(200, "text/plain", "User: '" + user + "' and Device: '" + device + "'"); diff --git a/libraries/ESP8266WebServer/src/detail/RequestHandler.h b/libraries/ESP8266WebServer/src/detail/RequestHandler.h index 9202f623b3..488849ccf3 100644 --- a/libraries/ESP8266WebServer/src/detail/RequestHandler.h +++ b/libraries/ESP8266WebServer/src/detail/RequestHandler.h @@ -23,6 +23,7 @@ class RequestHandler { protected: std::vector pathArgs; + bool _isRegex = false; public: const String& pathArg(unsigned int i) { diff --git a/libraries/ESP8266WebServer/src/detail/RequestHandlersImpl.h b/libraries/ESP8266WebServer/src/detail/RequestHandlersImpl.h index 1fcf9a970f..7a8cd8479f 100644 --- a/libraries/ESP8266WebServer/src/detail/RequestHandlersImpl.h +++ b/libraries/ESP8266WebServer/src/detail/RequestHandlersImpl.h @@ -2,6 +2,8 @@ #define REQUESTHANDLERSIMPL_H #include +#include +#include #include "RequestHandler.h" #include "mimetable.h" #include "WString.h" @@ -18,15 +20,16 @@ class FunctionRequestHandler : public RequestHandler { , _uri(uri) , _method(method) { - int numParams = 0, start = 0; - do { - start = _uri.indexOf("{}", start); - if (start > 0) { - numParams++; - start += 2; - } - } while (start > 0); - pathArgs.resize(numParams); + _isRegex = uri.startsWith("^") && uri.endsWith("$"); + if (_isRegex) { + std::regex rgx((_uri + "|").c_str()); + std::smatch matches; + std::string s{""}; + std::regex_search(s, matches, rgx); + pathArgs.resize(matches.size() - 1); + } else { + pathArgs.resize(0); + } } bool canHandle(HTTPMethod requestMethod, String requestUri) override { @@ -36,37 +39,21 @@ class FunctionRequestHandler : public RequestHandler { if (_uri == requestUri) return true; - size_t uriLength = _uri.length(); - unsigned int pathArgIndex = 0; - unsigned int requestUriIndex = 0; - for (unsigned int i = 0; i < uriLength; i++, requestUriIndex++) { - char uriChar = _uri[i]; - char requestUriChar = requestUri[requestUriIndex]; - - if (uriChar == requestUriChar) - continue; - if (uriChar != '{') - return false; - - i += 2; // index of char after '}' - if (i >= uriLength) { - // there is no char after '}' - pathArgs[pathArgIndex] = requestUri.substring(requestUriIndex); - return pathArgs[pathArgIndex].indexOf("/") == -1; // path argument may not contain a '/' - } - else - { - char charEnd = _uri[i]; - int uriIndex = requestUri.indexOf(charEnd, requestUriIndex); - if (uriIndex < 0) - return false; - pathArgs[pathArgIndex] = requestUri.substring(requestUriIndex, uriIndex); - requestUriIndex = (unsigned int) uriIndex; + if (_isRegex) { + unsigned int pathArgIndex = 0; + std::regex rgx(_uri.c_str()); + std::smatch matches; + std::string s(requestUri.c_str()); + if (std::regex_search(s, matches, rgx)) { + for (size_t i = 1; i < matches.size(); ++i) { // skip first + pathArgs[pathArgIndex] = String(matches[i].str().c_str()); + pathArgIndex++; + } + return true; } - pathArgIndex++; } - return requestUriIndex >= requestUri.length(); + return false; } bool canUpload(String requestUri) override { From afe785463fc2f6d5dea07a88c4a8d68643425e33 Mon Sep 17 00:00:00 2001 From: Bob Mooij Date: Fri, 1 Nov 2019 17:20:05 +0100 Subject: [PATCH 17/25] Fix to match templating --- libraries/ESP8266WebServer/src/ESP8266WebServer-impl.h | 3 ++- libraries/ESP8266WebServer/src/ESP8266WebServer.h | 2 +- libraries/ESP8266WebServer/src/detail/RequestHandler.h | 1 - .../ESP8266WebServer/src/detail/RequestHandlersImpl.h | 8 +++++--- 4 files changed, 8 insertions(+), 6 deletions(-) diff --git a/libraries/ESP8266WebServer/src/ESP8266WebServer-impl.h b/libraries/ESP8266WebServer/src/ESP8266WebServer-impl.h index 0532455e4d..9de4f393dd 100644 --- a/libraries/ESP8266WebServer/src/ESP8266WebServer-impl.h +++ b/libraries/ESP8266WebServer/src/ESP8266WebServer-impl.h @@ -542,7 +542,8 @@ void ESP8266WebServerTemplate::_streamFileCore(const size_t fileSize send(200, contentType, emptyString); } -const String& ESP8266WebServer::pathArg(unsigned int i) { +template +const String& ESP8266WebServerTemplate::pathArg(unsigned int i) const { if (_currentHandler != nullptr) return _currentHandler->pathArg(i); return emptyString; diff --git a/libraries/ESP8266WebServer/src/ESP8266WebServer.h b/libraries/ESP8266WebServer/src/ESP8266WebServer.h index dffa470a7f..5797548eae 100644 --- a/libraries/ESP8266WebServer/src/ESP8266WebServer.h +++ b/libraries/ESP8266WebServer/src/ESP8266WebServer.h @@ -107,7 +107,7 @@ class ESP8266WebServerTemplate // Allows setting server options (i.e. SSL keys) by the instantiator ServerType &getServer() { return _server; } - String pathArg(unsigned int i); // get request path argument by number + const String& pathArg(unsigned int i) const; // get request path argument by number const String& arg(const String& name) const; // get request argument value by name const String& arg(int i) const; // get request argument value by number const String& argName(int i) const; // get request argument name by number diff --git a/libraries/ESP8266WebServer/src/detail/RequestHandler.h b/libraries/ESP8266WebServer/src/detail/RequestHandler.h index 488849ccf3..9202f623b3 100644 --- a/libraries/ESP8266WebServer/src/detail/RequestHandler.h +++ b/libraries/ESP8266WebServer/src/detail/RequestHandler.h @@ -23,7 +23,6 @@ class RequestHandler { protected: std::vector pathArgs; - bool _isRegex = false; public: const String& pathArg(unsigned int i) { diff --git a/libraries/ESP8266WebServer/src/detail/RequestHandlersImpl.h b/libraries/ESP8266WebServer/src/detail/RequestHandlersImpl.h index 7a8cd8479f..bc81dcc0c7 100644 --- a/libraries/ESP8266WebServer/src/detail/RequestHandlersImpl.h +++ b/libraries/ESP8266WebServer/src/detail/RequestHandlersImpl.h @@ -19,6 +19,7 @@ class FunctionRequestHandler : public RequestHandler { , _ufn(ufn) , _uri(uri) , _method(method) + , _isRegex(false) { _isRegex = uri.startsWith("^") && uri.endsWith("$"); if (_isRegex) { @@ -26,9 +27,9 @@ class FunctionRequestHandler : public RequestHandler { std::smatch matches; std::string s{""}; std::regex_search(s, matches, rgx); - pathArgs.resize(matches.size() - 1); + RequestHandler::pathArgs.resize(matches.size() - 1); } else { - pathArgs.resize(0); + RequestHandler::pathArgs.resize(0); } } @@ -46,7 +47,7 @@ class FunctionRequestHandler : public RequestHandler { std::string s(requestUri.c_str()); if (std::regex_search(s, matches, rgx)) { for (size_t i = 1; i < matches.size(); ++i) { // skip first - pathArgs[pathArgIndex] = String(matches[i].str().c_str()); + RequestHandler::pathArgs[pathArgIndex] = String(matches[i].str().c_str()); pathArgIndex++; } return true; @@ -84,6 +85,7 @@ class FunctionRequestHandler : public RequestHandler { typename WebServerType::THandlerFunction _ufn; String _uri; HTTPMethod _method; + bool _isRegex; }; template From 8f5eda3b5912e1f69b1b3ad6a1a7f0e583ef62d9 Mon Sep 17 00:00:00 2001 From: Bob Mooij Date: Fri, 1 Nov 2019 17:29:30 +0100 Subject: [PATCH 18/25] Add Uri with support for staticUri, regexUri and globUri --- .../src/ESP8266WebServer-impl.h | 6 +- .../ESP8266WebServer/src/ESP8266WebServer.h | 7 +- libraries/ESP8266WebServer/src/Uri.h | 28 ++++++++ .../src/detail/RequestHandlersImpl.h | 41 ++---------- .../ESP8266WebServer/src/uri/UriBraces.h | 66 +++++++++++++++++++ libraries/ESP8266WebServer/src/uri/UriGlob.h | 22 +++++++ libraries/ESP8266WebServer/src/uri/UriRegex.h | 44 +++++++++++++ 7 files changed, 173 insertions(+), 41 deletions(-) create mode 100644 libraries/ESP8266WebServer/src/Uri.h create mode 100644 libraries/ESP8266WebServer/src/uri/UriBraces.h create mode 100644 libraries/ESP8266WebServer/src/uri/UriGlob.h create mode 100644 libraries/ESP8266WebServer/src/uri/UriRegex.h diff --git a/libraries/ESP8266WebServer/src/ESP8266WebServer-impl.h b/libraries/ESP8266WebServer/src/ESP8266WebServer-impl.h index 9de4f393dd..c8a841aa8f 100644 --- a/libraries/ESP8266WebServer/src/ESP8266WebServer-impl.h +++ b/libraries/ESP8266WebServer/src/ESP8266WebServer-impl.h @@ -263,17 +263,17 @@ void ESP8266WebServerTemplate::requestAuthentication(HTTPAuthMethod } template -void ESP8266WebServerTemplate::on(const String &uri, ESP8266WebServerTemplate::THandlerFunction handler) { +void ESP8266WebServerTemplate::on(const Uri &uri, ESP8266WebServerTemplate::THandlerFunction handler) { on(uri, HTTP_ANY, handler); } template -void ESP8266WebServerTemplate::on(const String &uri, HTTPMethod method, ESP8266WebServerTemplate::THandlerFunction fn) { +void ESP8266WebServerTemplate::on(const Uri &uri, HTTPMethod method, ESP8266WebServerTemplate::THandlerFunction fn) { on(uri, method, fn, _fileUploadHandler); } template -void ESP8266WebServerTemplate::on(const String &uri, HTTPMethod method, ESP8266WebServerTemplate::THandlerFunction fn, ESP8266WebServerTemplate::THandlerFunction ufn) { +void ESP8266WebServerTemplate::on(const Uri &uri, HTTPMethod method, ESP8266WebServerTemplate::THandlerFunction fn, ESP8266WebServerTemplate::THandlerFunction ufn) { _addRequestHandler(new FunctionRequestHandler(fn, ufn, uri, method)); } diff --git a/libraries/ESP8266WebServer/src/ESP8266WebServer.h b/libraries/ESP8266WebServer/src/ESP8266WebServer.h index 5797548eae..b58fadd4bd 100644 --- a/libraries/ESP8266WebServer/src/ESP8266WebServer.h +++ b/libraries/ESP8266WebServer/src/ESP8266WebServer.h @@ -29,6 +29,7 @@ #include #include #include "detail/mimetable.h" +#include "Uri.h" enum HTTPMethod { HTTP_ANY, HTTP_GET, HTTP_HEAD, HTTP_POST, HTTP_PUT, HTTP_PATCH, HTTP_DELETE, HTTP_OPTIONS }; enum HTTPUploadStatus { UPLOAD_FILE_START, UPLOAD_FILE_WRITE, UPLOAD_FILE_END, @@ -91,9 +92,9 @@ class ESP8266WebServerTemplate void requestAuthentication(HTTPAuthMethod mode = BASIC_AUTH, const char* realm = NULL, const String& authFailMsg = String("") ); typedef std::function THandlerFunction; - void on(const String &uri, THandlerFunction handler); - void on(const String &uri, HTTPMethod method, THandlerFunction fn); - void on(const String &uri, HTTPMethod method, THandlerFunction fn, THandlerFunction ufn); + void on(const Uri &uri, THandlerFunction handler); + void on(const Uri &uri, HTTPMethod method, THandlerFunction fn); + void on(const Uri &uri, HTTPMethod method, THandlerFunction fn, THandlerFunction ufn); void addHandler(RequestHandlerType* 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 diff --git a/libraries/ESP8266WebServer/src/Uri.h b/libraries/ESP8266WebServer/src/Uri.h new file mode 100644 index 0000000000..65d2344195 --- /dev/null +++ b/libraries/ESP8266WebServer/src/Uri.h @@ -0,0 +1,28 @@ +#ifndef URI_H +#define URI_H + +#include +#include + +class Uri { + + protected: + const String _uri; + + public: + Uri(const char *uri) : _uri(uri) {} + Uri(const String &uri) : _uri(uri) {} + virtual ~Uri() {} + + virtual Uri* clone() const { + return new Uri(_uri); + }; + + virtual void initPathArgs(std::vector &pathArgs) {} + + virtual bool canHandle(const String &requestUri, std::vector &pathArgs) { + return _uri == requestUri; + } +}; + +#endif diff --git a/libraries/ESP8266WebServer/src/detail/RequestHandlersImpl.h b/libraries/ESP8266WebServer/src/detail/RequestHandlersImpl.h index bc81dcc0c7..c6de19b8d9 100644 --- a/libraries/ESP8266WebServer/src/detail/RequestHandlersImpl.h +++ b/libraries/ESP8266WebServer/src/detail/RequestHandlersImpl.h @@ -2,11 +2,10 @@ #define REQUESTHANDLERSIMPL_H #include -#include -#include #include "RequestHandler.h" #include "mimetable.h" #include "WString.h" +#include "Uri.h" using namespace mime; @@ -14,47 +13,20 @@ template class FunctionRequestHandler : public RequestHandler { using WebServerType = ESP8266WebServerTemplate; public: - FunctionRequestHandler(typename WebServerType::THandlerFunction fn, typename WebServerType::THandlerFunction ufn, const String &uri, HTTPMethod method) + FunctionRequestHandler(typename WebServerType::THandlerFunction fn, typename WebServerType::THandlerFunction ufn, const Uri &uri, HTTPMethod method) : _fn(fn) , _ufn(ufn) - , _uri(uri) + , _uri(uri.clone()) , _method(method) - , _isRegex(false) { - _isRegex = uri.startsWith("^") && uri.endsWith("$"); - if (_isRegex) { - std::regex rgx((_uri + "|").c_str()); - std::smatch matches; - std::string s{""}; - std::regex_search(s, matches, rgx); - RequestHandler::pathArgs.resize(matches.size() - 1); - } else { - RequestHandler::pathArgs.resize(0); - } + _uri->initPathArgs(RequestHandler::pathArgs); } bool canHandle(HTTPMethod requestMethod, String requestUri) override { if (_method != HTTP_ANY && _method != requestMethod) return false; - if (_uri == requestUri) - return true; - - if (_isRegex) { - unsigned int pathArgIndex = 0; - std::regex rgx(_uri.c_str()); - std::smatch matches; - std::string s(requestUri.c_str()); - if (std::regex_search(s, matches, rgx)) { - for (size_t i = 1; i < matches.size(); ++i) { // skip first - RequestHandler::pathArgs[pathArgIndex] = String(matches[i].str().c_str()); - pathArgIndex++; - } - return true; - } - } - - return false; + return _uri->canHandle(requestUri, RequestHandler::pathArgs); } bool canUpload(String requestUri) override { @@ -83,9 +55,8 @@ class FunctionRequestHandler : public RequestHandler { protected: typename WebServerType::THandlerFunction _fn; typename WebServerType::THandlerFunction _ufn; - String _uri; + Uri *_uri; HTTPMethod _method; - bool _isRegex; }; template diff --git a/libraries/ESP8266WebServer/src/uri/UriBraces.h b/libraries/ESP8266WebServer/src/uri/UriBraces.h new file mode 100644 index 0000000000..189b480c43 --- /dev/null +++ b/libraries/ESP8266WebServer/src/uri/UriBraces.h @@ -0,0 +1,66 @@ +#ifndef URI_BRACES_H +#define URI_BRACES_H + +#include "Uri.h" + +class UriBraces : public Uri { + + public: + explicit UriBraces(const char *uri) : Uri(uri) {}; + explicit UriBraces(const String &uri) : Uri(uri) {}; + + Uri* clone() const override final { + return new UriBraces(_uri); + }; + + void initPathArgs(std::vector &pathArgs) override final { + int numParams = 0, start = 0; + do { + start = _uri.indexOf("{}", start); + if (start > 0) { + numParams++; + start += 2; + } + } while (start > 0); + pathArgs.resize(numParams); + } + + bool canHandle(const String &requestUri, std::vector &pathArgs) override final { + if (Uri::canHandle(requestUri, pathArgs)) + return true; + + size_t uriLength = _uri.length(); + unsigned int pathArgIndex = 0; + unsigned int requestUriIndex = 0; + for (unsigned int i = 0; i < uriLength; i++, requestUriIndex++) { + char uriChar = _uri[i]; + char requestUriChar = requestUri[requestUriIndex]; + + if (uriChar == requestUriChar) + continue; + if (uriChar != '{') + return false; + + i += 2; // index of char after '}' + if (i >= uriLength) { + // there is no char after '}' + pathArgs[pathArgIndex] = requestUri.substring(requestUriIndex); + return pathArgs[pathArgIndex].indexOf("/") == -1; // path argument may not contain a '/' + } + else + { + char charEnd = _uri[i]; + int uriIndex = requestUri.indexOf(charEnd, requestUriIndex); + if (uriIndex < 0) + return false; + pathArgs[pathArgIndex] = requestUri.substring(requestUriIndex, uriIndex); + requestUriIndex = (unsigned int) uriIndex; + } + pathArgIndex++; + } + + return requestUriIndex >= requestUri.length(); + } +}; + +#endif \ No newline at end of file diff --git a/libraries/ESP8266WebServer/src/uri/UriGlob.h b/libraries/ESP8266WebServer/src/uri/UriGlob.h new file mode 100644 index 0000000000..823f45e1e3 --- /dev/null +++ b/libraries/ESP8266WebServer/src/uri/UriGlob.h @@ -0,0 +1,22 @@ +#ifndef URI_GLOB_H +#define URI_GLOB_H + +#include "Uri.h" +#include + +class UriGlob : public Uri { + + public: + explicit UriGlob(const char *uri) : Uri(uri) {}; + explicit UriGlob(const String &uri) : Uri(uri) {}; + + Uri* clone() const override final { + return new UriGlob(_uri); + }; + + bool canHandle(const String &requestUri, std::vector &pathArgs) override final { + return fnmatch(_uri.c_str(), requestUri.c_str(), 0) == 0; + } +}; + +#endif \ No newline at end of file diff --git a/libraries/ESP8266WebServer/src/uri/UriRegex.h b/libraries/ESP8266WebServer/src/uri/UriRegex.h new file mode 100644 index 0000000000..34423d245f --- /dev/null +++ b/libraries/ESP8266WebServer/src/uri/UriRegex.h @@ -0,0 +1,44 @@ +#ifndef URI_REGEX_H +#define URI_REGEX_H + +#include "Uri.h" +#include + +class UriRegex : public Uri { + + public: + explicit UriRegex(const char *uri) : Uri(uri) {}; + explicit UriRegex(const String &uri) : Uri(uri) {}; + + Uri* clone() const override final { + return new UriRegex(_uri); + }; + + void initPathArgs(std::vector &pathArgs) override final { + std::regex rgx((_uri + "|").c_str()); + std::smatch matches; + std::string s{""}; + std::regex_search(s, matches, rgx); + pathArgs.resize(matches.size() - 1); + } + + bool canHandle(const String &requestUri, std::vector &pathArgs) override final { + if (Uri::canHandle(requestUri, pathArgs)) + return true; + + unsigned int pathArgIndex = 0; + std::regex rgx(_uri.c_str()); + std::smatch matches; + std::string s(requestUri.c_str()); + if (std::regex_search(s, matches, rgx)) { + for (size_t i = 1; i < matches.size(); ++i) { // skip first + pathArgs[pathArgIndex] = String(matches[i].str().c_str()); + pathArgIndex++; + } + return true; + } + return false; + } +}; + +#endif \ No newline at end of file From 2ee04d01c5d1235686fc1291aa15429c27958e8b Mon Sep 17 00:00:00 2001 From: Bob Mooij Date: Fri, 1 Nov 2019 17:32:53 +0100 Subject: [PATCH 19/25] Update example --- .../examples/PathArgServer/PathArgServer.ino | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/libraries/ESP8266WebServer/examples/PathArgServer/PathArgServer.ino b/libraries/ESP8266WebServer/examples/PathArgServer/PathArgServer.ino index db8bcfe039..cc5171826e 100644 --- a/libraries/ESP8266WebServer/examples/PathArgServer/PathArgServer.ino +++ b/libraries/ESP8266WebServer/examples/PathArgServer/PathArgServer.ino @@ -3,6 +3,9 @@ #include #include +#include +#include + const char *ssid = "........"; const char *password = "........"; @@ -33,12 +36,12 @@ void setup(void) { server.send(200, "text/plain", "hello from esp8266!"); }); - server.on("/users/{}", []() { + server.on(UriBraces("/users/{}"), []() { String user = server.pathArg(0); server.send(200, "text/plain", "User: '" + user + "'"); }); - server.on("^\\/users\\/([0-9]+)\\/devices\\/([0-9]+)$", []() { + server.on(UriRegex("^\\/users\\/([0-9]+)\\/devices\\/([0-9]+)$"), []() { String user = server.pathArg(0); String device = server.pathArg(1); server.send(200, "text/plain", "User: '" + user + "' and Device: '" + device + "'"); From 3edf15a37e9dc378daf366da6fb5d781c85f4406 Mon Sep 17 00:00:00 2001 From: Bob Mooij Date: Fri, 1 Nov 2019 20:33:33 +0100 Subject: [PATCH 20/25] Add deconstructor to remove _uri pointer --- libraries/ESP8266WebServer/src/detail/RequestHandlersImpl.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libraries/ESP8266WebServer/src/detail/RequestHandlersImpl.h b/libraries/ESP8266WebServer/src/detail/RequestHandlersImpl.h index c6de19b8d9..bf28ca75f1 100644 --- a/libraries/ESP8266WebServer/src/detail/RequestHandlersImpl.h +++ b/libraries/ESP8266WebServer/src/detail/RequestHandlersImpl.h @@ -22,6 +22,10 @@ class FunctionRequestHandler : public RequestHandler { _uri->initPathArgs(RequestHandler::pathArgs); } + ~FunctionRequestHandler() { + delete _uri; + } + bool canHandle(HTTPMethod requestMethod, String requestUri) override { if (_method != HTTP_ANY && _method != requestMethod) return false; From 820597cf063503e7945985a235616fdd2b9c56c4 Mon Sep 17 00:00:00 2001 From: Bob Mooij Date: Fri, 1 Nov 2019 20:34:03 +0100 Subject: [PATCH 21/25] Add newline to end of files --- libraries/ESP8266WebServer/src/uri/UriBraces.h | 2 +- libraries/ESP8266WebServer/src/uri/UriGlob.h | 2 +- libraries/ESP8266WebServer/src/uri/UriRegex.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/libraries/ESP8266WebServer/src/uri/UriBraces.h b/libraries/ESP8266WebServer/src/uri/UriBraces.h index 189b480c43..4a6049b3c4 100644 --- a/libraries/ESP8266WebServer/src/uri/UriBraces.h +++ b/libraries/ESP8266WebServer/src/uri/UriBraces.h @@ -63,4 +63,4 @@ class UriBraces : public Uri { } }; -#endif \ No newline at end of file +#endif diff --git a/libraries/ESP8266WebServer/src/uri/UriGlob.h b/libraries/ESP8266WebServer/src/uri/UriGlob.h index 823f45e1e3..0730164c21 100644 --- a/libraries/ESP8266WebServer/src/uri/UriGlob.h +++ b/libraries/ESP8266WebServer/src/uri/UriGlob.h @@ -19,4 +19,4 @@ class UriGlob : public Uri { } }; -#endif \ No newline at end of file +#endif diff --git a/libraries/ESP8266WebServer/src/uri/UriRegex.h b/libraries/ESP8266WebServer/src/uri/UriRegex.h index 34423d245f..05702017f4 100644 --- a/libraries/ESP8266WebServer/src/uri/UriRegex.h +++ b/libraries/ESP8266WebServer/src/uri/UriRegex.h @@ -41,4 +41,4 @@ class UriRegex : public Uri { } }; -#endif \ No newline at end of file +#endif From 8d95fb6f70c076f1b63879995dbc30f22a9d5610 Mon Sep 17 00:00:00 2001 From: Bob Mooij Date: Thu, 7 Nov 2019 15:06:12 +0100 Subject: [PATCH 22/25] Suppress gcc warnings (unused params) --- libraries/ESP8266WebServer/src/Uri.h | 4 ++-- libraries/ESP8266WebServer/src/uri/UriGlob.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/libraries/ESP8266WebServer/src/Uri.h b/libraries/ESP8266WebServer/src/Uri.h index 65d2344195..83772b2348 100644 --- a/libraries/ESP8266WebServer/src/Uri.h +++ b/libraries/ESP8266WebServer/src/Uri.h @@ -18,9 +18,9 @@ class Uri { return new Uri(_uri); }; - virtual void initPathArgs(std::vector &pathArgs) {} + virtual void initPathArgs(__attribute__((unused)) std::vector &pathArgs) {} - virtual bool canHandle(const String &requestUri, std::vector &pathArgs) { + virtual bool canHandle(const String &requestUri, __attribute__((unused)) std::vector &pathArgs) { return _uri == requestUri; } }; diff --git a/libraries/ESP8266WebServer/src/uri/UriGlob.h b/libraries/ESP8266WebServer/src/uri/UriGlob.h index 0730164c21..1e222cbabd 100644 --- a/libraries/ESP8266WebServer/src/uri/UriGlob.h +++ b/libraries/ESP8266WebServer/src/uri/UriGlob.h @@ -14,7 +14,7 @@ class UriGlob : public Uri { return new UriGlob(_uri); }; - bool canHandle(const String &requestUri, std::vector &pathArgs) override final { + bool canHandle(const String &requestUri, __attribute__((unused)) std::vector &pathArgs) override final { return fnmatch(_uri.c_str(), requestUri.c_str(), 0) == 0; } }; From baa4c49e5b521f5769bac83a90282fe6af6128a7 Mon Sep 17 00:00:00 2001 From: Bob Mooij Date: Fri, 27 Dec 2019 23:19:55 +0100 Subject: [PATCH 23/25] Replace regex with regex.h --- libraries/ESP8266WebServer/src/Uri.h | 2 - .../src/detail/RequestHandlersImpl.h | 1 - .../ESP8266WebServer/src/uri/UriBraces.h | 22 ++------- libraries/ESP8266WebServer/src/uri/UriRegex.h | 48 +++++++++++-------- 4 files changed, 34 insertions(+), 39 deletions(-) diff --git a/libraries/ESP8266WebServer/src/Uri.h b/libraries/ESP8266WebServer/src/Uri.h index 83772b2348..cb9b68c051 100644 --- a/libraries/ESP8266WebServer/src/Uri.h +++ b/libraries/ESP8266WebServer/src/Uri.h @@ -18,8 +18,6 @@ class Uri { return new Uri(_uri); }; - virtual void initPathArgs(__attribute__((unused)) std::vector &pathArgs) {} - virtual bool canHandle(const String &requestUri, __attribute__((unused)) std::vector &pathArgs) { return _uri == requestUri; } diff --git a/libraries/ESP8266WebServer/src/detail/RequestHandlersImpl.h b/libraries/ESP8266WebServer/src/detail/RequestHandlersImpl.h index 759f5d3467..4cd39a43a0 100644 --- a/libraries/ESP8266WebServer/src/detail/RequestHandlersImpl.h +++ b/libraries/ESP8266WebServer/src/detail/RequestHandlersImpl.h @@ -19,7 +19,6 @@ class FunctionRequestHandler : public RequestHandler { , _uri(uri.clone()) , _method(method) { - _uri->initPathArgs(RequestHandler::pathArgs); } ~FunctionRequestHandler() { diff --git a/libraries/ESP8266WebServer/src/uri/UriBraces.h b/libraries/ESP8266WebServer/src/uri/UriBraces.h index 4a6049b3c4..29652efc7f 100644 --- a/libraries/ESP8266WebServer/src/uri/UriBraces.h +++ b/libraries/ESP8266WebServer/src/uri/UriBraces.h @@ -13,24 +13,13 @@ class UriBraces : public Uri { return new UriBraces(_uri); }; - void initPathArgs(std::vector &pathArgs) override final { - int numParams = 0, start = 0; - do { - start = _uri.indexOf("{}", start); - if (start > 0) { - numParams++; - start += 2; - } - } while (start > 0); - pathArgs.resize(numParams); - } - bool canHandle(const String &requestUri, std::vector &pathArgs) override final { if (Uri::canHandle(requestUri, pathArgs)) return true; + pathArgs.clear(); + size_t uriLength = _uri.length(); - unsigned int pathArgIndex = 0; unsigned int requestUriIndex = 0; for (unsigned int i = 0; i < uriLength; i++, requestUriIndex++) { char uriChar = _uri[i]; @@ -44,8 +33,8 @@ class UriBraces : public Uri { i += 2; // index of char after '}' if (i >= uriLength) { // there is no char after '}' - pathArgs[pathArgIndex] = requestUri.substring(requestUriIndex); - return pathArgs[pathArgIndex].indexOf("/") == -1; // path argument may not contain a '/' + pathArgs.push_back(requestUri.substring(requestUriIndex)); + return pathArgs.back().indexOf("/") == -1; // path argument may not contain a '/' } else { @@ -53,10 +42,9 @@ class UriBraces : public Uri { int uriIndex = requestUri.indexOf(charEnd, requestUriIndex); if (uriIndex < 0) return false; - pathArgs[pathArgIndex] = requestUri.substring(requestUriIndex, uriIndex); + pathArgs.push_back(requestUri.substring(requestUriIndex, uriIndex)); requestUriIndex = (unsigned int) uriIndex; } - pathArgIndex++; } return requestUriIndex >= requestUri.length(); diff --git a/libraries/ESP8266WebServer/src/uri/UriRegex.h b/libraries/ESP8266WebServer/src/uri/UriRegex.h index 05702017f4..eef1b516d4 100644 --- a/libraries/ESP8266WebServer/src/uri/UriRegex.h +++ b/libraries/ESP8266WebServer/src/uri/UriRegex.h @@ -2,39 +2,49 @@ #define URI_REGEX_H #include "Uri.h" -#include +#include +#include + +#ifndef REGEX_MAX_GROUPS +#define REGEX_MAX_GROUPS 10 +#endif class UriRegex : public Uri { + private: + regex_t _regexCompiled; + public: - explicit UriRegex(const char *uri) : Uri(uri) {}; - explicit UriRegex(const String &uri) : Uri(uri) {}; + explicit UriRegex(const char *uri) : Uri(uri) { + assert(regcomp(&_regexCompiled, uri, REG_EXTENDED) == 0); + }; + explicit UriRegex(const String &uri) : UriRegex(uri.c_str()) {}; + + ~UriRegex() { + regfree(&_regexCompiled); + } Uri* clone() const override final { return new UriRegex(_uri); }; - void initPathArgs(std::vector &pathArgs) override final { - std::regex rgx((_uri + "|").c_str()); - std::smatch matches; - std::string s{""}; - std::regex_search(s, matches, rgx); - pathArgs.resize(matches.size() - 1); - } - bool canHandle(const String &requestUri, std::vector &pathArgs) override final { if (Uri::canHandle(requestUri, pathArgs)) return true; - unsigned int pathArgIndex = 0; - std::regex rgx(_uri.c_str()); - std::smatch matches; - std::string s(requestUri.c_str()); - if (std::regex_search(s, matches, rgx)) { - for (size_t i = 1; i < matches.size(); ++i) { // skip first - pathArgs[pathArgIndex] = String(matches[i].str().c_str()); - pathArgIndex++; + regmatch_t groupArray[REGEX_MAX_GROUPS]; + if (regexec(&_regexCompiled, requestUri.c_str(), REGEX_MAX_GROUPS, groupArray, 0) == 0) { + // matches + pathArgs.clear(); + + unsigned int g = 1; + for (; g < REGEX_MAX_GROUPS; g++) { + if (groupArray[g].rm_so == (long int)-1) + break; // No more groups + + pathArgs.push_back(requestUri.substring(groupArray[g].rm_so, groupArray[g].rm_eo)); } + return true; } return false; From bb77646797fbaa107709de8aa2b6a3476385d5ba Mon Sep 17 00:00:00 2001 From: "Earle F. Philhower, III" Date: Sat, 22 Feb 2020 10:03:32 -0800 Subject: [PATCH 24/25] Use the standard STASSID/PSK settings for example Make the example match the existing examples which allow setting the SSID/PSK in the local platform.txt file. --- .../examples/PathArgServer/PathArgServer.ino | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/libraries/ESP8266WebServer/examples/PathArgServer/PathArgServer.ino b/libraries/ESP8266WebServer/examples/PathArgServer/PathArgServer.ino index cc5171826e..156d32e88c 100644 --- a/libraries/ESP8266WebServer/examples/PathArgServer/PathArgServer.ino +++ b/libraries/ESP8266WebServer/examples/PathArgServer/PathArgServer.ino @@ -6,8 +6,13 @@ #include #include -const char *ssid = "........"; -const char *password = "........"; +#ifndef STASSID +#define STASSID "your-ssid" +#define STAPSK "your-password" +#endif + +const char *ssid = STASSID; +const char *password = STAPSK; ESP8266WebServer server(80); From be78c3b4e79a01ba01cdb1c695d0cab286296362 Mon Sep 17 00:00:00 2001 From: "Earle F. Philhower, III" Date: Sat, 22 Feb 2020 10:05:54 -0800 Subject: [PATCH 25/25] Use 115.2Kbaud for example, match others --- .../ESP8266WebServer/examples/PathArgServer/PathArgServer.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/ESP8266WebServer/examples/PathArgServer/PathArgServer.ino b/libraries/ESP8266WebServer/examples/PathArgServer/PathArgServer.ino index 156d32e88c..c2c7f56884 100644 --- a/libraries/ESP8266WebServer/examples/PathArgServer/PathArgServer.ino +++ b/libraries/ESP8266WebServer/examples/PathArgServer/PathArgServer.ino @@ -17,7 +17,7 @@ const char *password = STAPSK; ESP8266WebServer server(80); void setup(void) { - Serial.begin(9600); + Serial.begin(115200); WiFi.mode(WIFI_STA); WiFi.begin(ssid, password); Serial.println("");