From 3902aa4019134a353c925283440cb53efc16e2a1 Mon Sep 17 00:00:00 2001 From: Bob Date: Mon, 19 Nov 2018 17:00:52 +0100 Subject: [PATCH] Adding path arguments to WebServer (#1994) --- .../examples/PathArgServer/PathArgServer.ino | 53 +++++++++++++++++++ libraries/WebServer/src/WebServer.cpp | 5 ++ libraries/WebServer/src/WebServer.h | 1 + .../WebServer/src/detail/RequestHandler.h | 12 +++++ .../src/detail/RequestHandlersImpl.h | 45 ++++++++++++++-- 5 files changed, 113 insertions(+), 3 deletions(-) create mode 100644 libraries/WebServer/examples/PathArgServer/PathArgServer.ino diff --git a/libraries/WebServer/examples/PathArgServer/PathArgServer.ino b/libraries/WebServer/examples/PathArgServer/PathArgServer.ino new file mode 100644 index 000000000..8f22f1bea --- /dev/null +++ b/libraries/WebServer/examples/PathArgServer/PathArgServer.ino @@ -0,0 +1,53 @@ +#include +#include +#include +#include + +const char *ssid = "........"; +const char *password = "........"; + +WebServer server(80); + +void setup(void) { + 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("esp32")) { + Serial.println("MDNS responder started"); + } + + server.on("/", []() { + server.send(200, "text/plain", "hello from esp32!"); + }); + + 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(); + Serial.println("HTTP server started"); +} + +void loop(void) { + server.handleClient(); +} diff --git a/libraries/WebServer/src/WebServer.cpp b/libraries/WebServer/src/WebServer.cpp index 049b412a3..819e338bb 100644 --- a/libraries/WebServer/src/WebServer.cpp +++ b/libraries/WebServer/src/WebServer.cpp @@ -509,6 +509,11 @@ void WebServer::_streamFileCore(const size_t fileSize, const String & fileName, send(200, contentType, ""); } +String WebServer::pathArg(unsigned int i) { + if (_currentHandler != nullptr) + return _currentHandler->pathArg(i); + return ""; +} String WebServer::arg(String name) { for (int j = 0; j < _postArgsLen; ++j) { diff --git a/libraries/WebServer/src/WebServer.h b/libraries/WebServer/src/WebServer.h index aa7a00e2a..aedfb40fb 100644 --- a/libraries/WebServer/src/WebServer.h +++ b/libraries/WebServer/src/WebServer.h @@ -97,6 +97,7 @@ public: virtual WiFiClient client() { return _currentClient; } HTTPUpload& upload() { return *_currentUpload; } + String pathArg(unsigned int i); // get request path argument by number String arg(String name); // get request argument value by name String arg(int i); // get request argument value by number String argName(int i); // get request argument name by number diff --git a/libraries/WebServer/src/detail/RequestHandler.h b/libraries/WebServer/src/detail/RequestHandler.h index c1cc909d8..871ae5c8b 100644 --- a/libraries/WebServer/src/detail/RequestHandler.h +++ b/libraries/WebServer/src/detail/RequestHandler.h @@ -1,6 +1,9 @@ #ifndef REQUESTHANDLER_H #define REQUESTHANDLER_H +#include +#include + class RequestHandler { public: virtual ~RequestHandler() { } @@ -14,6 +17,15 @@ public: private: RequestHandler* _next = nullptr; + +protected: + std::vector pathArgs; + +public: + const String& pathArg(unsigned int i) { + assert(i < pathArgs.size()); + return pathArgs[i]; + } }; #endif //REQUESTHANDLER_H diff --git a/libraries/WebServer/src/detail/RequestHandlersImpl.h b/libraries/WebServer/src/detail/RequestHandlersImpl.h index 6db8a6740..babca4e27 100644 --- a/libraries/WebServer/src/detail/RequestHandlersImpl.h +++ b/libraries/WebServer/src/detail/RequestHandlersImpl.h @@ -15,16 +15,55 @@ public: , _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); } 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; + + 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 true; + return requestUriIndex >= requestUri.length(); } bool canUpload(String requestUri) override { -- GitLab