Chris Mullins %!s(int64=8) %!d(string=hai) anos
pai
achega
c58af7377f
Modificáronse 2 ficheiros con 180 adicións e 0 borrados
  1. 90 0
      lib/WebServer/PatternHandler.cpp
  2. 90 0
      lib/WebServer/PatternHandler.h

+ 90 - 0
lib/WebServer/PatternHandler.cpp

@@ -0,0 +1,90 @@
+#include <PatternHandler.h>
+  
+PatternHandler::PatternHandler(
+    const String& pattern, 
+    const HTTPMethod method, 
+    const PatternHandler::TPatternHandlerFn fn
+  ) : method(method), fn(fn) {
+  Vector<StringToken>* tokenPositions = new Vector<StringToken>();
+  tokenize(pattern, tokenPositions);
+  
+  numPatternTokens = tokenPositions->size();
+  patternTokens = new String[numPatternTokens];
+  
+  for (int i = 0; i < tokenPositions->size(); i++) {
+    patternTokens[i] = (*tokenPositions)[i].extract(pattern);
+  }
+  
+  delete tokenPositions;
+}
+  
+bool PatternHandler::canHandle(HTTPMethod requestMethod, String requestUri) {
+  if (requestMethod != HTTP_ANY && requestMethod != this->method) {
+    return false;
+  }
+  
+  if (tokenPositions) {
+    delete tokenPositions;
+  }
+  
+  bool canHandle = true;
+  
+  tokenPositions = new Vector<StringToken>();
+  tokenize(requestUri, tokenPositions);
+  
+  if (numPatternTokens == tokenPositions->size()) {
+    for (int i = 0; i < numPatternTokens; i++) {
+      const StringToken urlTokenP = (*tokenPositions)[i];
+      
+      if (!patternTokens[i].startsWith(":") 
+        && patternTokens[i] != urlTokenP.extract(requestUri)) {
+        canHandle = false;
+        break;
+      }
+    }
+  }
+  
+  return canHandle;
+}
+  
+bool PatternHandler::handle(ESP8266WebServer& server, HTTPMethod requestMethod, String requestUri) {
+  if (! canHandle(requestMethod, requestUri)) {
+    return false;
+  }
+  
+  Serial.println("Trying to handle.");
+  Serial.println(tokenPositions->size());
+  
+  UrlTokenBindings* bindings = new UrlTokenBindings(patternTokens, tokenPositions, requestUri);
+  
+  Serial.println("Constructed bindings");
+  
+  fn(bindings);
+  
+  Serial.println("Called handler");
+  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++;
+  }
+}

+ 90 - 0
lib/WebServer/PatternHandler.h

@@ -0,0 +1,90 @@
+#ifndef _PATTERNHANDLER_H
+#define _PATTERNHANDLER_H
+
+#include <Arduino.h>
+#include <ESP8266WebServer.h>
+#include <Vector.h>
+#include <functional>
+
+struct StringToken {
+  StringToken(const int start, const int end) 
+    : start(start), end(end) { }
+  
+  int start;
+  int end;
+  
+  const String extract(const String& s) const {
+    return s.substring(start, end);
+  }
+};
+
+class UrlTokenBindings {
+public:
+  
+  UrlTokenBindings(const String* patternTokens, 
+    const Vector<StringToken>* urlTokenPositions,
+    const String& url
+  ) 
+    : patternTokens(patternTokens),
+      numTokens(urlTokenPositions->size()) 
+  {
+    urlTokens = new String[numTokens];
+    for (int i = 0; i < numTokens; i++) {
+      urlTokens[i] = (*urlTokenPositions)[i].extract(url);
+    }
+  }
+  
+  ~UrlTokenBindings() {
+    delete[] urlTokens;
+  }
+  
+  bool hasBinding(const String& key) const {
+    for (int i = 0; i < numTokens; i++) {
+      if (patternTokens[i] == key) {
+        return true;
+      }
+    }
+    
+    return false;
+  }
+  
+  String get(const String& key) const {
+    for (int i = 0; i < numTokens; i++) {
+      if (patternTokens[i].substring(1) == key) {
+        return urlTokens[i];
+      }
+    }
+  }
+  
+private:
+  const String* patternTokens;
+  String* urlTokens;
+  const size_t numTokens;
+};
+
+class PatternHandler : public RequestHandler {
+public:
+  typedef std::function<void(UrlTokenBindings*)> TPatternHandlerFn;
+  
+  PatternHandler(const String& pattern, 
+    const HTTPMethod method, 
+    const TPatternHandlerFn fn);
+  
+  ~PatternHandler() {
+    delete patternTokens;
+  }
+  
+  static void tokenize(const String& path, Vector<StringToken>* tokenPositions);
+  
+  bool canHandle(HTTPMethod requestMethod, String requestUri) override;
+  bool handle(ESP8266WebServer& server, HTTPMethod requesetMethod, String requestUri) override;
+  
+private:
+  size_t numPatternTokens;
+  String* patternTokens;
+  Vector<StringToken>* tokenPositions;
+  const HTTPMethod method;
+  const PatternHandler::TPatternHandlerFn fn;
+};
+
+#endif