Skip to content

Commit

Permalink
ESPAsyncWebServer Migration
Browse files Browse the repository at this point in the history
  • Loading branch information
mathieucarbou committed Aug 10, 2024
1 parent 874ed11 commit 6f60f79
Show file tree
Hide file tree
Showing 11 changed files with 194 additions and 43 deletions.
44 changes: 44 additions & 0 deletions src/PsychicEndpoint.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,50 @@ String PsychicEndpoint::uri() {
return _uri;
}

esp_err_t PsychicEndpoint::install()
{
if (!_registered)
{
// URI handler structure
httpd_uri_t my_uri {
.uri = _uri.c_str(),
.method = _method,
.handler = PsychicEndpoint::requestCallback,
.user_ctx = this,
.is_websocket = _handler->isWebSocket(),
.handle_ws_control_frames = false,
.supported_subprotocol = _handler->getSubprotocol()
};

// Register endpoint with ESP-IDF server
esp_err_t ret = httpd_register_uri_handler(_server->server, &my_uri);
if (ret != ESP_OK) {
ESP_LOGE(PH_TAG, "Add endpoint failed (%s) for: %s", esp_err_to_name(ret), _uri.c_str());
return ret;
}

_registered = true;
}

return ESP_OK;
}

esp_err_t PsychicEndpoint::uninstall()
{
if (_registered)
{
esp_err_t ret = httpd_unregister_uri_handler(_server->server, _uri.c_str(), _method);
if (ret != ESP_OK) {
ESP_LOGE(PH_TAG, "Remove endpoint failed (%s) for: %s", esp_err_to_name(ret), _uri.c_str());
return ret;
}

_registered = false;
}

return ESP_OK;
}

esp_err_t PsychicEndpoint::requestCallback(httpd_req_t *req)
{
#ifdef ENABLE_ASYNC
Expand Down
4 changes: 4 additions & 0 deletions src/PsychicEndpoint.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ class PsychicEndpoint
String _uri;
http_method _method;
PsychicHandler *_handler;
bool _registered = false;

public:
PsychicEndpoint();
Expand All @@ -31,6 +32,9 @@ class PsychicEndpoint

String uri();

esp_err_t install();
esp_err_t uninstall();

static esp_err_t requestCallback(httpd_req_t *req);
};

Expand Down
16 changes: 16 additions & 0 deletions src/PsychicFromEspAsyncwebServer.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#pragma once

#include "PsychicHttpServer.h"
#include "PsychicRequest.h"
#include "PsychicWebHandler.h"

#include <esp_err.h>

using AsyncWebServer = PsychicHttpServer;
using AsyncCallbackWebHandler = PsychicEndpoint;
using AsyncWebServerRequest = PsychicRequest;
using AsyncWebServerResponse = PsychicResponse;
using AsyncJsonResponse = PsychicJsonResponse;

#define PSYCHIC_OK ESP_OK
#define PSYCHIC_REQ request,
4 changes: 4 additions & 0 deletions src/PsychicHttp.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,8 @@
#include "async_worker.h"
#endif

#ifdef PSYCHIC_TO_ESPASYNCWS
#include <PsychicFromEspAsyncwebServer.h>
#endif

#endif /* PsychicHttp_h */
73 changes: 47 additions & 26 deletions src/PsychicHttpServer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
#include "PsychicJson.h"
#include "WiFi.h"

PsychicHttpServer::PsychicHttpServer() :
PsychicHttpServer::PsychicHttpServer(uint16_t port) :
_onOpen(NULL),
_onClose(NULL)
{
Expand All @@ -23,7 +23,9 @@ PsychicHttpServer::PsychicHttpServer() :
config.close_fn = PsychicHttpServer::closeCallback;
config.uri_match_fn = httpd_uri_match_wildcard;
config.global_user_ctx = this;
config.global_user_ctx_free_fn = destroy;
config.max_uri_handlers = 20;
config.server_port = port;

#ifdef ENABLE_ASYNC
// It is advisable that httpd_config_t->max_open_sockets > MAX_ASYNC_REQUESTS
Expand Down Expand Up @@ -53,6 +55,11 @@ PsychicHttpServer::~PsychicHttpServer()
delete defaultEndpoint;
}

void PsychicHttpServer::destroy(void *ctx)
{
// do not release any resource for PsychicHttpServer in order to be able to restart it after stopping
}

esp_err_t PsychicHttpServer::listen(uint16_t port)
{
this->_use_ssl = false;
Expand All @@ -78,6 +85,16 @@ esp_err_t PsychicHttpServer::_start()
return ret;
}

_started = true;

for (PsychicEndpoint *endpoint : _endpoints)
endpoint->install();

_started = true;

for (PsychicEndpoint *endpoint : _endpoints)
endpoint->install();

// Register handler
ret = httpd_register_err_handler(server, HTTPD_404_NOT_FOUND, PsychicHttpServer::notFoundHandler);
if (ret != ESP_OK)
Expand All @@ -90,9 +107,18 @@ esp_err_t PsychicHttpServer::_startServer() {
return httpd_start(&this->server, &this->config);
}

void PsychicHttpServer::stop()
esp_err_t PsychicHttpServer::stop()
{
httpd_stop(this->server);
esp_err_t ret = httpd_stop(this->server);
if(ret != ESP_OK)
{
ESP_LOGE(PH_TAG, "Server stop failed (%s)", esp_err_to_name(ESP_FAIL));
return ret;
}

_started = false;
ESP_LOGI(PH_TAG, "Server stopped");
return ret;
}

PsychicHandler& PsychicHttpServer::addHandler(PsychicHandler* handler){
Expand All @@ -104,57 +130,52 @@ void PsychicHttpServer::removeHandler(PsychicHandler *handler){
_handlers.remove(handler);
}

PsychicEndpoint* PsychicHttpServer::on(const char* uri) {
esp_err_t PsychicHttpServer::removeEndpoint(PsychicEndpoint *endpoint){
_endpoints.remove(endpoint);
esp_err_t ret = endpoint->uninstall();
delete endpoint;
return ret;
}

PsychicEndpoint& PsychicHttpServer::on(const char* uri) {
return on(uri, HTTP_GET);
}

PsychicEndpoint* PsychicHttpServer::on(const char* uri, http_method method)
PsychicEndpoint& PsychicHttpServer::on(const char* uri, http_method method)
{
PsychicWebHandler *handler = new PsychicWebHandler();

return on(uri, method, handler);
}

PsychicEndpoint* PsychicHttpServer::on(const char* uri, PsychicHandler *handler)
PsychicEndpoint& PsychicHttpServer::on(const char* uri, PsychicHandler *handler)
{
return on(uri, HTTP_GET, handler);
}

PsychicEndpoint* PsychicHttpServer::on(const char* uri, http_method method, PsychicHandler *handler)
PsychicEndpoint& PsychicHttpServer::on(const char* uri, http_method method, PsychicHandler *handler)
{
//make our endpoint
PsychicEndpoint *endpoint = new PsychicEndpoint(this, method, uri);

//set our handler
endpoint->setHandler(handler);

// URI handler structure
httpd_uri_t my_uri {
.uri = uri,
.method = method,
.handler = PsychicEndpoint::requestCallback,
.user_ctx = endpoint,
.is_websocket = handler->isWebSocket(),
.supported_subprotocol = handler->getSubprotocol()
};

// Register endpoint with ESP-IDF server
esp_err_t ret = httpd_register_uri_handler(this->server, &my_uri);
if (ret != ESP_OK)
ESP_LOGE(PH_TAG, "Add endpoint failed (%s)", esp_err_to_name(ret));
if(_started)
endpoint->install();

//save it for later
_endpoints.push_back(endpoint);

return endpoint;
return *endpoint;
}

PsychicEndpoint* PsychicHttpServer::on(const char* uri, PsychicHttpRequestCallback fn)
PsychicEndpoint& PsychicHttpServer::on(const char* uri, PsychicHttpRequestCallback fn)
{
return on(uri, HTTP_GET, fn);
}

PsychicEndpoint* PsychicHttpServer::on(const char* uri, http_method method, PsychicHttpRequestCallback fn)
PsychicEndpoint& PsychicHttpServer::on(const char* uri, http_method method, PsychicHttpRequestCallback fn)
{
//these basic requests need a basic web handler
PsychicWebHandler *handler = new PsychicWebHandler();
Expand All @@ -163,12 +184,12 @@ PsychicEndpoint* PsychicHttpServer::on(const char* uri, http_method method, Psyc
return on(uri, method, handler);
}

PsychicEndpoint* PsychicHttpServer::on(const char* uri, PsychicJsonRequestCallback fn)
PsychicEndpoint& PsychicHttpServer::on(const char* uri, PsychicJsonRequestCallback fn)
{
return on(uri, HTTP_GET, fn);
}

PsychicEndpoint* PsychicHttpServer::on(const char* uri, http_method method, PsychicJsonRequestCallback fn)
PsychicEndpoint& PsychicHttpServer::on(const char* uri, http_method method, PsychicJsonRequestCallback fn)
{
//these basic requests need a basic web handler
PsychicJsonHandler *handler = new PsychicJsonHandler();
Expand Down
30 changes: 20 additions & 10 deletions src/PsychicHttpServer.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,10 @@ class PsychicHttpServer

esp_err_t _start();
virtual esp_err_t _startServer();
bool _started = false;

public:
PsychicHttpServer();
PsychicHttpServer(uint16_t port = 80);
virtual ~PsychicHttpServer();

//esp-idf specific stuff
Expand All @@ -37,12 +38,15 @@ class PsychicHttpServer

PsychicEndpoint *defaultEndpoint;

static void destroy(void *ctx);

esp_err_t listen(uint16_t port);

virtual void stop();
virtual esp_err_t stop();

PsychicHandler& addHandler(PsychicHandler* handler);
void removeHandler(PsychicHandler* handler);
esp_err_t removeEndpoint(PsychicEndpoint* endpoint);

void addClient(PsychicClient *client);
void removeClient(PsychicClient *client);
Expand All @@ -52,14 +56,14 @@ class PsychicHttpServer
int count() { return _clients.size(); };
const std::list<PsychicClient*>& getClientList();

PsychicEndpoint* on(const char* uri);
PsychicEndpoint* on(const char* uri, http_method method);
PsychicEndpoint* on(const char* uri, PsychicHandler *handler);
PsychicEndpoint* on(const char* uri, http_method method, PsychicHandler *handler);
PsychicEndpoint* on(const char* uri, PsychicHttpRequestCallback onRequest);
PsychicEndpoint* on(const char* uri, http_method method, PsychicHttpRequestCallback onRequest);
PsychicEndpoint* on(const char* uri, PsychicJsonRequestCallback onRequest);
PsychicEndpoint* on(const char* uri, http_method method, PsychicJsonRequestCallback onRequest);
PsychicEndpoint& on(const char* uri);
PsychicEndpoint& on(const char* uri, http_method method);
PsychicEndpoint& on(const char* uri, PsychicHandler *handler);
PsychicEndpoint& on(const char* uri, http_method method, PsychicHandler *handler);
PsychicEndpoint& on(const char* uri, PsychicHttpRequestCallback onRequest);
PsychicEndpoint& on(const char* uri, http_method method, PsychicHttpRequestCallback onRequest);
PsychicEndpoint& on(const char* uri, PsychicJsonRequestCallback onRequest);
PsychicEndpoint& on(const char* uri, http_method method, PsychicJsonRequestCallback onRequest);

static esp_err_t notFoundHandler(httpd_req_t *req, httpd_err_code_t err);
static esp_err_t defaultNotFoundHandler(PsychicRequest *request);
Expand All @@ -71,6 +75,12 @@ class PsychicHttpServer
static void closeCallback(httpd_handle_t hd, int sockfd);

PsychicStaticFileHandler* serveStatic(const char* uri, fs::FS& fs, const char* path, const char* cache_control = NULL);

#ifdef PSYCHIC_TO_ESPASYNCWS
void begin(uint16_t port = 80) { listen(port); }
void end() { stop(); }
void removeHandler(PsychicEndpoint* endpoint) { removeEndpoint(endpoint); }
#endif
};

bool ON_STA_FILTER(PsychicRequest *request);
Expand Down
21 changes: 17 additions & 4 deletions src/PsychicHttpsServer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,15 @@

#ifdef CONFIG_ESP_HTTPS_SERVER_ENABLE

PsychicHttpsServer::PsychicHttpsServer() : PsychicHttpServer()
PsychicHttpsServer::PsychicHttpsServer(uint16_t port) : PsychicHttpServer(port)
{
//for a SSL server
ssl_config = HTTPD_SSL_CONFIG_DEFAULT();
ssl_config.httpd.open_fn = PsychicHttpServer::openCallback;
ssl_config.httpd.close_fn = PsychicHttpServer::closeCallback;
ssl_config.httpd.uri_match_fn = httpd_uri_match_wildcard;
ssl_config.httpd.global_user_ctx = this;
ssl_config.httpd.global_user_ctx_free_fn = destroy;
ssl_config.httpd.max_uri_handlers = 20;

// each SSL connection takes about 45kb of heap
Expand Down Expand Up @@ -49,12 +50,24 @@ esp_err_t PsychicHttpsServer::_startServer()
return httpd_start(&this->server, &this->config);
}

void PsychicHttpsServer::stop()
esp_err_t PsychicHttpsServer::stop()
{
esp_err_t ret = ESP_OK

if (this->_use_ssl)
httpd_ssl_stop(this->server);
ret = httpd_ssl_stop(this->server);
else
httpd_stop(this->server);
ret = httpd_stop(this->server);

if(ret != ESP_OK)
{
ESP_LOGE(PH_TAG, "Server stop failed (%s)", esp_err_to_name(ESP_FAIL));
return ret;
}

_started = false;
ESP_LOGI(PH_TAG, "Server stopped");
return ret;
}

#endif // CONFIG_ESP_HTTPS_SERVER_ENABLE
4 changes: 2 additions & 2 deletions src/PsychicHttpsServer.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ class PsychicHttpsServer : public PsychicHttpServer
bool _use_ssl = false;

public:
PsychicHttpsServer();
PsychicHttpsServer(uint16_t port = 443);
~PsychicHttpsServer();

httpd_ssl_config_t ssl_config;
Expand All @@ -27,7 +27,7 @@ class PsychicHttpsServer : public PsychicHttpServer
esp_err_t listen(uint16_t port, const char *cert, const char *private_key);

virtual esp_err_t _startServer() override final;
virtual void stop() override final;
virtual esp_err_t stop() override final;
};

#endif // PsychicHttpsServer_h
Expand Down
4 changes: 4 additions & 0 deletions src/PsychicJson.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,10 @@ class PsychicJsonResponse : public PsychicResponse
size_t getLength();

virtual esp_err_t send() override;

#ifdef PSYCHIC_TO_ESPASYNCWS
void setLength() { setContentLength(measureJson(_root)); }
#endif
};

class PsychicJsonHandler : public PsychicWebHandler
Expand Down
Loading

0 comments on commit 6f60f79

Please sign in to comment.