diff --git a/libraries/WebServer/examples/PathArgServer/PathArgServer.ino b/libraries/WebServer/examples/PathArgServer/PathArgServer.ino new file mode 100644 index 0000000000000000000000000000000000000000..8f22f1bea921b6f2f6301fc278fcb2e48ac79432 --- /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 049b412a31ff84767d080cc2a7a1e97512e4765b..819e338bbf539e807f35521a7b86bf340ed09851 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 aa7a00e2add626018f869bb3e3491ed76d1308a3..aedfb40fb49d90e13002eb8baf00424522ed52ca 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 c1cc909d8403b35a58adf9099055b76e868e0299..871ae5c8b3d524c58dc9ffd9672ed998287f922d 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 6db8a674048b52d35f5973f4ba0cc5b34b1c3126..babca4e27e36f61a1bfc202e0308fcbd9f122d1b 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 {