|
|
@@ -1,21 +1,59 @@
|
|
|
#include <PatternHandler.h>
|
|
|
|
|
|
-PatternHandler::PatternHandler(
|
|
|
- const String& pattern,
|
|
|
- const HTTPMethod method,
|
|
|
- const PatternHandler::TPatternHandlerFn fn
|
|
|
- ) : method(method), fn(fn), tokenPositions(NULL) {
|
|
|
- Vector<StringToken>* tokenPositions = new Vector<StringToken>();
|
|
|
- tokenize(pattern, tokenPositions);
|
|
|
+UrlTokenBindings::UrlTokenBindings(TokenIterator& patternTokens, TokenIterator& requestTokens)
|
|
|
+ : patternTokens(patternTokens),
|
|
|
+ requestTokens(requestTokens)
|
|
|
+{ }
|
|
|
+
|
|
|
+bool UrlTokenBindings::hasBinding(const String &key) const {
|
|
|
+ const char* searchToken = key.c_str();
|
|
|
+
|
|
|
+ patternTokens.reset();
|
|
|
+ while (patternTokens.hasNext()) {
|
|
|
+ const char* token = patternTokens.nextToken();
|
|
|
+
|
|
|
+ if (strcmp(token, searchToken) == 0) {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
- numPatternTokens = tokenPositions->size();
|
|
|
- patternTokens = new String[numPatternTokens];
|
|
|
+ return false;
|
|
|
+}
|
|
|
+
|
|
|
+const char* UrlTokenBindings::get(const String &key) const {
|
|
|
+ const char* searchToken = key.c_str();
|
|
|
+
|
|
|
+ patternTokens.reset();
|
|
|
+ requestTokens.reset();
|
|
|
+
|
|
|
+ while (patternTokens.hasNext() && requestTokens.hasNext()) {
|
|
|
+ const char* token = patternTokens.nextToken();
|
|
|
+ const char* binding = requestTokens.nextToken();
|
|
|
|
|
|
- for (int i = 0; i < tokenPositions->size(); i++) {
|
|
|
- patternTokens[i] = (*tokenPositions)[i].extract(pattern);
|
|
|
+ if (token[0] == ':' && strcmp(token+1, searchToken) == 0) {
|
|
|
+ return binding;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
- delete tokenPositions;
|
|
|
+ return NULL;
|
|
|
+}
|
|
|
+
|
|
|
+PatternHandler::PatternHandler(
|
|
|
+ const String& pattern,
|
|
|
+ const HTTPMethod method,
|
|
|
+ const PatternHandler::TPatternHandlerFn fn)
|
|
|
+ : method(method),
|
|
|
+ fn(fn),
|
|
|
+ _pattern(new char[pattern.length() + 1]),
|
|
|
+ patternTokens(NULL)
|
|
|
+{
|
|
|
+ strcpy(_pattern, pattern.c_str());
|
|
|
+ patternTokens = new TokenIterator(_pattern, pattern.length(), '/');
|
|
|
+}
|
|
|
+
|
|
|
+PatternHandler::~PatternHandler() {
|
|
|
+ delete _pattern;
|
|
|
+ delete patternTokens;
|
|
|
}
|
|
|
|
|
|
bool PatternHandler::canHandle(HTTPMethod requestMethod, String requestUri) {
|
|
|
@@ -23,27 +61,26 @@ bool PatternHandler::canHandle(HTTPMethod requestMethod, String requestUri) {
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
- if (tokenPositions) {
|
|
|
- delete tokenPositions;
|
|
|
- }
|
|
|
-
|
|
|
bool canHandle = true;
|
|
|
|
|
|
- tokenPositions = new Vector<StringToken>();
|
|
|
- tokenize(requestUri, tokenPositions);
|
|
|
+ char requestUriCopy[requestUri.length() + 1];
|
|
|
+ strcpy(requestUriCopy, requestUri.c_str());
|
|
|
+ TokenIterator requestTokens(requestUriCopy, requestUri.length(), '/');
|
|
|
|
|
|
- if (numPatternTokens == tokenPositions->size()) {
|
|
|
- for (int i = 0; i < numPatternTokens; i++) {
|
|
|
- const StringToken urlTokenP = (*tokenPositions)[i];
|
|
|
+ patternTokens->reset();
|
|
|
+ while (patternTokens->hasNext() && requestTokens.hasNext()) {
|
|
|
+ const char* patternToken = patternTokens->nextToken();
|
|
|
+ const char* requestToken = requestTokens.nextToken();
|
|
|
+
|
|
|
+ if (patternToken[0] != ':' && strcmp(patternToken, requestToken) != 0) {
|
|
|
+ canHandle = false;
|
|
|
+ break;
|
|
|
+ }
|
|
|
|
|
|
- if (!patternTokens[i].startsWith(":")
|
|
|
- && patternTokens[i] != urlTokenP.extract(requestUri)) {
|
|
|
- canHandle = false;
|
|
|
- break;
|
|
|
- }
|
|
|
+ if (patternTokens->hasNext() != requestTokens.hasNext()) {
|
|
|
+ canHandle = false;
|
|
|
+ break;
|
|
|
}
|
|
|
- } else {
|
|
|
- canHandle = false;
|
|
|
}
|
|
|
|
|
|
return canHandle;
|
|
|
@@ -54,32 +91,10 @@ bool PatternHandler::handle(ESP8266WebServer& server, HTTPMethod requestMethod,
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
- UrlTokenBindings* bindings = new UrlTokenBindings(patternTokens, tokenPositions, requestUri);
|
|
|
- fn(bindings);
|
|
|
+ char requestUriCopy[requestUri.length()];
|
|
|
+ strcpy(requestUriCopy, requestUri.c_str());
|
|
|
+ TokenIterator requestTokens(requestUriCopy, requestUri.length(), '/');
|
|
|
|
|
|
- delete bindings;
|
|
|
-}
|
|
|
-
|
|
|
-void PatternHandler::tokenize(const String& path, Vector<StringToken>* tokenPositions) {
|
|
|
- int lastStart = 0;
|
|
|
- int currentPosition = 0;
|
|
|
-
|
|
|
- for (int i = 0; i < path.length(); i++) {
|
|
|
- if (path.charAt(i) == '/' || i == path.length()-1) {
|
|
|
- // If we're in the last position, include the last character if it isn't
|
|
|
- // a '/'
|
|
|
- if (path.charAt(i) != '/') {
|
|
|
- currentPosition++;
|
|
|
- }
|
|
|
-
|
|
|
- if (lastStart > 0 && currentPosition > lastStart) {
|
|
|
- StringToken token(lastStart, currentPosition);
|
|
|
- tokenPositions->push_back(token);
|
|
|
- }
|
|
|
-
|
|
|
- lastStart = i+1;
|
|
|
- }
|
|
|
-
|
|
|
- currentPosition++;
|
|
|
- }
|
|
|
+ UrlTokenBindings bindings(*patternTokens, requestTokens);
|
|
|
+ fn(&bindings);
|
|
|
}
|