diff --git a/libraries/ESP8266WebServer/src/ESP8266WebServer.cpp b/libraries/ESP8266WebServer/src/ESP8266WebServer.cpp index 04bda3152..de128d48e 100644 --- a/libraries/ESP8266WebServer/src/ESP8266WebServer.cpp +++ b/libraries/ESP8266WebServer/src/ESP8266WebServer.cpp @@ -33,6 +33,7 @@ ESP8266WebServer::ESP8266WebServer(IPAddress addr, int port) : _server(addr, port) +, _currentHandler(0) , _firstHandler(0) , _lastHandler(0) , _currentArgCount(0) @@ -44,6 +45,7 @@ ESP8266WebServer::ESP8266WebServer(IPAddress addr, int port) ESP8266WebServer::ESP8266WebServer(int port) : _server(port) +, _currentHandler(0) , _firstHandler(0) , _lastHandler(0) , _currentArgCount(0) @@ -74,7 +76,11 @@ void ESP8266WebServer::on(const char* uri, ESP8266WebServer::THandlerFunction ha } void ESP8266WebServer::on(const char* uri, HTTPMethod method, ESP8266WebServer::THandlerFunction fn) { - _addRequestHandler(new FunctionRequestHandler(fn, uri, method)); + on(uri, method, fn, _fileUploadHandler); +} + +void ESP8266WebServer::on(const char* uri, HTTPMethod method, ESP8266WebServer::THandlerFunction fn, ESP8266WebServer::THandlerFunction ufn) { + _addRequestHandler(new FunctionRequestHandler(fn, ufn, uri, method)); } void ESP8266WebServer::addHandler(RequestHandler* handler) { @@ -352,13 +358,7 @@ void ESP8266WebServer::onNotFound(THandlerFunction fn) { } void ESP8266WebServer::_handleRequest() { - RequestHandler* handler; - for (handler = _firstHandler; handler; handler = handler->next()) { - if (handler->handle(*this, _currentMethod, _currentUri)) - break; - } - - if (!handler){ + if (!_currentHandler){ #ifdef DEBUG DEBUG_OUTPUT.println("request handler not found"); #endif @@ -369,6 +369,8 @@ void ESP8266WebServer::_handleRequest() { else { send(404, "text/plain", String("Not found: ") + _currentUri); } + } else { + _currentHandler->handle(*this, _currentMethod, _currentUri); } uint16_t maxWait = HTTP_MAX_CLOSE_WAIT; diff --git a/libraries/ESP8266WebServer/src/ESP8266WebServer.h b/libraries/ESP8266WebServer/src/ESP8266WebServer.h index 65e44378f..16c9ae5a5 100644 --- a/libraries/ESP8266WebServer/src/ESP8266WebServer.h +++ b/libraries/ESP8266WebServer/src/ESP8266WebServer.h @@ -40,12 +40,6 @@ enum HTTPUploadStatus { UPLOAD_FILE_START, UPLOAD_FILE_WRITE, UPLOAD_FILE_END, class ESP8266WebServer; -#include "detail/RequestHandler.h" - -namespace fs { -class FS; -} - typedef struct { HTTPUploadStatus status; String filename; @@ -56,6 +50,12 @@ typedef struct { uint8_t buf[HTTP_UPLOAD_BUFLEN]; } HTTPUpload; +#include "detail/RequestHandler.h" + +namespace fs { +class FS; +} + class ESP8266WebServer { public: @@ -69,6 +69,7 @@ public: typedef std::function THandlerFunction; void on(const char* uri, THandlerFunction handler); void on(const char* uri, HTTPMethod method, THandlerFunction fn); + void on(const char* 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 @@ -155,6 +156,7 @@ protected: String _hostHeader; + RequestHandler* _currentHandler; RequestHandler* _firstHandler; RequestHandler* _lastHandler; THandlerFunction _notFoundHandler; diff --git a/libraries/ESP8266WebServer/src/Parsing.cpp b/libraries/ESP8266WebServer/src/Parsing.cpp index 0458a9980..318b0f547 100644 --- a/libraries/ESP8266WebServer/src/Parsing.cpp +++ b/libraries/ESP8266WebServer/src/Parsing.cpp @@ -81,6 +81,14 @@ bool ESP8266WebServer::_parseRequest(WiFiClient& client) { DEBUG_OUTPUT.println(searchStr); #endif + //attach handler + RequestHandler* handler; + for (handler = _firstHandler; handler; handler = handler->next()) { + if (handler->canHandle(_currentMethod, _currentUri)) + break; + } + _currentHandler = handler; + String formData; // below is needed only when POST type request if (method == HTTP_POST || method == HTTP_PUT || method == HTTP_PATCH || method == HTTP_DELETE){ @@ -279,7 +287,8 @@ void ESP8266WebServer::_parseArguments(String data) { void ESP8266WebServer::_uploadWriteByte(uint8_t b){ if (_currentUpload.currentSize == HTTP_UPLOAD_BUFLEN){ - if (_fileUploadHandler) _fileUploadHandler(); + if(_currentHandler && _currentHandler->canUpload(_currentUri)) + _currentHandler->upload(*this, _currentUri, _currentUpload); _currentUpload.totalSize += _currentUpload.currentSize; _currentUpload.currentSize = 0; } @@ -397,7 +406,8 @@ bool ESP8266WebServer::_parseForm(WiFiClient& client, String boundary, uint32_t DEBUG_OUTPUT.print(" Type: "); DEBUG_OUTPUT.println(_currentUpload.type); #endif - if (_fileUploadHandler) _fileUploadHandler(); + if(_currentHandler && _currentHandler->canUpload(_currentUri)) + _currentHandler->upload(*this, _currentUri, _currentUpload); _currentUpload.status = UPLOAD_FILE_WRITE; uint8_t argByte = _uploadReadByte(client); readfile: @@ -433,10 +443,12 @@ readfile: client.readBytes(endBuf, boundary.length()); if (strstr((const char*)endBuf, boundary.c_str()) != NULL){ - if (_fileUploadHandler) _fileUploadHandler(); + if(_currentHandler && _currentHandler->canUpload(_currentUri)) + _currentHandler->upload(*this, _currentUri, _currentUpload); _currentUpload.totalSize += _currentUpload.currentSize; _currentUpload.status = UPLOAD_FILE_END; - if (_fileUploadHandler) _fileUploadHandler(); + if(_currentHandler && _currentHandler->canUpload(_currentUri)) + _currentHandler->upload(*this, _currentUri, _currentUpload); #ifdef DEBUG DEBUG_OUTPUT.print("End File: "); DEBUG_OUTPUT.print(_currentUpload.filename); @@ -503,6 +515,7 @@ readfile: bool ESP8266WebServer::_parseFormUploadAborted(){ _currentUpload.status = UPLOAD_FILE_ABORTED; - if (_fileUploadHandler) _fileUploadHandler(); + if(_currentHandler && _currentHandler->canUpload(_currentUri)) + _currentHandler->upload(*this, _currentUri, _currentUpload); return false; } diff --git a/libraries/ESP8266WebServer/src/detail/RequestHandler.h b/libraries/ESP8266WebServer/src/detail/RequestHandler.h index dd3d15733..5a998bfbd 100644 --- a/libraries/ESP8266WebServer/src/detail/RequestHandler.h +++ b/libraries/ESP8266WebServer/src/detail/RequestHandler.h @@ -3,7 +3,10 @@ class RequestHandler { public: + virtual bool canHandle(HTTPMethod method, String uri) { return false; } + virtual bool canUpload(String uri) { return false; } virtual bool handle(ESP8266WebServer& server, HTTPMethod requestMethod, String requestUri) { return false; } + virtual void upload(ESP8266WebServer& server, String requestUri, HTTPUpload& upload) {} RequestHandler* next() { return _next; } void next(RequestHandler* r) { _next = r; } diff --git a/libraries/ESP8266WebServer/src/detail/RequestHandlersImpl.h b/libraries/ESP8266WebServer/src/detail/RequestHandlersImpl.h index accddee21..9ce8441e1 100644 --- a/libraries/ESP8266WebServer/src/detail/RequestHandlersImpl.h +++ b/libraries/ESP8266WebServer/src/detail/RequestHandlersImpl.h @@ -5,28 +5,49 @@ class FunctionRequestHandler : public RequestHandler { public: - FunctionRequestHandler(ESP8266WebServer::THandlerFunction fn, const char* uri, HTTPMethod method) + FunctionRequestHandler(ESP8266WebServer::THandlerFunction fn, ESP8266WebServer::THandlerFunction ufn, const char* uri, HTTPMethod method) : _fn(fn) + , _ufn(ufn) , _uri(uri) , _method(method) { } - bool handle(ESP8266WebServer& server, HTTPMethod requestMethod, String requestUri) override { + bool canHandle(HTTPMethod requestMethod, String requestUri) override { if (_method != HTTP_ANY && _method != requestMethod) return false; if (requestUri != _uri) return false; + return true; + } + + bool canUpload(String requestUri) override { + if (!_ufn || !canHandle(HTTP_POST, requestUri)) + return false; + + return true; + } + + bool handle(ESP8266WebServer& server, HTTPMethod requestMethod, String requestUri) override { + if (!canHandle(requestMethod, requestUri)) + return false; + _fn(); return true; } + void upload(ESP8266WebServer& server, String requestUri, HTTPUpload& upload) override { + if (canUpload(requestUri)) + _ufn(); + } + protected: String _uri; HTTPMethod _method; ESP8266WebServer::THandlerFunction _fn; + ESP8266WebServer::THandlerFunction _ufn; }; class StaticRequestHandler : public RequestHandler { @@ -41,13 +62,26 @@ public: DEBUGV("StaticRequestHandler: path=%s uri=%s isFile=%d, cache_header=%s\r\n", path, uri, _isFile, cache_header); _baseUriLength = _uri.length(); } - bool handle(ESP8266WebServer& server, HTTPMethod requestMethod, String requestUri) override { + + bool canHandle(HTTPMethod requestMethod, String requestUri) override { if (requestMethod != HTTP_GET) return false; - DEBUGV("StaticRequestHandler::handle: request=%s _uri=%s\r\n", requestUri.c_str(), _uri.c_str()); + if (!requestUri.startsWith(_uri)) return false; + if (requestUri != _uri) + return false; + + return true; + } + + bool handle(ESP8266WebServer& server, HTTPMethod requestMethod, String requestUri) override { + if (!canHandle(requestMethod, requestUri)) + return false; + + DEBUGV("StaticRequestHandler::handle: request=%s _uri=%s\r\n", requestUri.c_str(), _uri.c_str()); + String path(_path); if(path.endsWith("/")) path += "index.htm"; @@ -57,11 +91,6 @@ public: // URI in request to get the file path. path += requestUri.substring(_baseUriLength); } - - else if (requestUri != _uri) { - // Base URI points to a file but request doesn't match this URI exactly - return false; - } DEBUGV("StaticRequestHandler::handle: path=%s, isFile=%d\r\n", path.c_str(), _isFile); String contentType = getContentType(path);