diff --git a/libraries/ESP8266WebServer/README.rst b/libraries/ESP8266WebServer/README.rst
index 94bb6c5865..c37c6d5e64 100644
--- a/libraries/ESP8266WebServer/README.rst
+++ b/libraries/ESP8266WebServer/README.rst
@@ -54,8 +54,10 @@ Client request handlers
 
 .. code:: cpp
 
-  void on();
+  RequestHandler<ServerType>& on();
+  bool removeRoute();
   void addHandler();
+  bool removeHandler();
   void onNotFound();
   void onFileUpload();	
 
@@ -64,9 +66,26 @@ Client request handlers
 .. code:: cpp
 
   server.on("/", handlerFunction);
+  server.removeRoute("/"); // Removes any route which points to "/" and has HTTP_ANY attribute
+  server.removeRoute("/", HTTP_GET); // Removes any route which points to "/" and has HTTP_GET attribute
   server.onNotFound(handlerFunction); // called when handler is not assigned
   server.onFileUpload(handlerFunction); // handle file uploads
 
+Client request filters
+^^^^^^^^^^^^^^^^^^^^^^
+
+.. code:: cpp
+  
+  RequestHandler<ServerType>& setFilter();
+
+*Example:*
+
+More details about this in `Filters.ino` example.
+
+.. code:: cpp
+
+  server.on("/", handlerFunction).setFilter(ON_AP_FILTER)
+
 Sending responses to the client
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
diff --git a/libraries/ESP8266WebServer/examples/Filters/Filters.ino b/libraries/ESP8266WebServer/examples/Filters/Filters.ino
new file mode 100644
index 0000000000..24c26fc276
--- /dev/null
+++ b/libraries/ESP8266WebServer/examples/Filters/Filters.ino
@@ -0,0 +1,101 @@
+#include <ESP8266WiFi.h>
+#include <WiFiClient.h>
+#include <ESP8266WebServer.h>
+#include <ESP8266mDNS.h>
+
+// Your STA WiFi Credentials
+// ( This is the AP your ESP will connect to )
+const char *ssid = "...";
+const char *password = "...";
+
+// Your AP WiFi Credentials
+// ( This is the AP your ESP will broadcast )
+const char *ap_ssid = "ESP8266_Demo";
+const char *ap_password = "";
+
+ESP8266WebServer server(80);
+
+const int led = 13;
+
+// ON_STA_FILTER - Only accept requests coming from STA interface
+bool ON_STA_FILTER(ESP8266WebServer &server) {
+  return WiFi.localIP() == server.client().localIP();
+}
+
+// ON_AP_FILTER - Only accept requests coming from AP interface
+bool ON_AP_FILTER(ESP8266WebServer &server) {
+  return WiFi.softAPIP() == server.client().localIP();
+}
+
+void handleNotFound() {
+  digitalWrite(led, 1);
+  String message = "File Not Found\n\n";
+  message += "URI: ";
+  message += server.uri();
+  message += "\nMethod: ";
+  message += (server.method() == HTTP_GET) ? "GET" : "POST";
+  message += "\nArguments: ";
+  message += server.args();
+  message += "\n";
+  for (uint8_t i = 0; i < server.args(); i++) {
+    message += " " + server.argName(i) + ": " + server.arg(i) + "\n";
+  }
+  server.send(404, "text/plain", message);
+  digitalWrite(led, 0);
+}
+
+void setup(void) {
+  pinMode(led, OUTPUT);
+  digitalWrite(led, 0);
+  Serial.begin(115200);
+  WiFi.mode(WIFI_AP_STA);
+  // Connect to STA
+  WiFi.begin(ssid, password);
+  // Start AP
+  WiFi.softAP(ap_ssid, ap_password);
+  Serial.println("");
+
+  // Wait for connection
+  while (WiFi.status() != WL_CONNECTED) {
+    delay(500);
+    Serial.print(".");
+  }
+  Serial.println("");
+  Serial.print("Connected to ");
+  Serial.println(ssid);
+  Serial.print("IP address: ");
+  Serial.println(WiFi.localIP());
+
+  if (MDNS.begin("esp8266")) {
+    Serial.println("MDNS responder started");
+  }
+
+  // This route will be accessible by STA clients only
+  server.on("/", [&]() {
+          digitalWrite(led, 1);
+          server.send(200, "text/plain", "Hi!, This route is accessible for STA clients only");
+          digitalWrite(led, 0);
+        })
+    .setFilter(ON_STA_FILTER);
+
+  // This route will be accessible by AP clients only
+  server.on("/", [&]() {
+          digitalWrite(led, 1);
+          server.send(200, "text/plain", "Hi!, This route is accessible for AP clients only");
+          digitalWrite(led, 0);
+        })
+    .setFilter(ON_AP_FILTER);
+
+  server.on("/inline", []() {
+    server.send(200, "text/plain", "this works as well");
+  });
+
+  server.onNotFound(handleNotFound);
+
+  server.begin();
+  Serial.println("HTTP server started");
+}
+
+void loop(void) {
+  server.handleClient();
+}
diff --git a/libraries/ESP8266WebServer/src/ESP8266WebServer-impl.h b/libraries/ESP8266WebServer/src/ESP8266WebServer-impl.h
index f7a95da0af..dbcb251135 100644
--- a/libraries/ESP8266WebServer/src/ESP8266WebServer-impl.h
+++ b/libraries/ESP8266WebServer/src/ESP8266WebServer-impl.h
@@ -230,18 +230,61 @@ void ESP8266WebServerTemplate<ServerType>::requestAuthentication(HTTPAuthMethod
 }
 
 template <typename ServerType>
-void ESP8266WebServerTemplate<ServerType>::on(const Uri &uri, ESP8266WebServerTemplate<ServerType>::THandlerFunction handler) {
-  on(uri, HTTP_ANY, handler);
+RequestHandler<ServerType>& ESP8266WebServerTemplate<ServerType>::on(const Uri &uri, ESP8266WebServerTemplate<ServerType>::THandlerFunction handler) {
+  return on(uri, HTTP_ANY, handler);
 }
 
 template <typename ServerType>
-void ESP8266WebServerTemplate<ServerType>::on(const Uri &uri, HTTPMethod method, ESP8266WebServerTemplate<ServerType>::THandlerFunction fn) {
-  on(uri, method, fn, _fileUploadHandler);
+RequestHandler<ServerType>& ESP8266WebServerTemplate<ServerType>::on(const Uri &uri, HTTPMethod method, ESP8266WebServerTemplate<ServerType>::THandlerFunction fn) {
+  return on(uri, method, fn, _fileUploadHandler);
 }
 
 template <typename ServerType>
-void ESP8266WebServerTemplate<ServerType>::on(const Uri &uri, HTTPMethod method, ESP8266WebServerTemplate<ServerType>::THandlerFunction fn, ESP8266WebServerTemplate<ServerType>::THandlerFunction ufn) {
-  _addRequestHandler(new FunctionRequestHandler<ServerType>(fn, ufn, uri, method));
+RequestHandler<ServerType>& ESP8266WebServerTemplate<ServerType>::on(const Uri &uri, HTTPMethod method, ESP8266WebServerTemplate<ServerType>::THandlerFunction fn, ESP8266WebServerTemplate<ServerType>::THandlerFunction ufn) {
+  RequestHandler<ServerType> *handler = new FunctionRequestHandler<ServerType>(fn, ufn, uri, method);
+  _addRequestHandler(handler);
+  return *handler;
+}
+
+template <typename ServerType>
+bool ESP8266WebServerTemplate<ServerType>::removeRoute(const char *uri) {
+  return removeRoute(String(uri), HTTP_ANY);
+}
+
+template <typename ServerType>
+bool ESP8266WebServerTemplate<ServerType>::removeRoute(const char *uri, HTTPMethod method) {
+  return removeRoute(String(uri), method);
+}
+
+template <typename ServerType>
+bool ESP8266WebServerTemplate<ServerType>::removeRoute(const String &uri) {
+  return removeRoute(uri, HTTP_ANY);
+}
+
+template <typename ServerType>
+bool ESP8266WebServerTemplate<ServerType>::removeRoute(const String &uri, HTTPMethod method) {
+  bool anyHandlerRemoved = false;
+  RequestHandlerType *handler = _firstHandler;
+  RequestHandlerType *previousHandler = nullptr;
+
+  while (handler) {
+    if (handler->canHandle(method, uri)) {
+      if (_removeRequestHandler(handler)) {
+        anyHandlerRemoved = true;
+        // Move to the next handler
+        if (previousHandler) {
+          handler = previousHandler->next();
+        } else {
+          handler = _firstHandler;
+        }
+        continue;
+      }
+    }
+    previousHandler = handler;
+    handler = handler->next();
+  }
+
+  return anyHandlerRemoved;
 }
 
 template <typename ServerType>
@@ -249,6 +292,11 @@ void ESP8266WebServerTemplate<ServerType>::addHandler(RequestHandlerType* handle
     _addRequestHandler(handler);
 }
 
+template <typename ServerType>
+bool ESP8266WebServerTemplate<ServerType>::removeHandler(RequestHandlerType *handler) {
+  return _removeRequestHandler(handler);
+}
+
 template <typename ServerType>
 void ESP8266WebServerTemplate<ServerType>::_addRequestHandler(RequestHandlerType* handler) {
     if (!_lastHandler) {
@@ -261,6 +309,33 @@ void ESP8266WebServerTemplate<ServerType>::_addRequestHandler(RequestHandlerType
     }
 }
 
+template <typename ServerType>
+bool ESP8266WebServerTemplate<ServerType>::_removeRequestHandler(RequestHandlerType *handler) {
+  RequestHandlerType *current = _firstHandler;
+  RequestHandlerType *previous = nullptr;
+
+  while (current != nullptr) {
+    if (current == handler) {
+      if (previous == nullptr) {
+        _firstHandler = current->next();
+      } else {
+        previous->next(current->next());
+      }
+
+      if (current == _lastHandler) {
+        _lastHandler = previous;
+      }
+
+      // Delete 'matching' handler
+      delete current;
+      return true;
+    }
+    previous = current;
+    current = current->next();
+  }
+  return false;
+}
+
 template <typename ServerType>
 void ESP8266WebServerTemplate<ServerType>::serveStatic(const char* uri, FS& fs, const char* path, const char* cache_header) {
   bool is_file = false;
diff --git a/libraries/ESP8266WebServer/src/ESP8266WebServer.h b/libraries/ESP8266WebServer/src/ESP8266WebServer.h
index 9f2b8b19c3..f9eca1c8bc 100644
--- a/libraries/ESP8266WebServer/src/ESP8266WebServer.h
+++ b/libraries/ESP8266WebServer/src/ESP8266WebServer.h
@@ -116,11 +116,17 @@ class ESP8266WebServerTemplate
 
   typedef std::function<void(void)> THandlerFunction;
   typedef std::function<String(FS &fs, const String &fName)> ETagFunction;
-
-  void on(const Uri &uri, THandlerFunction handler);
-  void on(const Uri &uri, HTTPMethod method, THandlerFunction fn);
-  void on(const Uri &uri, HTTPMethod method, THandlerFunction fn, THandlerFunction ufn);
+  typedef std::function<bool(ESP8266WebServerTemplate<ServerType> &server)> FilterFunction;
+
+  RequestHandler<ServerType>& on(const Uri &uri, THandlerFunction handler);
+  RequestHandler<ServerType>& on(const Uri &uri, HTTPMethod method, THandlerFunction fn);
+  RequestHandler<ServerType>& on(const Uri &uri, HTTPMethod method, THandlerFunction fn, THandlerFunction ufn);
+  bool removeRoute(const char *uri);
+  bool removeRoute(const char *uri, HTTPMethod method);
+  bool removeRoute(const String &uri);
+  bool removeRoute(const String &uri, HTTPMethod method);
   void addHandler(RequestHandlerType* handler);
+  bool removeHandler(RequestHandlerType* 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
   void onFileUpload(THandlerFunction fn); //handle file uploads
@@ -306,6 +312,7 @@ class ESP8266WebServerTemplate
 
 protected:
   void _addRequestHandler(RequestHandlerType* handler);
+  bool _removeRequestHandler(RequestHandlerType *handler);
   void _handleRequest();
   void _finalizeResponse();
   ClientFuture _parseRequest(ClientType& client);
diff --git a/libraries/ESP8266WebServer/src/Parsing-impl.h b/libraries/ESP8266WebServer/src/Parsing-impl.h
index 238b7b72d3..672682706e 100644
--- a/libraries/ESP8266WebServer/src/Parsing-impl.h
+++ b/libraries/ESP8266WebServer/src/Parsing-impl.h
@@ -106,7 +106,7 @@ typename ESP8266WebServerTemplate<ServerType>::ClientFuture ESP8266WebServerTemp
   //attach handler
   RequestHandlerType* handler;
   for (handler = _firstHandler; handler; handler = handler->next()) {
-    if (handler->canHandle(_currentMethod, _currentUri))
+    if (handler->canHandle(*this, _currentMethod, _currentUri))
       break;
   }
   _currentHandler = handler;
@@ -324,7 +324,7 @@ int ESP8266WebServerTemplate<ServerType>::_parseArgumentsPrivate(const String& d
 template <typename ServerType>
 void ESP8266WebServerTemplate<ServerType>::_uploadWriteByte(uint8_t b){
   if (_currentUpload->currentSize == HTTP_UPLOAD_BUFLEN){
-    if(_currentHandler && _currentHandler->canUpload(_currentUri))
+    if(_currentHandler && _currentHandler->canUpload(*this, _currentUri))
       _currentHandler->upload(*this, _currentUri, *_currentUpload);
     _currentUpload->totalSize += _currentUpload->currentSize;
     _currentUpload->currentSize = 0;
@@ -425,7 +425,7 @@ bool ESP8266WebServerTemplate<ServerType>::_parseForm(ClientType& client, const
             _currentUpload->currentSize = 0;
             _currentUpload->contentLength = len;
             DBGWS("Start File: %s Type: %s\n", _currentUpload->filename.c_str(), _currentUpload->type.c_str());
-            if(_currentHandler && _currentHandler->canUpload(_currentUri))
+            if(_currentHandler && _currentHandler->canUpload(*this, _currentUri))
               _currentHandler->upload(*this, _currentUri, *_currentUpload);
             _currentUpload->status = UPLOAD_FILE_WRITE;
 
@@ -463,11 +463,11 @@ bool ESP8266WebServerTemplate<ServerType>::_parseForm(ClientType& client, const
                 }
             }
             // Found the boundary string, finish processing this file upload
-            if (_currentHandler && _currentHandler->canUpload(_currentUri))
+            if (_currentHandler && _currentHandler->canUpload(*this, _currentUri))
                 _currentHandler->upload(*this, _currentUri, *_currentUpload);
             _currentUpload->totalSize += _currentUpload->currentSize;
             _currentUpload->status = UPLOAD_FILE_END;
-            if (_currentHandler && _currentHandler->canUpload(_currentUri))
+            if (_currentHandler && _currentHandler->canUpload(*this, _currentUri))
                 _currentHandler->upload(*this, _currentUri, *_currentUpload);
             DBGWS("End File: %s Type: %s Size: %d\n",
                 _currentUpload->filename.c_str(),
@@ -542,7 +542,7 @@ String ESP8266WebServerTemplate<ServerType>::urlDecode(const String& text)
 template <typename ServerType>
 bool ESP8266WebServerTemplate<ServerType>::_parseFormUploadAborted(){
   _currentUpload->status = UPLOAD_FILE_ABORTED;
-  if(_currentHandler && _currentHandler->canUpload(_currentUri))
+  if(_currentHandler && _currentHandler->canUpload(*this, _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 4195f0ff3f..c373c58f1b 100644
--- a/libraries/ESP8266WebServer/src/detail/RequestHandler.h
+++ b/libraries/ESP8266WebServer/src/detail/RequestHandler.h
@@ -12,13 +12,60 @@ class RequestHandler {
     using WebServerType = ESP8266WebServerTemplate<ServerType>;
 public:
     virtual ~RequestHandler() { }
-    virtual bool canHandle(HTTPMethod method, const String& uri) { (void) method; (void) uri; return false; }
-    virtual bool canUpload(const String& uri) { (void) uri; return false; }
-    virtual bool handle(WebServerType& server, HTTPMethod requestMethod, const String& requestUri) { (void) server; (void) requestMethod; (void) requestUri; return false; }
-    virtual void upload(WebServerType& server, const String& requestUri, HTTPUpload& upload) { (void) server; (void) requestUri; (void) upload; }
 
-    RequestHandler<ServerType>* next() { return _next; }
-    void next(RequestHandler<ServerType>* r) { _next = r; }
+    /*
+        note: old handler API for backward compatibility
+    */
+    
+    virtual bool canHandle(HTTPMethod method, const String& uri) {
+        (void) method;
+        (void) uri;
+        return false;
+    }
+    virtual bool canUpload(const String& uri) {
+        (void) uri;
+        return false;
+    }
+
+    /*
+        note: new handler API with support for filters etc.
+    */
+
+    virtual bool canHandle(WebServerType& server, HTTPMethod method, const String& uri) {
+        (void) server;
+        (void) method;
+        (void) uri;
+        return false;
+    }
+    virtual bool canUpload(WebServerType& server, const String& uri) {
+        (void) server;
+        (void) uri;
+        return false;
+    }
+    virtual bool handle(WebServerType& server, HTTPMethod requestMethod, const String& requestUri) {
+        (void) server; 
+        (void) requestMethod;
+        (void) requestUri;
+        return false;
+    }
+    virtual void upload(WebServerType& server, const String& requestUri, HTTPUpload& upload) {
+        (void) server;
+        (void) requestUri;
+        (void) upload;
+    }
+
+    RequestHandler<ServerType>* next() {
+        return _next;
+    }
+
+    void next(RequestHandler<ServerType>* r) {
+        _next = r;
+    }
+
+    virtual RequestHandler<ServerType>& setFilter(std::function<bool(ESP8266WebServerTemplate<ServerType>&)> filter) {
+        (void)filter;
+        return *this;
+    }
 
 private:
     RequestHandler<ServerType>* _next = nullptr;
diff --git a/libraries/ESP8266WebServer/src/detail/RequestHandlersImpl.h b/libraries/ESP8266WebServer/src/detail/RequestHandlersImpl.h
index bb06033dea..fb36c5aba4 100644
--- a/libraries/ESP8266WebServer/src/detail/RequestHandlersImpl.h
+++ b/libraries/ESP8266WebServer/src/detail/RequestHandlersImpl.h
@@ -59,9 +59,22 @@ class FunctionRequestHandler : public RequestHandler<ServerType> {
         return true;
     }
 
+    bool canHandle(WebServerType& server, HTTPMethod requestMethod, const String& requestUri) override {
+        if (_method != HTTP_ANY && _method != requestMethod)
+            return false;
+
+        return _uri->canHandle(requestUri, RequestHandler<ServerType>::pathArgs) && (_filter != NULL ? _filter(server) : true);
+    }
+
+    bool canUpload(WebServerType& server, const String& requestUri) override {
+        if (!_ufn || !canHandle(server, HTTP_POST, requestUri))
+            return false;
+
+        return true;
+    }
+
     bool handle(WebServerType& server, HTTPMethod requestMethod, const String& requestUri) override {
-        (void) server;
-        if (!canHandle(requestMethod, requestUri))
+        if (!canHandle(server, requestMethod, requestUri))
             return false;
 
         _fn();
@@ -69,15 +82,22 @@ class FunctionRequestHandler : public RequestHandler<ServerType> {
     }
 
     void upload(WebServerType& server, const String& requestUri, HTTPUpload& upload) override {
-        (void) server;
         (void) upload;
-        if (canUpload(requestUri))
+        if (canUpload(server, requestUri))
             _ufn();
     }
 
+    FunctionRequestHandler& setFilter(typename WebServerType::FilterFunction filter) {
+        _filter = filter;
+        return *this;
+    }
+
 protected:
     typename WebServerType::THandlerFunction _fn;
     typename WebServerType::THandlerFunction _ufn;
+    // _filter should return 'true' when the request should be handled
+    // and 'false' when the request should be ignored
+    typename WebServerType::FilterFunction _filter;
     Uri *_uri;
     HTTPMethod _method;
 };
@@ -115,7 +135,6 @@ class StaticRequestHandler : public RequestHandler<ServerType> {
 // serve all files within a given directory
 template<typename ServerType>
 class StaticDirectoryRequestHandler : public StaticRequestHandler<ServerType> {
-
     using SRH = StaticRequestHandler<ServerType>;
     using WebServerType = ESP8266WebServerTemplate<ServerType>;
 
@@ -130,9 +149,12 @@ class StaticDirectoryRequestHandler : public StaticRequestHandler<ServerType> {
         return SRH::validMethod(requestMethod) && requestUri.startsWith(SRH::_uri);
     }
 
-    bool handle(WebServerType& server, HTTPMethod requestMethod, const String& requestUri) override {
+    bool canHandle(WebServerType& server, HTTPMethod requestMethod, const String& requestUri) override {
+        return SRH::validMethod(requestMethod) && requestUri.startsWith(SRH::_uri) && (_filter != NULL ? _filter(server) : true);
+    }
 
-        if (!canHandle(requestMethod, requestUri))
+    bool handle(WebServerType& server, HTTPMethod requestMethod, const String& requestUri) override {
+        if (!canHandle(server, requestMethod, requestUri))
             return false;
 
         DEBUGV("DirectoryRequestHandler::handle: request=%s _uri=%s\r\n", requestUri.c_str(), SRH::_uri.c_str());
@@ -203,8 +225,14 @@ class StaticDirectoryRequestHandler : public StaticRequestHandler<ServerType> {
         return true;
     }
 
+    StaticDirectoryRequestHandler& setFilter(typename WebServerType::FilterFunction filter) {
+        _filter = filter;
+        return *this;
+    }
+
 protected:
     size_t _baseUriLength;
+    typename WebServerType::FilterFunction _filter;
 };
 
 
@@ -228,8 +256,12 @@ public StaticRequestHandler<ServerType> {
         return SRH::validMethod(requestMethod) && requestUri == SRH::_uri;
     }
 
+    bool canHandle(WebServerType& server, HTTPMethod requestMethod, const String& requestUri) override {
+        return SRH::validMethod(requestMethod) && requestUri == SRH::_uri && (_filter != NULL ? _filter(server) : true);
+    }
+
     bool handle(WebServerType& server, HTTPMethod requestMethod, const String & requestUri) override {
-        if (!canHandle(requestMethod, requestUri))
+        if (!canHandle(server, requestMethod, requestUri))
             return false;
 
         if (server._eTagEnabled) {
@@ -266,8 +298,14 @@ public StaticRequestHandler<ServerType> {
         return true;
     }
 
+    StaticFileRequestHandler& setFilter(typename WebServerType::FilterFunction filter) {
+        _filter = filter;
+        return *this;
+    }
+
 protected:
     String _eTagCode; // ETag code calculated for this file as used in http header include quotes.
+    typename WebServerType::FilterFunction _filter;
 };
 
 } // namespace