diff --git a/libraries/ESP8266WebServer/keywords.txt b/libraries/ESP8266WebServer/keywords.txt index 6eee0f193..22e3d74e4 100644 --- a/libraries/ESP8266WebServer/keywords.txt +++ b/libraries/ESP8266WebServer/keywords.txt @@ -16,6 +16,7 @@ HTTPMethod KEYWORD1 begin KEYWORD2 handleClient KEYWORD2 on KEYWORD2 +addHandler KEYWORD2 uri KEYWORD2 method KEYWORD2 client KEYWORD2 diff --git a/libraries/ESP8266WebServer/src/ESP8266WebServer.cpp b/libraries/ESP8266WebServer/src/ESP8266WebServer.cpp index 5af09c38d..f0ab929f3 100644 --- a/libraries/ESP8266WebServer/src/ESP8266WebServer.cpp +++ b/libraries/ESP8266WebServer/src/ESP8266WebServer.cpp @@ -26,7 +26,7 @@ #include "WiFiClient.h" #include "ESP8266WebServer.h" #include "FS.h" -#include "detail/RequestHandler.h" +#include "detail/RequestHandlersImpl.h" // #define DEBUG #define DEBUG_OUTPUT Serial @@ -45,7 +45,7 @@ ESP8266WebServer::~ESP8266WebServer() { return; RequestHandler* handler = _firstHandler; while (handler) { - RequestHandler* next = handler->next; + RequestHandler* next = handler->next(); delete handler; handler = next; } @@ -63,13 +63,17 @@ void ESP8266WebServer::on(const char* uri, HTTPMethod method, ESP8266WebServer:: _addRequestHandler(new FunctionRequestHandler(fn, uri, method)); } +void ESP8266WebServer::addHandler(RequestHandler* handler) { + _addRequestHandler(handler); +} + void ESP8266WebServer::_addRequestHandler(RequestHandler* handler) { if (!_lastHandler) { _firstHandler = handler; _lastHandler = handler; } else { - _lastHandler->next = handler; + _lastHandler->next(handler); _lastHandler = handler; } } @@ -293,7 +297,7 @@ void ESP8266WebServer::onNotFound(THandlerFunction fn) { void ESP8266WebServer::_handleRequest() { RequestHandler* handler; - for (handler = _firstHandler; handler; handler = handler->next) { + for (handler = _firstHandler; handler; handler = handler->next()) { if (handler->handle(*this, _currentMethod, _currentUri)) break; } diff --git a/libraries/ESP8266WebServer/src/ESP8266WebServer.h b/libraries/ESP8266WebServer/src/ESP8266WebServer.h index 35f0bf863..8a640a935 100644 --- a/libraries/ESP8266WebServer/src/ESP8266WebServer.h +++ b/libraries/ESP8266WebServer/src/ESP8266WebServer.h @@ -38,7 +38,9 @@ enum HTTPUploadStatus { UPLOAD_FILE_START, UPLOAD_FILE_WRITE, UPLOAD_FILE_END, #define CONTENT_LENGTH_UNKNOWN ((size_t) -1) #define CONTENT_LENGTH_NOT_SET ((size_t) -2) -class RequestHandler; +class ESP8266WebServer; + +#include "detail/RequestHandler.h" namespace fs { class FS; @@ -66,6 +68,7 @@ public: typedef std::function THandlerFunction; void on(const char* uri, THandlerFunction handler); void on(const char* uri, HTTPMethod method, THandlerFunction fn); + void addHandler(RequestHandler* handler); void serveStatic(const char* uri, fs::FS& fs, const char* path); void onNotFound(THandlerFunction fn); //called when handler is not assigned void onFileUpload(THandlerFunction fn); //handle file uploads diff --git a/libraries/ESP8266WebServer/src/detail/RequestHandler.h b/libraries/ESP8266WebServer/src/detail/RequestHandler.h index 8cb4e61e1..dd3d15733 100644 --- a/libraries/ESP8266WebServer/src/detail/RequestHandler.h +++ b/libraries/ESP8266WebServer/src/detail/RequestHandler.h @@ -3,109 +3,13 @@ class RequestHandler { public: - RequestHandler(const char* uri, HTTPMethod method) - : _uri(uri) - , _method(method) - , next(NULL) - { - } + virtual bool handle(ESP8266WebServer& server, HTTPMethod requestMethod, String requestUri) { return false; } - virtual bool handle(ESP8266WebServer& server, HTTPMethod requestMethod, String requestUri) = 0; + RequestHandler* next() { return _next; } + void next(RequestHandler* r) { _next = r; } - RequestHandler* next; - -protected: - String _uri; - HTTPMethod _method; -}; - - -class FunctionRequestHandler : public RequestHandler { - typedef RequestHandler base; - -public: - FunctionRequestHandler(ESP8266WebServer::THandlerFunction fn, const char* uri, HTTPMethod method) - : _fn(fn) - , base(uri, method) - { - } - - bool handle(ESP8266WebServer& server, HTTPMethod requestMethod, String requestUri) override { - if (_method != HTTP_ANY && _method != requestMethod) - return false; - - if (requestUri != _uri) - return false; - - _fn(); - return true; - } - -protected: - ESP8266WebServer::THandlerFunction _fn; -}; - -class StaticRequestHandler : public RequestHandler { - typedef RequestHandler base; - -public: - StaticRequestHandler(FS& fs, const char* path, const char* uri) - : _fs(fs) - , base(uri, HTTP_GET) - , _path(path) - { - _isFile = fs.exists(path); - DEBUGV("StaticRequestHandler: path=%s uri=%s isFile=%d\r\n", path, uri, _isFile); - _baseUriLength = _uri.length(); - } - - bool handle(ESP8266WebServer& server, HTTPMethod requestMethod, String requestUri) override { - if (requestMethod != _method) - return false; - DEBUGV("StaticRequestHandler::handle: request=%s _uri=%s\r\n", requestUri.c_str(), _uri.c_str()); - if (!requestUri.startsWith(_uri)) - return false; - - String path(_path); - if (!_isFile) { - // Base URI doesn't point to a file. Append whatever follows this - // 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); - File f = _fs.open(path, "r"); - if (!f) - return false; - - server.streamFile(f, getContentType(path)); - return true; - } - - static String getContentType(const String& path) { - if (path.endsWith(".html")) return "text/html"; - else if (path.endsWith(".htm")) return "text/html"; - else if (path.endsWith(".css")) return "text/css"; - else if (path.endsWith(".txt")) return "text/plain"; - else if (path.endsWith(".js")) return "application/javascript"; - else if (path.endsWith(".png")) return "image/png"; - else if (path.endsWith(".gif")) return "image/gif"; - else if (path.endsWith(".jpg")) return "image/jpeg"; - else if (path.endsWith(".ico")) return "image/x-icon"; - else if (path.endsWith(".xml")) return "text/xml"; - else if (path.endsWith(".pdf")) return "application/pdf"; - else if (path.endsWith(".zip")) return "application/zip"; - return "text/plain"; - } - -protected: - FS _fs; - String _path; - bool _isFile; - size_t _baseUriLength; +private: + RequestHandler* _next = nullptr; }; #endif //REQUESTHANDLER_H diff --git a/libraries/ESP8266WebServer/src/detail/RequestHandlersImpl.h b/libraries/ESP8266WebServer/src/detail/RequestHandlersImpl.h new file mode 100644 index 000000000..7d6ab3f9e --- /dev/null +++ b/libraries/ESP8266WebServer/src/detail/RequestHandlersImpl.h @@ -0,0 +1,95 @@ +#ifndef REQUESTHANDLERSIMPL_H +#define REQUESTHANDLERSIMPL_H + +#include "RequestHandler.h" + +class FunctionRequestHandler : public RequestHandler { +public: + FunctionRequestHandler(ESP8266WebServer::THandlerFunction fn, const char* uri, HTTPMethod method) + : _fn(fn) + , _uri(uri) + , _method(method) + { + } + + bool handle(ESP8266WebServer& server, HTTPMethod requestMethod, String requestUri) override { + if (_method != HTTP_ANY && _method != requestMethod) + return false; + + if (requestUri != _uri) + return false; + + _fn(); + return true; + } + +protected: + String _uri; + HTTPMethod _method; + ESP8266WebServer::THandlerFunction _fn; +}; + +class StaticRequestHandler : public RequestHandler { +public: + StaticRequestHandler(FS& fs, const char* path, const char* uri) + : _fs(fs) + , _uri(uri) + , _path(path) + { + _isFile = fs.exists(path); + DEBUGV("StaticRequestHandler: path=%s uri=%s isFile=%d\r\n", path, uri, _isFile); + _baseUriLength = _uri.length(); + } + + bool handle(ESP8266WebServer& server, 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; + + String path(_path); + if (!_isFile) { + // Base URI doesn't point to a file. Append whatever follows this + // 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); + File f = _fs.open(path, "r"); + if (!f) + return false; + + server.streamFile(f, getContentType(path)); + return true; + } + + static String getContentType(const String& path) { + if (path.endsWith(".html")) return "text/html"; + else if (path.endsWith(".htm")) return "text/html"; + else if (path.endsWith(".css")) return "text/css"; + else if (path.endsWith(".txt")) return "text/plain"; + else if (path.endsWith(".js")) return "application/javascript"; + else if (path.endsWith(".png")) return "image/png"; + else if (path.endsWith(".gif")) return "image/gif"; + else if (path.endsWith(".jpg")) return "image/jpeg"; + else if (path.endsWith(".ico")) return "image/x-icon"; + else if (path.endsWith(".xml")) return "text/xml"; + else if (path.endsWith(".pdf")) return "application/pdf"; + else if (path.endsWith(".zip")) return "application/zip"; + return "text/plain"; + } + +protected: + FS _fs; + String _uri; + String _path; + bool _isFile; + size_t _baseUriLength; +}; + + +#endif //REQUESTHANDLERSIMPL_H