fhessel / esp32_https_server

Alternative ESP32 Webserver implementation for the ESP32 Arduino Core, supporting HTTPS and HTTP.
MIT License
345 stars 125 forks source link

WebServer Hooks like in esp8266 #95

Open luc-github opened 4 years ago

luc-github commented 4 years ago

Hello, Recently there was a PR https://github.com/esp8266/Arduino/pull/7459 in esp8266 that allows to use different protocol on same port of webserver

e.g WebDav on Webserver: https://github.com/d-a-v/ESPWebDAV/blob/v3/examples/Hooked/Hooked.ino

The esp8266 PR allows more generic approach as far I understand than the Websocket-Chat example

Could it be in plan to support such feature ?

Thank you ^_^

fhessel commented 4 years ago

Hi,

is your goal to intercept requests before they're processed, to check if a certain conditions is met, and then to either process the request as usual or to redirect it to another handler? Then middleware is what you're looking for. The basic middleware example shows only logging, but the authentication example covers more complex actions like requesting authentication or showing 401 pages if the user is not authenticated. The concept is quite similar to the middleware used in most NodeJS servers (like Express) or what you know as "Servlet Filters" in good old Java.

Or is the intention more to get in the direction of a modular webserver, so that you can create a server that handles /static by fetching static resources from your app image, /api to access your REST API, and for example /dav to have a WebDav interface to the SPIFFS? And then you would define a, let's call it, virtual server for each of those function which gets the stripped URL. So for example if you would call GET /api/gpio/23 this would be redirected to your API server instance as a GET /gpio/23 request? That isn't implemented yet, but I'd consider it a nice feature.

Or is the concept of these Hooks something completely different that I've misunderstood?

WebSockets are handled as a special case of incoming connections. Currently, for plain HTTP requests, the request handler function would be called and once it returns, that request is handled. If the request is for a websocket, an instance of the handler class will be instantiated and live as long as the websocket is used, while other requests can be processed in parallel.

luc-github commented 4 years ago

wow so detailed thank you!

yes the intention is more to get in the direction of a modular webserver which give up if some path are defined for other function - so the handler can be specific to used protocol and take the control according the path

http://xxx.xxx.xxx.xx/dav for webdav protocol : like here ws://xxx.xxx.xxx.xxx/ws for web socket protocol like in ESPAsyncWebserver htttp://xxx.xxx.xxx.xxx/xxxx for any standard web query

So it seems like you did for Websocket /chat but more generic allowing any protocol actually

fhessel commented 4 years ago

So it seems like you did for Websocket /chat but more generic allowing any protocol actually

That's an interesting thought. I already separated resource resolving and handling of connections early on, because I already had a modular server structure in mind. But I didn't made the (mental) connection to the WebSocket implementation, but always saw that as a somewhat orthogonal concept, or a special case of the normal request handling.

Rethinking this, it might indeed be the best solution to have a kind-of generic HTTPApplication class that you can hook to every base URL yourself, and from which a WebSocketApplication or a WebDavApplication and so on can inherit. Then you could do something like this:


class WebDavApplication : httpsserver::HTTPApplication {
  // Implement a new http-based protocol from scratch ...
}

class MyWebSocket : httpsserver::WebSocketApplication {
  // Base class WebSocketApplication handles lifecycle, this class defines the application level ...
}

HTTPServer *server;
WebDavApplication *webdav;
MyWebSocket *websocket;

void setupServer() {
  // Create the server
  server = new HTTPServer();

  // Create and register a WebDav Handler
  webdav = new WebDavApplication();
  server->registerApplication("/dav", webdav);

  // Create and register WebSocket Handler
  websocket = new MyWebSocket();
  server->registerApplication("/ws", websocket);

  // Add a generic handler function
  ResourceNode *node = new ResourceNode("GET", "/", &handleRoot);
  server->registerNode(node);

  server->start()
}

And those "Applications" then have more control over connection lifecycle etc., but for the simple use case of just serving basic HTTP request, it doesn't change much (even though one could implement that as another instance of HTTPApplication under the hood, too.)

luc-github commented 4 years ago

yes that is ^_^

luc-github commented 3 years ago

Hi, sorry to bother, but any update on this feature ? ^_^