From 49be21e3efbfccb47ec8ad96e167ddba1784cdd0 Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Fri, 10 Oct 2025 12:31:56 +0200 Subject: [PATCH] Code and CI cleanup in relation to regex support --- .github/workflows/build-esp32.yml | 53 ++-------------- platformio.ini | 100 +++++++++++++++++------------- src/ESPAsyncWebServer.h | 24 ++++--- src/WebHandlerImpl.h | 4 -- src/WebHandlers.cpp | 2 +- src/WebRequest.cpp | 17 ----- 6 files changed, 80 insertions(+), 120 deletions(-) diff --git a/.github/workflows/build-esp32.yml b/.github/workflows/build-esp32.yml index 296b3c7a2..caa4aaa2d 100644 --- a/.github/workflows/build-esp32.yml +++ b/.github/workflows/build-esp32.yml @@ -170,53 +170,6 @@ jobs: PLATFORMIO_SRC_DIR=examples/$i PIO_BOARD=${{ matrix.board }} pio run -e ci-arduino-3 done - platformio-esp32-arduino-latest: - name: ESP32 (pio) - Arduino Latest - runs-on: ubuntu-latest - strategy: - fail-fast: false - matrix: - board: - - esp32dev - - esp32-s2-saola-1 - - esp32-s3-devkitc-1 - - esp32-c3-devkitc-02 - - esp32-c6-devkitc-1 - - esp32-h2-devkitm-1 - - steps: - - name: Checkout - uses: actions/checkout@v5 - - # - name: Cache PlatformIO - # uses: actions/cache@v4 - # with: - # key: ${{ runner.os }}-pio - # path: | - # ~/.cache/pip - # ~/.platformio - - - name: Python - uses: actions/setup-python@v6 - with: - python-version: "3.x" - - - name: Install PIO - run: | - python -m pip install --upgrade pip - pip install --upgrade platformio - pip install --upgrade intelhex - pip install --upgrade rich_click - - - name: Build Examples - run: | - for i in `ls examples`; do - echo "=============================================================" - echo "Building examples/$i..." - echo "=============================================================" - PLATFORMIO_SRC_DIR=examples/$i PIO_BOARD=${{ matrix.board }} pio run -e ci-arduino-rc - done - platformio-specific-envs: name: ESP32 (pio) - Specific Envs runs-on: ubuntu-latest @@ -224,10 +177,12 @@ jobs: fail-fast: false matrix: env: - - ci-arduino-rc-asynctcp - - ci-arduino-3-no-json + - ci-latest-asynctcp + - ci-no-json + - ci-no-chunk-inflight - ci-arduino-2-esp-idf-log - ci-arduino-3-esp-idf-log + - ci-regex steps: - name: Checkout diff --git a/platformio.ini b/platformio.ini index 482edaa7c..380f859db 100644 --- a/platformio.ini +++ b/platformio.ini @@ -51,6 +51,7 @@ build_flags = -D CONFIG_ASYNC_TCP_QUEUE_SIZE=64 -D CONFIG_ASYNC_TCP_RUNNING_CORE=1 -D CONFIG_ASYNC_TCP_STACK_SIZE=4096 + ; -D ASYNCWEBSERVER_REGEX=1 ; -D CONFIG_ASYNC_TCP_USE_WDT=0 ; -D CONFIG_ARDUHAL_LOG_COLORS ; -D CORE_DEBUG_LEVEL=ARDUHAL_LOG_LEVEL_VERBOSE @@ -72,6 +73,8 @@ lib_deps = board_build.partitions = partitions-4MB.csv board_build.filesystem = littlefs +; PLATFORMS (ESP32, ESP8266, Raspberry, LibreTiny) + [env:arduino-2] platform = espressif32@6.12.0 @@ -79,26 +82,6 @@ platform = espressif32@6.12.0 ; board = esp32-p4 ; board = esp32-h2-devkitm-1 -[env:arduino-rc] -platform = https://github.com/pioarduino/platform-espressif32/releases/download/54.03.20-rc2/platform-espressif32.zip - -[env:arduino-3-no-json] -lib_deps = - ESP32Async/AsyncTCP @ 3.4.9 - -[env:arduino-rc-asynctcp] -lib_deps = - https://github.com/ESP32Async/AsyncTCP - -[env:arduino-3-no-chunk-inflight] -build_flags = ${env.build_flags} - -D ASYNCWEBSERVER_USE_CHUNK_INFLIGHT=0 - -[env:AsyncTCPSock] -lib_deps = - https://github.com/ESP32Async/AsyncTCPSock/archive/refs/tags/v1.0.3-dev.zip -build_flags = ${env.build_flags} - [env:esp8266] platform = espressif8266 ; board = huzzah @@ -130,46 +113,49 @@ lib_deps = ; (BK7231 already uses it) custom_versions.freertos = 9.0.0 -; CI - -[env:ci-arduino-2] -platform = espressif32@6.12.0 -board = ${sysenv.PIO_BOARD} - -[env:ci-arduino-3] -board = ${sysenv.PIO_BOARD} +; SPECIFIC ENVS (for testing various configurations) -[env:ci-arduino-rc] -platform = https://github.com/pioarduino/platform-espressif32/releases/download/54.03.20-rc2/platform-espressif32.zip -board = ${sysenv.PIO_BOARD} - -[env:ci-arduino-2-esp-idf-log] +[env:arduino-2-esp-idf-log] platform = espressif32@6.12.0 -board = ${sysenv.PIO_BOARD} build_flags = ${env.build_flags} -D USE_ESP_IDF_LOG=1 -D TAG=\"core\" -[env:ci-arduino-3-esp-idf-log] -board = ${sysenv.PIO_BOARD} +[env:arduino-3-esp-idf-log] build_flags = ${env.build_flags} -D USE_ESP_IDF_LOG=1 -[env:ci-arduino-3-no-json] -board = ${sysenv.PIO_BOARD} +[env:no-json] lib_deps = ESP32Async/AsyncTCP @ 3.4.9 -[env:ci-arduino-rc-asynctcp] +[env:latest-asynctcp] lib_deps = https://github.com/ESP32Async/AsyncTCP -[env:ci-arduino-3-no-chunk-inflight] -board = ${sysenv.PIO_BOARD} +[env:no-chunk-inflight] build_flags = ${env.build_flags} - -D ASYNCWEBSERVER_USE_CHUNK_INFLIGHT=1 + -D ASYNCWEBSERVER_USE_CHUNK_INFLIGHT=0 + +[env:regex] +build_flags = ${env.build_flags} + -D ASYNCWEBSERVER_REGEX=1 + +[env:AsyncTCPSock] +lib_deps = + https://github.com/ESP32Async/AsyncTCPSock/archive/refs/tags/v1.0.3-dev.zip +build_flags = ${env.build_flags} + +; PLATFORM CI (ESP32, ESP8266, Raspberry, LibreTiny) + +[env:ci-arduino-2] +platform = espressif32@6.12.0 +board = ${sysenv.PIO_BOARD} + +[env:ci-arduino-3] +board = ${sysenv.PIO_BOARD} [env:ci-esp8266] platform = espressif8266 @@ -199,3 +185,33 @@ lib_deps = DNSServer ESP32Async/AsyncTCP @ 3.4.3 custom_versions.freertos = 9.0.0 + +; CI FOR SPECIFIC CONFIGURATIONS + +[env:ci-arduino-2-esp-idf-log] +platform = espressif32@6.12.0 +build_flags = + ${env.build_flags} + -D USE_ESP_IDF_LOG=1 + -D TAG=\"core\" + +[env:ci-arduino-3-esp-idf-log] +build_flags = + ${env.build_flags} + -D USE_ESP_IDF_LOG=1 + +[env:ci-no-json] +lib_deps = + ESP32Async/AsyncTCP @ 3.4.9 + +[env:ci-latest-asynctcp] +lib_deps = + https://github.com/ESP32Async/AsyncTCP + +[env:ci-no-chunk-inflight] +build_flags = ${env.build_flags} + -D ASYNCWEBSERVER_USE_CHUNK_INFLIGHT=1 + +[env:ci-regex] +build_flags = ${env.build_flags} + -D ASYNCWEBSERVER_REGEX=1 diff --git a/src/ESPAsyncWebServer.h b/src/ESPAsyncWebServer.h index 2939759be..31267d710 100644 --- a/src/ESPAsyncWebServer.h +++ b/src/ESPAsyncWebServer.h @@ -50,9 +50,7 @@ #define ASYNCWEBSERVER_FORK_ESP32Async #ifdef ASYNCWEBSERVER_REGEX -#define ASYNCWEBSERVER_REGEX_ATTRIBUTE -#else -#define ASYNCWEBSERVER_REGEX_ATTRIBUTE __attribute__((warning("ASYNCWEBSERVER_REGEX not defined"))) +#include #endif // See https://github.com/ESP32Async/ESPAsyncWebServer/commit/3d3456e9e81502a477f6498c44d0691499dda8f9#diff-646b25b11691c11dce25529e3abce843f0ba4bd07ab75ec9eee7e72b06dbf13fR388-R392 @@ -254,7 +252,9 @@ class AsyncWebServerRequest { std::list _headers; std::list _params; +#ifdef ASYNCWEBSERVER_REGEX std::list _pathParams; +#endif std::unordered_map, std::equal_to> _attributes; @@ -277,8 +277,6 @@ class AsyncWebServerRequest { void _onDisconnect(); void _onData(void *buf, size_t len); - void _addPathParam(const char *param); - bool _parseReqHead(); bool _parseReqHeader(); void _parseLine(); @@ -615,10 +613,22 @@ class AsyncWebServerRequest { bool hasArg(const __FlashStringHelper *data) const; // check if F(argument) exists #endif - const String &ASYNCWEBSERVER_REGEX_ATTRIBUTE pathArg(size_t i) const; - const String &ASYNCWEBSERVER_REGEX_ATTRIBUTE pathArg(int i) const { +#ifdef ASYNCWEBSERVER_REGEX + const String &pathArg(size_t i) const { + if (i >= _pathParams.size()) { + return emptyString; + } + auto it = _pathParams.begin(); + std::advance(it, i); + return *it; + } + const String &pathArg(int i) const { return i < 0 ? emptyString : pathArg((size_t)i); } +#else + const String &pathArg(size_t i) const __attribute__((error("ERR: pathArg() requires -D ASYNCWEBSERVER_REGEX and only works on regex handlers"))); + const String &pathArg(int i) const __attribute__((error("ERR: pathArg() requires -D ASYNCWEBSERVER_REGEX and only works on regex handlers"))); +#endif // get request header value by name const String &header(const char *name) const; diff --git a/src/WebHandlerImpl.h b/src/WebHandlerImpl.h index 1f68d6273..8dca3f5ee 100644 --- a/src/WebHandlerImpl.h +++ b/src/WebHandlerImpl.h @@ -5,10 +5,6 @@ #define ASYNCWEBSERVERHANDLERIMPL_H_ #include -#ifdef ASYNCWEBSERVER_REGEX -#include -#endif - #include "stddef.h" #include diff --git a/src/WebHandlers.cpp b/src/WebHandlers.cpp index 1a3de2e87..0082937d4 100644 --- a/src/WebHandlers.cpp +++ b/src/WebHandlers.cpp @@ -312,7 +312,7 @@ bool AsyncCallbackWebHandler::canHandle(AsyncWebServerRequest *request) const { std::string s(request->url().c_str()); if (std::regex_search(s, matches, pattern)) { for (size_t i = 1; i < matches.size(); ++i) { // start from 1 - request->_addPathParam(matches[i].str().c_str()); + request->_pathParams.emplace_back(matches[i].str().c_str()); } } else { return false; diff --git a/src/WebRequest.cpp b/src/WebRequest.cpp index 5bbe0b723..a0b7e9cb8 100644 --- a/src/WebRequest.cpp +++ b/src/WebRequest.cpp @@ -90,10 +90,6 @@ AsyncWebServerRequest::~AsyncWebServerRequest() { _this.reset(); - _headers.clear(); - - _pathParams.clear(); - AsyncWebServerResponse *r = _response; _response = NULL; delete r; @@ -271,10 +267,6 @@ void AsyncWebServerRequest::_onDisconnect() { _server->_handleDisconnect(this); } -void AsyncWebServerRequest::_addPathParam(const char *p) { - _pathParams.emplace_back(p); -} - void AsyncWebServerRequest::_addGetParams(const String ¶ms) { size_t start = 0; while (start < params.length()) { @@ -1075,15 +1067,6 @@ const String &AsyncWebServerRequest::argName(size_t i) const { return getParam(i)->name(); } -const String &AsyncWebServerRequest::pathArg(size_t i) const { - if (i >= _pathParams.size()) { - return emptyString; - } - auto it = _pathParams.begin(); - std::advance(it, i); - return *it; -} - const String &AsyncWebServerRequest::header(const char *name) const { const AsyncWebHeader *h = getHeader(name); return h ? h->value() : emptyString;