Replace use of LinkedList<T> with std::list for request headers

Based on commit 2183addab047126b5ac259fc5dfffecfb21f60a0 of dumbfixes
branch of 0xFEEDC0DE64 fork of ESPAsyncWebServer.

Step two of removal of homebrewed LinkedList in favor of standard C++
containers. For consistency, the list of interesting headers in the
request has been converted to a std::vector<String>. Also, const
versions of header query functions have been implemented. The original
patch also happens to fix bug #837, and this manual cherry-pick replaces
the previous fix with the dumbfixes one.
This commit is contained in:
Alex Villacís Lasso
2020-12-29 14:15:44 -05:00
parent a20b7540ce
commit 04049f94c3
2 changed files with 86 additions and 41 deletions

View File

@@ -24,6 +24,7 @@
#include "Arduino.h" #include "Arduino.h"
#include <functional> #include <functional>
#include <list>
#include "FS.h" #include "FS.h"
#include "StringArray.h" #include "StringArray.h"
@@ -154,7 +155,7 @@ class AsyncWebServerRequest {
AsyncWebServer* _server; AsyncWebServer* _server;
AsyncWebHandler* _handler; AsyncWebHandler* _handler;
AsyncWebServerResponse* _response; AsyncWebServerResponse* _response;
StringArray _interestingHeaders; std::vector<String> _interestingHeaders;
ArDisconnectHandler _onDisconnectfn; ArDisconnectHandler _onDisconnectfn;
String _temp; String _temp;
@@ -176,7 +177,7 @@ class AsyncWebServerRequest {
size_t _contentLength; size_t _contentLength;
size_t _parsedLength; size_t _parsedLength;
LinkedList<AsyncWebHeader *> _headers; std::list<AsyncWebHeader> _headers;
LinkedList<AsyncWebParameter *> _params; LinkedList<AsyncWebParameter *> _params;
LinkedList<String *> _pathParams; LinkedList<String *> _pathParams;
@@ -270,9 +271,12 @@ class AsyncWebServerRequest {
bool hasHeader(const String& name) const; // check if header exists bool hasHeader(const String& name) const; // check if header exists
bool hasHeader(const __FlashStringHelper * data) const; // check if header exists bool hasHeader(const __FlashStringHelper * data) const; // check if header exists
AsyncWebHeader* getHeader(const String& name) const; AsyncWebHeader* getHeader(const String& name);
AsyncWebHeader* getHeader(const __FlashStringHelper * data) const; const AsyncWebHeader* getHeader(const String& name) const;
AsyncWebHeader* getHeader(size_t num) const; AsyncWebHeader* getHeader(const __FlashStringHelper * data);
const AsyncWebHeader* getHeader(const __FlashStringHelper * data) const;
AsyncWebHeader* getHeader(size_t num);
const AsyncWebHeader* getHeader(size_t num) const;
size_t params() const; // get arguments count size_t params() const; // get arguments count
bool hasParam(const String& name, bool post=false, bool file=false) const; bool hasParam(const String& name, bool post=false, bool file=false) const;

View File

@@ -51,7 +51,6 @@ AsyncWebServerRequest::AsyncWebServerRequest(AsyncWebServer* s, AsyncClient* c)
, _expectingContinue(false) , _expectingContinue(false)
, _contentLength(0) , _contentLength(0)
, _parsedLength(0) , _parsedLength(0)
, _headers(LinkedList<AsyncWebHeader *>([](AsyncWebHeader *h){ delete h; }))
, _params(LinkedList<AsyncWebParameter *>([](AsyncWebParameter *p){ delete p; })) , _params(LinkedList<AsyncWebParameter *>([](AsyncWebParameter *p){ delete p; }))
, _pathParams(LinkedList<String *>([](String *p){ delete p; })) , _pathParams(LinkedList<String *>([](String *p){ delete p; }))
, _multiParseState(0) , _multiParseState(0)
@@ -76,12 +75,12 @@ AsyncWebServerRequest::AsyncWebServerRequest(AsyncWebServer* s, AsyncClient* c)
} }
AsyncWebServerRequest::~AsyncWebServerRequest(){ AsyncWebServerRequest::~AsyncWebServerRequest(){
_headers.free(); _headers.clear();
_params.free(); _params.free();
_pathParams.free(); _pathParams.free();
_interestingHeaders.free(); _interestingHeaders.clear();
if(_response != NULL){ if(_response != NULL){
delete _response; delete _response;
@@ -182,20 +181,19 @@ void AsyncWebServerRequest::_onData(void *buf, size_t len){
} }
void AsyncWebServerRequest::_removeNotInterestingHeaders(){ void AsyncWebServerRequest::_removeNotInterestingHeaders(){
if (_interestingHeaders.containsIgnoreCase(F("ANY"))) { if (std::any_of(std::begin(_interestingHeaders), std::end(_interestingHeaders),
[](const String &str){ return str.equalsIgnoreCase(F("ANY")); }))
return; // nothing to do return; // nothing to do
}
// When removing items from the list, we must increase the iterator first for(auto iter = std::begin(_headers); iter != std::end(_headers); )
// before removing the current item, otherwise the iterator is invalidated {
// So, no for(;;) loop can be used, see: https://stackoverflow.com/q/596162 const auto name = iter->name();
auto i_header = _headers.begin();
const auto i_end = _headers.end(); if (std::none_of(std::begin(_interestingHeaders), std::end(_interestingHeaders),
while (i_header != i_end){ [&name](const String &str){ return str.equalsIgnoreCase(name); }))
const auto header = *i_header; iter = _headers.erase(iter);
++i_header; else
if(!_interestingHeaders.containsIgnoreCase(header->name().c_str())){ iter++;
_headers.remove(header);
}
} }
} }
@@ -370,7 +368,7 @@ bool AsyncWebServerRequest::_parseReqHeader(){
} }
} }
} }
_headers.add(new AsyncWebHeader(name, value)); _headers.emplace_back(name, value);
} }
_temp = String(); _temp = String();
return true; return true;
@@ -611,12 +609,12 @@ void AsyncWebServerRequest::_parseLine(){
} }
size_t AsyncWebServerRequest::headers() const{ size_t AsyncWebServerRequest::headers() const{
return _headers.length(); return _headers.size();
} }
bool AsyncWebServerRequest::hasHeader(const String& name) const { bool AsyncWebServerRequest::hasHeader(const String& name) const {
for(const auto& h: _headers){ for(const auto& h: _headers){
if(h->name().equalsIgnoreCase(name)){ if(h.name().equalsIgnoreCase(name)){
return true; return true;
} }
} }
@@ -627,22 +625,64 @@ bool AsyncWebServerRequest::hasHeader(const __FlashStringHelper * data) const {
return hasHeader(String(data)); return hasHeader(String(data));
} }
AsyncWebHeader* AsyncWebServerRequest::getHeader(const String& name) const { AsyncWebHeader* AsyncWebServerRequest::getHeader(const String& name) {
for(const auto& h: _headers){ auto iter = std::find_if(std::begin(_headers), std::end(_headers),
if(h->name().equalsIgnoreCase(name)){ [&name](const AsyncWebHeader &header){ return header.name().equalsIgnoreCase(name); });
return h;
} if (iter == std::end(_headers))
}
return nullptr; return nullptr;
return &(*iter);
} }
AsyncWebHeader* AsyncWebServerRequest::getHeader(const __FlashStringHelper * data) const { const AsyncWebHeader* AsyncWebServerRequest::getHeader(const String& name) const {
return getHeader(String(data)); auto iter = std::find_if(std::begin(_headers), std::end(_headers),
[&name](const AsyncWebHeader &header){ return header.name().equalsIgnoreCase(name); });
if (iter == std::end(_headers))
return nullptr;
return &(*iter);
} }
AsyncWebHeader* AsyncWebServerRequest::getHeader(size_t num) const { AsyncWebHeader* AsyncWebServerRequest::getHeader(const __FlashStringHelper * data) {
auto header = _headers.nth(num); PGM_P p = reinterpret_cast<PGM_P>(data);
return header ? *header : nullptr; size_t n = strlen_P(p);
char * name = (char*) malloc(n+1);
if (name) {
strcpy_P(name, p);
AsyncWebHeader* result = getHeader( String(name));
free(name);
return result;
} else {
return nullptr;
}
}
const AsyncWebHeader* AsyncWebServerRequest::getHeader(const __FlashStringHelper * data) const {
PGM_P p = reinterpret_cast<PGM_P>(data);
size_t n = strlen_P(p);
char * name = (char*) malloc(n+1);
if (name) {
strcpy_P(name, p);
const AsyncWebHeader* result = getHeader( String(name));
free(name);
return result;
} else {
return nullptr;
}
}
AsyncWebHeader* AsyncWebServerRequest::getHeader(size_t num) {
if (num >= _headers.size())
return nullptr;
return &(*std::next(std::begin(_headers), num));
}
const AsyncWebHeader* AsyncWebServerRequest::getHeader(size_t num) const {
if (num >= _headers.size())
return nullptr;
return &(*std::next(std::begin(_headers), num));
} }
size_t AsyncWebServerRequest::params() const { size_t AsyncWebServerRequest::params() const {
@@ -681,8 +721,9 @@ AsyncWebParameter* AsyncWebServerRequest::getParam(size_t num) const {
} }
void AsyncWebServerRequest::addInterestingHeader(const String& name){ void AsyncWebServerRequest::addInterestingHeader(const String& name){
if(!_interestingHeaders.containsIgnoreCase(name)) if(std::none_of(std::begin(_interestingHeaders), std::end(_interestingHeaders),
_interestingHeaders.add(name); [&name](const String &str){ return str.equalsIgnoreCase(name); }))
_interestingHeaders.push_back(name);
} }
void AsyncWebServerRequest::send(AsyncWebServerResponse *response){ void AsyncWebServerRequest::send(AsyncWebServerResponse *response){
@@ -879,7 +920,7 @@ const String& AsyncWebServerRequest::pathArg(size_t i) const {
} }
const String& AsyncWebServerRequest::header(const char* name) const { const String& AsyncWebServerRequest::header(const char* name) const {
AsyncWebHeader* h = getHeader(String(name)); const AsyncWebHeader* h = getHeader(String(name));
return h ? h->value() : emptyString; return h ? h->value() : emptyString;
} }
@@ -889,12 +930,12 @@ const String& AsyncWebServerRequest::header(const __FlashStringHelper * data) co
const String& AsyncWebServerRequest::header(size_t i) const { const String& AsyncWebServerRequest::header(size_t i) const {
AsyncWebHeader* h = getHeader(i); const AsyncWebHeader* h = getHeader(i);
return h ? h->value() : emptyString; return h ? h->value() : emptyString;
} }
const String& AsyncWebServerRequest::headerName(size_t i) const { const String& AsyncWebServerRequest::headerName(size_t i) const {
AsyncWebHeader* h = getHeader(i); const AsyncWebHeader* h = getHeader(i);
return h ? h->name() : emptyString; return h ? h->name() : emptyString;
} }