Aktualizace na verzi 3.2.4
This commit is contained in:
parent
d8ffb99455
commit
3ba4d9d10d
15
README.md
15
README.md
@ -1,11 +1,13 @@
|
|||||||
# ESPAsyncWebServer
|
# ESPAsyncWebServer
|
||||||
|
|
||||||
[![License: LGPL 3.0](https://img.shields.io/badge/License-LGPL%203.0-yellow.svg)](https://opensource.org/license/lgpl-3-0/)
|
|
||||||
[![Continuous Integration](https://github.com/mathieucarbou/ESPAsyncWebServer/actions/workflows/ci.yml/badge.svg)](https://github.com/mathieucarbou/ESPAsyncWebServer/actions/workflows/ci.yml)
|
|
||||||
|
|
||||||
[![Latest Release](https://img.shields.io/github/release/mathieucarbou/ESPAsyncWebServer.svg)](https://GitHub.com/mathieucarbou/ESPAsyncWebServer/releases/)
|
[![Latest Release](https://img.shields.io/github/release/mathieucarbou/ESPAsyncWebServer.svg)](https://GitHub.com/mathieucarbou/ESPAsyncWebServer/releases/)
|
||||||
[![PlatformIO Registry](https://badges.registry.platformio.org/packages/mathieucarbou/library/ESPAsyncWebServer.svg)](https://registry.platformio.org/libraries/mathieucarbou/ESPAsyncWebServer)
|
[![PlatformIO Registry](https://badges.registry.platformio.org/packages/mathieucarbou/library/ESPAsyncWebServer.svg)](https://registry.platformio.org/libraries/mathieucarbou/ESPAsyncWebServer)
|
||||||
|
|
||||||
|
[![License: LGPL 3.0](https://img.shields.io/badge/License-LGPL%203.0-yellow.svg)](https://opensource.org/license/lgpl-3-0/)
|
||||||
|
[![Contributor Covenant](https://img.shields.io/badge/Contributor%20Covenant-2.1-4baaaa.svg)](code_of_conduct.md)
|
||||||
|
|
||||||
|
[![Build](https://github.com/mathieucarbou/ESPAsyncWebServer/actions/workflows/ci.yml/badge.svg)](https://github.com/mathieucarbou/ESPAsyncWebServer/actions/workflows/ci.yml)
|
||||||
|
[![GitHub latest commit](https://badgen.net/github/last-commit/mathieucarbou/ESPAsyncWebServer)](https://GitHub.com/mathieucarbou/ESPAsyncWebServer/commit/)
|
||||||
[![Gitpod Ready-to-Code](https://img.shields.io/badge/Gitpod-Ready--to--Code-blue?logo=gitpod)](https://gitpod.io/#https://github.com/mathieucarbou/ESPAsyncWebServer)
|
[![Gitpod Ready-to-Code](https://img.shields.io/badge/Gitpod-Ready--to--Code-blue?logo=gitpod)](https://gitpod.io/#https://github.com/mathieucarbou/ESPAsyncWebServer)
|
||||||
|
|
||||||
Asynchronous HTTP and WebSocket Server Library for ESP32, ESP8266 and RP2040
|
Asynchronous HTTP and WebSocket Server Library for ESP32, ESP8266 and RP2040
|
||||||
@ -18,12 +20,12 @@ This fork is based on [yubox-node-org/ESPAsyncWebServer](https://github.com/yubo
|
|||||||
**WARNING** The library name was changed from `ESP Async WebServer` to `ESPAsyncWebServer` as per the Arduino Lint recommendations.
|
**WARNING** The library name was changed from `ESP Async WebServer` to `ESPAsyncWebServer` as per the Arduino Lint recommendations.
|
||||||
|
|
||||||
```
|
```
|
||||||
mathieucarbou/ESPAsyncWebServer @ 3.2.0
|
mathieucarbou/ESPAsyncWebServer @ 3.2.4
|
||||||
```
|
```
|
||||||
|
|
||||||
Dependency:
|
Dependency:
|
||||||
|
|
||||||
- **ESP32**: `mathieucarbou/AsyncTCP @ 3.2.4` (Arduino IDE: [https://github.com/mathieucarbou/AsyncTCP#v3.2.4](https://github.com/mathieucarbou/AsyncTCP/releases/tag/v3.2.0))
|
- **ESP32**: `mathieucarbou/AsyncTCP @ 3.2.5` (Arduino IDE: [https://github.com/mathieucarbou/AsyncTCP#v3.2.5](https://github.com/mathieucarbou/AsyncTCP/releases))
|
||||||
- **ESP8266**: `esphome/ESPAsyncTCP-esphome @ 2.0.0` (Arduino IDE: [https://github.com/mathieucarbou/esphome-ESPAsyncTCP#v2.0.0](https://github.com/mathieucarbou/esphome-ESPAsyncTCP/releases/tag/v2.0.0))
|
- **ESP8266**: `esphome/ESPAsyncTCP-esphome @ 2.0.0` (Arduino IDE: [https://github.com/mathieucarbou/esphome-ESPAsyncTCP#v2.0.0](https://github.com/mathieucarbou/esphome-ESPAsyncTCP/releases/tag/v2.0.0))
|
||||||
- **RP2040**: `khoih-prog/AsyncTCP_RP2040W @ 1.2.0` (Arduino IDE: [https://github.com/khoih-prog/AsyncTCP_RP2040W#v1.2.0](https://github.com/khoih-prog/AsyncTCP_RP2040W/releases/tag/v1.2.0))
|
- **RP2040**: `khoih-prog/AsyncTCP_RP2040W @ 1.2.0` (Arduino IDE: [https://github.com/khoih-prog/AsyncTCP_RP2040W#v1.2.0](https://github.com/khoih-prog/AsyncTCP_RP2040W/releases/tag/v1.2.0))
|
||||||
|
|
||||||
@ -40,10 +42,9 @@ Dependency:
|
|||||||
- [@mathieucarbou](https://github.com/mathieucarbou): Arduino 3 / ESP-IDF 5.1 compatibility
|
- [@mathieucarbou](https://github.com/mathieucarbou): Arduino 3 / ESP-IDF 5.1 compatibility
|
||||||
- [@mathieucarbou](https://github.com/mathieucarbou): Arduino Json 7 compatibility and backward compatible with 6 and 6 (changes in `AsyncJson.h`). The API to use Json has not changed. These are only internal changes.
|
- [@mathieucarbou](https://github.com/mathieucarbou): Arduino Json 7 compatibility and backward compatible with 6 and 6 (changes in `AsyncJson.h`). The API to use Json has not changed. These are only internal changes.
|
||||||
- [@mathieucarbou](https://github.com/mathieucarbou): CI
|
- [@mathieucarbou](https://github.com/mathieucarbou): CI
|
||||||
- [@mathieucarbou](https://github.com/mathieucarbou): Depends on `mathieucarbou/AsyncTCP @ 3.2.4`
|
- [@mathieucarbou](https://github.com/mathieucarbou): Depends on `mathieucarbou/AsyncTCP @ 3.2.5`
|
||||||
- [@mathieucarbou](https://github.com/mathieucarbou): Deployed in PlatformIO registry and Arduino IDE library manager
|
- [@mathieucarbou](https://github.com/mathieucarbou): Deployed in PlatformIO registry and Arduino IDE library manager
|
||||||
- [@mathieucarbou](https://github.com/mathieucarbou): Firmware size optimization: remove mbedtls dependency (accounts for 33KB in firmware)
|
- [@mathieucarbou](https://github.com/mathieucarbou): Firmware size optimization: remove mbedtls dependency (accounts for 33KB in firmware)
|
||||||
- [@mathieucarbou](https://github.com/mathieucarbou): Made DEFAULT_MAX_SSE_CLIENTS customizable
|
|
||||||
- [@mathieucarbou](https://github.com/mathieucarbou): Made DEFAULT_MAX_WS_CLIENTS customizable
|
- [@mathieucarbou](https://github.com/mathieucarbou): Made DEFAULT_MAX_WS_CLIENTS customizable
|
||||||
- [@mathieucarbou](https://github.com/mathieucarbou): MessagePack Support ([#62](https://github.com/mathieucarbou/ESPAsyncWebServer/pull/62))
|
- [@mathieucarbou](https://github.com/mathieucarbou): MessagePack Support ([#62](https://github.com/mathieucarbou/ESPAsyncWebServer/pull/62))
|
||||||
- [@mathieucarbou](https://github.com/mathieucarbou): Remove filename after inline in Content-Disposition header according to RFC2183
|
- [@mathieucarbou](https://github.com/mathieucarbou): Remove filename after inline in Content-Disposition header according to RFC2183
|
||||||
|
@ -1,11 +1,13 @@
|
|||||||
# ESPAsyncWebServer
|
# ESPAsyncWebServer
|
||||||
|
|
||||||
[![License: LGPL 3.0](https://img.shields.io/badge/License-LGPL%203.0-yellow.svg)](https://opensource.org/license/lgpl-3-0/)
|
|
||||||
[![Continuous Integration](https://github.com/mathieucarbou/ESPAsyncWebServer/actions/workflows/ci.yml/badge.svg)](https://github.com/mathieucarbou/ESPAsyncWebServer/actions/workflows/ci.yml)
|
|
||||||
|
|
||||||
[![Latest Release](https://img.shields.io/github/release/mathieucarbou/ESPAsyncWebServer.svg)](https://GitHub.com/mathieucarbou/ESPAsyncWebServer/releases/)
|
[![Latest Release](https://img.shields.io/github/release/mathieucarbou/ESPAsyncWebServer.svg)](https://GitHub.com/mathieucarbou/ESPAsyncWebServer/releases/)
|
||||||
[![PlatformIO Registry](https://badges.registry.platformio.org/packages/mathieucarbou/library/ESPAsyncWebServer.svg)](https://registry.platformio.org/libraries/mathieucarbou/ESPAsyncWebServer)
|
[![PlatformIO Registry](https://badges.registry.platformio.org/packages/mathieucarbou/library/ESPAsyncWebServer.svg)](https://registry.platformio.org/libraries/mathieucarbou/ESPAsyncWebServer)
|
||||||
|
|
||||||
|
[![License: LGPL 3.0](https://img.shields.io/badge/License-LGPL%203.0-yellow.svg)](https://opensource.org/license/lgpl-3-0/)
|
||||||
|
[![Contributor Covenant](https://img.shields.io/badge/Contributor%20Covenant-2.1-4baaaa.svg)](code_of_conduct.md)
|
||||||
|
|
||||||
|
[![Build](https://github.com/mathieucarbou/ESPAsyncWebServer/actions/workflows/ci.yml/badge.svg)](https://github.com/mathieucarbou/ESPAsyncWebServer/actions/workflows/ci.yml)
|
||||||
|
[![GitHub latest commit](https://badgen.net/github/last-commit/mathieucarbou/ESPAsyncWebServer)](https://GitHub.com/mathieucarbou/ESPAsyncWebServer/commit/)
|
||||||
[![Gitpod Ready-to-Code](https://img.shields.io/badge/Gitpod-Ready--to--Code-blue?logo=gitpod)](https://gitpod.io/#https://github.com/mathieucarbou/ESPAsyncWebServer)
|
[![Gitpod Ready-to-Code](https://img.shields.io/badge/Gitpod-Ready--to--Code-blue?logo=gitpod)](https://gitpod.io/#https://github.com/mathieucarbou/ESPAsyncWebServer)
|
||||||
|
|
||||||
Asynchronous HTTP and WebSocket Server Library for ESP32, ESP8266 and RP2040
|
Asynchronous HTTP and WebSocket Server Library for ESP32, ESP8266 and RP2040
|
||||||
@ -18,12 +20,12 @@ This fork is based on [yubox-node-org/ESPAsyncWebServer](https://github.com/yubo
|
|||||||
**WARNING** The library name was changed from `ESP Async WebServer` to `ESPAsyncWebServer` as per the Arduino Lint recommendations.
|
**WARNING** The library name was changed from `ESP Async WebServer` to `ESPAsyncWebServer` as per the Arduino Lint recommendations.
|
||||||
|
|
||||||
```
|
```
|
||||||
mathieucarbou/ESPAsyncWebServer @ 3.2.0
|
mathieucarbou/ESPAsyncWebServer @ 3.2.4
|
||||||
```
|
```
|
||||||
|
|
||||||
Dependency:
|
Dependency:
|
||||||
|
|
||||||
- **ESP32**: `mathieucarbou/AsyncTCP @ 3.2.4` (Arduino IDE: [https://github.com/mathieucarbou/AsyncTCP#v3.2.4](https://github.com/mathieucarbou/AsyncTCP/releases/tag/v3.2.0))
|
- **ESP32**: `mathieucarbou/AsyncTCP @ 3.2.5` (Arduino IDE: [https://github.com/mathieucarbou/AsyncTCP#v3.2.5](https://github.com/mathieucarbou/AsyncTCP/releases))
|
||||||
- **ESP8266**: `esphome/ESPAsyncTCP-esphome @ 2.0.0` (Arduino IDE: [https://github.com/mathieucarbou/esphome-ESPAsyncTCP#v2.0.0](https://github.com/mathieucarbou/esphome-ESPAsyncTCP/releases/tag/v2.0.0))
|
- **ESP8266**: `esphome/ESPAsyncTCP-esphome @ 2.0.0` (Arduino IDE: [https://github.com/mathieucarbou/esphome-ESPAsyncTCP#v2.0.0](https://github.com/mathieucarbou/esphome-ESPAsyncTCP/releases/tag/v2.0.0))
|
||||||
- **RP2040**: `khoih-prog/AsyncTCP_RP2040W @ 1.2.0` (Arduino IDE: [https://github.com/khoih-prog/AsyncTCP_RP2040W#v1.2.0](https://github.com/khoih-prog/AsyncTCP_RP2040W/releases/tag/v1.2.0))
|
- **RP2040**: `khoih-prog/AsyncTCP_RP2040W @ 1.2.0` (Arduino IDE: [https://github.com/khoih-prog/AsyncTCP_RP2040W#v1.2.0](https://github.com/khoih-prog/AsyncTCP_RP2040W/releases/tag/v1.2.0))
|
||||||
|
|
||||||
@ -40,10 +42,9 @@ Dependency:
|
|||||||
- [@mathieucarbou](https://github.com/mathieucarbou): Arduino 3 / ESP-IDF 5.1 compatibility
|
- [@mathieucarbou](https://github.com/mathieucarbou): Arduino 3 / ESP-IDF 5.1 compatibility
|
||||||
- [@mathieucarbou](https://github.com/mathieucarbou): Arduino Json 7 compatibility and backward compatible with 6 and 6 (changes in `AsyncJson.h`). The API to use Json has not changed. These are only internal changes.
|
- [@mathieucarbou](https://github.com/mathieucarbou): Arduino Json 7 compatibility and backward compatible with 6 and 6 (changes in `AsyncJson.h`). The API to use Json has not changed. These are only internal changes.
|
||||||
- [@mathieucarbou](https://github.com/mathieucarbou): CI
|
- [@mathieucarbou](https://github.com/mathieucarbou): CI
|
||||||
- [@mathieucarbou](https://github.com/mathieucarbou): Depends on `mathieucarbou/AsyncTCP @ 3.2.4`
|
- [@mathieucarbou](https://github.com/mathieucarbou): Depends on `mathieucarbou/AsyncTCP @ 3.2.5`
|
||||||
- [@mathieucarbou](https://github.com/mathieucarbou): Deployed in PlatformIO registry and Arduino IDE library manager
|
- [@mathieucarbou](https://github.com/mathieucarbou): Deployed in PlatformIO registry and Arduino IDE library manager
|
||||||
- [@mathieucarbou](https://github.com/mathieucarbou): Firmware size optimization: remove mbedtls dependency (accounts for 33KB in firmware)
|
- [@mathieucarbou](https://github.com/mathieucarbou): Firmware size optimization: remove mbedtls dependency (accounts for 33KB in firmware)
|
||||||
- [@mathieucarbou](https://github.com/mathieucarbou): Made DEFAULT_MAX_SSE_CLIENTS customizable
|
|
||||||
- [@mathieucarbou](https://github.com/mathieucarbou): Made DEFAULT_MAX_WS_CLIENTS customizable
|
- [@mathieucarbou](https://github.com/mathieucarbou): Made DEFAULT_MAX_WS_CLIENTS customizable
|
||||||
- [@mathieucarbou](https://github.com/mathieucarbou): MessagePack Support ([#62](https://github.com/mathieucarbou/ESPAsyncWebServer/pull/62))
|
- [@mathieucarbou](https://github.com/mathieucarbou): MessagePack Support ([#62](https://github.com/mathieucarbou/ESPAsyncWebServer/pull/62))
|
||||||
- [@mathieucarbou](https://github.com/mathieucarbou): Remove filename after inline in Content-Disposition header according to RFC2183
|
- [@mathieucarbou](https://github.com/mathieucarbou): Remove filename after inline in Content-Disposition header according to RFC2183
|
||||||
|
@ -25,8 +25,40 @@
|
|||||||
#include <LittleFS.h>
|
#include <LittleFS.h>
|
||||||
|
|
||||||
AsyncWebServer server(80);
|
AsyncWebServer server(80);
|
||||||
|
AsyncEventSource events("/events");
|
||||||
|
AsyncWebSocket ws("/ws");
|
||||||
|
|
||||||
const char* PARAM_MESSAGE = "message";
|
const char* PARAM_MESSAGE PROGMEM = "message";
|
||||||
|
const char* SSE_HTLM PROGMEM = R"(
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Server-Sent Events</title>
|
||||||
|
<script>
|
||||||
|
if (!!window.EventSource) {
|
||||||
|
var source = new EventSource('/events');
|
||||||
|
source.addEventListener('open', function(e) {
|
||||||
|
console.log("Events Connected");
|
||||||
|
}, false);
|
||||||
|
source.addEventListener('error', function(e) {
|
||||||
|
if (e.target.readyState != EventSource.OPEN) {
|
||||||
|
console.log("Events Disconnected");
|
||||||
|
}
|
||||||
|
}, false);
|
||||||
|
source.addEventListener('message', function(e) {
|
||||||
|
console.log("message", e.data);
|
||||||
|
}, false);
|
||||||
|
source.addEventListener('heartbeat', function(e) {
|
||||||
|
console.log("heartbeat", e.data);
|
||||||
|
}, false);
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1>Open your browser console!</h1>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
)";
|
||||||
|
|
||||||
void notFound(AsyncWebServerRequest* request) {
|
void notFound(AsyncWebServerRequest* request) {
|
||||||
request->send(404, "text/plain", "Not found");
|
request->send(404, "text/plain", "Not found");
|
||||||
@ -69,12 +101,15 @@ void setup() {
|
|||||||
Connection: close
|
Connection: close
|
||||||
Accept-Ranges: bytes
|
Accept-Ranges: bytes
|
||||||
*/
|
*/
|
||||||
// Ref: https://github.com/mathieucarbou/ESPAsyncWebServer/pull/80
|
// Ref: https://github.com/mathieucarbou/ESPAsyncWebServer/pull/80
|
||||||
server.on("/download", HTTP_HEAD | HTTP_GET, [](AsyncWebServerRequest* request) {
|
server.on("/download", HTTP_HEAD | HTTP_GET, [](AsyncWebServerRequest* request) {
|
||||||
if (request->method() == HTTP_HEAD) {
|
if (request->method() == HTTP_HEAD) {
|
||||||
AsyncWebServerResponse* response = request->beginResponse(200, "application/octet-stream");
|
AsyncWebServerResponse* response = request->beginResponse(200, "application/octet-stream");
|
||||||
response->setContentLength(1024); // myFile.getSize()
|
response->addHeader(asyncsrv::T_Accept_Ranges, "bytes");
|
||||||
response->addHeader("Accept-Ranges", "bytes");
|
response->addHeader(asyncsrv::T_Content_Length, 10);
|
||||||
|
response->setContentLength(1024); // overrides previous one
|
||||||
|
response->addHeader(asyncsrv::T_Content_Type, "foo");
|
||||||
|
response->setContentType("application/octet-stream"); // overrides previous one
|
||||||
// ...
|
// ...
|
||||||
request->send(response);
|
request->send(response);
|
||||||
} else {
|
} else {
|
||||||
@ -108,7 +143,7 @@ void setup() {
|
|||||||
|
|
||||||
// receives JSON and sends JSON
|
// receives JSON and sends JSON
|
||||||
jsonHandler->onRequest([](AsyncWebServerRequest* request, JsonVariant& json) {
|
jsonHandler->onRequest([](AsyncWebServerRequest* request, JsonVariant& json) {
|
||||||
JsonObject jsonObj = json.as<JsonObject>();
|
// JsonObject jsonObj = json.as<JsonObject>();
|
||||||
// ...
|
// ...
|
||||||
|
|
||||||
AsyncJsonResponse* response = new AsyncJsonResponse();
|
AsyncJsonResponse* response = new AsyncJsonResponse();
|
||||||
@ -131,7 +166,7 @@ void setup() {
|
|||||||
|
|
||||||
// receives MessagePack and sends MessagePack
|
// receives MessagePack and sends MessagePack
|
||||||
msgPackHandler->onRequest([](AsyncWebServerRequest* request, JsonVariant& json) {
|
msgPackHandler->onRequest([](AsyncWebServerRequest* request, JsonVariant& json) {
|
||||||
JsonObject jsonObj = json.as<JsonObject>();
|
// JsonObject jsonObj = json.as<JsonObject>();
|
||||||
// ...
|
// ...
|
||||||
|
|
||||||
AsyncMessagePackResponse* response = new AsyncMessagePackResponse();
|
AsyncMessagePackResponse* response = new AsyncMessagePackResponse();
|
||||||
@ -150,6 +185,43 @@ void setup() {
|
|||||||
request->send(response);
|
request->send(response);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
events.onConnect([](AsyncEventSourceClient* client) {
|
||||||
|
if (client->lastId()) {
|
||||||
|
Serial.printf("SSE Client reconnected! Last message ID that it gat is: %" PRIu32 "\n", client->lastId());
|
||||||
|
}
|
||||||
|
client->send("hello!", NULL, millis(), 1000);
|
||||||
|
});
|
||||||
|
|
||||||
|
server.on("/sse", HTTP_GET, [](AsyncWebServerRequest* request) {
|
||||||
|
request->send(200, "text/html", SSE_HTLM);
|
||||||
|
});
|
||||||
|
|
||||||
|
ws.onEvent([](AsyncWebSocket* server, AsyncWebSocketClient* client, AwsEventType type, void* arg, uint8_t* data, size_t len) {
|
||||||
|
(void) len;
|
||||||
|
if (type == WS_EVT_CONNECT) {
|
||||||
|
Serial.println("ws connect");
|
||||||
|
client->setCloseClientOnQueueFull(false);
|
||||||
|
client->ping();
|
||||||
|
} else if (type == WS_EVT_DISCONNECT) {
|
||||||
|
Serial.println("ws disconnect");
|
||||||
|
} else if (type == WS_EVT_ERROR) {
|
||||||
|
Serial.println("ws error");
|
||||||
|
} else if (type == WS_EVT_PONG) {
|
||||||
|
Serial.println("ws pong");
|
||||||
|
} else if (type == WS_EVT_DATA) {
|
||||||
|
AwsFrameInfo* info = (AwsFrameInfo*)arg;
|
||||||
|
String msg = "";
|
||||||
|
if (info->final && info->index == 0 && info->len == len) {
|
||||||
|
if (info->opcode == WS_TEXT) {
|
||||||
|
data[len] = 0;
|
||||||
|
Serial.printf("ws text: %s\n", (char*)data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
server.addHandler(&events);
|
||||||
|
server.addHandler(&ws);
|
||||||
server.addHandler(jsonHandler);
|
server.addHandler(jsonHandler);
|
||||||
server.addHandler(msgPackHandler);
|
server.addHandler(msgPackHandler);
|
||||||
|
|
||||||
@ -158,5 +230,20 @@ void setup() {
|
|||||||
server.begin();
|
server.begin();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t lastSSE = 0;
|
||||||
|
uint32_t deltaSSE = 5;
|
||||||
|
|
||||||
|
uint32_t lastWS = 0;
|
||||||
|
uint32_t deltaWS = 100;
|
||||||
|
|
||||||
void loop() {
|
void loop() {
|
||||||
|
uint32_t now = millis();
|
||||||
|
if (now - lastSSE >= deltaSSE) {
|
||||||
|
events.send(String("ping-") + now, "heartbeat", now);
|
||||||
|
lastSSE = millis();
|
||||||
|
}
|
||||||
|
if (now - lastWS >= deltaWS) {
|
||||||
|
ws.printfAll("kp%.4f", (10.0 / 3.0));
|
||||||
|
lastWS = millis();
|
||||||
|
}
|
||||||
}
|
}
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "ESPAsyncWebServer",
|
"name": "ESPAsyncWebServer",
|
||||||
"version": "3.2.0",
|
"version": "3.2.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.",
|
"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",
|
"keywords": "http,async,websocket,webserver",
|
||||||
"homepage": "https://github.com/mathieucarbou/ESPAsyncWebServer",
|
"homepage": "https://github.com/mathieucarbou/ESPAsyncWebServer",
|
||||||
@ -28,7 +28,7 @@
|
|||||||
{
|
{
|
||||||
"owner": "mathieucarbou",
|
"owner": "mathieucarbou",
|
||||||
"name": "AsyncTCP",
|
"name": "AsyncTCP",
|
||||||
"version": "^3.2.4",
|
"version": "^3.2.5",
|
||||||
"platforms": "espressif32"
|
"platforms": "espressif32"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
name=ESPAsyncWebServer
|
name=ESPAsyncWebServer
|
||||||
version=3.2.0
|
version=3.2.4
|
||||||
author=Me-No-Dev
|
author=Me-No-Dev
|
||||||
maintainer=Mathieu Carbou <mathieu.carbou@gmail.com>
|
maintainer=Mathieu Carbou <mathieu.carbou@gmail.com>
|
||||||
sentence=Asynchronous HTTP and WebSocket Server Library for ESP32, ESP8266 and RP2040
|
sentence=Asynchronous HTTP and WebSocket Server Library for ESP32, ESP8266 and RP2040
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
framework = arduino
|
framework = arduino
|
||||||
build_flags =
|
build_flags =
|
||||||
-Wall -Wextra
|
-Wall -Wextra
|
||||||
|
-Wno-unused-parameter
|
||||||
-D CONFIG_ARDUHAL_LOG_COLORS
|
-D CONFIG_ARDUHAL_LOG_COLORS
|
||||||
-D CORE_DEBUG_LEVEL=ARDUHAL_LOG_LEVEL_VERBOSE
|
-D CORE_DEBUG_LEVEL=ARDUHAL_LOG_LEVEL_VERBOSE
|
||||||
-D CONFIG_ASYNC_TCP_MAX_ACK_TIME=3000
|
-D CONFIG_ASYNC_TCP_MAX_ACK_TIME=3000
|
||||||
@ -22,19 +23,12 @@ src_dir = examples/SimpleServer
|
|||||||
; src_dir = examples/Draft
|
; src_dir = examples/Draft
|
||||||
; src_dir = examples/issues/Issue14
|
; src_dir = examples/issues/Issue14
|
||||||
|
|
||||||
[env:arduino]
|
|
||||||
platform = espressif32
|
|
||||||
board = esp32dev
|
|
||||||
lib_deps =
|
|
||||||
bblanchon/ArduinoJson @ 7.1.0
|
|
||||||
mathieucarbou/AsyncTCP @ 3.2.4
|
|
||||||
|
|
||||||
[env:arduino-2]
|
[env:arduino-2]
|
||||||
platform = espressif32@6.8.1
|
platform = espressif32@6.8.1
|
||||||
board = esp32dev
|
board = esp32dev
|
||||||
lib_deps =
|
lib_deps =
|
||||||
bblanchon/ArduinoJson @ 7.1.0
|
bblanchon/ArduinoJson @ 7.1.0
|
||||||
mathieucarbou/AsyncTCP @ 3.2.4
|
mathieucarbou/AsyncTCP @ 3.2.5
|
||||||
|
|
||||||
[env:arduino-3]
|
[env:arduino-3]
|
||||||
platform = espressif32
|
platform = espressif32
|
||||||
@ -44,7 +38,7 @@ platform_packages=
|
|||||||
board = esp32dev
|
board = esp32dev
|
||||||
lib_deps =
|
lib_deps =
|
||||||
bblanchon/ArduinoJson @ 7.1.0
|
bblanchon/ArduinoJson @ 7.1.0
|
||||||
mathieucarbou/AsyncTCP @ 3.2.4
|
mathieucarbou/AsyncTCP @ 3.2.5
|
||||||
|
|
||||||
[env:esp8266]
|
[env:esp8266]
|
||||||
platform = espressif8266
|
platform = espressif8266
|
||||||
@ -70,18 +64,18 @@ platform = https://github.com/pioarduino/platform-espressif32/releases/download/
|
|||||||
board = esp32dev
|
board = esp32dev
|
||||||
lib_deps =
|
lib_deps =
|
||||||
bblanchon/ArduinoJson @ 7.1.0
|
bblanchon/ArduinoJson @ 7.1.0
|
||||||
mathieucarbou/AsyncTCP @ 3.2.4
|
mathieucarbou/AsyncTCP @ 3.2.5
|
||||||
|
|
||||||
[env:pioarduino-c6]
|
[env:pioarduino-c6]
|
||||||
platform = https://github.com/pioarduino/platform-espressif32/releases/download/51.03.04/platform-espressif32.zip
|
platform = https://github.com/pioarduino/platform-espressif32/releases/download/51.03.04/platform-espressif32.zip
|
||||||
board = esp32-c6-devkitc-1
|
board = esp32-c6-devkitc-1
|
||||||
lib_deps =
|
lib_deps =
|
||||||
bblanchon/ArduinoJson @ 7.1.0
|
bblanchon/ArduinoJson @ 7.1.0
|
||||||
mathieucarbou/AsyncTCP @ 3.2.4
|
mathieucarbou/AsyncTCP @ 3.2.5
|
||||||
|
|
||||||
[env:pioarduino-h2]
|
[env:pioarduino-h2]
|
||||||
platform = https://github.com/pioarduino/platform-espressif32/releases/download/51.03.04/platform-espressif32.zip
|
platform = https://github.com/pioarduino/platform-espressif32/releases/download/51.03.04/platform-espressif32.zip
|
||||||
board = esp32-h2-devkitm-1
|
board = esp32-h2-devkitm-1
|
||||||
lib_deps =
|
lib_deps =
|
||||||
bblanchon/ArduinoJson @ 7.1.0
|
bblanchon/ArduinoJson @ 7.1.0
|
||||||
mathieucarbou/AsyncTCP @ 3.2.4
|
mathieucarbou/AsyncTCP @ 3.2.5
|
||||||
|
@ -128,8 +128,7 @@ AsyncEventSourceMessage::~AsyncEventSourceMessage() {
|
|||||||
free(_data);
|
free(_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t AsyncEventSourceMessage::ack(size_t len, uint32_t time) {
|
size_t AsyncEventSourceMessage::ack(size_t len, __attribute__((unused)) uint32_t time) {
|
||||||
(void)time;
|
|
||||||
// If the whole message is now acked...
|
// If the whole message is now acked...
|
||||||
if (_acked + len > _len) {
|
if (_acked + len > _len) {
|
||||||
// Return the number of extra bytes acked (they will be carried on to the next message)
|
// Return the number of extra bytes acked (they will be carried on to the next message)
|
||||||
@ -142,17 +141,19 @@ size_t AsyncEventSourceMessage::ack(size_t len, uint32_t time) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// This could also return void as the return value is not used.
|
size_t AsyncEventSourceMessage::write(AsyncClient* client) {
|
||||||
// Leaving as-is for compatibility...
|
if (_sent >= _len || !client->canSend()) {
|
||||||
size_t AsyncEventSourceMessage::send(AsyncClient* client) {
|
|
||||||
if (_sent >= _len) {
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
const size_t len_to_send = _len - _sent;
|
size_t len = min(_len - _sent, client->space());
|
||||||
auto position = reinterpret_cast<const char*>(_data + _sent);
|
size_t sent = client->add((const char*)_data + _sent, len);
|
||||||
const size_t sent_now = client->write(position, len_to_send);
|
_sent += sent;
|
||||||
_sent += sent_now;
|
return sent;
|
||||||
return sent_now;
|
}
|
||||||
|
|
||||||
|
size_t AsyncEventSourceMessage::send(AsyncClient* client) {
|
||||||
|
size_t sent = write(client);
|
||||||
|
return sent && client->send() ? sent : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Client
|
// Client
|
||||||
@ -174,6 +175,8 @@ AsyncEventSourceClient::AsyncEventSourceClient(AsyncWebServerRequest* request, A
|
|||||||
|
|
||||||
_server->_addClient(this);
|
_server->_addClient(this);
|
||||||
delete request;
|
delete request;
|
||||||
|
|
||||||
|
_client->setNoDelay(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
AsyncEventSourceClient::~AsyncEventSourceClient() {
|
AsyncEventSourceClient::~AsyncEventSourceClient() {
|
||||||
@ -211,11 +214,6 @@ void AsyncEventSourceClient::_onAck(size_t len, uint32_t time) {
|
|||||||
// Same here, acquiring the lock early
|
// Same here, acquiring the lock early
|
||||||
std::lock_guard<std::mutex> lock(_lockmq);
|
std::lock_guard<std::mutex> lock(_lockmq);
|
||||||
#endif
|
#endif
|
||||||
while (len && _messageQueue.size()) {
|
|
||||||
len = _messageQueue.front().ack(len, time);
|
|
||||||
if (_messageQueue.front().finished())
|
|
||||||
_messageQueue.pop_front();
|
|
||||||
}
|
|
||||||
_runQueue();
|
_runQueue();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -264,11 +262,24 @@ size_t AsyncEventSourceClient::packetsWaiting() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void AsyncEventSourceClient::_runQueue() {
|
void AsyncEventSourceClient::_runQueue() {
|
||||||
// Calls to this private method now already protected by _lockmq acquisition
|
size_t total_bytes_written = 0;
|
||||||
// so no extra call of _lockmq.lock() here..
|
for (auto i = _messageQueue.begin(); i != _messageQueue.end(); ++i) {
|
||||||
for (auto& i : _messageQueue) {
|
if (!i->sent()) {
|
||||||
if (!i.sent())
|
const size_t bytes_written = i->write(_client);
|
||||||
i.send(_client);
|
total_bytes_written += bytes_written;
|
||||||
|
if (bytes_written == 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (total_bytes_written > 0)
|
||||||
|
_client->send();
|
||||||
|
|
||||||
|
size_t len = total_bytes_written;
|
||||||
|
while (len && _messageQueue.size()) {
|
||||||
|
len = _messageQueue.front().ack(len);
|
||||||
|
if (_messageQueue.front().finished()) {
|
||||||
|
_messageQueue.pop_front();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -392,7 +403,8 @@ AsyncEventSourceResponse::AsyncEventSourceResponse(AsyncEventSource* server) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void AsyncEventSourceResponse::_respond(AsyncWebServerRequest* request) {
|
void AsyncEventSourceResponse::_respond(AsyncWebServerRequest* request) {
|
||||||
String out = _assembleHead(request->version());
|
String out;
|
||||||
|
_assembleHead(out, request->version());
|
||||||
request->client()->write(out.c_str(), _headLength);
|
request->client()->write(out.c_str(), _headLength);
|
||||||
_state = RESPONSE_WAIT_ACK;
|
_state = RESPONSE_WAIT_ACK;
|
||||||
}
|
}
|
||||||
|
@ -49,14 +49,6 @@
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef DEFAULT_MAX_SSE_CLIENTS
|
|
||||||
#ifdef ESP32
|
|
||||||
#define DEFAULT_MAX_SSE_CLIENTS 8
|
|
||||||
#else
|
|
||||||
#define DEFAULT_MAX_SSE_CLIENTS 4
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
class AsyncEventSource;
|
class AsyncEventSource;
|
||||||
class AsyncEventSourceResponse;
|
class AsyncEventSourceResponse;
|
||||||
class AsyncEventSourceClient;
|
class AsyncEventSourceClient;
|
||||||
@ -74,7 +66,8 @@ class AsyncEventSourceMessage {
|
|||||||
public:
|
public:
|
||||||
AsyncEventSourceMessage(const char* data, size_t len);
|
AsyncEventSourceMessage(const char* data, size_t len);
|
||||||
~AsyncEventSourceMessage();
|
~AsyncEventSourceMessage();
|
||||||
size_t ack(size_t len, uint32_t time __attribute__((unused)));
|
size_t ack(size_t len, uint32_t time = 0);
|
||||||
|
size_t write(AsyncClient* client);
|
||||||
size_t send(AsyncClient* client);
|
size_t send(AsyncClient* client);
|
||||||
bool finished() { return _acked == _len; }
|
bool finished() { return _acked == _len; }
|
||||||
bool sent() { return _sent == _len; }
|
bool sent() { return _sent == _len; }
|
||||||
@ -99,6 +92,8 @@ class AsyncEventSourceClient {
|
|||||||
AsyncClient* client() { return _client; }
|
AsyncClient* client() { return _client; }
|
||||||
void close();
|
void close();
|
||||||
void write(const char* message, size_t len);
|
void write(const char* message, size_t len);
|
||||||
|
void send(const String& message, const String& event, uint32_t id = 0, uint32_t reconnect = 0) { send(message.c_str(), event.c_str(), id, reconnect); }
|
||||||
|
void send(const String& message, const char* event, uint32_t id = 0, uint32_t reconnect = 0) { send(message.c_str(), event, id, reconnect); }
|
||||||
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() const { return (_client != NULL) && _client->connected(); }
|
bool connected() const { return (_client != NULL) && _client->connected(); }
|
||||||
uint32_t lastId() const { return _lastId; }
|
uint32_t lastId() const { return _lastId; }
|
||||||
@ -124,13 +119,15 @@ class AsyncEventSource : public AsyncWebHandler {
|
|||||||
ArAuthorizeConnectHandler _authorizeConnectHandler;
|
ArAuthorizeConnectHandler _authorizeConnectHandler;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
AsyncEventSource(const String& url) : _url(url){};
|
AsyncEventSource(const String& url) : _url(url) {};
|
||||||
~AsyncEventSource() { close(); };
|
~AsyncEventSource() { close(); };
|
||||||
|
|
||||||
const char* url() const { 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 authorizeConnect(ArAuthorizeConnectHandler cb);
|
void authorizeConnect(ArAuthorizeConnectHandler cb);
|
||||||
|
void send(const String& message, const String& event, uint32_t id = 0, uint32_t reconnect = 0) { send(message.c_str(), event.c_str(), id, reconnect); }
|
||||||
|
void send(const String& message, const char* event, uint32_t id = 0, uint32_t reconnect = 0) { send(message.c_str(), event, id, reconnect); }
|
||||||
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);
|
||||||
// number of clients connected
|
// number of clients connected
|
||||||
size_t count() const;
|
size_t count() const;
|
||||||
|
@ -27,7 +27,7 @@
|
|||||||
|
|
||||||
#if defined(ESP32)
|
#if defined(ESP32)
|
||||||
#if ESP_IDF_VERSION_MAJOR < 5
|
#if ESP_IDF_VERSION_MAJOR < 5
|
||||||
#include "./port/SHA1Builder.h"
|
#include "BackPort_SHA1Builder.h"
|
||||||
#else
|
#else
|
||||||
#include <SHA1Builder.h>
|
#include <SHA1Builder.h>
|
||||||
#endif
|
#endif
|
||||||
@ -36,11 +36,8 @@
|
|||||||
#include <Hash.h>
|
#include <Hash.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define MAX_PRINTF_LEN 64
|
|
||||||
|
|
||||||
using namespace asyncsrv;
|
using namespace asyncsrv;
|
||||||
|
|
||||||
|
|
||||||
size_t webSocketSendFrameWindow(AsyncClient* client) {
|
size_t webSocketSendFrameWindow(AsyncClient* client) {
|
||||||
if (!client->canSend())
|
if (!client->canSend())
|
||||||
return 0;
|
return 0;
|
||||||
@ -589,30 +586,23 @@ void AsyncWebSocketClient::_onData(void* pbuf, size_t plen) {
|
|||||||
size_t AsyncWebSocketClient::printf(const char* format, ...) {
|
size_t AsyncWebSocketClient::printf(const char* format, ...) {
|
||||||
va_list arg;
|
va_list arg;
|
||||||
va_start(arg, format);
|
va_start(arg, format);
|
||||||
char* temp = new char[MAX_PRINTF_LEN];
|
size_t len = vsnprintf(nullptr, 0, format, arg);
|
||||||
if (!temp) {
|
va_end(arg);
|
||||||
va_end(arg);
|
|
||||||
return 0;
|
if (len == 0)
|
||||||
}
|
return 0;
|
||||||
char* buffer = temp;
|
|
||||||
size_t len = vsnprintf(temp, MAX_PRINTF_LEN, format, arg);
|
char* buffer = new char[len + 1];
|
||||||
|
|
||||||
|
if (!buffer)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
va_start(arg, format);
|
||||||
|
len = vsnprintf(buffer, len + 1, format, arg);
|
||||||
va_end(arg);
|
va_end(arg);
|
||||||
|
|
||||||
if (len > (MAX_PRINTF_LEN - 1)) {
|
|
||||||
buffer = new char[len + 1];
|
|
||||||
if (!buffer) {
|
|
||||||
delete[] temp;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
va_start(arg, format);
|
|
||||||
vsnprintf(buffer, len + 1, format, arg);
|
|
||||||
va_end(arg);
|
|
||||||
}
|
|
||||||
text(buffer, len);
|
text(buffer, len);
|
||||||
if (buffer != temp) {
|
delete[] buffer;
|
||||||
delete[] buffer;
|
|
||||||
}
|
|
||||||
delete[] temp;
|
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -620,30 +610,23 @@ size_t AsyncWebSocketClient::printf(const char* format, ...) {
|
|||||||
size_t AsyncWebSocketClient::printf_P(PGM_P formatP, ...) {
|
size_t AsyncWebSocketClient::printf_P(PGM_P formatP, ...) {
|
||||||
va_list arg;
|
va_list arg;
|
||||||
va_start(arg, formatP);
|
va_start(arg, formatP);
|
||||||
char* temp = new char[MAX_PRINTF_LEN];
|
size_t len = vsnprintf_P(nullptr, 0, formatP, arg);
|
||||||
if (!temp) {
|
va_end(arg);
|
||||||
va_end(arg);
|
|
||||||
return 0;
|
if (len == 0)
|
||||||
}
|
return 0;
|
||||||
char* buffer = temp;
|
|
||||||
size_t len = vsnprintf_P(temp, MAX_PRINTF_LEN, formatP, arg);
|
char* buffer = new char[len + 1];
|
||||||
|
|
||||||
|
if (!buffer)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
va_start(arg, formatP);
|
||||||
|
len = vsnprintf_P(buffer, len + 1, formatP, arg);
|
||||||
va_end(arg);
|
va_end(arg);
|
||||||
|
|
||||||
if (len > (MAX_PRINTF_LEN - 1)) {
|
|
||||||
buffer = new char[len + 1];
|
|
||||||
if (!buffer) {
|
|
||||||
delete[] temp;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
va_start(arg, formatP);
|
|
||||||
vsnprintf_P(buffer, len + 1, formatP, arg);
|
|
||||||
va_end(arg);
|
|
||||||
}
|
|
||||||
text(buffer, len);
|
text(buffer, len);
|
||||||
if (buffer != temp) {
|
delete[] buffer;
|
||||||
delete[] buffer;
|
|
||||||
}
|
|
||||||
delete[] temp;
|
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -1008,22 +991,24 @@ size_t AsyncWebSocket::printf(uint32_t id, const char* format, ...) {
|
|||||||
|
|
||||||
size_t AsyncWebSocket::printfAll(const char* format, ...) {
|
size_t AsyncWebSocket::printfAll(const char* format, ...) {
|
||||||
va_list arg;
|
va_list arg;
|
||||||
char* temp = new char[MAX_PRINTF_LEN];
|
va_start(arg, format);
|
||||||
if (!temp)
|
size_t len = vsnprintf(nullptr, 0, format, arg);
|
||||||
|
va_end(arg);
|
||||||
|
|
||||||
|
if (len == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
char* buffer = new char[len + 1];
|
||||||
|
|
||||||
|
if (!buffer)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
va_start(arg, format);
|
va_start(arg, format);
|
||||||
size_t len = vsnprintf(temp, MAX_PRINTF_LEN, format, arg);
|
len = vsnprintf(buffer, len + 1, format, arg);
|
||||||
va_end(arg);
|
|
||||||
delete[] temp;
|
|
||||||
|
|
||||||
AsyncWebSocketSharedBuffer buffer = std::make_shared<std::vector<uint8_t>>(len);
|
|
||||||
|
|
||||||
va_start(arg, format);
|
|
||||||
vsnprintf((char*)buffer->data(), len + 1, format, arg);
|
|
||||||
va_end(arg);
|
va_end(arg);
|
||||||
|
|
||||||
textAll(buffer);
|
textAll(buffer, len);
|
||||||
|
delete[] buffer;
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1042,22 +1027,24 @@ size_t AsyncWebSocket::printf_P(uint32_t id, PGM_P formatP, ...) {
|
|||||||
|
|
||||||
size_t AsyncWebSocket::printfAll_P(PGM_P formatP, ...) {
|
size_t AsyncWebSocket::printfAll_P(PGM_P formatP, ...) {
|
||||||
va_list arg;
|
va_list arg;
|
||||||
char* temp = new char[MAX_PRINTF_LEN];
|
va_start(arg, formatP);
|
||||||
if (!temp)
|
size_t len = vsnprintf_P(nullptr, 0, formatP, arg);
|
||||||
|
va_end(arg);
|
||||||
|
|
||||||
|
if (len == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
char* buffer = new char[len + 1];
|
||||||
|
|
||||||
|
if (!buffer)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
va_start(arg, formatP);
|
va_start(arg, formatP);
|
||||||
size_t len = vsnprintf_P(temp, MAX_PRINTF_LEN, formatP, arg);
|
len = vsnprintf_P(buffer, len + 1, formatP, arg);
|
||||||
va_end(arg);
|
|
||||||
delete[] temp;
|
|
||||||
|
|
||||||
AsyncWebSocketSharedBuffer buffer = std::make_shared<std::vector<uint8_t>>(len + 1);
|
|
||||||
|
|
||||||
va_start(arg, formatP);
|
|
||||||
vsnprintf_P((char*)buffer->data(), len + 1, formatP, arg);
|
|
||||||
va_end(arg);
|
va_end(arg);
|
||||||
|
|
||||||
textAll(buffer);
|
textAll(buffer, len);
|
||||||
|
delete[] buffer;
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -1192,7 +1179,8 @@ void AsyncWebSocketResponse::_respond(AsyncWebServerRequest* request) {
|
|||||||
request->client()->close(true);
|
request->client()->close(true);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
String out(_assembleHead(request->version()));
|
String out;
|
||||||
|
_assembleHead(out, request->version());
|
||||||
request->client()->write(out.c_str(), _headLength);
|
request->client()->write(out.c_str(), _headLength);
|
||||||
_state = RESPONSE_WAIT_ACK;
|
_state = RESPONSE_WAIT_ACK;
|
||||||
}
|
}
|
||||||
|
@ -23,7 +23,7 @@
|
|||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
#if ESP_IDF_VERSION_MAJOR < 5
|
#if ESP_IDF_VERSION_MAJOR < 5
|
||||||
|
|
||||||
#include "SHA1Builder.h"
|
#include "BackPort_SHA1Builder.h"
|
||||||
|
|
||||||
// 32-bit integer manipulation macros (big endian)
|
// 32-bit integer manipulation macros (big endian)
|
||||||
|
|
||||||
@ -202,7 +202,7 @@ void SHA1Builder::process(const uint8_t *data) {
|
|||||||
|
|
||||||
// Public methods
|
// Public methods
|
||||||
|
|
||||||
void SHA1Builder::begin(void) {
|
void SHA1Builder::begin() {
|
||||||
total[0] = 0;
|
total[0] = 0;
|
||||||
total[1] = 0;
|
total[1] = 0;
|
||||||
|
|
@ -12,6 +12,9 @@
|
|||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
|
#include <Arduino.h>
|
||||||
|
#if ESP_IDF_VERSION_MAJOR < 5
|
||||||
|
|
||||||
#ifndef SHA1Builder_h
|
#ifndef SHA1Builder_h
|
||||||
#define SHA1Builder_h
|
#define SHA1Builder_h
|
||||||
|
|
||||||
@ -37,3 +40,5 @@ class SHA1Builder {
|
|||||||
};
|
};
|
||||||
|
|
||||||
#endif // SHA1Builder_h
|
#endif // SHA1Builder_h
|
||||||
|
|
||||||
|
#endif // ESP_IDF_VERSION_MAJOR < 5
|
@ -45,10 +45,10 @@
|
|||||||
|
|
||||||
#include "literals.h"
|
#include "literals.h"
|
||||||
|
|
||||||
#define ASYNCWEBSERVER_VERSION "3.2.0"
|
#define ASYNCWEBSERVER_VERSION "3.2.4"
|
||||||
#define ASYNCWEBSERVER_VERSION_MAJOR 3
|
#define ASYNCWEBSERVER_VERSION_MAJOR 3
|
||||||
#define ASYNCWEBSERVER_VERSION_MINOR 2
|
#define ASYNCWEBSERVER_VERSION_MINOR 2
|
||||||
#define ASYNCWEBSERVER_VERSION_REVISION 0
|
#define ASYNCWEBSERVER_VERSION_REVISION 4
|
||||||
#define ASYNCWEBSERVER_FORK_mathieucarbou
|
#define ASYNCWEBSERVER_FORK_mathieucarbou
|
||||||
|
|
||||||
#ifdef ASYNCWEBSERVER_REGEX
|
#ifdef ASYNCWEBSERVER_REGEX
|
||||||
@ -155,7 +155,9 @@ class AsyncWebHeader {
|
|||||||
const String& name() const { return _name; }
|
const String& name() const { return _name; }
|
||||||
const String& value() const { return _value; }
|
const String& value() const { return _value; }
|
||||||
String toString() const {
|
String toString() const {
|
||||||
String str = _name;
|
String str;
|
||||||
|
str.reserve(_name.length() + _value.length() + 2);
|
||||||
|
str.concat(_name);
|
||||||
str.concat((char)0x3a);
|
str.concat((char)0x3a);
|
||||||
str.concat((char)0x20);
|
str.concat((char)0x20);
|
||||||
str.concat(_value);
|
str.concat(_value);
|
||||||
@ -333,11 +335,15 @@ class AsyncWebServerRequest {
|
|||||||
void sendChunked(const char* contentType, AwsResponseFiller callback, AwsTemplateProcessor templateCallback = nullptr) { send(beginChunkedResponse(contentType, callback, templateCallback)); }
|
void sendChunked(const char* contentType, AwsResponseFiller callback, AwsTemplateProcessor templateCallback = nullptr) { send(beginChunkedResponse(contentType, callback, templateCallback)); }
|
||||||
void sendChunked(const String& contentType, AwsResponseFiller callback, AwsTemplateProcessor templateCallback = nullptr) { send(beginChunkedResponse(contentType, callback, templateCallback)); }
|
void sendChunked(const String& contentType, AwsResponseFiller callback, AwsTemplateProcessor templateCallback = nullptr) { send(beginChunkedResponse(contentType, callback, templateCallback)); }
|
||||||
|
|
||||||
|
#ifndef ESP8266
|
||||||
[[deprecated("Replaced by send(...)")]]
|
[[deprecated("Replaced by send(...)")]]
|
||||||
|
#endif
|
||||||
void send_P(int code, const String& contentType, const uint8_t* content, size_t len, AwsTemplateProcessor callback = nullptr) {
|
void send_P(int code, const String& contentType, const uint8_t* content, size_t len, AwsTemplateProcessor callback = nullptr) {
|
||||||
send(code, contentType, content, len, callback);
|
send(code, contentType, content, len, callback);
|
||||||
}
|
}
|
||||||
|
#ifndef ESP8266
|
||||||
[[deprecated("Replaced by send(...)")]]
|
[[deprecated("Replaced by send(...)")]]
|
||||||
|
#endif
|
||||||
void send_P(int code, const String& contentType, PGM_P content, AwsTemplateProcessor callback = nullptr) {
|
void send_P(int code, const String& contentType, PGM_P content, AwsTemplateProcessor callback = nullptr) {
|
||||||
send(code, contentType, content, callback);
|
send(code, contentType, content, callback);
|
||||||
}
|
}
|
||||||
@ -370,13 +376,17 @@ class AsyncWebServerRequest {
|
|||||||
AsyncResponseStream* beginResponseStream(const char* contentType, size_t bufferSize = 1460);
|
AsyncResponseStream* beginResponseStream(const char* contentType, size_t bufferSize = 1460);
|
||||||
AsyncResponseStream* beginResponseStream(const String& contentType, size_t bufferSize = 1460) { return beginResponseStream(contentType.c_str(), bufferSize); }
|
AsyncResponseStream* beginResponseStream(const String& contentType, size_t bufferSize = 1460) { return beginResponseStream(contentType.c_str(), bufferSize); }
|
||||||
|
|
||||||
|
#ifndef ESP8266
|
||||||
[[deprecated("Replaced by beginResponse(...)")]]
|
[[deprecated("Replaced by beginResponse(...)")]]
|
||||||
|
#endif
|
||||||
AsyncWebServerResponse* beginResponse_P(int code, const String& contentType, const uint8_t* content, size_t len, AwsTemplateProcessor callback = nullptr) {
|
AsyncWebServerResponse* beginResponse_P(int code, const String& contentType, const uint8_t* content, size_t len, AwsTemplateProcessor callback = nullptr) {
|
||||||
return beginResponse(code, contentType, content, len, callback);
|
return beginResponse(code, contentType.c_str(), content, len, callback);
|
||||||
}
|
}
|
||||||
|
#ifndef ESP8266
|
||||||
[[deprecated("Replaced by beginResponse(...)")]]
|
[[deprecated("Replaced by beginResponse(...)")]]
|
||||||
|
#endif
|
||||||
AsyncWebServerResponse* beginResponse_P(int code, const String& contentType, PGM_P content, AwsTemplateProcessor callback = nullptr) {
|
AsyncWebServerResponse* beginResponse_P(int code, const String& contentType, PGM_P content, AwsTemplateProcessor callback = nullptr) {
|
||||||
return beginResponse(code, contentType, content, callback);
|
return beginResponse(code, contentType.c_str(), content, callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef ESP8266
|
#ifdef ESP8266
|
||||||
@ -583,8 +593,21 @@ class AsyncWebServerResponse {
|
|||||||
virtual void setContentType(const char* type);
|
virtual void setContentType(const char* type);
|
||||||
virtual bool addHeader(const char* name, const char* value, bool replaceExisting = true);
|
virtual bool addHeader(const char* name, const char* value, bool replaceExisting = true);
|
||||||
bool addHeader(const String& name, const String& value, bool replaceExisting = true) { return addHeader(name.c_str(), value.c_str(), replaceExisting); }
|
bool addHeader(const String& name, const String& value, bool replaceExisting = true) { return addHeader(name.c_str(), value.c_str(), replaceExisting); }
|
||||||
|
bool addHeader(const char* name, long value, bool replaceExisting = true) { return addHeader(name, String(value), replaceExisting); }
|
||||||
|
bool addHeader(const String& name, long value, bool replaceExisting = true) { return addHeader(name.c_str(), value, replaceExisting); }
|
||||||
virtual bool removeHeader(const char* name);
|
virtual bool removeHeader(const char* name);
|
||||||
virtual String _assembleHead(uint8_t version);
|
virtual const AsyncWebHeader* getHeader(const char* name) const;
|
||||||
|
|
||||||
|
#ifndef ESP8266
|
||||||
|
[[deprecated("Use instead: _assembleHead(String& buffer, uint8_t version)")]]
|
||||||
|
#endif
|
||||||
|
String _assembleHead(uint8_t version) {
|
||||||
|
String buffer;
|
||||||
|
_assembleHead(buffer, version);
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
virtual void _assembleHead(String& buffer, uint8_t version);
|
||||||
|
|
||||||
virtual bool _started() const;
|
virtual bool _started() const;
|
||||||
virtual bool _finished() const;
|
virtual bool _finished() const;
|
||||||
virtual bool _failed() const;
|
virtual bool _failed() const;
|
||||||
|
@ -624,7 +624,6 @@ bool AsyncWebServerRequest::hasHeader(const __FlashStringHelper* data) const {
|
|||||||
|
|
||||||
const AsyncWebHeader* AsyncWebServerRequest::getHeader(const char* name) const {
|
const AsyncWebHeader* AsyncWebServerRequest::getHeader(const char* name) const {
|
||||||
auto iter = std::find_if(std::begin(_headers), std::end(_headers), [&name](const AsyncWebHeader& header) { return header.name().equalsIgnoreCase(name); });
|
auto iter = std::find_if(std::begin(_headers), std::end(_headers), [&name](const AsyncWebHeader& header) { return header.name().equalsIgnoreCase(name); });
|
||||||
|
|
||||||
return (iter == std::end(_headers)) ? nullptr : &(*iter);
|
return (iter == std::end(_headers)) ? nullptr : &(*iter);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -125,9 +125,8 @@ const char* AsyncWebServerResponse::responseCodeToString(int code) {
|
|||||||
return T_HTTP_CODE_ANY;
|
return T_HTTP_CODE_ANY;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#else // ESP8266
|
#else // ESP8266
|
||||||
const __FlashStringHelper* AsyncWebServerResponse::responseCodeToString(int code)
|
const __FlashStringHelper* AsyncWebServerResponse::responseCodeToString(int code) {
|
||||||
{
|
|
||||||
switch (code) {
|
switch (code) {
|
||||||
case 100:
|
case 100:
|
||||||
return FPSTR(T_HTTP_CODE_100);
|
return FPSTR(T_HTTP_CODE_100);
|
||||||
@ -230,12 +229,12 @@ void AsyncWebServerResponse::setCode(int code) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void AsyncWebServerResponse::setContentLength(size_t len) {
|
void AsyncWebServerResponse::setContentLength(size_t len) {
|
||||||
if (_state == RESPONSE_SETUP)
|
if (_state == RESPONSE_SETUP && addHeader(T_Content_Length, len, true))
|
||||||
_contentLength = len;
|
_contentLength = len;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AsyncWebServerResponse::setContentType(const char* type) {
|
void AsyncWebServerResponse::setContentType(const char* type) {
|
||||||
if (_state == RESPONSE_SETUP)
|
if (_state == RESPONSE_SETUP && addHeader(T_Content_Type, type, true))
|
||||||
_contentType = type;
|
_contentType = type;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -249,6 +248,11 @@ bool AsyncWebServerResponse::removeHeader(const char* name) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const AsyncWebHeader* AsyncWebServerResponse::getHeader(const char* name) const {
|
||||||
|
auto iter = std::find_if(std::begin(_headers), std::end(_headers), [&name](const AsyncWebHeader& header) { return header.name().equalsIgnoreCase(name); });
|
||||||
|
return (iter == std::end(_headers)) ? nullptr : &(*iter);
|
||||||
|
}
|
||||||
|
|
||||||
bool AsyncWebServerResponse::addHeader(const char* name, const char* value, bool replaceExisting) {
|
bool AsyncWebServerResponse::addHeader(const char* name, const char* value, bool replaceExisting) {
|
||||||
for (auto i = _headers.begin(); i != _headers.end(); ++i) {
|
for (auto i = _headers.begin(); i != _headers.end(); ++i) {
|
||||||
if (i->name().equalsIgnoreCase(name)) {
|
if (i->name().equalsIgnoreCase(name)) {
|
||||||
@ -268,41 +272,56 @@ bool AsyncWebServerResponse::addHeader(const char* name, const char* value, bool
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
String AsyncWebServerResponse::_assembleHead(uint8_t version) {
|
void AsyncWebServerResponse::_assembleHead(String& buffer, uint8_t version) {
|
||||||
if (version) {
|
if (version) {
|
||||||
addHeader(T_Accept_Ranges, T_none, false);
|
addHeader(T_Accept_Ranges, T_none, false);
|
||||||
if (_chunked)
|
if (_chunked)
|
||||||
addHeader(T_Transfer_Encoding, T_chunked, false);
|
addHeader(T_Transfer_Encoding, T_chunked, false);
|
||||||
}
|
}
|
||||||
String out;
|
|
||||||
constexpr size_t bufSize = 300;
|
|
||||||
char buf[bufSize];
|
|
||||||
|
|
||||||
#ifndef ESP8266
|
if (_sendContentLength)
|
||||||
snprintf(buf, bufSize, "HTTP/1.%d %d %s\r\n", version, _code, responseCodeToString(_code));
|
addHeader(T_Content_Length, String(_contentLength), false);
|
||||||
|
|
||||||
|
if (_contentType.length())
|
||||||
|
addHeader(T_Content_Type, _contentType.c_str(), false);
|
||||||
|
|
||||||
|
// precompute buffer size to avoid reallocations by String class
|
||||||
|
size_t len = 0;
|
||||||
|
len += 50; // HTTP/1.1 200 <reason>\r\n
|
||||||
|
for (const auto& header : _headers)
|
||||||
|
len += header.name().length() + header.value().length() + 4;
|
||||||
|
|
||||||
|
// prepare buffer
|
||||||
|
buffer.reserve(len);
|
||||||
|
|
||||||
|
// HTTP header
|
||||||
|
#ifdef ESP8266
|
||||||
|
buffer.concat(PSTR("HTTP/1."));
|
||||||
#else
|
#else
|
||||||
snprintf_P(buf, bufSize, PSTR("HTTP/1.%d %d %s\r\n"), version, _code, String(responseCodeToString(_code)).c_str());
|
buffer.concat("HTTP/1.");
|
||||||
#endif
|
#endif
|
||||||
out.concat(buf);
|
buffer.concat(version);
|
||||||
|
buffer.concat(' ');
|
||||||
if (_sendContentLength) {
|
buffer.concat(_code);
|
||||||
snprintf_P(buf, bufSize, PSTR("Content-Length: %d\r\n"), _contentLength);
|
buffer.concat(' ');
|
||||||
out.concat(buf);
|
buffer.concat(responseCodeToString(_code));
|
||||||
}
|
buffer.concat(T_rn);
|
||||||
if (_contentType.length()) {
|
|
||||||
snprintf_P(buf, bufSize, PSTR("Content-Type: %s\r\n"), _contentType.c_str());
|
|
||||||
out.concat(buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// Add headers
|
||||||
for (const auto& header : _headers) {
|
for (const auto& header : _headers) {
|
||||||
snprintf_P(buf, bufSize, PSTR("%s: %s\r\n"), header.name().c_str(), header.value().c_str());
|
buffer.concat(header.name());
|
||||||
out.concat(buf);
|
#ifdef ESP8266
|
||||||
|
buffer.concat(PSTR(": "));
|
||||||
|
#else
|
||||||
|
buffer.concat(": ");
|
||||||
|
#endif
|
||||||
|
buffer.concat(header.value());
|
||||||
|
buffer.concat(T_rn);
|
||||||
}
|
}
|
||||||
_headers.clear();
|
_headers.clear();
|
||||||
|
|
||||||
out.concat(T_rn);
|
buffer.concat(T_rn);
|
||||||
_headLength = out.length();
|
_headLength = buffer.length();
|
||||||
return out;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AsyncWebServerResponse::_started() const { return _state > RESPONSE_SETUP; }
|
bool AsyncWebServerResponse::_started() const { return _state > RESPONSE_SETUP; }
|
||||||
@ -337,7 +356,8 @@ AsyncBasicResponse::AsyncBasicResponse(int code, const char* contentType, const
|
|||||||
|
|
||||||
void AsyncBasicResponse::_respond(AsyncWebServerRequest* request) {
|
void AsyncBasicResponse::_respond(AsyncWebServerRequest* request) {
|
||||||
_state = RESPONSE_HEADERS;
|
_state = RESPONSE_HEADERS;
|
||||||
String out = _assembleHead(request->version());
|
String out;
|
||||||
|
_assembleHead(out, request->version());
|
||||||
size_t outLen = out.length();
|
size_t outLen = out.length();
|
||||||
size_t space = request->client()->space();
|
size_t space = request->client()->space();
|
||||||
if (!_contentLength && space >= outLen) {
|
if (!_contentLength && space >= outLen) {
|
||||||
@ -411,7 +431,7 @@ AsyncAbstractResponse::AsyncAbstractResponse(AwsTemplateProcessor callback) : _c
|
|||||||
|
|
||||||
void AsyncAbstractResponse::_respond(AsyncWebServerRequest* request) {
|
void AsyncAbstractResponse::_respond(AsyncWebServerRequest* request) {
|
||||||
addHeader(T_Connection, T_close, false);
|
addHeader(T_Connection, T_close, false);
|
||||||
_head = _assembleHead(request->version());
|
_assembleHead(_head, request->version());
|
||||||
_state = RESPONSE_HEADERS;
|
_state = RESPONSE_HEADERS;
|
||||||
_ack(request, 0, 0);
|
_ack(request, 0, 0);
|
||||||
}
|
}
|
||||||
@ -472,9 +492,7 @@ size_t AsyncAbstractResponse::_ack(AsyncWebServerRequest* request, size_t len, u
|
|||||||
free(buf);
|
free(buf);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
outLen = sprintf_P((char*)buf + headLen, PSTR("%x"), readLen) + headLen;
|
outLen = sprintf((char*)buf+headLen, "%04x", readLen) + headLen;
|
||||||
while (outLen < headLen + 4)
|
|
||||||
buf[outLen++] = ' ';
|
|
||||||
buf[outLen++] = '\r';
|
buf[outLen++] = '\r';
|
||||||
buf[outLen++] = '\n';
|
buf[outLen++] = '\n';
|
||||||
outLen += readLen;
|
outLen += readLen;
|
||||||
@ -635,9 +653,9 @@ AsyncFileResponse::~AsyncFileResponse() {
|
|||||||
void AsyncFileResponse::_setContentTypeFromPath(const String& path) {
|
void AsyncFileResponse::_setContentTypeFromPath(const String& path) {
|
||||||
#if HAVE_EXTERN_GET_Content_Type_FUNCTION
|
#if HAVE_EXTERN_GET_Content_Type_FUNCTION
|
||||||
#ifndef ESP8266
|
#ifndef ESP8266
|
||||||
extern const char* getContentType(const String& path);
|
extern const char* getContentType(const String& path);
|
||||||
#else
|
#else
|
||||||
extern const __FlashStringHelper* getContentType(const String& path);
|
extern const __FlashStringHelper* getContentType(const String& path);
|
||||||
#endif
|
#endif
|
||||||
_contentType = getContentType(path);
|
_contentType = getContentType(path);
|
||||||
#else
|
#else
|
||||||
|
Loading…
Reference in New Issue
Block a user