Template container instead of direct pointer manipulation. (#95)

* using Container instead ofdirect pointers list manipulation

* fixed different type of virtual methods.

* Fixed typo in conditional

* Renamed ListArray to LinkedList

* Const reference to String as method parameters to prevent additional copy and memory allocation when String passed by value

* fix 'min' redefinition

* removed #include <iterator>
begin/end methods it's enough for 'for( : )' loop
count() renamed to length()
spacing fixing

* Const reference to String as method parameters to prevent additional copy and memory allocation when String passed by value

* Fixed unused params warnings
This commit is contained in:
Max Lunin
2016-11-27 17:42:09 +02:00
committed by Me No Dev
parent 3e6e890808
commit a7c4dfb04f
17 changed files with 478 additions and 659 deletions

View File

@@ -189,7 +189,7 @@ void setup(){
request->send(404); request->send(404);
}); });
server.onFileUpload([](AsyncWebServerRequest *request, String filename, size_t index, uint8_t *data, size_t len, bool final){ server.onFileUpload([](AsyncWebServerRequest *request, const String& filename, size_t index, uint8_t *data, size_t len, bool final){
if(!index) if(!index)
Serial.printf("UploadStart: %s\n", filename.c_str()); Serial.printf("UploadStart: %s\n", filename.c_str());
Serial.printf("%s", (const char*)data); Serial.printf("%s", (const char*)data);

View File

@@ -110,7 +110,6 @@ AsyncEventSourceClient::AsyncEventSourceClient(AsyncWebServerRequest *request, A
_client = request->client(); _client = request->client();
_server = server; _server = server;
_lastId = 0; _lastId = 0;
next = NULL;
if(request->hasHeader("Last-Event-ID")) if(request->hasHeader("Last-Event-ID"))
_lastId = atoi(request->getHeader("Last-Event-ID")->value().c_str()); _lastId = atoi(request->getHeader("Last-Event-ID")->value().c_str());
@@ -119,7 +118,7 @@ AsyncEventSourceClient::AsyncEventSourceClient(AsyncWebServerRequest *request, A
_client->onAck(NULL, NULL); _client->onAck(NULL, NULL);
_client->onPoll(NULL, NULL); _client->onPoll(NULL, NULL);
_client->onData(NULL, NULL); _client->onData(NULL, NULL);
_client->onTimeout([](void *r, AsyncClient* c, uint32_t time){ ((AsyncEventSourceClient*)(r))->_onTimeout(time); }, this); _client->onTimeout([](void *r, AsyncClient* c __attribute__((unused)), uint32_t time){ ((AsyncEventSourceClient*)(r))->_onTimeout(time); }, this);
_client->onDisconnect([](void *r, AsyncClient* c){ ((AsyncEventSourceClient*)(r))->_onDisconnect(); delete c; }, this); _client->onDisconnect([](void *r, AsyncClient* c){ ((AsyncEventSourceClient*)(r))->_onDisconnect(); delete c; }, this);
_server->_addClient(this); _server->_addClient(this);
delete request; delete request;
@@ -129,7 +128,7 @@ AsyncEventSourceClient::~AsyncEventSourceClient(){
close(); close();
} }
void AsyncEventSourceClient::_onTimeout(uint32_t time){ void AsyncEventSourceClient::_onTimeout(uint32_t time __attribute__((unused))){
_client->close(true); _client->close(true);
} }
@@ -161,9 +160,9 @@ void AsyncEventSourceClient::send(const char *message, const char *event, uint32
// Handler // Handler
AsyncEventSource::AsyncEventSource(String url) AsyncEventSource::AsyncEventSource(const String& url)
: _url(url) : _url(url)
, _clients(NULL) , _clients(LinkedList<AsyncEventSourceClient *>([](AsyncEventSourceClient *c){ delete c; }))
, _connectcb(NULL) , _connectcb(NULL)
{} {}
@@ -188,68 +187,38 @@ void AsyncEventSource::_addClient(AsyncEventSourceClient * client){
client->write((const char *)temp, 2053); client->write((const char *)temp, 2053);
free(temp); free(temp);
}*/ }*/
if(_clients == NULL){
_clients = client; _clients.add(client);
if(_connectcb)
_connectcb(client);
return;
}
AsyncEventSourceClient * c = _clients;
while(c->next != NULL) c = c->next;
c->next = client;
if(_connectcb) if(_connectcb)
_connectcb(client); _connectcb(client);
} }
void AsyncEventSource::_handleDisconnect(AsyncEventSourceClient * client){ void AsyncEventSource::_handleDisconnect(AsyncEventSourceClient * client){
if(_clients == NULL){ _clients.remove(client);
return;
}
if(_clients == client){
_clients = client->next;
delete client;
return;
}
AsyncEventSourceClient * c = _clients;
while(c->next != NULL && c->next != client) c = c->next;
if(c->next == NULL){
return;
}
c->next = client->next;
delete client;
} }
void AsyncEventSource::close(){ void AsyncEventSource::close(){
AsyncEventSourceClient * c = _clients; for(const auto &c: _clients){
while(c != NULL){
if(c->connected()) if(c->connected())
c->close(); c->close();
c = c->next;
} }
} }
void AsyncEventSource::send(const char *message, const char *event, uint32_t id, uint32_t reconnect){ void AsyncEventSource::send(const char *message, const char *event, uint32_t id, uint32_t reconnect){
if(_clients == NULL) if(_clients.isEmpty())
return; return;
String ev = generateEventMessage(message, event, id, reconnect); String ev = generateEventMessage(message, event, id, reconnect);
AsyncEventSourceClient * c = _clients; for(const auto &c: _clients){
while(c != NULL){
if(c->connected()) if(c->connected())
c->write(ev.c_str(), ev.length()); c->write(ev.c_str(), ev.length());
c = c->next;
} }
} }
size_t AsyncEventSource::count(){ size_t AsyncEventSource::count() const {
size_t i = 0; return _clients.count_if([](AsyncEventSourceClient *c){
AsyncEventSourceClient * c = _clients; return c->connected();
while(c != NULL){ });
if(c->connected())
i++;
c = c->next;
}
return i;
} }
bool AsyncEventSource::canHandle(AsyncWebServerRequest *request){ bool AsyncEventSource::canHandle(AsyncWebServerRequest *request){
@@ -280,7 +249,7 @@ void AsyncEventSourceResponse::_respond(AsyncWebServerRequest *request){
_state = RESPONSE_WAIT_ACK; _state = RESPONSE_WAIT_ACK;
} }
size_t AsyncEventSourceResponse::_ack(AsyncWebServerRequest *request, size_t len, uint32_t time){ size_t AsyncEventSourceResponse::_ack(AsyncWebServerRequest *request, size_t len, uint32_t time __attribute__((unused))){
if(len){ if(len){
new AsyncEventSourceClient(request, _server); new AsyncEventSourceClient(request, _server);
} }

View File

@@ -36,7 +36,6 @@ class AsyncEventSourceClient {
uint32_t _lastId; uint32_t _lastId;
public: public:
AsyncEventSourceClient * next;
AsyncEventSourceClient(AsyncWebServerRequest *request, AsyncEventSource *server); AsyncEventSourceClient(AsyncWebServerRequest *request, AsyncEventSource *server);
~AsyncEventSourceClient(); ~AsyncEventSourceClient();
@@ -45,8 +44,8 @@ class AsyncEventSourceClient {
void close(); void close();
void write(const char * message, size_t len); void write(const char * message, size_t len);
void send(const char *message, const char *event=NULL, uint32_t id=0, uint32_t reconnect=0); void send(const char *message, const char *event=NULL, uint32_t id=0, uint32_t reconnect=0);
bool connected(){ return (_client != NULL) && _client->connected(); } bool connected() const { return (_client != NULL) && _client->connected(); }
uint32_t lastId(){ return _lastId; } uint32_t lastId() const { return _lastId; }
//system callbacks (do not call) //system callbacks (do not call)
void _onTimeout(uint32_t time); void _onTimeout(uint32_t time);
@@ -56,23 +55,23 @@ class AsyncEventSourceClient {
class AsyncEventSource: public AsyncWebHandler { class AsyncEventSource: public AsyncWebHandler {
private: private:
String _url; String _url;
AsyncEventSourceClient * _clients; LinkedList<AsyncEventSourceClient *> _clients;
ArEventHandlerFunction _connectcb; ArEventHandlerFunction _connectcb;
public: public:
AsyncEventSource(String url); AsyncEventSource(const String& url);
~AsyncEventSource(); ~AsyncEventSource();
const char * url(){ return _url.c_str(); } const char * url() const { return _url.c_str(); }
void close(); void close();
void onConnect(ArEventHandlerFunction cb); void onConnect(ArEventHandlerFunction cb);
void send(const char *message, const char *event=NULL, uint32_t id=0, uint32_t reconnect=0); void send(const char *message, const char *event=NULL, uint32_t id=0, uint32_t reconnect=0);
size_t count(); //number clinets connected size_t count() const; //number clinets connected
//system callbacks (do not call) //system callbacks (do not call)
void _addClient(AsyncEventSourceClient * client); void _addClient(AsyncEventSourceClient * client);
void _handleDisconnect(AsyncEventSourceClient * client); void _handleDisconnect(AsyncEventSourceClient * client);
bool canHandle(AsyncWebServerRequest *request); virtual bool canHandle(AsyncWebServerRequest *request) override final;
void handleRequest(AsyncWebServerRequest *request); virtual void handleRequest(AsyncWebServerRequest *request) override final;
}; };
class AsyncEventSourceResponse: public AsyncWebServerResponse { class AsyncEventSourceResponse: public AsyncWebServerResponse {

View File

@@ -133,13 +133,12 @@ class AsyncWebSocketControl {
bool _mask; bool _mask;
bool _finished; bool _finished;
public: public:
AsyncWebSocketControl * next;
AsyncWebSocketControl(uint8_t opcode, uint8_t *data=NULL, size_t len=0, bool mask=false) AsyncWebSocketControl(uint8_t opcode, uint8_t *data=NULL, size_t len=0, bool mask=false)
:_opcode(opcode) :_opcode(opcode)
,_len(len) ,_len(len)
,_mask(len && mask) ,_mask(len && mask)
,_finished(false) ,_finished(false)
,next(NULL){ {
if(data == NULL) if(data == NULL)
_len = 0; _len = 0;
if(_len){ if(_len){
@@ -151,11 +150,11 @@ class AsyncWebSocketControl {
else memcpy(_data, data, len); else memcpy(_data, data, len);
} else _data = NULL; } else _data = NULL;
} }
~AsyncWebSocketControl(){ virtual ~AsyncWebSocketControl(){
if(_data != NULL) if(_data != NULL)
free(_data); free(_data);
} }
bool finished(){ return _finished; } virtual bool finished(){ return _finished; }
uint8_t opcode(){ return _opcode; } uint8_t opcode(){ return _opcode; }
uint8_t len(){ return _len + 2; } uint8_t len(){ return _len + 2; }
size_t send(AsyncClient *client){ size_t send(AsyncClient *client){
@@ -195,18 +194,18 @@ class AsyncWebSocketBasicMessage: public AsyncWebSocketMessage {
_data[_len] = 0; _data[_len] = 0;
} }
} }
virtual ~AsyncWebSocketBasicMessage(){ virtual ~AsyncWebSocketBasicMessage() override {
if(_data != NULL) if(_data != NULL)
free(_data); free(_data);
} }
virtual bool betweenFrames(){ return _acked == _ack; } virtual bool betweenFrames() const override { return _acked == _ack; }
virtual void ack(size_t len, uint32_t time){ virtual void ack(size_t len, uint32_t time) override {
_acked += len; _acked += len;
if(_sent == _len && _acked == _ack){ if(_sent == _len && _acked == _ack){
_status = WS_MSG_SENT; _status = WS_MSG_SENT;
} }
} }
virtual size_t send(AsyncClient *client){ virtual size_t send(AsyncClient *client) override {
if(_status != WS_MSG_SENDING) if(_status != WS_MSG_SENDING)
return 0; return 0;
if(_acked < _ack){ if(_acked < _ack){
@@ -239,17 +238,17 @@ class AsyncWebSocketBasicMessage: public AsyncWebSocketMessage {
const char * AWSC_PING_PAYLOAD = "ESPAsyncWebServer-PING"; const char * AWSC_PING_PAYLOAD = "ESPAsyncWebServer-PING";
const size_t AWSC_PING_PAYLOAD_LEN = 22; const size_t AWSC_PING_PAYLOAD_LEN = 22;
AsyncWebSocketClient::AsyncWebSocketClient(AsyncWebServerRequest *request, AsyncWebSocket *server){ AsyncWebSocketClient::AsyncWebSocketClient(AsyncWebServerRequest *request, AsyncWebSocket *server)
: _controlQueue(LinkedList<AsyncWebSocketControl *>([](AsyncWebSocketControl *c){ delete c; }))
, _messageQueue(LinkedList<AsyncWebSocketMessage *>([](AsyncWebSocketMessage *m){ delete m; }))
{
_client = request->client(); _client = request->client();
_server = server; _server = server;
_clientId = _server->_getNextId(); _clientId = _server->_getNextId();
_status = WS_CONNECTED; _status = WS_CONNECTED;
_controlQueue = NULL;
_messageQueue = NULL;
_pstate = 0; _pstate = 0;
_lastMessageTime = millis(); _lastMessageTime = millis();
_keepAlivePeriod = 0; _keepAlivePeriod = 0;
next = NULL;
_client->setRxTimeout(0); _client->setRxTimeout(0);
_client->onError([](void *r, AsyncClient* c, int8_t error){ ((AsyncWebSocketClient*)(r))->_onError(error); }, this); _client->onError([](void *r, AsyncClient* c, int8_t error){ ((AsyncWebSocketClient*)(r))->_onError(error); }, this);
_client->onAck([](void *r, AsyncClient* c, size_t len, uint32_t time){ ((AsyncWebSocketClient*)(r))->_onAck(len, time); }, this); _client->onAck([](void *r, AsyncClient* c, size_t len, uint32_t time){ ((AsyncWebSocketClient*)(r))->_onAck(len, time); }, this);
@@ -263,61 +262,49 @@ AsyncWebSocketClient::AsyncWebSocketClient(AsyncWebServerRequest *request, Async
} }
AsyncWebSocketClient::~AsyncWebSocketClient(){ AsyncWebSocketClient::~AsyncWebSocketClient(){
while(_messageQueue != NULL){ _messageQueue.free();
AsyncWebSocketMessage * m = _messageQueue; _controlQueue.free();
_messageQueue = _messageQueue->next;
delete(m);
}
while(_controlQueue != NULL){
AsyncWebSocketControl * c = _controlQueue;
_controlQueue = _controlQueue->next;
delete(c);
}
_server->_handleEvent(this, WS_EVT_DISCONNECT, NULL, NULL, 0); _server->_handleEvent(this, WS_EVT_DISCONNECT, NULL, NULL, 0);
} }
void AsyncWebSocketClient::_onAck(size_t len, uint32_t time){ void AsyncWebSocketClient::_onAck(size_t len, uint32_t time){
_lastMessageTime = millis(); _lastMessageTime = millis();
if(_controlQueue != NULL){ if(!_controlQueue.isEmpty()){
AsyncWebSocketControl *controlMessage = _controlQueue; auto head = _controlQueue.front();
if(controlMessage->finished()){ if(head->finished()){
_controlQueue = _controlQueue->next; len -= head->len();
len -= controlMessage->len(); if(_status == WS_DISCONNECTING && head->opcode() == WS_DISCONNECT){
if(_status == WS_DISCONNECTING && controlMessage->opcode() == WS_DISCONNECT){ _controlQueue.remove(head);
delete controlMessage;
_status = WS_DISCONNECTED; _status = WS_DISCONNECTED;
_client->close(true); _client->close(true);
return; return;
} }
delete controlMessage; _controlQueue.remove(head);
} }
} }
if(len && _messageQueue != NULL){ if(len && !_messageQueue.isEmpty()){
_messageQueue->ack(len, time); _messageQueue.front()->ack(len, time);
} }
_runQueue(); _runQueue();
} }
void AsyncWebSocketClient::_onPoll(){ void AsyncWebSocketClient::_onPoll(){
if(_client->canSend() && (_controlQueue != NULL || _messageQueue != NULL)){ if(_client->canSend() && (!_controlQueue.isEmpty() || !_messageQueue.isEmpty())){
_runQueue(); _runQueue();
} else if(_keepAlivePeriod > 0 && _controlQueue == NULL && _messageQueue == NULL && (millis() - _lastMessageTime) >= _keepAlivePeriod){ } else if(_keepAlivePeriod > 0 && _controlQueue.isEmpty() && _messageQueue.isEmpty() && (millis() - _lastMessageTime) >= _keepAlivePeriod){
ping((uint8_t *)AWSC_PING_PAYLOAD, AWSC_PING_PAYLOAD_LEN); ping((uint8_t *)AWSC_PING_PAYLOAD, AWSC_PING_PAYLOAD_LEN);
} }
} }
void AsyncWebSocketClient::_runQueue(){ void AsyncWebSocketClient::_runQueue(){
while(_messageQueue != NULL && _messageQueue->finished()){ while(!_messageQueue.isEmpty() && _messageQueue.front()->finished()){
AsyncWebSocketMessage * m = _messageQueue; _messageQueue.remove(_messageQueue.front());
_messageQueue = _messageQueue->next;
delete(m);
} }
if(_controlQueue != NULL && (_messageQueue == NULL || _messageQueue->betweenFrames()) && webSocketSendFrameWindow(_client) > (size_t)(_controlQueue->len() - 1)){ if(!_controlQueue.isEmpty() && (_messageQueue.isEmpty() || _messageQueue.front()->betweenFrames()) && webSocketSendFrameWindow(_client) > (size_t)(_controlQueue.front()->len() - 1)){
AsyncWebSocketControl *control = _controlQueue; _controlQueue.front()->send(_client);
control->send(_client); } else if(!_messageQueue.isEmpty() && _messageQueue.front()->betweenFrames() && webSocketSendFrameWindow(_client)){
} else if(_messageQueue != NULL && _messageQueue->betweenFrames() && webSocketSendFrameWindow(_client)){ _messageQueue.front()->send(_client);
_messageQueue->send(_client);
} }
} }
@@ -328,13 +315,7 @@ void AsyncWebSocketClient::_queueMessage(AsyncWebSocketMessage *dataMessage){
delete dataMessage; delete dataMessage;
return; return;
} }
if(_messageQueue == NULL){ _messageQueue.add(dataMessage);
_messageQueue = dataMessage;
} else {
AsyncWebSocketMessage * m = _messageQueue;
while(m->next != NULL) m = m->next;
m->next = dataMessage;
}
if(_client->canSend()) if(_client->canSend())
_runQueue(); _runQueue();
} }
@@ -342,13 +323,7 @@ void AsyncWebSocketClient::_queueMessage(AsyncWebSocketMessage *dataMessage){
void AsyncWebSocketClient::_queueControl(AsyncWebSocketControl *controlMessage){ void AsyncWebSocketClient::_queueControl(AsyncWebSocketControl *controlMessage){
if(controlMessage == NULL) if(controlMessage == NULL)
return; return;
if(_controlQueue == NULL){ _controlQueue.add(controlMessage);
_controlQueue = controlMessage;
} else {
AsyncWebSocketControl * m = _controlQueue;
while(m->next != NULL) m = m->next;
m->next = controlMessage;
}
if(_client->canSend()) if(_client->canSend())
_runQueue(); _runQueue();
} }
@@ -604,9 +579,9 @@ uint16_t AsyncWebSocketClient::remotePort() {
* Async Web Socket - Each separate socket location * Async Web Socket - Each separate socket location
*/ */
AsyncWebSocket::AsyncWebSocket(String url) AsyncWebSocket::AsyncWebSocket(const String& url)
:_url(url) :_url(url)
,_clients(NULL) ,_clients(LinkedList<AsyncWebSocketClient *>([](AsyncWebSocketClient *c){ delete c; }))
,_cNextId(1) ,_cNextId(1)
,_enabled(true) ,_enabled(true)
{ {
@@ -622,133 +597,100 @@ void AsyncWebSocket::_handleEvent(AsyncWebSocketClient * client, AwsEventType ty
} }
void AsyncWebSocket::_addClient(AsyncWebSocketClient * client){ void AsyncWebSocket::_addClient(AsyncWebSocketClient * client){
if(_clients == NULL){ _clients.add(client);
_clients = client;
return;
}
AsyncWebSocketClient * c = _clients;
while(c->next != NULL) c = c->next;
c->next = client;
} }
void AsyncWebSocket::_handleDisconnect(AsyncWebSocketClient * client){ void AsyncWebSocket::_handleDisconnect(AsyncWebSocketClient * client){
if(_clients == NULL){
return; _clients.remove_first([=](AsyncWebSocketClient * c){
} return c->id() == client->id();
if(_clients->id() == client->id()){ });
_clients = client->next;
delete client;
return;
}
AsyncWebSocketClient * c = _clients;
while(c->next != NULL && c->next->id() != client->id()) c = c->next;
if(c->next == NULL){
return;
}
c->next = client->next;
delete client;
} }
size_t AsyncWebSocket::count(){ size_t AsyncWebSocket::count() const {
size_t i = 0; return _clients.count_if([](AsyncWebSocketClient * c){
AsyncWebSocketClient * c = _clients; return c->status() == WS_CONNECTED;
while(c != NULL){ });
if(c->status() == WS_CONNECTED)
i++;
c = c->next;
}
return i;
} }
AsyncWebSocketClient * AsyncWebSocket::client(uint32_t id){ AsyncWebSocketClient * AsyncWebSocket::client(uint32_t id){
AsyncWebSocketClient * c = _clients; for(const auto &c: _clients){
while(c != NULL && c->id() != id) if(c->id() == id && c->status() == WS_CONNECTED){
c = c->next; return c;
if(c != NULL && c->status() == WS_CONNECTED) }
return c; }
return NULL; return nullptr;
} }
void AsyncWebSocket::close(uint32_t id, uint16_t code, const char * message){ void AsyncWebSocket::close(uint32_t id, uint16_t code, const char * message){
AsyncWebSocketClient * c = client(id); AsyncWebSocketClient * c = client(id);
if(c != NULL) if(c)
c->close(code, message); c->close(code, message);
} }
void AsyncWebSocket::closeAll(uint16_t code, const char * message){ void AsyncWebSocket::closeAll(uint16_t code, const char * message){
AsyncWebSocketClient * c = _clients; for(const auto& c: _clients){
while(c != NULL){
if(c->status() == WS_CONNECTED) if(c->status() == WS_CONNECTED)
c->close(code, message); c->close(code, message);
c = c->next;
} }
} }
void AsyncWebSocket::ping(uint32_t id, uint8_t *data, size_t len){ void AsyncWebSocket::ping(uint32_t id, uint8_t *data, size_t len){
AsyncWebSocketClient * c = client(id); AsyncWebSocketClient * c = client(id);
if(c != NULL) if(c)
c->ping(data, len); c->ping(data, len);
} }
void AsyncWebSocket::pingAll(uint8_t *data, size_t len){ void AsyncWebSocket::pingAll(uint8_t *data, size_t len){
AsyncWebSocketClient * c = _clients; for(const auto& c: _clients){
while(c != NULL){
if(c->status() == WS_CONNECTED) if(c->status() == WS_CONNECTED)
c->ping(data, len); c->ping(data, len);
c = c->next;
} }
} }
void AsyncWebSocket::text(uint32_t id, const char * message, size_t len){ void AsyncWebSocket::text(uint32_t id, const char * message, size_t len){
AsyncWebSocketClient * c = client(id); AsyncWebSocketClient * c = client(id);
if(c != NULL) if(c)
c->text(message, len); c->text(message, len);
} }
void AsyncWebSocket::textAll(const char * message, size_t len){ void AsyncWebSocket::textAll(const char * message, size_t len){
AsyncWebSocketClient * c = _clients; for(const auto& c: _clients){
while(c != NULL){
if(c->status() == WS_CONNECTED) if(c->status() == WS_CONNECTED)
c->text(message, len); c->text(message, len);
c = c->next;
} }
} }
void AsyncWebSocket::binary(uint32_t id, const char * message, size_t len){ void AsyncWebSocket::binary(uint32_t id, const char * message, size_t len){
AsyncWebSocketClient * c = client(id); AsyncWebSocketClient * c = client(id);
if(c != NULL) if(c)
c->binary(message, len); c->binary(message, len);
} }
void AsyncWebSocket::binaryAll(const char * message, size_t len){ void AsyncWebSocket::binaryAll(const char * message, size_t len){
AsyncWebSocketClient * c = _clients; for(const auto& c: _clients){
while(c != NULL){
if(c->status() == WS_CONNECTED) if(c->status() == WS_CONNECTED)
c->binary(message, len); c->binary(message, len);
c = c->next;
} }
} }
void AsyncWebSocket::message(uint32_t id, AsyncWebSocketMessage *message){ void AsyncWebSocket::message(uint32_t id, AsyncWebSocketMessage *message){
AsyncWebSocketClient * c = client(id); AsyncWebSocketClient * c = client(id);
if(c != NULL) if(c)
c->message(message); c->message(message);
} }
void AsyncWebSocket::messageAll(AsyncWebSocketMessage *message){ void AsyncWebSocket::messageAll(AsyncWebSocketMessage *message){
AsyncWebSocketClient * c = _clients; for(const auto& c: _clients){
while(c != NULL){
if(c->status() == WS_CONNECTED) if(c->status() == WS_CONNECTED)
c->message(message); c->message(message);
c = c->next;
} }
} }
size_t AsyncWebSocket::printf(uint32_t id, const char *format, ...){ size_t AsyncWebSocket::printf(uint32_t id, const char *format, ...){
AsyncWebSocketClient * c = client(id); AsyncWebSocketClient * c = client(id);
if(c != NULL){ if(c){
va_list arg; va_list arg;
va_start(arg, format); va_start(arg, format);
size_t len = c->printf(format, arg); size_t len = c->printf(format, arg);
@@ -854,11 +796,9 @@ void AsyncWebSocket::textAll(const String &message){
textAll(message.c_str(), message.length()); textAll(message.c_str(), message.length());
} }
void AsyncWebSocket::textAll(const __FlashStringHelper *message){ void AsyncWebSocket::textAll(const __FlashStringHelper *message){
AsyncWebSocketClient * c = _clients; for(const auto& c: _clients){
while(c != NULL){
if(c->status() == WS_CONNECTED) if(c->status() == WS_CONNECTED)
c->text(message); c->text(message);
c = c->next;
} }
} }
void AsyncWebSocket::binary(uint32_t id, const char * message){ void AsyncWebSocket::binary(uint32_t id, const char * message){
@@ -891,11 +831,9 @@ void AsyncWebSocket::binaryAll(const String &message){
binaryAll(message.c_str(), message.length()); binaryAll(message.c_str(), message.length());
} }
void AsyncWebSocket::binaryAll(const __FlashStringHelper *message, size_t len){ void AsyncWebSocket::binaryAll(const __FlashStringHelper *message, size_t len){
AsyncWebSocketClient * c = _clients; for(const auto& c: _clients){
while(c != NULL){
if(c->status() == WS_CONNECTED) if(c->status() == WS_CONNECTED)
c-> binary(message, len); c-> binary(message, len);
c = c->next;
} }
} }
@@ -952,7 +890,7 @@ void AsyncWebSocket::handleRequest(AsyncWebServerRequest *request){
* Authentication code from https://github.com/Links2004/arduinoWebSockets/blob/master/src/WebSockets.cpp#L480 * Authentication code from https://github.com/Links2004/arduinoWebSockets/blob/master/src/WebSockets.cpp#L480
*/ */
AsyncWebSocketResponse::AsyncWebSocketResponse(String key, AsyncWebSocket *server){ AsyncWebSocketResponse::AsyncWebSocketResponse(const String& key, AsyncWebSocket *server){
_server = server; _server = server;
_code = 101; _code = 101;
uint8_t * hash = (uint8_t*)malloc(20); uint8_t * hash = (uint8_t*)malloc(20);

View File

@@ -52,13 +52,12 @@ class AsyncWebSocketMessage {
bool _mask; bool _mask;
AwsMessageStatus _status; AwsMessageStatus _status;
public: public:
AsyncWebSocketMessage * next; AsyncWebSocketMessage():_opcode(WS_TEXT),_mask(false),_status(WS_MSG_ERROR){}
AsyncWebSocketMessage():_opcode(WS_TEXT),_mask(false),_status(WS_MSG_ERROR),next(NULL){}
virtual ~AsyncWebSocketMessage(){} virtual ~AsyncWebSocketMessage(){}
virtual void ack(size_t len, uint32_t time){} virtual void ack(size_t len __attribute__((unused)), uint32_t time __attribute__((unused))){}
virtual size_t send(AsyncClient *client){ return 0; } virtual size_t send(AsyncClient *client __attribute__((unused))){ return 0; }
virtual bool finished(){ return _status != WS_MSG_SENDING; } virtual bool finished(){ return _status != WS_MSG_SENDING; }
virtual bool betweenFrames(){ return false; } virtual bool betweenFrames() const { return false; }
}; };
class AsyncWebSocketClient { class AsyncWebSocketClient {
@@ -68,8 +67,8 @@ class AsyncWebSocketClient {
uint32_t _clientId; uint32_t _clientId;
AwsClientStatus _status; AwsClientStatus _status;
AsyncWebSocketControl * _controlQueue; LinkedList<AsyncWebSocketControl *> _controlQueue;
AsyncWebSocketMessage * _messageQueue; LinkedList<AsyncWebSocketMessage *> _messageQueue;
uint8_t _pstate; uint8_t _pstate;
AwsFrameInfo _pinfo; AwsFrameInfo _pinfo;
@@ -82,8 +81,6 @@ class AsyncWebSocketClient {
void _runQueue(); void _runQueue();
public: public:
AsyncWebSocketClient * next;
AsyncWebSocketClient(AsyncWebServerRequest *request, AsyncWebSocket *server); AsyncWebSocketClient(AsyncWebServerRequest *request, AsyncWebSocket *server);
~AsyncWebSocketClient(); ~AsyncWebSocketClient();
@@ -142,18 +139,18 @@ typedef std::function<void(AsyncWebSocket * server, AsyncWebSocketClient * clien
class AsyncWebSocket: public AsyncWebHandler { class AsyncWebSocket: public AsyncWebHandler {
private: private:
String _url; String _url;
AsyncWebSocketClient * _clients; LinkedList<AsyncWebSocketClient *> _clients;
uint32_t _cNextId; uint32_t _cNextId;
AwsEventHandler _eventHandler; AwsEventHandler _eventHandler;
bool _enabled; bool _enabled;
public: public:
AsyncWebSocket(String url); AsyncWebSocket(const String& url);
~AsyncWebSocket(); ~AsyncWebSocket();
const char * url(){ return _url.c_str(); } const char * url() const { return _url.c_str(); }
void enable(bool e){ _enabled = e; } void enable(bool e){ _enabled = e; }
bool enabled() { return _enabled; } bool enabled() const { return _enabled; }
size_t count(); size_t count() const;
AsyncWebSocketClient * client(uint32_t id); AsyncWebSocketClient * client(uint32_t id);
bool hasClient(uint32_t id){ return client(id) != NULL; } bool hasClient(uint32_t id){ return client(id) != NULL; }
@@ -209,8 +206,8 @@ class AsyncWebSocket: public AsyncWebHandler {
void _addClient(AsyncWebSocketClient * client); void _addClient(AsyncWebSocketClient * client);
void _handleDisconnect(AsyncWebSocketClient * client); void _handleDisconnect(AsyncWebSocketClient * client);
void _handleEvent(AsyncWebSocketClient * client, AwsEventType type, void * arg, uint8_t *data, size_t len); void _handleEvent(AsyncWebSocketClient * client, AwsEventType type, void * arg, uint8_t *data, size_t len);
bool canHandle(AsyncWebServerRequest *request); virtual bool canHandle(AsyncWebServerRequest *request) override final;
void handleRequest(AsyncWebServerRequest *request); virtual void handleRequest(AsyncWebServerRequest *request) override final;
}; };
//WebServer response to authenticate the socket and detach the tcp client from the web server request //WebServer response to authenticate the socket and detach the tcp client from the web server request
@@ -219,7 +216,7 @@ class AsyncWebSocketResponse: public AsyncWebServerResponse {
String _content; String _content;
AsyncWebSocket *_server; AsyncWebSocket *_server;
public: public:
AsyncWebSocketResponse(String key, AsyncWebSocket *server); AsyncWebSocketResponse(const String& key, AsyncWebSocket *server);
void _respond(AsyncWebServerRequest *request); void _respond(AsyncWebServerRequest *request);
size_t _ack(AsyncWebServerRequest *request, size_t len, uint32_t time); size_t _ack(AsyncWebServerRequest *request, size_t len, uint32_t time);
bool _sourceValid(){ return true; } bool _sourceValid(){ return true; }

View File

@@ -76,14 +76,13 @@ class AsyncWebParameter {
bool _isFile; bool _isFile;
public: public:
AsyncWebParameter *next;
AsyncWebParameter(String name, String value, bool form=false, bool file=false, size_t size=0): _name(name), _value(value), _size(size), _isForm(form), _isFile(file), next(NULL){} AsyncWebParameter(const String& name, const String& value, bool form=false, bool file=false, size_t size=0): _name(name), _value(value), _size(size), _isForm(form), _isFile(file){}
String name(){ return _name; } const String& name() const { return _name; }
String value(){ return _value; } const String& value() const { return _value; }
size_t size(){ return _size; } size_t size() const { return _size; }
bool isPost(){ return _isForm; } bool isPost() const { return _isForm; }
bool isFile(){ return _isFile; } bool isFile() const { return _isFile; }
}; };
/* /*
@@ -96,10 +95,8 @@ class AsyncWebHeader {
String _value; String _value;
public: public:
AsyncWebHeader *next; AsyncWebHeader(const String& name, const String& value): _name(name), _value(value){}
AsyncWebHeader(const String& data): _name(), _value(){
AsyncWebHeader(String name, String value): _name(name), _value(value), next(NULL){}
AsyncWebHeader(String data): _name(), _value(), next(NULL){
if(!data) return; if(!data) return;
int index = data.indexOf(':'); int index = data.indexOf(':');
if (index < 0) return; if (index < 0) return;
@@ -107,9 +104,9 @@ class AsyncWebHeader {
_value = data.substring(index + 2); _value = data.substring(index + 2);
} }
~AsyncWebHeader(){} ~AsyncWebHeader(){}
String name(){ return _name; } const String& name() const { return _name; }
String value(){ return _value; } const String& value() const { return _value; }
String toString(){ return String(_name+": "+_value+"\r\n"); } String toString() const { return String(_name+": "+_value+"\r\n"); }
}; };
/* /*
@@ -125,7 +122,7 @@ class AsyncWebServerRequest {
AsyncWebServer* _server; AsyncWebServer* _server;
AsyncWebHandler* _handler; AsyncWebHandler* _handler;
AsyncWebServerResponse* _response; AsyncWebServerResponse* _response;
StringArray* _interestingHeaders; StringArray _interestingHeaders;
String _temp; String _temp;
uint8_t _parseState; uint8_t _parseState;
@@ -144,8 +141,8 @@ class AsyncWebServerRequest {
size_t _contentLength; size_t _contentLength;
size_t _parsedLength; size_t _parsedLength;
AsyncWebHeader *_headers; LinkedList<AsyncWebHeader *> _headers;
AsyncWebParameter *_params; LinkedList<AsyncWebParameter *> _params;
uint8_t _multiParseState; uint8_t _multiParseState;
uint8_t _boundaryPosition; uint8_t _boundaryPosition;
@@ -173,7 +170,7 @@ class AsyncWebServerRequest {
void _parseLine(); void _parseLine();
void _parsePlainPostChar(uint8_t data); void _parsePlainPostChar(uint8_t data);
void _parseMultipartPostByte(uint8_t data, bool last); void _parseMultipartPostByte(uint8_t data, bool last);
void _addGetParams(String params); void _addGetParams(const String& params);
void _handleUploadStart(); void _handleUploadStart();
void _handleUploadByte(uint8_t data, bool last); void _handleUploadByte(uint8_t data, bool last);
@@ -182,20 +179,19 @@ class AsyncWebServerRequest {
public: public:
File _tempFile; File _tempFile;
void *_tempObject; void *_tempObject;
AsyncWebServerRequest *next;
AsyncWebServerRequest(AsyncWebServer*, AsyncClient*); AsyncWebServerRequest(AsyncWebServer*, AsyncClient*);
~AsyncWebServerRequest(); ~AsyncWebServerRequest();
AsyncClient* client(){ return _client; } AsyncClient* client(){ return _client; }
uint8_t version(){ return _version; } uint8_t version() const { return _version; }
WebRequestMethodComposite method(){ return _method; } WebRequestMethodComposite method() const { return _method; }
String url(){ return _url; } const String& url() const { return _url; }
String host(){ return _host; } const String& host() const { return _host; }
String contentType(){ return _contentType; } const String& contentType() const { return _contentType; }
size_t contentLength(){ return _contentLength; } size_t contentLength() const { return _contentLength; }
bool multipart(){ return _isMultipart; } bool multipart() const { return _isMultipart; }
const char * methodToString(); const char * methodToString() const;
//hash is the string representation of: //hash is the string representation of:
@@ -206,52 +202,50 @@ class AsyncWebServerRequest {
void requestAuthentication(const char * realm = NULL, bool isDigest = true); void requestAuthentication(const char * realm = NULL, bool isDigest = true);
void setHandler(AsyncWebHandler *handler){ _handler = handler; } void setHandler(AsyncWebHandler *handler){ _handler = handler; }
void addInterestingHeader(String name); void addInterestingHeader(const String& name);
void redirect(String url); void redirect(const String& url);
void send(AsyncWebServerResponse *response); void send(AsyncWebServerResponse *response);
void send(int code, String contentType=String(), String content=String()); void send(int code, const String& contentType=String(), const String& content=String());
void send(FS &fs, String path, String contentType=String(), bool download=false); void send(FS &fs, const String& path, const String& contentType=String(), bool download=false);
void send(File content, String path, String contentType=String(), bool download=false); void send(File content, const String& path, const String& contentType=String(), bool download=false);
void send(Stream &stream, String contentType, size_t len); void send(Stream &stream, const String& contentType, size_t len);
void send(String contentType, size_t len, AwsResponseFiller callback); void send(const String& contentType, size_t len, AwsResponseFiller callback);
void sendChunked(String contentType, AwsResponseFiller callback); void sendChunked(const String& contentType, AwsResponseFiller callback);
void send_P(int code, String contentType, const uint8_t * content, size_t len); void send_P(int code, const String& contentType, const uint8_t * content, size_t len);
void send_P(int code, String contentType, PGM_P content); void send_P(int code, const String& contentType, PGM_P content);
AsyncWebServerResponse *beginResponse(int code, String contentType=String(), String content=String()); AsyncWebServerResponse *beginResponse(int code, const String& contentType=String(), const String& content=String());
AsyncWebServerResponse *beginResponse(FS &fs, String path, String contentType=String(), bool download=false); AsyncWebServerResponse *beginResponse(FS &fs, const String& path, const String& contentType=String(), bool download=false);
AsyncWebServerResponse *beginResponse(File content, String path, String contentType=String(), bool download=false); AsyncWebServerResponse *beginResponse(File content, const String& path, const String& contentType=String(), bool download=false);
AsyncWebServerResponse *beginResponse(Stream &stream, String contentType, size_t len); AsyncWebServerResponse *beginResponse(Stream &stream, const String& contentType, size_t len);
AsyncWebServerResponse *beginResponse(String contentType, size_t len, AwsResponseFiller callback); AsyncWebServerResponse *beginResponse(const String& contentType, size_t len, AwsResponseFiller callback);
AsyncWebServerResponse *beginChunkedResponse(String contentType, AwsResponseFiller callback); AsyncWebServerResponse *beginChunkedResponse(const String& contentType, AwsResponseFiller callback);
AsyncResponseStream *beginResponseStream(String contentType, size_t bufferSize=1460); AsyncResponseStream *beginResponseStream(const String& contentType, size_t bufferSize=1460);
AsyncWebServerResponse *beginResponse_P(int code, String contentType, const uint8_t * content, size_t len); AsyncWebServerResponse *beginResponse_P(int code, const String& contentType, const uint8_t * content, size_t len);
AsyncWebServerResponse *beginResponse_P(int code, String contentType, PGM_P content); AsyncWebServerResponse *beginResponse_P(int code, const String& contentType, PGM_P content);
int headers(); // get header count size_t headers() const; // get header count
bool hasHeader(String name); bool hasHeader(const String& name) const; // check if header exists
AsyncWebHeader* getHeader(String name); AsyncWebHeader* getHeader(const String& name) const;
AsyncWebHeader* getHeader(int num); AsyncWebHeader* getHeader(size_t num) const;
int params(); // get arguments count size_t params() const; // get arguments count
bool hasParam(String name, bool post=false, bool file=false); bool hasParam(const String& name, bool post=false, bool file=false) const;
AsyncWebParameter* getParam(String name, bool post=false, bool file=false); AsyncWebParameter* getParam(const String& name, bool post=false, bool file=false) const;
AsyncWebParameter* getParam(int num); AsyncWebParameter* getParam(size_t num) const;
int args(){ return params(); } // get arguments count size_t args() const { return params(); } // get arguments count
String arg(const char* name); // get request argument value by name const String& arg(const String& name) const; // get request argument value by name
String arg(int i); // get request argument value by number const String& arg(size_t i) const; // get request argument value by number
String argName(int i); // get request argument name by number const String& argName(size_t i) const; // get request argument name by number
bool hasArg(const char* name); // check if argument exists bool hasArg(const char* name) const; // check if argument exists
String header(const char* name); // get request header value by name const String& header(const char* name) const;// get request header value by name
String header(int i); // get request header value by number const String& header(size_t i) const; // get request header value by number
String headerName(int i); // get request header name by number const String& headerName(size_t i) const; // get request header name by number
bool hasHeader(const char* name); // check if header exists String urlDecode(const String& text) const;
String urlDecode(const String& text);
}; };
/* /*
@@ -260,13 +254,9 @@ class AsyncWebServerRequest {
typedef std::function<bool(AsyncWebServerRequest *request)> ArRequestFilterFunction; typedef std::function<bool(AsyncWebServerRequest *request)> ArRequestFilterFunction;
static bool ON_STA_FILTER(AsyncWebServerRequest *request) { bool ON_STA_FILTER(AsyncWebServerRequest *request);
return WiFi.localIP() == request->client()->localIP();
}
static bool ON_AP_FILTER(AsyncWebServerRequest *request) { bool ON_AP_FILTER(AsyncWebServerRequest *request);
return WiFi.localIP() != request->client()->localIP();
}
/* /*
* REWRITE :: One instance can be handle any Request (done by the Server) * REWRITE :: One instance can be handle any Request (done by the Server)
@@ -279,8 +269,7 @@ class AsyncWebRewrite {
String _params; String _params;
ArRequestFilterFunction _filter; ArRequestFilterFunction _filter;
public: public:
AsyncWebRewrite* next; AsyncWebRewrite(const char* from, const char* to): _from(from), _toUrl(to), _params(String()), _filter(NULL){
AsyncWebRewrite(const char* from, const char* to): _from(from), _toUrl(to), _params(String()), _filter(NULL), next(NULL){
int index = _toUrl.indexOf('?'); int index = _toUrl.indexOf('?');
if (index > 0) { if (index > 0) {
_params = _toUrl.substring(index +1); _params = _toUrl.substring(index +1);
@@ -288,10 +277,10 @@ class AsyncWebRewrite {
} }
} }
AsyncWebRewrite& setFilter(ArRequestFilterFunction fn) { _filter = fn; return *this; } AsyncWebRewrite& setFilter(ArRequestFilterFunction fn) { _filter = fn; return *this; }
bool filter(AsyncWebServerRequest *request){ return _filter == NULL || _filter(request); } bool filter(AsyncWebServerRequest *request) const { return _filter == NULL || _filter(request); }
String from(void) { return _from; } const String& from(void) const { return _from; }
String toUrl(void) { return _toUrl; } const String& toUrl(void) const { return _toUrl; }
String params(void) { return _params; } const String& params(void) const { return _params; }
}; };
/* /*
@@ -302,15 +291,16 @@ class AsyncWebHandler {
protected: protected:
ArRequestFilterFunction _filter; ArRequestFilterFunction _filter;
public: public:
AsyncWebHandler* next; AsyncWebHandler(){}
AsyncWebHandler(): next(NULL){}
AsyncWebHandler& setFilter(ArRequestFilterFunction fn) { _filter = fn; return *this; } AsyncWebHandler& setFilter(ArRequestFilterFunction fn) { _filter = fn; return *this; }
bool filter(AsyncWebServerRequest *request){ return _filter == NULL || _filter(request); } bool filter(AsyncWebServerRequest *request){ return _filter == NULL || _filter(request); }
virtual ~AsyncWebHandler(){} virtual ~AsyncWebHandler(){}
virtual bool canHandle(AsyncWebServerRequest *request){ return false; } virtual bool canHandle(AsyncWebServerRequest *request __attribute__((unused))){
virtual void handleRequest(AsyncWebServerRequest *request){} return false;
virtual void handleUpload(AsyncWebServerRequest *request, String filename, size_t index, uint8_t *data, size_t len, bool final){} }
virtual void handleBody(AsyncWebServerRequest *request, uint8_t *data, size_t len, size_t index, size_t total){} virtual void handleRequest(AsyncWebServerRequest *request __attribute__((unused))){}
virtual void handleUpload(AsyncWebServerRequest *request __attribute__((unused)), const String& filename __attribute__((unused)), size_t index __attribute__((unused)), uint8_t *data __attribute__((unused)), size_t len __attribute__((unused)), bool final __attribute__((unused))){}
virtual void handleBody(AsyncWebServerRequest *request __attribute__((unused)), uint8_t *data __attribute__((unused)), size_t len __attribute__((unused)), size_t index __attribute__((unused)), size_t total __attribute__((unused))){}
}; };
/* /*
@@ -324,7 +314,7 @@ typedef enum {
class AsyncWebServerResponse { class AsyncWebServerResponse {
protected: protected:
int _code; int _code;
AsyncWebHeader *_headers; LinkedList<AsyncWebHeader *> _headers;
String _contentType; String _contentType;
size_t _contentLength; size_t _contentLength;
bool _sendContentLength; bool _sendContentLength;
@@ -341,13 +331,13 @@ class AsyncWebServerResponse {
virtual ~AsyncWebServerResponse(); virtual ~AsyncWebServerResponse();
virtual void setCode(int code); virtual void setCode(int code);
virtual void setContentLength(size_t len); virtual void setContentLength(size_t len);
virtual void setContentType(String type); virtual void setContentType(const String& type);
virtual void addHeader(String name, String value); virtual void addHeader(const String& name, const String& value);
virtual String _assembleHead(uint8_t version); virtual String _assembleHead(uint8_t version);
virtual bool _started(); virtual bool _started() const;
virtual bool _finished(); virtual bool _finished() const;
virtual bool _failed(); virtual bool _failed() const;
virtual bool _sourceValid(); virtual bool _sourceValid() const;
virtual void _respond(AsyncWebServerRequest *request); virtual void _respond(AsyncWebServerRequest *request);
virtual size_t _ack(AsyncWebServerRequest *request, size_t len, uint32_t time); virtual size_t _ack(AsyncWebServerRequest *request, size_t len, uint32_t time);
}; };
@@ -357,14 +347,14 @@ class AsyncWebServerResponse {
* */ * */
typedef std::function<void(AsyncWebServerRequest *request)> ArRequestHandlerFunction; typedef std::function<void(AsyncWebServerRequest *request)> ArRequestHandlerFunction;
typedef std::function<void(AsyncWebServerRequest *request, String filename, size_t index, uint8_t *data, size_t len, bool final)> ArUploadHandlerFunction; typedef std::function<void(AsyncWebServerRequest *request, const String& filename, size_t index, uint8_t *data, size_t len, bool final)> ArUploadHandlerFunction;
typedef std::function<void(AsyncWebServerRequest *request, uint8_t *data, size_t len, size_t index, size_t total)> ArBodyHandlerFunction; typedef std::function<void(AsyncWebServerRequest *request, uint8_t *data, size_t len, size_t index, size_t total)> ArBodyHandlerFunction;
class AsyncWebServer { class AsyncWebServer {
protected: protected:
AsyncServer _server; AsyncServer _server;
AsyncWebRewrite* _rewrites; LinkedList<AsyncWebRewrite*> _rewrites;
AsyncWebHandler* _handlers; LinkedList<AsyncWebHandler*> _handlers;
AsyncWebHandler* _catchAllHandler; AsyncWebHandler* _catchAllHandler;
public: public:
@@ -380,7 +370,6 @@ class AsyncWebServer {
AsyncWebRewrite& addRewrite(AsyncWebRewrite* rewrite); AsyncWebRewrite& addRewrite(AsyncWebRewrite* rewrite);
bool removeRewrite(AsyncWebRewrite* rewrite); bool removeRewrite(AsyncWebRewrite* rewrite);
AsyncWebRewrite& rewrite(const char* from, const char* to); AsyncWebRewrite& rewrite(const char* from, const char* to);
AsyncWebHandler& addHandler(AsyncWebHandler* handler); AsyncWebHandler& addHandler(AsyncWebHandler* handler);

View File

@@ -317,7 +317,7 @@ const uint8_t edit_htm_gz[] PROGMEM = {
// WEB HANDLER IMPLEMENTATION // WEB HANDLER IMPLEMENTATION
SPIFFSEditor::SPIFFSEditor(String username, String password) SPIFFSEditor::SPIFFSEditor(const String& username, const String& password)
:_username(username) :_username(username)
,_password(password) ,_password(password)
,_authenticated(false) ,_authenticated(false)
@@ -418,7 +418,7 @@ void SPIFFSEditor::handleRequest(AsyncWebServerRequest *request){
} }
} }
void SPIFFSEditor::handleUpload(AsyncWebServerRequest *request, String filename, size_t index, uint8_t *data, size_t len, bool final){ void SPIFFSEditor::handleUpload(AsyncWebServerRequest *request, const String& filename, size_t index, uint8_t *data, size_t len, bool final){
if(!index){ if(!index){
if(!_username.length() || request->authenticate(_username.c_str(),_password.c_str())){ if(!_username.length() || request->authenticate(_username.c_str(),_password.c_str())){
_authenticated = true; _authenticated = true;

View File

@@ -9,10 +9,10 @@ class SPIFFSEditor: public AsyncWebHandler {
bool _authenticated; bool _authenticated;
uint32_t _startTime; uint32_t _startTime;
public: public:
SPIFFSEditor(String username=String(), String password=String()); SPIFFSEditor(const String& username=String(), const String& password=String());
bool canHandle(AsyncWebServerRequest *request); virtual bool canHandle(AsyncWebServerRequest *request) override final;
void handleRequest(AsyncWebServerRequest *request); virtual void handleRequest(AsyncWebServerRequest *request) override final;
void handleUpload(AsyncWebServerRequest *request, String filename, size_t index, uint8_t *data, size_t len, bool final); virtual void handleUpload(AsyncWebServerRequest *request, const String& filename, size_t index, uint8_t *data, size_t len, bool final) override final;
}; };
#endif #endif

View File

@@ -24,88 +24,110 @@
#include "stddef.h" #include "stddef.h"
#include "WString.h" #include "WString.h"
class StringArrayItem; template <typename T>
class StringArrayItem { class LinkedListNode {
private: T _value;
String _string;
public: public:
StringArrayItem *next; LinkedListNode<T>* next;
StringArrayItem(String str):_string(str), next(NULL){} LinkedListNode(const T val): _value(val), next(nullptr) {}
~StringArrayItem(){} ~LinkedListNode(){}
String string(){ return _string; } const T& value() const { return _value; };
T& value(){ return _value; }
}; };
class StringArray { template <typename T, template<typename> class Item = LinkedListNode>
private: class LinkedList {
StringArrayItem *_items;
public: public:
StringArray():_items(NULL){} typedef Item<T> ItemType;
StringArray(StringArrayItem *items):_items(items){} typedef std::function<void(const T&)> OnRemove;
~StringArray(){} typedef std::function<bool(const T&)> Predicate;
StringArrayItem *items(){ private:
return _items; ItemType* _root;
} OnRemove _onRemove;
void add(String str){
StringArrayItem *it = new StringArrayItem(str); class Iterator {
if(_items == NULL){ ItemType* _node;
_items = it; public:
Iterator(ItemType* current = nullptr) : _node(current) {}
Iterator(const Iterator& i) : _node(i._node) {}
Iterator& operator ++() { _node = _node->next; return *this; }
bool operator != (const Iterator& i) const { return _node != i._node; }
const T& operator * () const { return _node->value(); }
const T* operator -> () const { return &_node->value(); }
};
public:
typedef const Iterator ConstIterator;
ConstIterator begin() const { return ConstIterator(_root); }
ConstIterator end() const { return ConstIterator(nullptr); }
LinkedList(OnRemove onRemove) : _root(nullptr), _onRemove(onRemove) {}
~LinkedList(){}
void add(const T& t){
auto it = new ItemType(t);
if(!_root){
_root = it;
} else { } else {
StringArrayItem *i = _items; auto i = _root;
while(i->next != NULL) i = i->next; while(i->next) i = i->next;
i->next = it; i->next = it;
} }
} }
size_t length(){ T& front() const {
return _root->value();
}
bool isEmpty() const {
return _root == nullptr;
}
size_t length() const {
size_t i = 0; size_t i = 0;
StringArrayItem *it = _items; auto it = _root;
while(it != NULL){ while(it){
i++; i++;
it = it->next; it = it->next;
} }
return i; return i;
} }
bool contains(String str){ size_t count_if(Predicate predicate) const {
StringArrayItem *it = _items;
while(it != NULL){
if(it->string() == str)
return true;
it = it->next;
}
return false;
}
bool containsIgnoreCase(String str){
StringArrayItem *it = _items;
while(it != NULL){
if(it->string().equalsIgnoreCase(str))
return true;
it = it->next;
}
return false;
}
String get(size_t index){
size_t i = 0; size_t i = 0;
StringArrayItem *it = _items; auto it = _root;
while(it != NULL){ while(it){
if(i++ == index) if (!predicate){
return it->string(); i++;
}
else if (predicate(it->value())) {
i++;
}
it = it->next; it = it->next;
} }
return String(); return i;
} }
bool remove(size_t index){ const T* nth(size_t N) const {
StringArrayItem *it = _items;
if(!index){
if(_items == NULL)
return false;
_items = _items->next;
delete it;
return true;
}
size_t i = 0; size_t i = 0;
StringArrayItem *pit = _items; auto it = _root;
while(it != NULL){ while(it){
if(i++ == index){ if(i++ == N)
pit->next = it->next; return &(it->value());
it = it->next;
}
return nullptr;
}
bool remove(const T& t){
auto it = _root;
auto pit = _root;
while(it){
if(it->value() == t){
if(it == _root){
_root = _root->next;
} else {
pit->next = it->next;
}
if (_onRemove) {
_onRemove(it->value());
}
delete it; delete it;
return true; return true;
} }
@@ -114,16 +136,19 @@ class StringArray {
} }
return false; return false;
} }
bool remove(String str){ bool remove_first(Predicate predicate){
StringArrayItem *it = _items; auto it = _root;
StringArrayItem *pit = _items; auto pit = _root;
while(it != NULL){ while(it){
if(it->string() == str){ if(predicate(it->value())){
if(it == _items){ if(it == _root){
_items = _items->next; _root = _root->next;
} else { } else {
pit->next = it->next; pit->next = it->next;
} }
if (_onRemove) {
_onRemove(it->value());
}
delete it; delete it;
return true; return true;
} }
@@ -132,16 +157,37 @@ class StringArray {
} }
return false; return false;
} }
void free(){ void free(){
StringArrayItem *it; while(_root != nullptr){
while(_items != NULL){ auto it = _root;
it = _items; _root = _root->next;
_items = _items->next; if (_onRemove) {
_onRemove(it->value());
}
delete it; delete it;
} }
_root = nullptr;
} }
}; };
class StringArray : public LinkedList<String> {
public:
StringArray() : LinkedList(nullptr) {}
bool containsIgnoreCase(const String& str){
for (const auto& s : *this) {
if (str.equalsIgnoreCase(s)) {
return true;
}
}
return false;
}
};
#endif /* STRINGARRAY_H_ */ #endif /* STRINGARRAY_H_ */

View File

@@ -84,7 +84,7 @@ static String genRandomMD5(){
return res; return res;
} }
static String stringMD5(String in){ static String stringMD5(const String& in){
char * out = (char*)malloc(33); char * out = (char*)malloc(33);
if(out == NULL || !getMD5((uint8_t*)(in.c_str()), in.length(), out)) if(out == NULL || !getMD5((uint8_t*)(in.c_str()), in.length(), out))
return ""; return "";

View File

@@ -28,8 +28,8 @@
class AsyncStaticWebHandler: public AsyncWebHandler { class AsyncStaticWebHandler: public AsyncWebHandler {
private: private:
bool _getFile(AsyncWebServerRequest *request); bool _getFile(AsyncWebServerRequest *request);
bool _fileExists(AsyncWebServerRequest *request, const String path); bool _fileExists(AsyncWebServerRequest *request, const String& path);
uint8_t _countBits(const uint8_t value); uint8_t _countBits(const uint8_t value) const;
protected: protected:
FS _fs; FS _fs;
String _uri; String _uri;
@@ -42,8 +42,8 @@ class AsyncStaticWebHandler: public AsyncWebHandler {
uint8_t _gzipStats; uint8_t _gzipStats;
public: public:
AsyncStaticWebHandler(const char* uri, FS& fs, const char* path, const char* cache_control); AsyncStaticWebHandler(const char* uri, FS& fs, const char* path, const char* cache_control);
bool canHandle(AsyncWebServerRequest *request); virtual bool canHandle(AsyncWebServerRequest *request) override final;
void handleRequest(AsyncWebServerRequest *request); virtual void handleRequest(AsyncWebServerRequest *request) override final;
AsyncStaticWebHandler& setIsDir(bool isDir); AsyncStaticWebHandler& setIsDir(bool isDir);
AsyncStaticWebHandler& setDefaultFile(const char* filename); AsyncStaticWebHandler& setDefaultFile(const char* filename);
AsyncStaticWebHandler& setCacheControl(const char* cache_control); AsyncStaticWebHandler& setCacheControl(const char* cache_control);
@@ -65,13 +65,14 @@ class AsyncCallbackWebHandler: public AsyncWebHandler {
ArBodyHandlerFunction _onBody; ArBodyHandlerFunction _onBody;
public: public:
AsyncCallbackWebHandler() : _uri(), _method(HTTP_ANY), _onRequest(NULL), _onUpload(NULL), _onBody(NULL){} AsyncCallbackWebHandler() : _uri(), _method(HTTP_ANY), _onRequest(NULL), _onUpload(NULL), _onBody(NULL){}
void setUri(String uri){ _uri = uri; } void setUri(const String& uri){ _uri = uri; }
void setMethod(WebRequestMethodComposite method){ _method = method; } void setMethod(WebRequestMethodComposite method){ _method = method; }
void onRequest(ArRequestHandlerFunction fn){ _onRequest = fn; } void onRequest(ArRequestHandlerFunction fn){ _onRequest = fn; }
void onUpload(ArUploadHandlerFunction fn){ _onUpload = fn; } void onUpload(ArUploadHandlerFunction fn){ _onUpload = fn; }
void onBody(ArBodyHandlerFunction fn){ _onBody = fn; } void onBody(ArBodyHandlerFunction fn){ _onBody = fn; }
bool canHandle(AsyncWebServerRequest *request){ virtual bool canHandle(AsyncWebServerRequest *request) override final{
if(!_onRequest) if(!_onRequest)
return false; return false;
@@ -84,17 +85,18 @@ class AsyncCallbackWebHandler: public AsyncWebHandler {
request->addInterestingHeader("ANY"); request->addInterestingHeader("ANY");
return true; return true;
} }
void handleRequest(AsyncWebServerRequest *request){
virtual void handleRequest(AsyncWebServerRequest *request) override final {
if(_onRequest) if(_onRequest)
_onRequest(request); _onRequest(request);
else else
request->send(500); request->send(500);
} }
void handleUpload(AsyncWebServerRequest *request, String filename, size_t index, uint8_t *data, size_t len, bool final){ virtual void handleUpload(AsyncWebServerRequest *request, const String& filename, size_t index, uint8_t *data, size_t len, bool final) override final {
if(_onUpload) if(_onUpload)
_onUpload(request, filename, index, data, len, final); _onUpload(request, filename, index, data, len, final);
} }
void handleBody(AsyncWebServerRequest *request, uint8_t *data, size_t len, size_t index, size_t total){ virtual void handleBody(AsyncWebServerRequest *request, uint8_t *data, size_t len, size_t index, size_t total) override final {
if(_onBody) if(_onBody)
_onBody(request, data, len, index, total); _onBody(request, data, len, index, total);
} }

View File

@@ -79,8 +79,7 @@ AsyncStaticWebHandler& AsyncStaticWebHandler::setLastModified(){
return setLastModified(last_modified); return setLastModified(last_modified);
} }
#endif #endif
bool AsyncStaticWebHandler::canHandle(AsyncWebServerRequest *request) bool AsyncStaticWebHandler::canHandle(AsyncWebServerRequest *request){
{
if (request->method() == HTTP_GET && if (request->method() == HTTP_GET &&
request->url().startsWith(_uri) && request->url().startsWith(_uri) &&
_getFile(request)) { _getFile(request)) {
@@ -125,7 +124,7 @@ bool AsyncStaticWebHandler::_getFile(AsyncWebServerRequest *request)
return _fileExists(request, path); return _fileExists(request, path);
} }
bool AsyncStaticWebHandler::_fileExists(AsyncWebServerRequest *request, const String path) bool AsyncStaticWebHandler::_fileExists(AsyncWebServerRequest *request, const String& path)
{ {
bool fileFound = false; bool fileFound = false;
bool gzipFound = false; bool gzipFound = false;
@@ -167,7 +166,7 @@ bool AsyncStaticWebHandler::_fileExists(AsyncWebServerRequest *request, const St
return found; return found;
} }
uint8_t AsyncStaticWebHandler::_countBits(const uint8_t value) uint8_t AsyncStaticWebHandler::_countBits(const uint8_t value) const
{ {
uint8_t w = value; uint8_t w = value;
uint8_t n; uint8_t n;

View File

@@ -26,6 +26,8 @@
#define os_strlen strlen #define os_strlen strlen
#endif #endif
static const String SharedEmptyString = String();
#define __is_param_char(c) ((c) && ((c) != '{') && ((c) != '[') && ((c) != '&') && ((c) != '=')) #define __is_param_char(c) ((c) && ((c) != '{') && ((c) != '[') && ((c) != '&') && ((c) != '='))
enum { PARSE_REQ_START, PARSE_REQ_HEADERS, PARSE_REQ_BODY, PARSE_REQ_END, PARSE_REQ_FAIL }; enum { PARSE_REQ_START, PARSE_REQ_HEADERS, PARSE_REQ_BODY, PARSE_REQ_END, PARSE_REQ_FAIL };
@@ -35,7 +37,6 @@ AsyncWebServerRequest::AsyncWebServerRequest(AsyncWebServer* s, AsyncClient* c)
, _server(s) , _server(s)
, _handler(NULL) , _handler(NULL)
, _response(NULL) , _response(NULL)
, _interestingHeaders(new StringArray())
, _temp() , _temp()
, _parseState(0) , _parseState(0)
, _version(0) , _version(0)
@@ -51,8 +52,8 @@ AsyncWebServerRequest::AsyncWebServerRequest(AsyncWebServer* s, AsyncClient* c)
, _expectingContinue(false) , _expectingContinue(false)
, _contentLength(0) , _contentLength(0)
, _parsedLength(0) , _parsedLength(0)
, _headers(NULL) , _headers(LinkedList<AsyncWebHeader *>([](AsyncWebHeader *h){ delete h; }))
, _params(NULL) , _params(LinkedList<AsyncWebParameter *>([](AsyncWebParameter *p){ delete p; }))
, _multiParseState(0) , _multiParseState(0)
, _boundaryPosition(0) , _boundaryPosition(0)
, _itemStartIndex(0) , _itemStartIndex(0)
@@ -65,7 +66,6 @@ AsyncWebServerRequest::AsyncWebServerRequest(AsyncWebServer* s, AsyncClient* c)
, _itemBufferIndex(0) , _itemBufferIndex(0)
, _itemIsFile(false) , _itemIsFile(false)
, _tempObject(NULL) , _tempObject(NULL)
, next(NULL)
{ {
c->onError([](void *r, AsyncClient* c, int8_t error){ AsyncWebServerRequest *req = (AsyncWebServerRequest*)r; req->_onError(error); }, this); c->onError([](void *r, AsyncClient* c, int8_t error){ AsyncWebServerRequest *req = (AsyncWebServerRequest*)r; req->_onError(error); }, this);
c->onAck([](void *r, AsyncClient* c, size_t len, uint32_t time){ AsyncWebServerRequest *req = (AsyncWebServerRequest*)r; req->_onAck(len, time); }, this); c->onAck([](void *r, AsyncClient* c, size_t len, uint32_t time){ AsyncWebServerRequest *req = (AsyncWebServerRequest*)r; req->_onAck(len, time); }, this);
@@ -76,20 +76,11 @@ AsyncWebServerRequest::AsyncWebServerRequest(AsyncWebServer* s, AsyncClient* c)
} }
AsyncWebServerRequest::~AsyncWebServerRequest(){ AsyncWebServerRequest::~AsyncWebServerRequest(){
while(_headers != NULL){ _headers.free();
AsyncWebHeader *h = _headers;
_headers = h->next;
delete h;
}
while(_params != NULL){ _params.free();
AsyncWebParameter *p = _params;
_params = p->next;
delete p;
}
_interestingHeaders->free(); _interestingHeaders.free();
delete _interestingHeaders;
if(_response != NULL){ if(_response != NULL){
delete _response; delete _response;
@@ -199,18 +190,10 @@ void AsyncWebServerRequest::_onDisconnect(){
} }
void AsyncWebServerRequest::_addParam(AsyncWebParameter *p){ void AsyncWebServerRequest::_addParam(AsyncWebParameter *p){
if(p == NULL) _params.add(p);
return;
if(_params == NULL)
_params = p;
else {
AsyncWebParameter *ps = _params;
while(ps->next != NULL) ps = ps->next;
ps->next = p;
}
} }
void AsyncWebServerRequest::_addGetParams(String params){ void AsyncWebServerRequest::_addGetParams(const String& params){
size_t start = 0; size_t start = 0;
while (start < params.length()){ while (start < params.length()){
int end = params.indexOf('&', start); int end = params.indexOf('&', start);
@@ -294,15 +277,8 @@ bool AsyncWebServerRequest::_parseReqHeader(){
_authorization = value.substring(7); _authorization = value.substring(7);
} }
} else { } else {
if(_interestingHeaders->containsIgnoreCase(name) || _interestingHeaders->containsIgnoreCase("ANY")){ if(_interestingHeaders.containsIgnoreCase(name) || _interestingHeaders.containsIgnoreCase("ANY")){
AsyncWebHeader *h = new AsyncWebHeader(name, value); _headers.add(new AsyncWebHeader(name, value));
if(_headers == NULL)
_headers = h;
else {
AsyncWebHeader *hs = _headers;
while(hs->next != NULL) hs = hs->next;
hs->next = h;
}
} }
} }
} }
@@ -541,89 +517,63 @@ void AsyncWebServerRequest::_parseLine(){
} }
} }
size_t AsyncWebServerRequest::headers() const{
int AsyncWebServerRequest::headers(){ return _headers.length();
int i = 0;
AsyncWebHeader* h = _headers;
while(h != NULL){
i++; h = h->next;
}
return i;
} }
bool AsyncWebServerRequest::hasHeader(String name){ bool AsyncWebServerRequest::hasHeader(const String& name) const {
AsyncWebHeader* h = _headers; for(const auto& h: _headers){
while(h != NULL){ if(h->name().equalsIgnoreCase(name)){
if(h->name().equalsIgnoreCase(name))
return true; return true;
h = h->next; }
} }
return false; return false;
} }
AsyncWebHeader* AsyncWebServerRequest::getHeader(String name){ AsyncWebHeader* AsyncWebServerRequest::getHeader(const String& name) const {
AsyncWebHeader* h = _headers; for(const auto& h: _headers){
while(h != NULL){ if(h->name().equalsIgnoreCase(name)){
if(h->name().equalsIgnoreCase(name))
return h; return h;
h = h->next; }
} }
return NULL; return nullptr;
} }
AsyncWebHeader* AsyncWebServerRequest::getHeader(int num){ AsyncWebHeader* AsyncWebServerRequest::getHeader(size_t num) const {
int i = 0; auto header = _headers.nth(num);
AsyncWebHeader* h = _headers; return header ? *header : nullptr;
while(h != NULL){
if(num == i++)
return h;
h = h->next;
}
return NULL;
} }
int AsyncWebServerRequest::params(){ size_t AsyncWebServerRequest::params() const {
int i = 0; return _params.length();
AsyncWebParameter* h = _params;
while(h != NULL){
i++; h = h->next;
}
return i;
} }
bool AsyncWebServerRequest::hasParam(String name, bool post, bool file){ bool AsyncWebServerRequest::hasParam(const String& name, bool post, bool file) const {
AsyncWebParameter* h = _params; for(const auto& p: _params){
while(h != NULL){ if(p->name() == name && p->isPost() == post && p->isFile() == file){
if(h->name() == name && h->isPost() == post && h->isFile() == file)
return true; return true;
h = h->next; }
} }
return false; return false;
} }
AsyncWebParameter* AsyncWebServerRequest::getParam(String name, bool post, bool file){ AsyncWebParameter* AsyncWebServerRequest::getParam(const String& name, bool post, bool file) const {
AsyncWebParameter* h = _params; for(const auto& p: _params){
while(h != NULL){ if(p->name() == name && p->isPost() == post && p->isFile() == file){
if(h->name() == name && h->isPost() == post && h->isFile() == file) return p;
return h; }
h = h->next;
} }
return NULL; return nullptr;
} }
AsyncWebParameter* AsyncWebServerRequest::getParam(int num){ AsyncWebParameter* AsyncWebServerRequest::getParam(size_t num) const {
int i = 0; auto param = _params.nth(num);
AsyncWebParameter* h = _params; return param ? *param : nullptr;
while(h != NULL){
if(num == i++)
return h;
h = h->next;
}
return NULL;
} }
void AsyncWebServerRequest::addInterestingHeader(String name){ void AsyncWebServerRequest::addInterestingHeader(const String& name){
if(!_interestingHeaders->containsIgnoreCase(name)) _interestingHeaders->add(name); if(!_interestingHeaders.containsIgnoreCase(name))
_interestingHeaders.add(name);
} }
void AsyncWebServerRequest::send(AsyncWebServerResponse *response){ void AsyncWebServerRequest::send(AsyncWebServerResponse *response){
@@ -642,85 +592,85 @@ void AsyncWebServerRequest::send(AsyncWebServerResponse *response){
_response->_respond(this); _response->_respond(this);
} }
AsyncWebServerResponse * AsyncWebServerRequest::beginResponse(int code, String contentType, String content){ AsyncWebServerResponse * AsyncWebServerRequest::beginResponse(int code, const String& contentType, const String& content){
return new AsyncBasicResponse(code, contentType, content); return new AsyncBasicResponse(code, contentType, content);
} }
AsyncWebServerResponse * AsyncWebServerRequest::beginResponse(FS &fs, String path, String contentType, bool download){ AsyncWebServerResponse * AsyncWebServerRequest::beginResponse(FS &fs, const String& path, const String& contentType, bool download){
if(fs.exists(path) || (!download && fs.exists(path+".gz"))) if(fs.exists(path) || (!download && fs.exists(path+".gz")))
return new AsyncFileResponse(fs, path, contentType, download); return new AsyncFileResponse(fs, path, contentType, download);
return NULL; return NULL;
} }
AsyncWebServerResponse * AsyncWebServerRequest::beginResponse(File content, String path, String contentType, bool download){ AsyncWebServerResponse * AsyncWebServerRequest::beginResponse(File content, const String& path, const String& contentType, bool download){
if(content == true) if(content == true)
return new AsyncFileResponse(content, path, contentType, download); return new AsyncFileResponse(content, path, contentType, download);
return NULL; return NULL;
} }
AsyncWebServerResponse * AsyncWebServerRequest::beginResponse(Stream &stream, String contentType, size_t len){ AsyncWebServerResponse * AsyncWebServerRequest::beginResponse(Stream &stream, const String& contentType, size_t len){
return new AsyncStreamResponse(stream, contentType, len); return new AsyncStreamResponse(stream, contentType, len);
} }
AsyncWebServerResponse * AsyncWebServerRequest::beginResponse(String contentType, size_t len, AwsResponseFiller callback){ AsyncWebServerResponse * AsyncWebServerRequest::beginResponse(const String& contentType, size_t len, AwsResponseFiller callback){
return new AsyncCallbackResponse(contentType, len, callback); return new AsyncCallbackResponse(contentType, len, callback);
} }
AsyncWebServerResponse * AsyncWebServerRequest::beginChunkedResponse(String contentType, AwsResponseFiller callback){ AsyncWebServerResponse * AsyncWebServerRequest::beginChunkedResponse(const String& contentType, AwsResponseFiller callback){
if(_version) if(_version)
return new AsyncChunkedResponse(contentType, callback); return new AsyncChunkedResponse(contentType, callback);
return new AsyncCallbackResponse(contentType, 0, callback); return new AsyncCallbackResponse(contentType, 0, callback);
} }
AsyncResponseStream * AsyncWebServerRequest::beginResponseStream(String contentType, size_t bufferSize){ AsyncResponseStream * AsyncWebServerRequest::beginResponseStream(const String& contentType, size_t bufferSize){
return new AsyncResponseStream(contentType, bufferSize); return new AsyncResponseStream(contentType, bufferSize);
} }
AsyncWebServerResponse * AsyncWebServerRequest::beginResponse_P(int code, String contentType, const uint8_t * content, size_t len){ AsyncWebServerResponse * AsyncWebServerRequest::beginResponse_P(int code, const String& contentType, const uint8_t * content, size_t len){
return new AsyncProgmemResponse(code, contentType, content, len); return new AsyncProgmemResponse(code, contentType, content, len);
} }
AsyncWebServerResponse * AsyncWebServerRequest::beginResponse_P(int code, String contentType, PGM_P content){ AsyncWebServerResponse * AsyncWebServerRequest::beginResponse_P(int code, const String& contentType, PGM_P content){
return beginResponse_P(code, contentType, (const uint8_t *)content, strlen_P(content)); return beginResponse_P(code, contentType, (const uint8_t *)content, strlen_P(content));
} }
void AsyncWebServerRequest::send(int code, String contentType, String content){ void AsyncWebServerRequest::send(int code, const String& contentType, const String& content){
send(beginResponse(code, contentType, content)); send(beginResponse(code, contentType, content));
} }
void AsyncWebServerRequest::send(FS &fs, String path, String contentType, bool download){ void AsyncWebServerRequest::send(FS &fs, const String& path, const String& contentType, bool download){
if(fs.exists(path) || (!download && fs.exists(path+".gz"))){ if(fs.exists(path) || (!download && fs.exists(path+".gz"))){
send(beginResponse(fs, path, contentType, download)); send(beginResponse(fs, path, contentType, download));
} else send(404); } else send(404);
} }
void AsyncWebServerRequest::send(File content, String path, String contentType, bool download){ void AsyncWebServerRequest::send(File content, const String& path, const String& contentType, bool download){
if(content == true){ if(content == true){
send(beginResponse(content, path, contentType, download)); send(beginResponse(content, path, contentType, download));
} else send(404); } else send(404);
} }
void AsyncWebServerRequest::send(Stream &stream, String contentType, size_t len){ void AsyncWebServerRequest::send(Stream &stream, const String& contentType, size_t len){
send(beginResponse(stream, contentType, len)); send(beginResponse(stream, contentType, len));
} }
void AsyncWebServerRequest::send(String contentType, size_t len, AwsResponseFiller callback){ void AsyncWebServerRequest::send(const String& contentType, size_t len, AwsResponseFiller callback){
send(beginResponse(contentType, len, callback)); send(beginResponse(contentType, len, callback));
} }
void AsyncWebServerRequest::sendChunked(String contentType, AwsResponseFiller callback){ void AsyncWebServerRequest::sendChunked(const String& contentType, AwsResponseFiller callback){
send(beginChunkedResponse(contentType, callback)); send(beginChunkedResponse(contentType, callback));
} }
void AsyncWebServerRequest::send_P(int code, String contentType, const uint8_t * content, size_t len){ void AsyncWebServerRequest::send_P(int code, const String& contentType, const uint8_t * content, size_t len){
send(beginResponse_P(code, contentType, content, len)); send(beginResponse_P(code, contentType, content, len));
} }
void AsyncWebServerRequest::send_P(int code, String contentType, PGM_P content){ void AsyncWebServerRequest::send_P(int code, const String& contentType, PGM_P content){
send(beginResponse_P(code, contentType, content)); send(beginResponse_P(code, contentType, content));
} }
void AsyncWebServerRequest::redirect(String url){ void AsyncWebServerRequest::redirect(const String& url){
AsyncWebServerResponse * response = beginResponse(302); AsyncWebServerResponse * response = beginResponse(302);
response->addHeader("Location",url); response->addHeader("Location",url);
send(response); send(response);
@@ -777,61 +727,48 @@ void AsyncWebServerRequest::requestAuthentication(const char * realm, bool isDig
send(r); send(r);
} }
bool AsyncWebServerRequest::hasArg(const char* name){ bool AsyncWebServerRequest::hasArg(const char* name) const {
AsyncWebParameter* h = _params; for(const auto& arg: _params){
while(h != NULL){ if(arg->name() == name){
if(h->name() == String(name))
return true; return true;
h = h->next; }
} }
return false; return false;
} }
String AsyncWebServerRequest::arg(const char* name){ const String& AsyncWebServerRequest::arg(const String& name) const {
AsyncWebParameter* h = _params; for(const auto& arg: _params){
while(h != NULL){ if(arg->name() == name){
if(h->name() == String(name)) return arg->value();
return h->value(); }
h = h->next;
} }
return String(); return SharedEmptyString;
} }
String AsyncWebServerRequest::arg(int i){ const String& AsyncWebServerRequest::arg(size_t i) const {
return getParam(i)->value(); return getParam(i)->value();
} }
String AsyncWebServerRequest::argName(int i){ const String& AsyncWebServerRequest::argName(size_t i) const {
return getParam(i)->name(); return getParam(i)->name();
} }
String AsyncWebServerRequest::header(const char* name){ const String& AsyncWebServerRequest::header(const char* name) const {
AsyncWebHeader* h = getHeader(String(name)); AsyncWebHeader* h = getHeader(String(name));
if(h) return h ? h->value() : SharedEmptyString;
return h->value();
return String();
} }
String AsyncWebServerRequest::header(int i){ const String& AsyncWebServerRequest::header(size_t i) const {
AsyncWebHeader* h = getHeader(i); AsyncWebHeader* h = getHeader(i);
if(h) return h ? h->value() : SharedEmptyString;
return h->value();
return String();
} }
String AsyncWebServerRequest::headerName(int i){ const String& AsyncWebServerRequest::headerName(size_t i) const {
AsyncWebHeader* h = getHeader(i); AsyncWebHeader* h = getHeader(i);
if(h) return h ? h->name() : SharedEmptyString;
return h->name();
return String();
} }
bool AsyncWebServerRequest::hasHeader(const char* name){ String AsyncWebServerRequest::urlDecode(const String& text) const {
return hasHeader(String(name));
}
String AsyncWebServerRequest::urlDecode(const String& text){
char temp[] = "0x00"; char temp[] = "0x00";
unsigned int len = text.length(); unsigned int len = text.length();
unsigned int i = 0; unsigned int i = 0;
@@ -855,7 +792,7 @@ String AsyncWebServerRequest::urlDecode(const String& text){
} }
const char * AsyncWebServerRequest::methodToString(){ const char * AsyncWebServerRequest::methodToString() const {
if(_method == HTTP_ANY) return "ANY"; if(_method == HTTP_ANY) return "ANY";
else if(_method & HTTP_GET) return "GET"; else if(_method & HTTP_GET) return "GET";
else if(_method & HTTP_POST) return "POST"; else if(_method & HTTP_POST) return "POST";

View File

@@ -25,10 +25,10 @@ class AsyncBasicResponse: public AsyncWebServerResponse {
private: private:
String _content; String _content;
public: public:
AsyncBasicResponse(int code, String contentType=String(), String content=String()); AsyncBasicResponse(int code, const String& contentType=String(), const String& content=String());
void _respond(AsyncWebServerRequest *request); void _respond(AsyncWebServerRequest *request);
size_t _ack(AsyncWebServerRequest *request, size_t len, uint32_t time); size_t _ack(AsyncWebServerRequest *request, size_t len, uint32_t time);
bool _sourceValid(){ return true; } bool _sourceValid() const { return true; }
}; };
class AsyncAbstractResponse: public AsyncWebServerResponse { class AsyncAbstractResponse: public AsyncWebServerResponse {
@@ -37,57 +37,57 @@ class AsyncAbstractResponse: public AsyncWebServerResponse {
public: public:
void _respond(AsyncWebServerRequest *request); void _respond(AsyncWebServerRequest *request);
size_t _ack(AsyncWebServerRequest *request, size_t len, uint32_t time); size_t _ack(AsyncWebServerRequest *request, size_t len, uint32_t time);
bool _sourceValid(){ return false; } bool _sourceValid() const { return false; }
virtual size_t _fillBuffer(uint8_t *buf, size_t maxLen){ return 0; } virtual size_t _fillBuffer(uint8_t *buf __attribute__((unused)), size_t maxLen __attribute__((unused))) { return 0; }
}; };
class AsyncFileResponse: public AsyncAbstractResponse { class AsyncFileResponse: public AsyncAbstractResponse {
private: private:
File _content; File _content;
String _path; String _path;
void _setContentType(String path); void _setContentType(const String& path);
public: public:
AsyncFileResponse(FS &fs, String path, String contentType=String(), bool download=false); AsyncFileResponse(FS &fs, const String& path, const String& contentType=String(), bool download=false);
AsyncFileResponse(File content, String path, String contentType=String(), bool download=false); AsyncFileResponse(File content, const String& path, const String& contentType=String(), bool download=false);
~AsyncFileResponse(); ~AsyncFileResponse();
bool _sourceValid(){ return !!(_content); } bool _sourceValid() const { return !!(_content); }
size_t _fillBuffer(uint8_t *buf, size_t maxLen); virtual size_t _fillBuffer(uint8_t *buf, size_t maxLen) override;
}; };
class AsyncStreamResponse: public AsyncAbstractResponse { class AsyncStreamResponse: public AsyncAbstractResponse {
private: private:
Stream *_content; Stream *_content;
public: public:
AsyncStreamResponse(Stream &stream, String contentType, size_t len); AsyncStreamResponse(Stream &stream, const String& contentType, size_t len);
bool _sourceValid(){ return !!(_content); } bool _sourceValid() const { return !!(_content); }
size_t _fillBuffer(uint8_t *buf, size_t maxLen); virtual size_t _fillBuffer(uint8_t *buf, size_t maxLen) override;
}; };
class AsyncCallbackResponse: public AsyncAbstractResponse { class AsyncCallbackResponse: public AsyncAbstractResponse {
private: private:
AwsResponseFiller _content; AwsResponseFiller _content;
public: public:
AsyncCallbackResponse(String contentType, size_t len, AwsResponseFiller callback); AsyncCallbackResponse(const String& contentType, size_t len, AwsResponseFiller callback);
bool _sourceValid(){ return !!(_content); } bool _sourceValid() const { return !!(_content); }
size_t _fillBuffer(uint8_t *buf, size_t maxLen); virtual size_t _fillBuffer(uint8_t *buf, size_t maxLen) override;
}; };
class AsyncChunkedResponse: public AsyncAbstractResponse { class AsyncChunkedResponse: public AsyncAbstractResponse {
private: private:
AwsResponseFiller _content; AwsResponseFiller _content;
public: public:
AsyncChunkedResponse(String contentType, AwsResponseFiller callback); AsyncChunkedResponse(const String& contentType, AwsResponseFiller callback);
bool _sourceValid(){ return !!(_content); } bool _sourceValid() const { return !!(_content); }
size_t _fillBuffer(uint8_t *buf, size_t maxLen); virtual size_t _fillBuffer(uint8_t *buf, size_t maxLen) override;
}; };
class AsyncProgmemResponse: public AsyncAbstractResponse { class AsyncProgmemResponse: public AsyncAbstractResponse {
private: private:
const uint8_t * _content; const uint8_t * _content;
public: public:
AsyncProgmemResponse(int code, String contentType, const uint8_t * content, size_t len); AsyncProgmemResponse(int code, const String& contentType, const uint8_t * content, size_t len);
bool _sourceValid(){ return true; } bool _sourceValid() const { return true; }
size_t _fillBuffer(uint8_t *buf, size_t maxLen); virtual size_t _fillBuffer(uint8_t *buf, size_t maxLen) override;
}; };
class cbuf; class cbuf;
@@ -96,10 +96,10 @@ class AsyncResponseStream: public AsyncAbstractResponse, public Print {
private: private:
cbuf *_content; cbuf *_content;
public: public:
AsyncResponseStream(String contentType, size_t bufferSize); AsyncResponseStream(const String& contentType, size_t bufferSize);
~AsyncResponseStream(); ~AsyncResponseStream();
bool _sourceValid(){ return (_state < RESPONSE_END); } bool _sourceValid() const { return (_state < RESPONSE_END); }
size_t _fillBuffer(uint8_t *buf, size_t maxLen); virtual size_t _fillBuffer(uint8_t *buf, size_t maxLen) override;
size_t write(const uint8_t *data, size_t len); size_t write(const uint8_t *data, size_t len);
size_t write(uint8_t data); size_t write(uint8_t data);
using Print::write; using Print::write;

View File

@@ -73,7 +73,7 @@ const char* AsyncWebServerResponse::_responseCodeToString(int code) {
AsyncWebServerResponse::AsyncWebServerResponse() AsyncWebServerResponse::AsyncWebServerResponse()
: _code(0) : _code(0)
, _headers(NULL) , _headers(LinkedList<AsyncWebHeader *>([](AsyncWebHeader *h){ delete h; }))
, _contentType() , _contentType()
, _contentLength(0) , _contentLength(0)
, _sendContentLength(true) , _sendContentLength(true)
@@ -86,11 +86,7 @@ AsyncWebServerResponse::AsyncWebServerResponse()
{} {}
AsyncWebServerResponse::~AsyncWebServerResponse(){ AsyncWebServerResponse::~AsyncWebServerResponse(){
while(_headers != NULL){ _headers.free();
AsyncWebHeader *h = _headers;
_headers = h->next;
delete h;
}
} }
void AsyncWebServerResponse::setCode(int code){ void AsyncWebServerResponse::setCode(int code){
@@ -103,20 +99,13 @@ void AsyncWebServerResponse::setContentLength(size_t len){
_contentLength = len; _contentLength = len;
} }
void AsyncWebServerResponse::setContentType(String type){ void AsyncWebServerResponse::setContentType(const String& type){
if(_state == RESPONSE_SETUP) if(_state == RESPONSE_SETUP)
_contentType = type; _contentType = type;
} }
void AsyncWebServerResponse::addHeader(String name, String value){ void AsyncWebServerResponse::addHeader(const String& name, const String& value){
AsyncWebHeader *header = new AsyncWebHeader(name, value); _headers.add(new AsyncWebHeader(name, value));
if(_headers == NULL){
_headers = header;
} else {
AsyncWebHeader *h = _headers;
while(h->next != NULL) h = h->next;
h->next = header;
}
} }
String AsyncWebServerResponse::_assembleHead(uint8_t version){ String AsyncWebServerResponse::_assembleHead(uint8_t version){
@@ -141,30 +130,28 @@ String AsyncWebServerResponse::_assembleHead(uint8_t version){
out.concat(buf); out.concat(buf);
} }
AsyncWebHeader *h; for(const auto& header: _headers){
while(_headers != NULL){ snprintf(buf, bufSize, "%s: %s\r\n", header->name().c_str(), header->value().c_str());
h = _headers;
_headers = _headers->next;
snprintf(buf, bufSize, "%s: %s\r\n", h->name().c_str(), h->value().c_str());
out.concat(buf); out.concat(buf);
delete h;
} }
_headers.free();
out.concat("\r\n"); out.concat("\r\n");
_headLength = out.length(); _headLength = out.length();
return out; return out;
} }
bool AsyncWebServerResponse::_started(){ return _state > RESPONSE_SETUP; } bool AsyncWebServerResponse::_started() const { return _state > RESPONSE_SETUP; }
bool AsyncWebServerResponse::_finished(){ return _state > RESPONSE_WAIT_ACK; } bool AsyncWebServerResponse::_finished() const { return _state > RESPONSE_WAIT_ACK; }
bool AsyncWebServerResponse::_failed(){ return _state == RESPONSE_FAILED; } bool AsyncWebServerResponse::_failed() const { return _state == RESPONSE_FAILED; }
bool AsyncWebServerResponse::_sourceValid(){ return false; } bool AsyncWebServerResponse::_sourceValid() const { return false; }
void AsyncWebServerResponse::_respond(AsyncWebServerRequest *request){ _state = RESPONSE_END; request->client()->close(); } void AsyncWebServerResponse::_respond(AsyncWebServerRequest *request){ _state = RESPONSE_END; request->client()->close(); }
size_t AsyncWebServerResponse::_ack(AsyncWebServerRequest *request, size_t len, uint32_t time){ return 0; } size_t AsyncWebServerResponse::_ack(AsyncWebServerRequest *request, size_t len, uint32_t time){ return 0; }
/* /*
* String/Code Response * String/Code Response
* */ * */
AsyncBasicResponse::AsyncBasicResponse(int code, String contentType, String content){ AsyncBasicResponse::AsyncBasicResponse(int code, const String& contentType, const String& content){
_code = code; _code = code;
_content = content; _content = content;
_contentType = contentType; _contentType = contentType;
@@ -343,7 +330,7 @@ AsyncFileResponse::~AsyncFileResponse(){
_content.close(); _content.close();
} }
void AsyncFileResponse::_setContentType(String path){ void AsyncFileResponse::_setContentType(const String& path){
if (path.endsWith(".html")) _contentType = "text/html"; if (path.endsWith(".html")) _contentType = "text/html";
else if (path.endsWith(".htm")) _contentType = "text/html"; else if (path.endsWith(".htm")) _contentType = "text/html";
else if (path.endsWith(".css")) _contentType = "text/css"; else if (path.endsWith(".css")) _contentType = "text/css";
@@ -365,7 +352,7 @@ void AsyncFileResponse::_setContentType(String path){
else _contentType = "text/plain"; else _contentType = "text/plain";
} }
AsyncFileResponse::AsyncFileResponse(FS &fs, String path, String contentType, bool download){ AsyncFileResponse::AsyncFileResponse(FS &fs, const String& path, const String& contentType, bool download){
_code = 200; _code = 200;
_path = path; _path = path;
@@ -397,7 +384,7 @@ AsyncFileResponse::AsyncFileResponse(FS &fs, String path, String contentType, bo
} }
AsyncFileResponse::AsyncFileResponse(File content, String path, String contentType, bool download){ AsyncFileResponse::AsyncFileResponse(File content, const String& path, const String& contentType, bool download){
_code = 200; _code = 200;
_path = path; _path = path;
_content = content; _content = content;
@@ -432,7 +419,7 @@ size_t AsyncFileResponse::_fillBuffer(uint8_t *data, size_t len){
* Stream Response * Stream Response
* */ * */
AsyncStreamResponse::AsyncStreamResponse(Stream &stream, String contentType, size_t len){ AsyncStreamResponse::AsyncStreamResponse(Stream &stream, const String& contentType, size_t len){
_code = 200; _code = 200;
_content = &stream; _content = &stream;
_contentLength = len; _contentLength = len;
@@ -452,7 +439,7 @@ size_t AsyncStreamResponse::_fillBuffer(uint8_t *data, size_t len){
* Callback Response * Callback Response
* */ * */
AsyncCallbackResponse::AsyncCallbackResponse(String contentType, size_t len, AwsResponseFiller callback){ AsyncCallbackResponse::AsyncCallbackResponse(const String& contentType, size_t len, AwsResponseFiller callback){
_code = 200; _code = 200;
_content = callback; _content = callback;
_contentLength = len; _contentLength = len;
@@ -469,7 +456,7 @@ size_t AsyncCallbackResponse::_fillBuffer(uint8_t *data, size_t len){
* Chunked Response * Chunked Response
* */ * */
AsyncChunkedResponse::AsyncChunkedResponse(String contentType, AwsResponseFiller callback){ AsyncChunkedResponse::AsyncChunkedResponse(const String& contentType, AwsResponseFiller callback){
_code = 200; _code = 200;
_content = callback; _content = callback;
_contentLength = 0; _contentLength = 0;
@@ -486,7 +473,7 @@ size_t AsyncChunkedResponse::_fillBuffer(uint8_t *data, size_t len){
* Progmem Response * Progmem Response
* */ * */
AsyncProgmemResponse::AsyncProgmemResponse(int code, String contentType, const uint8_t * content, size_t len){ AsyncProgmemResponse::AsyncProgmemResponse(int code, const String& contentType, const uint8_t * content, size_t len){
_code = code; _code = code;
_content = content; _content = content;
_contentType = contentType; _contentType = contentType;
@@ -508,7 +495,7 @@ size_t AsyncProgmemResponse::_fillBuffer(uint8_t *data, size_t len){
* Response Stream (You can print/write/printf to it, up to the contentLen bytes) * Response Stream (You can print/write/printf to it, up to the contentLen bytes)
* */ * */
AsyncResponseStream::AsyncResponseStream(String contentType, size_t bufferSize){ AsyncResponseStream::AsyncResponseStream(const String& contentType, size_t bufferSize){
_code = 200; _code = 200;
_contentLength = 0; _contentLength = 0;
_contentType = contentType; _contentType = contentType;

View File

@@ -21,8 +21,20 @@
#include "ESPAsyncWebServer.h" #include "ESPAsyncWebServer.h"
#include "WebHandlerImpl.h" #include "WebHandlerImpl.h"
bool ON_STA_FILTER(AsyncWebServerRequest *request) {
return WiFi.localIP() == request->client()->localIP();
}
AsyncWebServer::AsyncWebServer(uint16_t port):_server(port), _rewrites(0), _handlers(0){ bool ON_AP_FILTER(AsyncWebServerRequest *request) {
return WiFi.localIP() != request->client()->localIP();
}
AsyncWebServer::AsyncWebServer(uint16_t port)
: _server(port)
, _rewrites(LinkedList<AsyncWebRewrite*>([](AsyncWebRewrite* r){ delete r; }))
, _handlers(LinkedList<AsyncWebHandler*>([](AsyncWebHandler* h){ delete h; }))
{
_catchAllHandler = new AsyncCallbackWebHandler(); _catchAllHandler = new AsyncCallbackWebHandler();
if(_catchAllHandler == NULL) if(_catchAllHandler == NULL)
return; return;
@@ -45,32 +57,12 @@ AsyncWebServer::~AsyncWebServer(){
} }
AsyncWebRewrite& AsyncWebServer::addRewrite(AsyncWebRewrite* rewrite){ AsyncWebRewrite& AsyncWebServer::addRewrite(AsyncWebRewrite* rewrite){
if (_rewrites == NULL){ _rewrites.add(rewrite);
_rewrites = rewrite;
} else {
AsyncWebRewrite *r = _rewrites;
while(r->next != NULL) r = r->next;
r->next = rewrite;
}
return *rewrite; return *rewrite;
} }
bool AsyncWebServer::removeRewrite(AsyncWebRewrite *rewrite){ bool AsyncWebServer::removeRewrite(AsyncWebRewrite *rewrite){
if(rewrite == _rewrites){ return _rewrites.remove(rewrite);
_rewrites = _rewrites->next;
return true;
}
AsyncWebRewrite *r = _rewrites;
while(r != NULL){
if(rewrite == r->next){
AsyncWebRewrite *d = r->next;
r->next = d->next;
delete d;
return true;
}
r = r->next;
}
return false;
} }
AsyncWebRewrite& AsyncWebServer::rewrite(const char* from, const char* to){ AsyncWebRewrite& AsyncWebServer::rewrite(const char* from, const char* to){
@@ -78,32 +70,12 @@ AsyncWebRewrite& AsyncWebServer::rewrite(const char* from, const char* to){
} }
AsyncWebHandler& AsyncWebServer::addHandler(AsyncWebHandler* handler){ AsyncWebHandler& AsyncWebServer::addHandler(AsyncWebHandler* handler){
if(_handlers == NULL){ _handlers.add(handler);
_handlers = handler;
} else {
AsyncWebHandler* h = _handlers;
while(h->next != NULL) h = h->next;
h->next = handler;
}
return *handler; return *handler;
} }
bool AsyncWebServer::removeHandler(AsyncWebHandler *handler){ bool AsyncWebServer::removeHandler(AsyncWebHandler *handler){
if(handler == _handlers){ return _handlers.remove(handler);
_handlers = _handlers->next;
return true;
}
AsyncWebHandler *h = _handlers;
while(h != NULL){
if(handler == h->next){
AsyncWebHandler *d = h->next;
h->next = d->next;
delete d;
return true;
}
h = h->next;
}
return false;
} }
void AsyncWebServer::begin(){ void AsyncWebServer::begin(){
@@ -125,27 +97,22 @@ void AsyncWebServer::_handleDisconnect(AsyncWebServerRequest *request){
} }
void AsyncWebServer::_rewriteRequest(AsyncWebServerRequest *request){ void AsyncWebServer::_rewriteRequest(AsyncWebServerRequest *request){
AsyncWebRewrite *r = _rewrites; for(const auto& r: _rewrites){
while(r){
if (r->from() == request->_url && r->filter(request)){ if (r->from() == request->_url && r->filter(request)){
request->_url = r->toUrl(); request->_url = r->toUrl();
request->_addGetParams(r->params()); request->_addGetParams(r->params());
} }
r = r->next;
} }
} }
void AsyncWebServer::_attachHandler(AsyncWebServerRequest *request){ void AsyncWebServer::_attachHandler(AsyncWebServerRequest *request){
if(_handlers){ for(const auto& h: _handlers){
AsyncWebHandler* h = _handlers; if (h->filter(request) && h->canHandle(request)){
while(h){ request->setHandler(h);
if (h->filter(request) && h->canHandle(request)){ return;
request->setHandler(h);
return;
}
h = h->next;
} }
} }
request->addInterestingHeader("ANY"); request->addInterestingHeader("ANY");
request->setHandler(_catchAllHandler); request->setHandler(_catchAllHandler);
} }
@@ -208,19 +175,8 @@ void AsyncWebServer::onRequestBody(ArBodyHandlerFunction fn){
} }
void AsyncWebServer::reset(){ void AsyncWebServer::reset(){
while(_rewrites != NULL){ _rewrites.free();
AsyncWebRewrite *r = _rewrites; _handlers.free();
_rewrites = r->next;
delete r;
}
_rewrites = NULL;
while(_handlers != NULL){
AsyncWebHandler *h = _handlers;
_handlers = h->next;
delete h;
}
_handlers = NULL;
if (_catchAllHandler != NULL){ if (_catchAllHandler != NULL){
((AsyncCallbackWebHandler*)_catchAllHandler)->onRequest(NULL); ((AsyncCallbackWebHandler*)_catchAllHandler)->onRequest(NULL);