diff --git a/README.md b/README.md index 92fec33..9bb7575 100644 --- a/README.md +++ b/README.md @@ -38,7 +38,7 @@ It is also deployed in these registries: - Arduino Library Registry: [https://github.com/arduino/library-registry](https://github.com/arduino/library-registry) -- ESP Component Registry [https://components.espressif.com/components/esp32async/espasyncbebserver/](https://components.espressif.com/components/esp32async/espasyncbebserver/) +- ESP Component Registry [https://components.espressif.com/components/esp32async/espasyncwebserver](https://components.espressif.com/components/esp32async/espasyncwebserver) - PlatformIO Registry: [https://registry.platformio.org/libraries/esp32async/ESPAsyncWebServer](https://registry.platformio.org/libraries/esp32async/ESPAsyncWebServer) @@ -100,7 +100,7 @@ platform = https://github.com/maxgerhardt/platform-raspberrypi.git board = rpipicow board_build.core = earlephilhower lib_deps = - ayushsharma82/RPAsyncTCP@^1.3.1 + ayushsharma82/RPAsyncTCP@^1.3.2 ESP32Async/ESPAsyncWebServer lib_ignore = lwIP_ESPHost diff --git a/examples/ServerState/ServerState.ino b/examples/ServerState/ServerState.ino new file mode 100644 index 0000000..8501758 --- /dev/null +++ b/examples/ServerState/ServerState.ino @@ -0,0 +1,66 @@ +// SPDX-License-Identifier: LGPL-3.0-or-later +// Copyright 2016-2025 Hristo Gochkov, Mathieu Carbou, Emil Muratov + +// +// Server state example +// + +#include +#ifdef ESP32 +#include +#include +#elif defined(ESP8266) +#include +#include +#elif defined(TARGET_RP2040) || defined(TARGET_RP2350) || defined(PICO_RP2040) || defined(PICO_RP2350) +#include +#include +#endif + +#include + +static AsyncWebServer server1(80); +static AsyncWebServer server2(80); + +void setup() { + Serial.begin(115200); + +#ifndef CONFIG_IDF_TARGET_ESP32H2 + WiFi.mode(WIFI_AP); + WiFi.softAP("esp-captive"); +#endif + + // server state returns one of the tcp_state enum values: + // enum tcp_state { + // CLOSED = 0, + // LISTEN = 1, + // SYN_SENT = 2, + // SYN_RCVD = 3, + // ESTABLISHED = 4, + // FIN_WAIT_1 = 5, + // FIN_WAIT_2 = 6, + // CLOSE_WAIT = 7, + // CLOSING = 8, + // LAST_ACK = 9, + // TIME_WAIT = 10 + // }; + + assert(server1.state() == tcp_state::CLOSED); + assert(server2.state() == tcp_state::CLOSED); + + server1.begin(); + + assert(server1.state() == tcp_state::LISTEN); + assert(server2.state() == tcp_state::CLOSED); + + server2.begin(); + + assert(server1.state() == tcp_state::LISTEN); + assert(server2.state() == tcp_state::CLOSED); + + Serial.println("Done!"); +} + +void loop() { + delay(100); +} diff --git a/examples/StaticFile/StaticFile.ino b/examples/StaticFile/StaticFile.ino index 3cdf188..331f287 100644 --- a/examples/StaticFile/StaticFile.ino +++ b/examples/StaticFile/StaticFile.ino @@ -105,6 +105,22 @@ void setup() { f.close(); } + LittleFS.mkdir("/files"); + + { + File f = LittleFS.open("/files/a.txt", "w"); + assert(f); + f.print("Hello from a.txt"); + f.close(); + } + + { + File f = LittleFS.open("/files/b.txt", "w"); + assert(f); + f.print("Hello from b.txt"); + f.close(); + } + // curl -v http://192.168.4.1/ server.on("/", HTTP_GET, [](AsyncWebServerRequest *request) { request->redirect("/index.html"); @@ -113,6 +129,12 @@ void setup() { // curl -v http://192.168.4.1/index.html server.serveStatic("/index.html", LittleFS, "/index.html"); + // Example to serve a directory content + // curl -v http://192.168.4.1/base/ => serves a.txt + // curl -v http://192.168.4.1/base/a.txt => serves a.txt + // curl -v http://192.168.4.1/base/b.txt => serves b.txt + server.serveStatic("/base", LittleFS, "/files").setDefaultFile("a.txt"); + server.begin(); } diff --git a/idf_component.yml b/idf_component.yml index 905a36a..7969fda 100644 --- a/idf_component.yml +++ b/idf_component.yml @@ -26,7 +26,7 @@ files: - "pre-commit.requirements.txt" dependencies: esp32async/asynctcp: - version: "^3.3.6" + version: "^3.3.8" require: public bblanchon/arduinojson: version: "^7.3.1" diff --git a/library.json b/library.json index 22cb862..70d5044 100644 --- a/library.json +++ b/library.json @@ -1,6 +1,6 @@ { "name": "ESPAsyncWebServer", - "version": "3.7.2", + "version": "3.7.4", "description": "Asynchronous HTTP and WebSocket Server Library for ESP32, ESP8266 and RP2040. Supports: WebSocket, SSE, Authentication, Arduino Json 7, File Upload, Static File serving, URL Rewrite, URL Redirect, etc.", "keywords": "http,async,websocket,webserver", "homepage": "https://github.com/ESP32Async/ESPAsyncWebServer", @@ -24,7 +24,7 @@ { "owner": "ESP32Async", "name": "AsyncTCP", - "version": "^3.3.6", + "version": "^3.3.8", "platforms": "espressif32" }, { @@ -40,7 +40,7 @@ { "owner": "ayushsharma82", "name": "RPAsyncTCP", - "version": "^1.3.1", + "version": "^1.3.2", "platforms": "raspberrypi" } ], diff --git a/library.properties b/library.properties index 0f7229a..7894456 100644 --- a/library.properties +++ b/library.properties @@ -1,6 +1,6 @@ name=ESP Async WebServer includes=ESPAsyncWebServer.h -version=3.7.2 +version=3.7.4 author=ESP32Async maintainer=ESP32Async sentence=Asynchronous HTTP and WebSocket Server Library for ESP32, ESP8266 and RP2040 diff --git a/pioarduino_examples/IncreaseMaxSockets/platformio.ini b/pioarduino_examples/IncreaseMaxSockets/platformio.ini index e132ec4..20291d1 100644 --- a/pioarduino_examples/IncreaseMaxSockets/platformio.ini +++ b/pioarduino_examples/IncreaseMaxSockets/platformio.ini @@ -17,7 +17,7 @@ monitor_filters = esp32_exception_decoder, log2file lib_compat_mode = strict lib_ldf_mode = chain lib_deps = - ESP32Async/AsyncTCP @ 3.3.6 + ESP32Async/AsyncTCP @ 3.3.8 ESP32Async/ESpAsyncWebServer @ 3.7.0 custom_sdkconfig = CONFIG_LWIP_MAX_ACTIVE_TCP=32 diff --git a/platformio.ini b/platformio.ini index 2fa4f99..025d011 100644 --- a/platformio.ini +++ b/platformio.ini @@ -25,6 +25,7 @@ src_dir = examples/PerfTests ; src_dir = examples/ResumableDownload ; src_dir = examples/Rewrite ; src_dir = examples/ServerSentEvents +; src_dir = examples/ServerState ; src_dir = examples/SkipServerMiddleware ; src_dir = examples/SlowChunkResponse ; src_dir = examples/StaticFile @@ -55,7 +56,7 @@ lib_compat_mode = strict lib_ldf_mode = chain lib_deps = bblanchon/ArduinoJson @ 7.3.1 - ESP32Async/AsyncTCP @ 3.3.6 + ESP32Async/AsyncTCP @ 3.3.8 board_build.partitions = partitions-4MB.csv board_build.filesystem = littlefs @@ -69,7 +70,7 @@ platform = https://github.com/pioarduino/platform-espressif32/releases/download/ [env:arduino-3-no-json] lib_deps = - ESP32Async/AsyncTCP @ 3.3.6 + ESP32Async/AsyncTCP @ 3.3.8 [env:arduino-3-latest-asynctcp] lib_deps = @@ -98,7 +99,7 @@ board = rpipicow board_build.core = earlephilhower lib_deps = bblanchon/ArduinoJson @ 7.3.0 - ayushsharma82/RPAsyncTCP@^1.3.1 + ayushsharma82/RPAsyncTCP@^1.3.2 lib_ignore = lwIP_ESPHost build_flags = ${env.build_flags} @@ -120,7 +121,7 @@ board = ${sysenv.PIO_BOARD} [env:ci-arduino-3-no-json] board = ${sysenv.PIO_BOARD} lib_deps = - ESP32Async/AsyncTCP @ 3.3.6 + ESP32Async/AsyncTCP @ 3.3.8 [env:ci-arduino-3-latest-asynctcp] lib_deps = @@ -144,7 +145,7 @@ board = ${sysenv.PIO_BOARD} board_build.core = earlephilhower lib_deps = bblanchon/ArduinoJson @ 7.3.0 - ayushsharma82/RPAsyncTCP@^1.3.1 + ayushsharma82/RPAsyncTCP@^1.3.2 lib_ignore = lwIP_ESPHost build_flags = ${env.build_flags} diff --git a/src/AsyncWebServerVersion.h b/src/AsyncWebServerVersion.h index 35aeba3..ecab8a7 100644 --- a/src/AsyncWebServerVersion.h +++ b/src/AsyncWebServerVersion.h @@ -12,7 +12,7 @@ extern "C" { /** Minor version number (x.X.x) */ #define ASYNCWEBSERVER_VERSION_MINOR 7 /** Patch version number (x.x.X) */ -#define ASYNCWEBSERVER_VERSION_PATCH 2 +#define ASYNCWEBSERVER_VERSION_PATCH 4 /** * Macro to convert version number into an integer diff --git a/src/ESPAsyncWebServer.h b/src/ESPAsyncWebServer.h index 009d648..24233cd 100644 --- a/src/ESPAsyncWebServer.h +++ b/src/ESPAsyncWebServer.h @@ -4,9 +4,10 @@ #ifndef _ESPAsyncWebServer_H_ #define _ESPAsyncWebServer_H_ -#include "Arduino.h" +#include +#include +#include -#include "FS.h" #include #include #include @@ -468,7 +469,9 @@ public: } AsyncWebServerResponse *beginChunkedResponse(const char *contentType, AwsResponseFiller callback, AwsTemplateProcessor templateCallback = nullptr); - AsyncWebServerResponse *beginChunkedResponse(const String &contentType, AwsResponseFiller callback, AwsTemplateProcessor templateCallback = nullptr); + AsyncWebServerResponse *beginChunkedResponse(const String &contentType, AwsResponseFiller callback, AwsTemplateProcessor templateCallback = nullptr) { + return beginChunkedResponse(contentType.c_str(), callback, templateCallback); + } AsyncResponseStream *beginResponseStream(const char *contentType, size_t bufferSize = RESPONSE_STREAM_BUFFER_SIZE); AsyncResponseStream *beginResponseStream(const String &contentType, size_t bufferSize = RESPONSE_STREAM_BUFFER_SIZE) { @@ -537,6 +540,9 @@ public: * @return const AsyncWebParameter* */ const AsyncWebParameter *getParam(size_t num) const; + const AsyncWebParameter *getParam(int num) const { + return num < 0 ? nullptr : getParam((size_t)num); + } size_t args() const { return params(); @@ -551,9 +557,15 @@ public: #ifdef ESP8266 const String &arg(const __FlashStringHelper *data) const; // get request argument value by F(name) #endif - const String &arg(size_t i) const; // get request argument value by number + const String &arg(size_t i) const; // get request argument value by number + const String &arg(int i) const { + return i < 0 ? emptyString : arg((size_t)i); + }; const String &argName(size_t i) const; // get request argument name by number - bool hasArg(const char *name) const; // check if argument exists + const String &argName(int i) const { + return i < 0 ? emptyString : argName((size_t)i); + }; + bool hasArg(const char *name) const; // check if argument exists bool hasArg(const String &name) const { return hasArg(name.c_str()); }; @@ -562,6 +574,9 @@ public: #endif const String &ASYNCWEBSERVER_REGEX_ATTRIBUTE pathArg(size_t i) const; + const String &ASYNCWEBSERVER_REGEX_ATTRIBUTE pathArg(int i) const { + return i < 0 ? emptyString : pathArg((size_t)i); + } // get request header value by name const String &header(const char *name) const; @@ -573,8 +588,14 @@ public: const String &header(const __FlashStringHelper *data) const; // get request header value by F(name) #endif - const String &header(size_t i) const; // get request header value by number + const String &header(size_t i) const; // get request header value by number + const String &header(int i) const { + return i < 0 ? emptyString : header((size_t)i); + }; const String &headerName(size_t i) const; // get request header name by number + const String &headerName(int i) const { + return i < 0 ? emptyString : headerName((size_t)i); + }; size_t headers() const; // get header count @@ -596,6 +617,9 @@ public: #endif const AsyncWebHeader *getHeader(size_t num) const; + const AsyncWebHeader *getHeader(int num) const { + return num < 0 ? nullptr : getHeader((size_t)num); + }; const std::list &getHeaders() const { return _headers; @@ -1075,6 +1099,15 @@ public: void begin(); void end(); + tcp_state state() const { +#ifdef ESP8266 + // ESPAsyncTCP and RPAsyncTCP methods are not corrected declared with const for immutable ones. + return static_cast(const_cast(this)->_server.status()); +#else + return static_cast(_server.status()); +#endif + } + #if ASYNC_TCP_SSL_ENABLED void onSslFileRequest(AcSSlFileHandler cb, void *arg); void beginSecure(const char *cert, const char *private_key_file, const char *password); diff --git a/src/WebHandlerImpl.h b/src/WebHandlerImpl.h index 99a9111..1f68d62 100644 --- a/src/WebHandlerImpl.h +++ b/src/WebHandlerImpl.h @@ -19,7 +19,6 @@ class AsyncStaticWebHandler : public AsyncWebHandler { private: bool _getFile(AsyncWebServerRequest *request) const; bool _searchFile(AsyncWebServerRequest *request, const String &path); - uint8_t _countBits(const uint8_t value) const; protected: FS _fs; diff --git a/src/WebHandlers.cpp b/src/WebHandlers.cpp index 516ffc2..acfc7c0 100644 --- a/src/WebHandlers.cpp +++ b/src/WebHandlers.cpp @@ -187,15 +187,6 @@ bool AsyncStaticWebHandler::_searchFile(AsyncWebServerRequest *request, const St return found; } -uint8_t AsyncStaticWebHandler::_countBits(const uint8_t value) const { - uint8_t w = value; - uint8_t n; - for (n = 0; w != 0; n++) { - w &= w - 1; - } - return n; -} - void AsyncStaticWebHandler::handleRequest(AsyncWebServerRequest *request) { // Get the filename from request->_tempObject and free it String filename((char *)request->_tempObject);