Add Uri with support for regexUri and globUri (#3441)
* Add Uri with support for staticUri, regexUri and globUri * Add newline to end of files * Update example * Suppress gcc warnings (unused params)
This commit is contained in:
		
							parent
							
								
									c09ec5bd3d
								
							
						
					
					
						commit
						cfe8526ec8
					
				| @ -3,6 +3,9 @@ | ||||
| #include <WebServer.h> | ||||
| #include <ESPmDNS.h> | ||||
| 
 | ||||
| #include <uri/UriBraces.h> | ||||
| #include <uri/UriRegex.h> | ||||
| 
 | ||||
| const char *ssid = "........"; | ||||
| const char *password = "........"; | ||||
| 
 | ||||
| @ -33,12 +36,12 @@ void setup(void) { | ||||
|     server.send(200, "text/plain", "hello from esp32!"); | ||||
|   }); | ||||
| 
 | ||||
|   server.on("/users/{}", []() { | ||||
|   server.on(UriBraces("/users/{}"), []() { | ||||
|     String user = server.pathArg(0); | ||||
|     server.send(200, "text/plain", "User: '" + user + "'"); | ||||
|   }); | ||||
|    | ||||
|   server.on("/users/{}/devices/{}", []() { | ||||
|   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 + "'"); | ||||
|  | ||||
							
								
								
									
										28
									
								
								libraries/WebServer/src/Uri.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								libraries/WebServer/src/Uri.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,28 @@ | ||||
| #ifndef URI_H | ||||
| #define URI_H | ||||
| 
 | ||||
| #include <Arduino.h> | ||||
| #include <vector> | ||||
| 
 | ||||
| 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(__attribute__((unused)) std::vector<String> &pathArgs) {} | ||||
| 
 | ||||
|         virtual bool canHandle(const String &requestUri, __attribute__((unused)) std::vector<String> &pathArgs) { | ||||
|             return _uri == requestUri; | ||||
|         } | ||||
| }; | ||||
| 
 | ||||
| #endif | ||||
| @ -245,15 +245,15 @@ void WebServer::requestAuthentication(HTTPAuthMethod mode, const char* realm, co | ||||
|   send(401, String(FPSTR(mimeTable[html].mimeType)), authFailMsg); | ||||
| } | ||||
| 
 | ||||
| void WebServer::on(const String &uri, WebServer::THandlerFunction handler) { | ||||
| void WebServer::on(const Uri &uri, WebServer::THandlerFunction handler) { | ||||
|   on(uri, HTTP_ANY, handler); | ||||
| } | ||||
| 
 | ||||
| void WebServer::on(const String &uri, HTTPMethod method, WebServer::THandlerFunction fn) { | ||||
| void WebServer::on(const Uri &uri, HTTPMethod method, WebServer::THandlerFunction fn) { | ||||
|   on(uri, method, fn, _fileUploadHandler); | ||||
| } | ||||
| 
 | ||||
| void WebServer::on(const String &uri, HTTPMethod method, WebServer::THandlerFunction fn, WebServer::THandlerFunction ufn) { | ||||
| void WebServer::on(const Uri &uri, HTTPMethod method, WebServer::THandlerFunction fn, WebServer::THandlerFunction ufn) { | ||||
|   _addRequestHandler(new FunctionRequestHandler(fn, ufn, uri, method)); | ||||
| } | ||||
| 
 | ||||
|  | ||||
| @ -28,6 +28,7 @@ | ||||
| #include <memory> | ||||
| #include <WiFi.h> | ||||
| #include "HTTP_Method.h" | ||||
| #include "Uri.h" | ||||
| 
 | ||||
| enum HTTPUploadStatus { UPLOAD_FILE_START, UPLOAD_FILE_WRITE, UPLOAD_FILE_END, | ||||
|                         UPLOAD_FILE_ABORTED }; | ||||
| @ -84,9 +85,9 @@ public: | ||||
|   void requestAuthentication(HTTPAuthMethod mode = BASIC_AUTH, const char* realm = NULL, const String& authFailMsg = String("") ); | ||||
| 
 | ||||
|   typedef std::function<void(void)> 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(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
 | ||||
|  | ||||
| @ -4,66 +4,30 @@ | ||||
| #include "RequestHandler.h" | ||||
| #include "mimetable.h" | ||||
| #include "WString.h" | ||||
| #include "Uri.h" | ||||
| 
 | ||||
| using namespace mime; | ||||
| 
 | ||||
| class FunctionRequestHandler : public RequestHandler { | ||||
| public: | ||||
|     FunctionRequestHandler(WebServer::THandlerFunction fn, WebServer::THandlerFunction ufn, const String &uri, HTTPMethod method) | ||||
|     FunctionRequestHandler(WebServer::THandlerFunction fn, WebServer::THandlerFunction ufn, const Uri &uri, HTTPMethod method) | ||||
|     : _fn(fn) | ||||
|     , _ufn(ufn) | ||||
|     , _uri(uri) | ||||
|     , _uri(uri.clone()) | ||||
|     , _method(method) | ||||
|     { | ||||
|         int numParams = 0, start = 0; | ||||
|         do { | ||||
|             start = _uri.indexOf("{}", start); | ||||
|             if (start > 0) { | ||||
|                 numParams++; | ||||
|                 start += 2; | ||||
|             } | ||||
|         } while (start > 0); | ||||
|         pathArgs.resize(numParams); | ||||
|         _uri->initPathArgs(pathArgs); | ||||
|     } | ||||
| 
 | ||||
|     ~FunctionRequestHandler() { | ||||
|         delete _uri; | ||||
|     } | ||||
| 
 | ||||
|     bool canHandle(HTTPMethod requestMethod, String requestUri) override  { | ||||
|         if (_method != HTTP_ANY && _method != requestMethod) | ||||
|             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 requestUriIndex >= requestUri.length(); | ||||
|         return _uri->canHandle(requestUri, pathArgs); | ||||
|     } | ||||
| 
 | ||||
|     bool canUpload(String requestUri) override  { | ||||
| @ -92,7 +56,7 @@ public: | ||||
| protected: | ||||
|     WebServer::THandlerFunction _fn; | ||||
|     WebServer::THandlerFunction _ufn; | ||||
|     String _uri; | ||||
|     Uri *_uri; | ||||
|     HTTPMethod _method; | ||||
| }; | ||||
| 
 | ||||
|  | ||||
							
								
								
									
										66
									
								
								libraries/WebServer/src/uri/UriBraces.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										66
									
								
								libraries/WebServer/src/uri/UriBraces.h
									
									
									
									
									
										Normal file
									
								
							| @ -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<String> &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<String> &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 | ||||
							
								
								
									
										22
									
								
								libraries/WebServer/src/uri/UriGlob.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								libraries/WebServer/src/uri/UriGlob.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,22 @@ | ||||
| #ifndef URI_GLOB_H | ||||
| #define URI_GLOB_H | ||||
| 
 | ||||
| #include "Uri.h" | ||||
| #include <fnmatch.h> | ||||
| 
 | ||||
| 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, __attribute__((unused)) std::vector<String> &pathArgs) override final { | ||||
|             return fnmatch(_uri.c_str(), requestUri.c_str(), 0) == 0; | ||||
|         } | ||||
| }; | ||||
| 
 | ||||
| #endif | ||||
							
								
								
									
										44
									
								
								libraries/WebServer/src/uri/UriRegex.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								libraries/WebServer/src/uri/UriRegex.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,44 @@ | ||||
| #ifndef URI_REGEX_H | ||||
| #define URI_REGEX_H | ||||
| 
 | ||||
| #include "Uri.h" | ||||
| #include <regex> | ||||
| 
 | ||||
| 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<String> &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<String> &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 | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user