mirror of
https://github.com/emsesp/EMS-ESP32.git
synced 2025-12-06 15:59:52 +03:00
json is always chunked
This commit is contained in:
329
lib/PsychicHttp/src_old/PsychicHttpServer.cpp
Normal file
329
lib/PsychicHttp/src_old/PsychicHttpServer.cpp
Normal file
@@ -0,0 +1,329 @@
|
||||
#include "PsychicHttpServer.h"
|
||||
#include "PsychicEndpoint.h"
|
||||
#include "PsychicHandler.h"
|
||||
#include "PsychicWebHandler.h"
|
||||
#include "PsychicStaticFileHandler.h"
|
||||
#include "PsychicWebSocket.h"
|
||||
#include "WiFi.h"
|
||||
#include "PsychicJson.h" // added by proddy
|
||||
|
||||
PsychicHttpServer::PsychicHttpServer()
|
||||
: _onOpen(NULL)
|
||||
, _onClose(NULL) {
|
||||
maxRequestBodySize = MAX_REQUEST_BODY_SIZE;
|
||||
maxUploadSize = MAX_UPLOAD_SIZE;
|
||||
|
||||
defaultEndpoint = new PsychicEndpoint(this, HTTP_GET, "");
|
||||
onNotFound(PsychicHttpServer::defaultNotFoundHandler);
|
||||
|
||||
//for a regular server
|
||||
config = HTTPD_DEFAULT_CONFIG();
|
||||
config.open_fn = PsychicHttpServer::openCallback;
|
||||
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;
|
||||
|
||||
#ifdef ENABLE_ASYNC
|
||||
// It is advisable that httpd_config_t->max_open_sockets > MAX_ASYNC_REQUESTS
|
||||
// Why? This leaves at least one socket still available to handle
|
||||
// quick synchronous requests. Otherwise, all the sockets will
|
||||
// get taken by the long async handlers, and your server will no
|
||||
// longer be responsive.
|
||||
config.max_open_sockets = ASYNC_WORKER_COUNT + 1;
|
||||
config.lru_purge_enable = true;
|
||||
#endif
|
||||
}
|
||||
|
||||
PsychicHttpServer::~PsychicHttpServer() {
|
||||
for (auto * client : _clients)
|
||||
delete (client);
|
||||
_clients.clear();
|
||||
|
||||
for (auto * endpoint : _endpoints)
|
||||
delete (endpoint);
|
||||
_endpoints.clear();
|
||||
|
||||
for (auto * handler : _handlers)
|
||||
delete (handler);
|
||||
_handlers.clear();
|
||||
|
||||
delete defaultEndpoint;
|
||||
}
|
||||
|
||||
void PsychicHttpServer::destroy(void * ctx) {
|
||||
PsychicHttpServer * temp = (PsychicHttpServer *)ctx;
|
||||
delete temp;
|
||||
}
|
||||
|
||||
esp_err_t PsychicHttpServer::listen(uint16_t port) {
|
||||
this->_use_ssl = false;
|
||||
this->config.server_port = port;
|
||||
|
||||
return this->_start();
|
||||
}
|
||||
|
||||
esp_err_t PsychicHttpServer::_start() {
|
||||
esp_err_t ret;
|
||||
|
||||
#ifdef ENABLE_ASYNC
|
||||
// start workers
|
||||
start_async_req_workers();
|
||||
#endif
|
||||
|
||||
//fire it up.
|
||||
ret = _startServer();
|
||||
if (ret != ESP_OK) {
|
||||
ESP_LOGE(PH_TAG, "Server start failed (%s)", esp_err_to_name(ret));
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Register handler
|
||||
ret = httpd_register_err_handler(server, HTTPD_404_NOT_FOUND, PsychicHttpServer::notFoundHandler);
|
||||
if (ret != ESP_OK)
|
||||
ESP_LOGE(PH_TAG, "Add 404 handler failed (%s)", esp_err_to_name(ret));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
esp_err_t PsychicHttpServer::_startServer() {
|
||||
return httpd_start(&this->server, &this->config);
|
||||
}
|
||||
|
||||
void PsychicHttpServer::stop() {
|
||||
httpd_stop(this->server);
|
||||
}
|
||||
|
||||
PsychicHandler & PsychicHttpServer::addHandler(PsychicHandler * handler) {
|
||||
_handlers.push_back(handler);
|
||||
return *handler;
|
||||
}
|
||||
|
||||
void PsychicHttpServer::removeHandler(PsychicHandler * handler) {
|
||||
_handlers.remove(handler);
|
||||
}
|
||||
|
||||
PsychicEndpoint * PsychicHttpServer::on(const char * uri) {
|
||||
return on(uri, HTTP_GET);
|
||||
}
|
||||
|
||||
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) {
|
||||
//these basic requests need a basic web handler
|
||||
PsychicWebHandler * handler = new PsychicWebHandler();
|
||||
handler->onRequest(fn);
|
||||
|
||||
return on(uri, method, handler);
|
||||
}
|
||||
|
||||
// added by Proddy
|
||||
PsychicEndpoint * PsychicHttpServer::on(const char * uri, http_method method, PsychicJsonRequestCallback fn) {
|
||||
PsychicJsonHandler * handler = new PsychicJsonHandler(fn);
|
||||
|
||||
return on(uri, method, handler);
|
||||
}
|
||||
|
||||
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) {
|
||||
return on(uri, HTTP_GET, 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()};
|
||||
|
||||
// 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 %s failed (%s)", uri, esp_err_to_name(ret)); // modified by proddy
|
||||
}
|
||||
|
||||
//save it for later
|
||||
_endpoints.push_back(endpoint);
|
||||
|
||||
return endpoint;
|
||||
}
|
||||
|
||||
void PsychicHttpServer::onNotFound(PsychicHttpRequestCallback fn) {
|
||||
PsychicWebHandler * handler = new PsychicWebHandler();
|
||||
handler->onRequest(fn);
|
||||
|
||||
this->defaultEndpoint->setHandler(handler);
|
||||
}
|
||||
|
||||
esp_err_t PsychicHttpServer::notFoundHandler(httpd_req_t * req, httpd_err_code_t err) {
|
||||
PsychicHttpServer * server = (PsychicHttpServer *)httpd_get_global_user_ctx(req->handle);
|
||||
PsychicRequest request(server, req);
|
||||
|
||||
//loop through our global handlers and see if anyone wants it
|
||||
for (auto * handler : server->_handlers) {
|
||||
//are we capable of handling this?
|
||||
if (handler->filter(&request) && handler->canHandle(&request)) {
|
||||
//check our credentials
|
||||
if (handler->needsAuthentication(&request))
|
||||
return handler->authenticate(&request);
|
||||
else
|
||||
return handler->handleRequest(&request);
|
||||
}
|
||||
}
|
||||
|
||||
//nothing found, give it to our defaultEndpoint
|
||||
PsychicHandler * handler = server->defaultEndpoint->handler();
|
||||
if (handler->filter(&request) && handler->canHandle(&request))
|
||||
return handler->handleRequest(&request);
|
||||
|
||||
//not sure how we got this far.
|
||||
return ESP_ERR_HTTPD_INVALID_REQ;
|
||||
}
|
||||
|
||||
esp_err_t PsychicHttpServer::defaultNotFoundHandler(PsychicRequest * request) {
|
||||
request->reply(404, "text/html", "That URI does not exist.");
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
void PsychicHttpServer::onOpen(PsychicClientCallback handler) {
|
||||
this->_onOpen = handler;
|
||||
}
|
||||
|
||||
esp_err_t PsychicHttpServer::openCallback(httpd_handle_t hd, int sockfd) {
|
||||
ESP_LOGI(PH_TAG, "New client connected %d", sockfd);
|
||||
|
||||
//get our global server reference
|
||||
PsychicHttpServer * server = (PsychicHttpServer *)httpd_get_global_user_ctx(hd);
|
||||
|
||||
//lookup our client
|
||||
PsychicClient * client = server->getClient(sockfd);
|
||||
if (client == NULL) {
|
||||
client = new PsychicClient(hd, sockfd);
|
||||
server->addClient(client);
|
||||
}
|
||||
|
||||
//user callback
|
||||
if (server->_onOpen != NULL)
|
||||
server->_onOpen(client);
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
void PsychicHttpServer::onClose(PsychicClientCallback handler) {
|
||||
this->_onClose = handler;
|
||||
}
|
||||
|
||||
void PsychicHttpServer::closeCallback(httpd_handle_t hd, int sockfd) {
|
||||
ESP_LOGI(PH_TAG, "Client disconnected %d", sockfd);
|
||||
|
||||
PsychicHttpServer * server = (PsychicHttpServer *)httpd_get_global_user_ctx(hd);
|
||||
|
||||
//lookup our client
|
||||
PsychicClient * client = server->getClient(sockfd);
|
||||
if (client != NULL) {
|
||||
//give our handlers a chance to handle a disconnect first
|
||||
for (PsychicEndpoint * endpoint : server->_endpoints) {
|
||||
PsychicHandler * handler = endpoint->handler();
|
||||
handler->checkForClosedClient(client);
|
||||
}
|
||||
|
||||
//do we have a callback attached?
|
||||
if (server->_onClose != NULL)
|
||||
server->_onClose(client);
|
||||
|
||||
//remove it from our list
|
||||
server->removeClient(client);
|
||||
} else
|
||||
ESP_LOGE(PH_TAG, "No client record %d", sockfd);
|
||||
|
||||
//finally close it out.
|
||||
close(sockfd);
|
||||
}
|
||||
|
||||
PsychicStaticFileHandler * PsychicHttpServer::serveStatic(const char * uri, fs::FS & fs, const char * path, const char * cache_control) {
|
||||
PsychicStaticFileHandler * handler = new PsychicStaticFileHandler(uri, fs, path, cache_control);
|
||||
this->addHandler(handler);
|
||||
|
||||
return handler;
|
||||
}
|
||||
|
||||
void PsychicHttpServer::addClient(PsychicClient * client) {
|
||||
_clients.push_back(client);
|
||||
}
|
||||
|
||||
void PsychicHttpServer::removeClient(PsychicClient * client) {
|
||||
_clients.remove(client);
|
||||
delete client;
|
||||
}
|
||||
|
||||
PsychicClient * PsychicHttpServer::getClient(int socket) {
|
||||
for (PsychicClient * client : _clients)
|
||||
if (client->socket() == socket)
|
||||
return client;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
PsychicClient * PsychicHttpServer::getClient(httpd_req_t * req) {
|
||||
return getClient(httpd_req_to_sockfd(req));
|
||||
}
|
||||
|
||||
bool PsychicHttpServer::hasClient(int socket) {
|
||||
return getClient(socket) != NULL;
|
||||
}
|
||||
|
||||
const std::list<PsychicClient *> & PsychicHttpServer::getClientList() {
|
||||
return _clients;
|
||||
}
|
||||
|
||||
bool ON_STA_FILTER(PsychicRequest * request) {
|
||||
return WiFi.localIP() == request->client()->localIP();
|
||||
}
|
||||
|
||||
bool ON_AP_FILTER(PsychicRequest * request) {
|
||||
return WiFi.softAPIP() == request->client()->localIP();
|
||||
}
|
||||
|
||||
String urlDecode(const char * encoded) {
|
||||
size_t length = strlen(encoded);
|
||||
char * decoded = (char *)malloc(length + 1);
|
||||
if (!decoded) {
|
||||
return "";
|
||||
}
|
||||
|
||||
size_t i, j = 0;
|
||||
for (i = 0; i < length; ++i) {
|
||||
if (encoded[i] == '%' && isxdigit(encoded[i + 1]) && isxdigit(encoded[i + 2])) {
|
||||
// Valid percent-encoded sequence
|
||||
int hex;
|
||||
sscanf(encoded + i + 1, "%2x", &hex);
|
||||
decoded[j++] = (char)hex;
|
||||
i += 2; // Skip the two hexadecimal characters
|
||||
} else if (encoded[i] == '+') {
|
||||
// Convert '+' to space
|
||||
decoded[j++] = ' ';
|
||||
} else {
|
||||
// Copy other characters as they are
|
||||
decoded[j++] = encoded[i];
|
||||
}
|
||||
}
|
||||
|
||||
decoded[j] = '\0'; // Null-terminate the decoded string
|
||||
|
||||
String output(decoded);
|
||||
free(decoded);
|
||||
|
||||
return output;
|
||||
}
|
||||
Reference in New Issue
Block a user