Преглед изворни кода

make pattern handlers less dumb

Chris Mullins пре 8 година
родитељ
комит
a096854407
4 измењених фајлова са 13 додато и 149 уклоњено
  1. 4 102
      lib/WebServer/WebServer.cpp
  2. 3 41
      lib/WebServer/WebServer.h
  3. 1 1
      platformio.ini
  4. 5 5
      src/main.cpp

+ 4 - 102
lib/WebServer/WebServer.cpp

@@ -1,104 +1,6 @@
 #include <WebServer.h>
-#include <Vector.h>
+#include <PatternHandler.h>
 
-struct StringToken {
-  StringToken(const int start, const int end) 
-    : start(start), end(end) { }
-  
-  int start;
-  int end;
-  
-  const String extract(const String& s) {
-    return s.substring(start, end);
-  }
-};
-
-Vector<StringToken> 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++;
-  }
-  
-  return tokenPositions;
-}
-
-void WebServer::resetPathMatches() {
-  delete buffer;
-  buffer = new DynamicJsonBuffer();
-  pathMatches = &buffer->createObject();
-}
-
-bool WebServer::matchesPattern(const String& pattern, const String& url) {
-  Vector<StringToken> patternTokens = tokenize(pattern);
-  Vector<StringToken> urlTokens = tokenize(url);
-  
-  for (int i = 0; i < patternTokens.size(); i++) {
-    String a = patternTokens[i].extract(pattern);
-    String b = urlTokens.size() <= i ? "" : urlTokens[i].extract(url);
-  }
-  
-  if (patternTokens.size() != urlTokens.size()) {
-    return false;
-  }
-  
-  for (int i = 0; i < patternTokens.size(); i++) {
-    const String& pT = patternTokens[i].extract(pattern);
-    const String& uT = urlTokens[i].extract(url);
-    
-    if (!pT.startsWith(":") && pT != uT) {
-      return false;
-    }
-  }
-  
-  resetPathMatches();
-  
-  for (int i = 0; i < patternTokens.size(); i++) {
-    // Trim off leading ':'
-    const String& pT = patternTokens[i].extract(pattern).substring(1);
-    const String& uT = urlTokens[i].extract(url);
-    
-    (*pathMatches)[pT] = uT;
-  }
-  
-  return true;
-}
-
-void WebServer::checkPatterns() {
-  for (int i = 0; i < handlers.size(); i++) {
-    const PatternHandler* handler = handlers[i];
-    
-    if (method() == handler->method 
-      && matchesPattern(handler->pattern, uri())) {
-      handler->fn();
-      return;
-    }
-  }
-  
-  if (notFoundHandler) {
-    notFoundHandler();
-  } else {
-    send(404, "text/plain", String("Not found: ") + _currentUri);
-  }
-}
-
-void WebServer::onPattern(const String& pattern, const HTTPMethod method, const THandlerFunction fn) {
-  handlers.push_back(new PatternHandler(pattern, method, fn));
-}
+void WebServer::onPattern(const String& pattern, const HTTPMethod method, PatternHandler::TPatternHandlerFn fn) {
+  addHandler(new PatternHandler(pattern, method, fn));
+}

+ 3 - 41
lib/WebServer/WebServer.h

@@ -4,61 +4,23 @@
 #include <Arduino.h>
 #include <ArduinoJson.h>
 #include <ESP8266WebServer.h>
-#include <Vector.h>
-
-struct PatternHandler {
-  PatternHandler(const String& pattern, const HTTPMethod method, const ESP8266WebServer::THandlerFunction fn)
-    : pattern(pattern),
-      method(method),
-      fn(fn)
-    { }
-    
-  const String pattern;
-  const HTTPMethod method;
-  const ESP8266WebServer::THandlerFunction fn;
-};
+#include <PatternHandler.h>
 
 class WebServer : public ESP8266WebServer {
 public:
-  WebServer(int port) : 
-    ESP8266WebServer(port) { 
-    
-    ESP8266WebServer::onNotFound([&]() { checkPatterns(); });
-  }
-  
-  ~WebServer() {
-    delete buffer;
-  }
+  WebServer(int port) : ESP8266WebServer(port) { }
   
   bool matchesPattern(const String& pattern, const String& url);
-  void onPattern(const String& pattern, const HTTPMethod method, const THandlerFunction fn);
-  
-  String arg(String key) {
-    if (pathMatches && pathMatches->containsKey(key)) {
-      return pathMatches->get<String>(key);
-    }
-    
-    return ESP8266WebServer::arg(key);
-  }
+  void onPattern(const String& pattern, const HTTPMethod method, PatternHandler::TPatternHandlerFn fn);
   
   inline bool clientConnected() { 
     return _currentClient && _currentClient.connected();
   }
   
-  inline void onNotFound(THandlerFunction fn) {
-    notFoundHandler = fn;
-  }
-  
 private:
   
   void resetPathMatches();
   void checkPatterns();
-  
-  DynamicJsonBuffer* buffer;
-  JsonObject* pathMatches;
-  Vector<PatternHandler*> handlers;
-  THandlerFunction notFoundHandler;
-
 };
 
 #endif

+ 1 - 1
platformio.ini

@@ -17,4 +17,4 @@ lib_deps =
   SPI
   WiFiManager
   ArduinoJson
-  http://github.com/zacsketches/Arduino_Vector.git
+  Vector

+ 5 - 5
src/main.cpp

@@ -26,11 +26,11 @@ WiFiManager wifiManager;
 WebServer server(80);
 File updateFile;
 
-void handleUpdateGateway() {
+void handleUpdateGateway(const UrlTokenBindings* urlBindings) {
   DynamicJsonBuffer buffer;
   JsonObject& request = buffer.parse(server.arg("plain"));
   
-  const uint16_t deviceId = parseInt<uint16_t>(server.arg("device_id"));
+  const uint16_t deviceId = parseInt<uint16_t>(urlBindings->get("device_id"));
   
   if (request.containsKey("status")) {
     if (request["status"] == "on") {
@@ -43,12 +43,12 @@ void handleUpdateGateway() {
   server.send(200, "application/json", "true");
 }
 
-void handleUpdateGroup() {
+void handleUpdateGroup(const UrlTokenBindings* urlBindings) {
   DynamicJsonBuffer buffer;
   JsonObject& request = buffer.parse(server.arg("plain"));
   
-  const uint16_t deviceId = parseInt<uint16_t>(server.arg("device_id"));
-  const uint8_t groupId = server.arg("group_id").toInt();
+  const uint16_t deviceId = parseInt<uint16_t>(urlBindings->get("device_id"));
+  const uint8_t groupId = urlBindings->get("group_id").toInt();
   
   if (request.containsKey("status")) {
     const String& statusStr = request.get<String>("status");