forked from me-no-dev/ESPAsyncWebServer
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:
@@ -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);
|
||||||
|
@@ -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);
|
||||||
}
|
}
|
||||||
|
@@ -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 {
|
||||||
|
@@ -69,7 +69,7 @@ class AsyncJsonResponse: public AsyncAbstractResponse {
|
|||||||
size_t setLength() {
|
size_t setLength() {
|
||||||
_contentLength = _root.measureLength();
|
_contentLength = _root.measureLength();
|
||||||
if (_contentLength) { _isValid = true; }
|
if (_contentLength) { _isValid = true; }
|
||||||
return _contentLength;
|
return _contentLength;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t _fillBuffer(uint8_t *data, size_t len){
|
size_t _fillBuffer(uint8_t *data, size_t len){
|
||||||
|
@@ -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);
|
||||||
|
@@ -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; }
|
||||||
|
@@ -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);
|
||||||
|
@@ -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;
|
||||||
|
@@ -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
|
||||||
|
@@ -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_ */
|
||||||
|
@@ -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 "";
|
||||||
|
@@ -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);
|
||||||
}
|
}
|
||||||
|
@@ -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;
|
||||||
|
@@ -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";
|
||||||
|
@@ -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;
|
||||||
|
@@ -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;
|
||||||
|
@@ -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);
|
||||||
|
Reference in New Issue
Block a user