mirror of
https://github.com/me-no-dev/ESPAsyncWebServer.git
synced 2025-09-30 08:10:56 +02:00
Merge branch 'main' into sse_shareddata
This commit is contained in:
12
.github/workflows/ci.yml
vendored
12
.github/workflows/ci.yml
vendored
@@ -22,9 +22,9 @@ jobs:
|
||||
- core: esp32:esp32
|
||||
board: esp32:esp32:esp32
|
||||
index_url: https://espressif.github.io/arduino-esp32/package_esp32_index.json
|
||||
- core: esp32:esp32
|
||||
board: esp32:esp32:esp32
|
||||
index_url: https://espressif.github.io/arduino-esp32/package_esp32_dev_index.json
|
||||
# - core: esp32:esp32
|
||||
# board: esp32:esp32:esp32
|
||||
# index_url: https://espressif.github.io/arduino-esp32/package_esp32_dev_index.json
|
||||
- core: esp8266:esp8266
|
||||
board: esp8266:esp8266:huzzah
|
||||
index_url: https://arduino.esp8266.com/stable/package_esp8266com_index.json
|
||||
@@ -55,7 +55,7 @@ jobs:
|
||||
|
||||
- name: Install AsyncTCP (ESP32)
|
||||
if: ${{ matrix.core == 'esp32:esp32' }}
|
||||
run: ARDUINO_LIBRARY_ENABLE_UNSAFE_INSTALL=true arduino-cli lib install --git-url https://github.com/mathieucarbou/AsyncTCP#v3.2.12
|
||||
run: ARDUINO_LIBRARY_ENABLE_UNSAFE_INSTALL=true arduino-cli lib install --git-url https://github.com/mathieucarbou/AsyncTCP#v3.2.14
|
||||
|
||||
- name: Install ESPAsyncTCP (ESP8266)
|
||||
if: ${{ matrix.core == 'esp8266:esp8266' }}
|
||||
@@ -127,8 +127,8 @@ jobs:
|
||||
- env: ci-esp8266
|
||||
board: d1_mini
|
||||
|
||||
- env: ci-raspberrypi
|
||||
board: rpipicow
|
||||
# - env: ci-raspberrypi
|
||||
# board: rpipicow
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
64
README.md
64
README.md
@@ -52,6 +52,20 @@ This fork is based on [yubox-node-org/ESPAsyncWebServer](https://github.com/yubo
|
||||
- (perf) Lot of code cleanup and optimizations
|
||||
- (perf) Performance improvements in terms of memory, speed and size
|
||||
|
||||
---
|
||||
|
||||
## WARNING: Important notes about future version 4.x
|
||||
|
||||
This ESPAsyncWebServer fork is now at version 3.x.
|
||||
|
||||
Next version 4.x will:
|
||||
|
||||
1. Drop support for ESP8266, which goes EOL in a few years. All ESP8266 boards can be replaced by equivalent ESP32 boards.
|
||||
2. Drop support for Arduino 2.x and ESP-IDF 4.x. The library will be compatible with Arduino 3.x and ESP-IDF 5.x.
|
||||
3. Drop support for ArduinoJson 5.x and 6.x. The library will be compatible with ArduinoJson 7.x.
|
||||
|
||||
So if you need one of these feature, you will have to stick with 3.x or another fork.
|
||||
|
||||
## Dependencies
|
||||
|
||||
**WARNING** The library name was changed from `ESP Async WebServer` to `ESPAsyncWebServer` as per the Arduino Lint recommendations, but its name had to stay `ESP Async WebServer` in Arduino Registry.
|
||||
@@ -61,13 +75,13 @@ This fork is based on [yubox-node-org/ESPAsyncWebServer](https://github.com/yubo
|
||||
```ini
|
||||
lib_compat_mode = strict
|
||||
lib_ldf_mode = chain
|
||||
lib_deps = mathieucarbou/ESPAsyncWebServer @ 3.3.22
|
||||
lib_deps = mathieucarbou/ESPAsyncWebServer @ 3.3.23
|
||||
```
|
||||
|
||||
**Dependencies:**
|
||||
|
||||
- **ESP32 with AsyncTCP**: `mathieucarbou/AsyncTCP @ 3.2.12`
|
||||
Arduino IDE: [https://github.com/mathieucarbou/AsyncTCP#v3.2.12](https://github.com/mathieucarbou/AsyncTCP/releases)
|
||||
- **ESP32 with AsyncTCP**: `mathieucarbou/AsyncTCP @ 3.2.14`
|
||||
Arduino IDE: [https://github.com/mathieucarbou/AsyncTCP#v3.2.14](https://github.com/mathieucarbou/AsyncTCP/releases)
|
||||
|
||||
- **ESP32 with AsyncTCPSock**: `https://github.com/mathieucarbou/AsyncTCPSock/archive/refs/tags/v1.0.3-dev.zip`
|
||||
|
||||
@@ -85,9 +99,9 @@ AsyncTCPSock can be used instead of AsyncTCP by excluding AsyncTCP from the libr
|
||||
lib_compat_mode = strict
|
||||
lib_ldf_mode = chain
|
||||
lib_deps =
|
||||
; mathieucarbou/AsyncTCP @ 3.2.12
|
||||
; mathieucarbou/AsyncTCP @ 3.2.14
|
||||
https://github.com/mathieucarbou/AsyncTCPSock/archive/refs/tags/v1.0.3-dev.zip
|
||||
mathieucarbou/ESPAsyncWebServer @ 3.3.22
|
||||
mathieucarbou/ESPAsyncWebServer @ 3.3.23
|
||||
lib_ignore =
|
||||
AsyncTCP
|
||||
mathieucarbou/AsyncTCP
|
||||
@@ -95,14 +109,14 @@ lib_ignore =
|
||||
|
||||
## Performance
|
||||
|
||||
Performance of `mathieucarbou/ESPAsyncWebServer @ 3.3.22`:
|
||||
Performance of `mathieucarbou/ESPAsyncWebServer @ 3.3.23`:
|
||||
|
||||
```bash
|
||||
> brew install autocannon
|
||||
> autocannon -c 10 -w 10 -d 20 http://192.168.4.1
|
||||
```
|
||||
|
||||
With `mathieucarbou/AsyncTCP @ 3.2.12`
|
||||
With `mathieucarbou/AsyncTCP @ 3.2.14`
|
||||
|
||||
[](https://mathieu.carbou.me/ESPAsyncWebServer/perf-c10.png)
|
||||
|
||||
@@ -110,6 +124,40 @@ With `https://github.com/mathieucarbou/AsyncTCPSock/archive/refs/tags/v1.0.3-dev
|
||||
|
||||
[](https://mathieu.carbou.me/ESPAsyncWebServer/perf-c10-asynctcpsock.png)
|
||||
|
||||
**SSE performance**
|
||||
|
||||
In the example, there is an endpoint `/events` with some comments showing how these metrics are calculated.
|
||||
|
||||
Test is running for 20 seconds with 10 connections.
|
||||
|
||||
```
|
||||
// With AsyncTCP, with 10 workers: no message discarded from the queue
|
||||
//
|
||||
// Total: 1875 events, 468.75000000000000000000 events / second
|
||||
// Total: 1870 events, 467.50000000000000000000 events / second
|
||||
// Total: 1871 events, 467.75000000000000000000 events / second
|
||||
// Total: 1875 events, 468.75000000000000000000 events / second
|
||||
// Total: 1871 events, 467.75000000000000000000 events / second
|
||||
// Total: 1805 events, 451.25000000000000000000 events / second
|
||||
// Total: 1803 events, 450.75000000000000000000 events / second
|
||||
// Total: 1873 events, 468.25000000000000000000 events / second
|
||||
// Total: 1872 events, 468.00000000000000000000 events / second
|
||||
// Total: 1805 events, 451.25000000000000000000 events / second
|
||||
//
|
||||
// With AsyncTCPSock, with 10 workers: no message discarded from the queue
|
||||
//
|
||||
// Total: 1242 events, 310.50000000000000000000 events / second
|
||||
// Total: 1242 events, 310.50000000000000000000 events / second
|
||||
// Total: 1242 events, 310.50000000000000000000 events / second
|
||||
// Total: 1242 events, 310.50000000000000000000 events / second
|
||||
// Total: 1181 events, 295.25000000000000000000 events / second
|
||||
// Total: 1182 events, 295.50000000000000000000 events / second
|
||||
// Total: 1240 events, 310.00000000000000000000 events / second
|
||||
// Total: 1181 events, 295.25000000000000000000 events / second
|
||||
// Total: 1181 events, 295.25000000000000000000 events / second
|
||||
// Total: 1183 events, 295.75000000000000000000 events / second
|
||||
```
|
||||
|
||||
## Important recommendations
|
||||
|
||||
Most of the crashes are caused by improper configuration of the library for the project.
|
||||
@@ -574,7 +622,7 @@ Endpoints which consume JSON can use a special handler to get ready to use JSON
|
||||
#include "ArduinoJson.h"
|
||||
|
||||
AsyncCallbackJsonWebHandler* handler = new AsyncCallbackJsonWebHandler("/rest/endpoint", [](AsyncWebServerRequest *request, JsonVariant &json) {
|
||||
JsonObject& jsonObj = json.as<JsonObject>();
|
||||
JsonObject jsonObj = json.as<JsonObject>();
|
||||
// ...
|
||||
});
|
||||
server.addHandler(handler);
|
||||
|
@@ -52,6 +52,20 @@ This fork is based on [yubox-node-org/ESPAsyncWebServer](https://github.com/yubo
|
||||
- (perf) Lot of code cleanup and optimizations
|
||||
- (perf) Performance improvements in terms of memory, speed and size
|
||||
|
||||
---
|
||||
|
||||
## WARNING: Important notes about future version 4.x
|
||||
|
||||
This ESPAsyncWebServer fork is now at version 3.x.
|
||||
|
||||
Next version 4.x will:
|
||||
|
||||
1. Drop support for ESP8266, which goes EOL in a few years. All ESP8266 boards can be replaced by equivalent ESP32 boards.
|
||||
2. Drop support for Arduino 2.x and ESP-IDF 4.x. The library will be compatible with Arduino 3.x and ESP-IDF 5.x.
|
||||
3. Drop support for ArduinoJson 5.x and 6.x. The library will be compatible with ArduinoJson 7.x.
|
||||
|
||||
So if you need one of these feature, you will have to stick with 3.x or another fork.
|
||||
|
||||
## Dependencies
|
||||
|
||||
**WARNING** The library name was changed from `ESP Async WebServer` to `ESPAsyncWebServer` as per the Arduino Lint recommendations, but its name had to stay `ESP Async WebServer` in Arduino Registry.
|
||||
@@ -61,13 +75,13 @@ This fork is based on [yubox-node-org/ESPAsyncWebServer](https://github.com/yubo
|
||||
```ini
|
||||
lib_compat_mode = strict
|
||||
lib_ldf_mode = chain
|
||||
lib_deps = mathieucarbou/ESPAsyncWebServer @ 3.3.22
|
||||
lib_deps = mathieucarbou/ESPAsyncWebServer @ 3.3.23
|
||||
```
|
||||
|
||||
**Dependencies:**
|
||||
|
||||
- **ESP32 with AsyncTCP**: `mathieucarbou/AsyncTCP @ 3.2.12`
|
||||
Arduino IDE: [https://github.com/mathieucarbou/AsyncTCP#v3.2.12](https://github.com/mathieucarbou/AsyncTCP/releases)
|
||||
- **ESP32 with AsyncTCP**: `mathieucarbou/AsyncTCP @ 3.2.14`
|
||||
Arduino IDE: [https://github.com/mathieucarbou/AsyncTCP#v3.2.14](https://github.com/mathieucarbou/AsyncTCP/releases)
|
||||
|
||||
- **ESP32 with AsyncTCPSock**: `https://github.com/mathieucarbou/AsyncTCPSock/archive/refs/tags/v1.0.3-dev.zip`
|
||||
|
||||
@@ -85,9 +99,9 @@ AsyncTCPSock can be used instead of AsyncTCP by excluding AsyncTCP from the libr
|
||||
lib_compat_mode = strict
|
||||
lib_ldf_mode = chain
|
||||
lib_deps =
|
||||
; mathieucarbou/AsyncTCP @ 3.2.12
|
||||
; mathieucarbou/AsyncTCP @ 3.2.14
|
||||
https://github.com/mathieucarbou/AsyncTCPSock/archive/refs/tags/v1.0.3-dev.zip
|
||||
mathieucarbou/ESPAsyncWebServer @ 3.3.22
|
||||
mathieucarbou/ESPAsyncWebServer @ 3.3.23
|
||||
lib_ignore =
|
||||
AsyncTCP
|
||||
mathieucarbou/AsyncTCP
|
||||
@@ -95,14 +109,14 @@ lib_ignore =
|
||||
|
||||
## Performance
|
||||
|
||||
Performance of `mathieucarbou/ESPAsyncWebServer @ 3.3.22`:
|
||||
Performance of `mathieucarbou/ESPAsyncWebServer @ 3.3.23`:
|
||||
|
||||
```bash
|
||||
> brew install autocannon
|
||||
> autocannon -c 10 -w 10 -d 20 http://192.168.4.1
|
||||
```
|
||||
|
||||
With `mathieucarbou/AsyncTCP @ 3.2.12`
|
||||
With `mathieucarbou/AsyncTCP @ 3.2.14`
|
||||
|
||||
[](https://mathieu.carbou.me/ESPAsyncWebServer/perf-c10.png)
|
||||
|
||||
@@ -110,6 +124,40 @@ With `https://github.com/mathieucarbou/AsyncTCPSock/archive/refs/tags/v1.0.3-dev
|
||||
|
||||
[](https://mathieu.carbou.me/ESPAsyncWebServer/perf-c10-asynctcpsock.png)
|
||||
|
||||
**SSE performance**
|
||||
|
||||
In the example, there is an endpoint `/events` with some comments showing how these metrics are calculated.
|
||||
|
||||
Test is running for 20 seconds with 10 connections.
|
||||
|
||||
```
|
||||
// With AsyncTCP, with 10 workers: no message discarded from the queue
|
||||
//
|
||||
// Total: 1875 events, 468.75000000000000000000 events / second
|
||||
// Total: 1870 events, 467.50000000000000000000 events / second
|
||||
// Total: 1871 events, 467.75000000000000000000 events / second
|
||||
// Total: 1875 events, 468.75000000000000000000 events / second
|
||||
// Total: 1871 events, 467.75000000000000000000 events / second
|
||||
// Total: 1805 events, 451.25000000000000000000 events / second
|
||||
// Total: 1803 events, 450.75000000000000000000 events / second
|
||||
// Total: 1873 events, 468.25000000000000000000 events / second
|
||||
// Total: 1872 events, 468.00000000000000000000 events / second
|
||||
// Total: 1805 events, 451.25000000000000000000 events / second
|
||||
//
|
||||
// With AsyncTCPSock, with 10 workers: no message discarded from the queue
|
||||
//
|
||||
// Total: 1242 events, 310.50000000000000000000 events / second
|
||||
// Total: 1242 events, 310.50000000000000000000 events / second
|
||||
// Total: 1242 events, 310.50000000000000000000 events / second
|
||||
// Total: 1242 events, 310.50000000000000000000 events / second
|
||||
// Total: 1181 events, 295.25000000000000000000 events / second
|
||||
// Total: 1182 events, 295.50000000000000000000 events / second
|
||||
// Total: 1240 events, 310.00000000000000000000 events / second
|
||||
// Total: 1181 events, 295.25000000000000000000 events / second
|
||||
// Total: 1181 events, 295.25000000000000000000 events / second
|
||||
// Total: 1183 events, 295.75000000000000000000 events / second
|
||||
```
|
||||
|
||||
## Important recommendations
|
||||
|
||||
Most of the crashes are caused by improper configuration of the library for the project.
|
||||
@@ -1232,7 +1280,7 @@ For actual serving the file.
|
||||
|
||||
### Param Rewrite With Matching
|
||||
|
||||
It is possible to rewrite the request url with parameter matchg. Here is an example with one parameter:
|
||||
It is possible to rewrite the request url with parameter match. Here is an example with one parameter:
|
||||
Rewrite for example "/radio/{frequence}" -> "/radio?f={frequence}"
|
||||
|
||||
```cpp
|
||||
|
@@ -16,7 +16,7 @@ AsyncWebServer server(80);
|
||||
|
||||
class CaptiveRequestHandler : public AsyncWebHandler {
|
||||
public:
|
||||
bool canHandle(__unused AsyncWebServerRequest* request) {
|
||||
bool canHandle(__unused AsyncWebServerRequest* request) const override {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@@ -18,11 +18,11 @@ AsyncWebServer server(80);
|
||||
|
||||
class CaptiveRequestHandler : public AsyncWebHandler {
|
||||
public:
|
||||
bool canHandle(__unused AsyncWebServerRequest* request) {
|
||||
bool canHandle(__unused AsyncWebServerRequest* request) const override {
|
||||
return true;
|
||||
}
|
||||
|
||||
void handleRequest(AsyncWebServerRequest* request) {
|
||||
void handleRequest(AsyncWebServerRequest* request) override {
|
||||
AsyncResponseStream* response = request->beginResponseStream("text/html");
|
||||
response->print("<!DOCTYPE html><html><head><title>Captive Portal</title></head><body>");
|
||||
response->print("<p>This is out captive portal front page.</p>");
|
||||
|
84
examples/Issue162/Issue162.ino
Normal file
84
examples/Issue162/Issue162.ino
Normal file
@@ -0,0 +1,84 @@
|
||||
/**
|
||||
*
|
||||
* Connect to AP and run in bash:
|
||||
*
|
||||
* > while true; do echo "PING"; sleep 0.1; done | websocat ws://192.168.4.1/ws
|
||||
*
|
||||
*/
|
||||
#include <Arduino.h>
|
||||
#ifdef ESP8266
|
||||
#include <ESP8266WiFi.h>
|
||||
#endif
|
||||
#ifdef ESP32
|
||||
#include <WiFi.h>
|
||||
#endif
|
||||
#include <ESPAsyncWebServer.h>
|
||||
|
||||
#include <list>
|
||||
AsyncWebServer server(80);
|
||||
AsyncWebSocket ws("/ws");
|
||||
|
||||
void onWsEvent(AsyncWebSocket* server, AsyncWebSocketClient* client, AwsEventType type, void* arg, uint8_t* data, size_t len) {
|
||||
if (type == WS_EVT_CONNECT) {
|
||||
Serial.printf("Client #%" PRIu32 " connected.\n", client->id());
|
||||
} else if (type == WS_EVT_DISCONNECT) {
|
||||
Serial.printf("Client #%" PRIu32 " disconnected.\n", client->id());
|
||||
} else if (type == WS_EVT_ERROR) {
|
||||
Serial.printf("Client #%" PRIu32 " error.\n", client->id());
|
||||
} else if (type == WS_EVT_DATA) {
|
||||
Serial.printf("Client #%" PRIu32 " len: %u\n", client->id(), len);
|
||||
} else if (type == WS_EVT_PONG) {
|
||||
Serial.printf("Client #%" PRIu32 " pong.\n", client->id());
|
||||
} else if (type == WS_EVT_PING) {
|
||||
Serial.printf("Client #%" PRIu32 " ping.\n", client->id());
|
||||
}
|
||||
}
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
|
||||
WiFi.mode(WIFI_AP);
|
||||
WiFi.softAP("esp-captive");
|
||||
|
||||
ws.onEvent(onWsEvent);
|
||||
server.addHandler(&ws);
|
||||
|
||||
server.on("/close_all_ws_clients", HTTP_GET | HTTP_POST, [](AsyncWebServerRequest* request) {
|
||||
Serial.println("Closing all WebSocket clients...");
|
||||
ws.closeAll();
|
||||
request->send(200, "application/json", "{\"status\":\"all clients closed\"}");
|
||||
});
|
||||
|
||||
server.on("/", HTTP_GET, [](AsyncWebServerRequest* request) {
|
||||
request->send(200, "text/html", R"rawliteral(
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head></head>
|
||||
<script>
|
||||
let ws = new WebSocket("ws://" + window.location.host + "/ws");
|
||||
|
||||
document.addEventListener("DOMContentLoaded", function () {
|
||||
ws.onopen = function () {
|
||||
console.log("WebSocket connected");
|
||||
};
|
||||
});
|
||||
|
||||
function closeAllWsClients() {
|
||||
fetch("/close_all_ws_clients", {
|
||||
method : "POST",
|
||||
});
|
||||
};
|
||||
</script>
|
||||
<body>
|
||||
<button onclick = "closeAllWsClients()" style = "width: 200px"> ws close all</button><p></p>
|
||||
</body>
|
||||
</html>
|
||||
)rawliteral");
|
||||
});
|
||||
|
||||
server.begin();
|
||||
}
|
||||
|
||||
void loop() {
|
||||
vTaskDelete(NULL);
|
||||
}
|
@@ -87,6 +87,8 @@ const char* htmlContent PROGMEM = R"(
|
||||
</html>
|
||||
)";
|
||||
|
||||
const size_t htmlContentLength = strlen_P(htmlContent);
|
||||
|
||||
const char* staticContent PROGMEM = R"(
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
@@ -467,6 +469,40 @@ void setup() {
|
||||
request->send(response);
|
||||
});
|
||||
|
||||
// curl -N -v -X GET http://192.168.4.1/chunked.html --output -
|
||||
// curl -N -v -X GET -H "if-none-match: 4272" http://192.168.4.1/chunked.html --output -
|
||||
server.on("/chunked.html", HTTP_GET, [](AsyncWebServerRequest* request) {
|
||||
String len = String(htmlContentLength);
|
||||
|
||||
if (request->header(asyncsrv::T_INM) == len) {
|
||||
request->send(304);
|
||||
return;
|
||||
}
|
||||
|
||||
AsyncWebServerResponse* response = request->beginChunkedResponse("text/html", [](uint8_t* buffer, size_t maxLen, size_t index) -> size_t {
|
||||
Serial.printf("%u / %u\n", index, htmlContentLength);
|
||||
|
||||
// finished ?
|
||||
if (htmlContentLength <= index) {
|
||||
Serial.println("finished");
|
||||
return 0;
|
||||
}
|
||||
|
||||
// serve a maximum of 1024 or maxLen bytes of the remaining content
|
||||
const int chunkSize = min((size_t)1024, min(maxLen, htmlContentLength - index));
|
||||
Serial.printf("sending: %u\n", chunkSize);
|
||||
|
||||
memcpy(buffer, htmlContent + index, chunkSize);
|
||||
|
||||
return chunkSize;
|
||||
});
|
||||
|
||||
response->addHeader(asyncsrv::T_Cache_Control, "public,max-age=60");
|
||||
response->addHeader(asyncsrv::T_ETag, len);
|
||||
|
||||
request->send(response);
|
||||
});
|
||||
|
||||
/*
|
||||
❯ curl -I -X HEAD http://192.168.4.1/download
|
||||
HTTP/1.1 200 OK
|
||||
@@ -516,18 +552,6 @@ void setup() {
|
||||
#if __has_include("ArduinoJson.h")
|
||||
// JSON
|
||||
|
||||
// receives JSON and sends JSON
|
||||
jsonHandler->onRequest([](AsyncWebServerRequest* request, JsonVariant& json) {
|
||||
// JsonObject jsonObj = json.as<JsonObject>();
|
||||
// ...
|
||||
|
||||
AsyncJsonResponse* response = new AsyncJsonResponse();
|
||||
JsonObject root = response->getRoot().to<JsonObject>();
|
||||
root["hello"] = "world";
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
});
|
||||
|
||||
// sends JSON
|
||||
// curl -v -X GET http://192.168.4.1/json1
|
||||
server.on("/json1", HTTP_GET, [](AsyncWebServerRequest* request) {
|
||||
@@ -543,11 +567,23 @@ void setup() {
|
||||
AsyncResponseStream* response = request->beginResponseStream("application/json");
|
||||
JsonDocument doc;
|
||||
JsonObject root = doc.to<JsonObject>();
|
||||
root["hello"] = "world";
|
||||
root["foo"] = "bar";
|
||||
serializeJson(root, *response);
|
||||
request->send(response);
|
||||
});
|
||||
|
||||
// curl -v -X POST -H 'Content-Type: application/json' -d '{"name":"You"}' http://192.168.4.1/json2
|
||||
// curl -v -X PUT -H 'Content-Type: application/json' -d '{"name":"You"}' http://192.168.4.1/json2
|
||||
jsonHandler->setMethod(HTTP_POST | HTTP_PUT);
|
||||
jsonHandler->onRequest([](AsyncWebServerRequest* request, JsonVariant& json) {
|
||||
serializeJson(json, Serial);
|
||||
AsyncJsonResponse* response = new AsyncJsonResponse();
|
||||
JsonObject root = response->getRoot().to<JsonObject>();
|
||||
root["hello"] = json.as<JsonObject>()["name"];
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
});
|
||||
|
||||
// MessagePack
|
||||
|
||||
// receives MessagePack and sends MessagePack
|
||||
@@ -607,11 +643,82 @@ void setup() {
|
||||
}
|
||||
});
|
||||
|
||||
// SSS endpoints
|
||||
// sends a message every 10 ms
|
||||
//
|
||||
// go to http://192.168.4.1/sse
|
||||
// > curl -v -N -H "Accept: text/event-stream" http://192.168.4.1/events
|
||||
//
|
||||
// some perf tests:
|
||||
// launch 16 concurrent workers for 30 seconds
|
||||
// > for i in {1..16}; do ( count=$(gtimeout 30 curl -s -N -H "Accept: text/event-stream" http://192.168.4.1/events 2>&1 | grep -c "^data:"); echo "Total: $count events, $(echo "$count / 4" | bc -l) events / second" ) & done;
|
||||
//
|
||||
// With AsyncTCP, with 16 workers: a lot of Too many messages queued: deleting message
|
||||
//
|
||||
// Total: 119 events, 29.75000000000000000000 events / second
|
||||
// Total: 727 events, 181.75000000000000000000 events / second
|
||||
// Total: 1386 events, 346.50000000000000000000 events / second
|
||||
// Total: 1385 events, 346.25000000000000000000 events / second
|
||||
// Total: 1276 events, 319.00000000000000000000 events / second
|
||||
// Total: 1411 events, 352.75000000000000000000 events / second
|
||||
// Total: 1276 events, 319.00000000000000000000 events / second
|
||||
// Total: 1333 events, 333.25000000000000000000 events / second
|
||||
// Total: 1250 events, 312.50000000000000000000 events / second
|
||||
// Total: 1275 events, 318.75000000000000000000 events / second
|
||||
// Total: 1271 events, 317.75000000000000000000 events / second
|
||||
// Total: 1271 events, 317.75000000000000000000 events / second
|
||||
// Total: 1254 events, 313.50000000000000000000 events / second
|
||||
// Total: 1251 events, 312.75000000000000000000 events / second
|
||||
// Total: 1254 events, 313.50000000000000000000 events / second
|
||||
// Total: 1262 events, 315.50000000000000000000 events / second
|
||||
//
|
||||
// With AsyncTCP, with 10 workers:
|
||||
//
|
||||
// Total: 1875 events, 468.75000000000000000000 events / second
|
||||
// Total: 1870 events, 467.50000000000000000000 events / second
|
||||
// Total: 1871 events, 467.75000000000000000000 events / second
|
||||
// Total: 1875 events, 468.75000000000000000000 events / second
|
||||
// Total: 1871 events, 467.75000000000000000000 events / second
|
||||
// Total: 1805 events, 451.25000000000000000000 events / second
|
||||
// Total: 1803 events, 450.75000000000000000000 events / second
|
||||
// Total: 1873 events, 468.25000000000000000000 events / second
|
||||
// Total: 1872 events, 468.00000000000000000000 events / second
|
||||
// Total: 1805 events, 451.25000000000000000000 events / second
|
||||
//
|
||||
// With AsyncTCPSock, with 16 workers: ESP32 CRASH !!!
|
||||
//
|
||||
// With AsyncTCPSock, with 10 workers:
|
||||
//
|
||||
// Total: 1242 events, 310.50000000000000000000 events / second
|
||||
// Total: 1242 events, 310.50000000000000000000 events / second
|
||||
// Total: 1242 events, 310.50000000000000000000 events / second
|
||||
// Total: 1242 events, 310.50000000000000000000 events / second
|
||||
// Total: 1181 events, 295.25000000000000000000 events / second
|
||||
// Total: 1182 events, 295.50000000000000000000 events / second
|
||||
// Total: 1240 events, 310.00000000000000000000 events / second
|
||||
// Total: 1181 events, 295.25000000000000000000 events / second
|
||||
// Total: 1181 events, 295.25000000000000000000 events / second
|
||||
// Total: 1183 events, 295.75000000000000000000 events / second
|
||||
//
|
||||
server.addHandler(&events);
|
||||
|
||||
// Run: websocat ws://192.168.4.1/ws
|
||||
server.addHandler(&ws);
|
||||
// Run in terminal 1: websocat ws://192.168.4.1/ws => stream data
|
||||
// Run in terminal 2: websocat ws://192.168.4.1/ws => stream data
|
||||
// Run in terminal 3: websocat ws://192.168.4.1/ws => should fail:
|
||||
/*
|
||||
❯ websocat ws://192.168.4.1/ws
|
||||
websocat: WebSocketError: WebSocketError: Received unexpected status code (503 Service Unavailable)
|
||||
websocat: error running
|
||||
*/
|
||||
server.addHandler(&ws).addMiddleware([](AsyncWebServerRequest* request, ArMiddlewareNext next) {
|
||||
if (ws.count() > 2) {
|
||||
// too many clients - answer back immediately and stop processing next middlewares and handler
|
||||
request->send(503, "text/plain", "Server is busy");
|
||||
} else {
|
||||
// process next middleware and at the end the handler
|
||||
next();
|
||||
}
|
||||
});
|
||||
|
||||
#if __has_include("ArduinoJson.h")
|
||||
server.addHandler(jsonHandler);
|
||||
@@ -624,7 +731,7 @@ void setup() {
|
||||
}
|
||||
|
||||
uint32_t lastSSE = 0;
|
||||
uint32_t deltaSSE = 5;
|
||||
uint32_t deltaSSE = 10;
|
||||
|
||||
uint32_t lastWS = 0;
|
||||
uint32_t deltaWS = 100;
|
||||
@@ -637,9 +744,9 @@ void loop() {
|
||||
}
|
||||
if (now - lastWS >= deltaWS) {
|
||||
ws.printfAll("kp%.4f", (10.0 / 3.0));
|
||||
for (auto& client : ws.getClients()) {
|
||||
client.printf("kp%.4f", (10.0 / 3.0));
|
||||
}
|
||||
// for (auto& client : ws.getClients()) {
|
||||
// client.printf("kp%.4f", (10.0 / 3.0));
|
||||
// }
|
||||
lastWS = millis();
|
||||
}
|
||||
}
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "ESPAsyncWebServer",
|
||||
"version": "3.3.22",
|
||||
"version": "3.3.23",
|
||||
"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/mathieucarbou/ESPAsyncWebServer",
|
||||
@@ -28,7 +28,7 @@
|
||||
{
|
||||
"owner": "mathieucarbou",
|
||||
"name": "AsyncTCP",
|
||||
"version": "^3.2.12",
|
||||
"version": "^3.2.14",
|
||||
"platforms": "espressif32"
|
||||
},
|
||||
{
|
||||
|
@@ -1,6 +1,6 @@
|
||||
name=ESP Async WebServer
|
||||
includes=ESPAsyncWebServer.h
|
||||
version=3.3.22
|
||||
version=3.3.23
|
||||
author=Me-No-Dev
|
||||
maintainer=Mathieu Carbou <mathieu.carbou@gmail.com>
|
||||
sentence=Asynchronous HTTP and WebSocket Server Library for ESP32, ESP8266 and RP2040
|
||||
|
@@ -6,6 +6,7 @@ src_dir = examples/SimpleServer
|
||||
; src_dir = examples/StreamFiles
|
||||
; src_dir = examples/Filters
|
||||
; src_dir = examples/Issue85
|
||||
; src_dir = examples/Issue162
|
||||
|
||||
[env]
|
||||
framework = arduino
|
||||
@@ -29,8 +30,8 @@ lib_ldf_mode = chain
|
||||
lib_deps =
|
||||
; bblanchon/ArduinoJson @ 5.13.4
|
||||
; bblanchon/ArduinoJson @ 6.21.5
|
||||
bblanchon/ArduinoJson @ 7.2.0
|
||||
mathieucarbou/AsyncTCP @ 3.2.12
|
||||
bblanchon/ArduinoJson @ 7.2.1
|
||||
mathieucarbou/AsyncTCP @ 3.2.14
|
||||
board = esp32dev
|
||||
board_build.partitions = partitions-4MB.csv
|
||||
board_build.filesystem = littlefs
|
||||
@@ -48,21 +49,21 @@ platform = https://github.com/pioarduino/platform-espressif32/releases/download/
|
||||
; board = esp32-s3-devkitc-1
|
||||
; board = esp32-c6-devkitc-1
|
||||
lib_deps =
|
||||
mathieucarbou/AsyncTCP @ 3.2.12
|
||||
mathieucarbou/AsyncTCP @ 3.2.14
|
||||
|
||||
[env:arduino-310]
|
||||
platform = https://github.com/pioarduino/platform-espressif32/releases/download/53.03.10-rc2/platform-espressif32.zip
|
||||
platform = https://github.com/pioarduino/platform-espressif32/releases/download/53.03.10-rc3/platform-espressif32.zip
|
||||
; board = esp32-s3-devkitc-1
|
||||
; board = esp32-c6-devkitc-1
|
||||
; board = esp32-h2-devkitm-1
|
||||
|
||||
[env:perf-test-AsyncTCP]
|
||||
platform = https://github.com/pioarduino/platform-espressif32/releases/download/53.03.10-rc2/platform-espressif32.zip
|
||||
platform = https://github.com/pioarduino/platform-espressif32/releases/download/53.03.10-rc3/platform-espressif32.zip
|
||||
build_flags = ${env.build_flags}
|
||||
-D PERF_TEST=1
|
||||
|
||||
[env:perf-test-AsyncTCPSock]
|
||||
platform = https://github.com/pioarduino/platform-espressif32/releases/download/53.03.10-rc2/platform-espressif32.zip
|
||||
platform = https://github.com/pioarduino/platform-espressif32/releases/download/53.03.10-rc3/platform-espressif32.zip
|
||||
lib_deps =
|
||||
https://github.com/mathieucarbou/AsyncTCPSock/archive/refs/tags/v1.0.3-dev.zip
|
||||
build_flags = ${env.build_flags}
|
||||
@@ -73,14 +74,14 @@ platform = espressif8266
|
||||
; board = huzzah
|
||||
board = d1_mini
|
||||
lib_deps =
|
||||
bblanchon/ArduinoJson @ 7.2.0
|
||||
bblanchon/ArduinoJson @ 7.2.1
|
||||
esphome/ESPAsyncTCP-esphome @ 2.0.0
|
||||
|
||||
[env:raspberrypi]
|
||||
platform = https://github.com/maxgerhardt/platform-raspberrypi.git
|
||||
board = rpipicow
|
||||
lib_deps =
|
||||
bblanchon/ArduinoJson @ 7.2.0
|
||||
bblanchon/ArduinoJson @ 7.2.1
|
||||
khoih-prog/AsyncTCP_RP2040W @ 1.2.0
|
||||
lib_ignore =
|
||||
lwIP_ESPHost
|
||||
@@ -101,24 +102,24 @@ board = ${sysenv.PIO_BOARD}
|
||||
platform = https://github.com/pioarduino/platform-espressif32/releases/download/51.03.05/platform-espressif32.zip
|
||||
board = ${sysenv.PIO_BOARD}
|
||||
lib_deps =
|
||||
mathieucarbou/AsyncTCP @ 3.2.12
|
||||
mathieucarbou/AsyncTCP @ 3.2.14
|
||||
|
||||
[env:ci-arduino-310]
|
||||
platform = https://github.com/pioarduino/platform-espressif32/releases/download/53.03.10-rc2/platform-espressif32.zip
|
||||
platform = https://github.com/pioarduino/platform-espressif32/releases/download/53.03.10-rc3/platform-espressif32.zip
|
||||
board = ${sysenv.PIO_BOARD}
|
||||
|
||||
[env:ci-esp8266]
|
||||
platform = espressif8266
|
||||
board = ${sysenv.PIO_BOARD}
|
||||
lib_deps =
|
||||
bblanchon/ArduinoJson @ 7.2.0
|
||||
bblanchon/ArduinoJson @ 7.2.1
|
||||
esphome/ESPAsyncTCP-esphome @ 2.0.0
|
||||
|
||||
[env:ci-raspberrypi]
|
||||
platform = https://github.com/maxgerhardt/platform-raspberrypi.git
|
||||
board = ${sysenv.PIO_BOARD}
|
||||
lib_deps =
|
||||
bblanchon/ArduinoJson @ 7.2.0
|
||||
bblanchon/ArduinoJson @ 7.2.1
|
||||
khoih-prog/AsyncTCP_RP2040W @ 1.2.0
|
||||
lib_ignore =
|
||||
lwIP_ESPHost
|
||||
|
@@ -544,7 +544,7 @@ void AsyncWebSocketClient::_onData(void* pbuf, size_t plen) {
|
||||
}
|
||||
}
|
||||
if (datalen > 0)
|
||||
_server->_handleEvent(this, WS_EVT_DATA, (void*)&_pinfo, (uint8_t*)data, datalen);
|
||||
_server->_handleEvent(this, WS_EVT_DATA, (void*)&_pinfo, data, datalen);
|
||||
|
||||
_pinfo.index += datalen;
|
||||
} else if ((datalen + _pinfo.index) == _pinfo.len) {
|
||||
@@ -568,11 +568,12 @@ void AsyncWebSocketClient::_onData(void* pbuf, size_t plen) {
|
||||
_queueControl(WS_DISCONNECT, data, datalen);
|
||||
}
|
||||
} else if (_pinfo.opcode == WS_PING) {
|
||||
_server->_handleEvent(this, WS_EVT_PING, NULL, NULL, 0);
|
||||
_queueControl(WS_PONG, data, datalen);
|
||||
} else if (_pinfo.opcode == WS_PONG) {
|
||||
if (datalen != AWSC_PING_PAYLOAD_LEN || memcmp(AWSC_PING_PAYLOAD, data, AWSC_PING_PAYLOAD_LEN) != 0)
|
||||
_server->_handleEvent(this, WS_EVT_PONG, NULL, data, datalen);
|
||||
} else if (_pinfo.opcode < 8) { // continuation or text/binary frame
|
||||
_server->_handleEvent(this, WS_EVT_PONG, NULL, NULL, 0);
|
||||
} else if (_pinfo.opcode < WS_DISCONNECT) { // continuation or text/binary frame
|
||||
_server->_handleEvent(this, WS_EVT_DATA, (void*)&_pinfo, data, datalen);
|
||||
if (_pinfo.final)
|
||||
_pinfo.num = 0;
|
||||
@@ -586,7 +587,7 @@ void AsyncWebSocketClient::_onData(void* pbuf, size_t plen) {
|
||||
}
|
||||
|
||||
// restore byte as _handleEvent may have added a null terminator i.e., data[len] = 0;
|
||||
if (datalen > 0)
|
||||
if (datalen)
|
||||
data[datalen] = datalast;
|
||||
|
||||
data += datalen;
|
||||
|
@@ -104,6 +104,7 @@ typedef enum { WS_MSG_SENDING,
|
||||
WS_MSG_ERROR } AwsMessageStatus;
|
||||
typedef enum { WS_EVT_CONNECT,
|
||||
WS_EVT_DISCONNECT,
|
||||
WS_EVT_PING,
|
||||
WS_EVT_PONG,
|
||||
WS_EVT_ERROR,
|
||||
WS_EVT_DATA } AwsEventType;
|
||||
|
@@ -48,10 +48,10 @@
|
||||
|
||||
#include "literals.h"
|
||||
|
||||
#define ASYNCWEBSERVER_VERSION "3.3.22"
|
||||
#define ASYNCWEBSERVER_VERSION "3.3.23"
|
||||
#define ASYNCWEBSERVER_VERSION_MAJOR 3
|
||||
#define ASYNCWEBSERVER_VERSION_MINOR 3
|
||||
#define ASYNCWEBSERVER_VERSION_REVISION 22
|
||||
#define ASYNCWEBSERVER_VERSION_REVISION 23
|
||||
#define ASYNCWEBSERVER_FORK_mathieucarbou
|
||||
|
||||
#ifdef ASYNCWEBSERVER_REGEX
|
||||
|
Reference in New Issue
Block a user