Verze 3.1.1

This commit is contained in:
Pavel Brychta 2024-07-18 17:31:53 +02:00
parent e0375a1fb6
commit 34ec983d80
18 changed files with 886 additions and 316 deletions

View File

@ -1,8 +1,8 @@
# ESP Async WebServer
# 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)
[![PlatformIO Registry](https://badges.registry.platformio.org/packages/mathieucarbou/library/ESP%20Async%20WebServer.svg)](https://registry.platformio.org/libraries/mathieucarbou/ESP%20Async%20WebServer)
[![PlatformIO Registry](https://badges.registry.platformio.org/packages/mathieucarbou/library/ESPAsyncWebServer.svg)](https://registry.platformio.org/libraries/mathieucarbou/ESPAsyncWebServer)
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.
@ -22,7 +22,7 @@ This fork is based on [yubox-node-org/ESPAsyncWebServer](https://github.com/yubo
- [@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): CI
- [@mathieucarbou](https://github.com/mathieucarbou): Depends on `mathieucarbou/Async TCP @ ^3.1.4`
- [@mathieucarbou](https://github.com/mathieucarbou): Depends on `mathieucarbou/AsyncTCP @ 3.2.3`
- [@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): Made DEFAULT_MAX_SSE_CLIENTS customizable
@ -41,7 +41,7 @@ This fork is based on [yubox-node-org/ESPAsyncWebServer](https://github.com/yubo
## Dependencies:
- **ESP32**: `mathieucarbou/Async TCP @ ^3.1.4` (Arduino IDE: [https://github.com/mathieucarbou/AsyncTCP#v3.1.4](https://github.com/mathieucarbou/AsyncTCP/releases/tag/v3.1.4))
- **ESP32**: `mathieucarbou/AsyncTCP @ 3.2.3` (Arduino IDE: [https://github.com/mathieucarbou/AsyncTCP#v3.2.3](https://github.com/mathieucarbou/AsyncTCP/releases/tag/v3.2.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))

View File

@ -1,6 +1,6 @@
# bundle exec jekyll serve --host=0.0.0.0
title: ESP Async WebServer
title: ESPAsyncWebServer
description: "Asynchronous HTTP and WebSocket Server Library for ESP32, ESP8266 and RP2040"
remote_theme: pages-themes/cayman@v0.2.0
plugins:

View File

@ -1,8 +1,8 @@
# ESP Async WebServer
# 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)
[![PlatformIO Registry](https://badges.registry.platformio.org/packages/mathieucarbou/library/ESP%20Async%20WebServer.svg)](https://registry.platformio.org/libraries/mathieucarbou/ESP%20Async%20WebServer)
[![PlatformIO Registry](https://badges.registry.platformio.org/packages/mathieucarbou/library/ESPAsyncWebServer.svg)](https://registry.platformio.org/libraries/mathieucarbou/ESPAsyncWebServer)
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.
@ -22,7 +22,7 @@ This fork is based on [yubox-node-org/ESPAsyncWebServer](https://github.com/yubo
- [@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): CI
- [@mathieucarbou](https://github.com/mathieucarbou): Depends on `mathieucarbou/Async TCP @ ^3.1.4`
- [@mathieucarbou](https://github.com/mathieucarbou): Depends on `mathieucarbou/AsyncTCP @ 3.2.3`
- [@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): Made DEFAULT_MAX_SSE_CLIENTS customizable
@ -41,7 +41,7 @@ This fork is based on [yubox-node-org/ESPAsyncWebServer](https://github.com/yubo
## Dependencies:
- **ESP32**: `mathieucarbou/Async TCP @ ^3.1.4` (Arduino IDE: [https://github.com/mathieucarbou/AsyncTCP#v3.1.4](https://github.com/mathieucarbou/AsyncTCP/releases/tag/v3.1.4))
- **ESP32**: `mathieucarbou/AsyncTCP @ 3.2.3` (Arduino IDE: [https://github.com/mathieucarbou/AsyncTCP#v3.2.3](https://github.com/mathieucarbou/AsyncTCP/releases/tag/v3.2.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))

View File

@ -0,0 +1,107 @@
#include <DNSServer.h>
#ifdef ESP32
#include <AsyncTCP.h>
#include <WiFi.h>
#elif defined(ESP8266)
#include <ESP8266WiFi.h>
#include <ESPAsyncTCP.h>
#elif defined(TARGET_RP2040)
#include <WebServer.h>
#include <WiFi.h>
#endif
#include "ESPAsyncWebServer.h"
const char appWebPage[] PROGMEM = R"rawliteral(
<body>
<button id="button1" onclick="fetch('/button1');">Relay1</button>
<script>
const evtSource = new EventSource("/events");
button1 = document.getElementById("button1");
evtSource.addEventListener('state', (e) => {
const data = JSON.parse(e.data);
console.log('Event Source data: ', data);
if (data.button1) {
button1.style.backgroundColor = "green";
}
else {
button1.style.backgroundColor = "red";
}
});
</script>
</body>
)rawliteral";
AsyncWebServer server(80);
AsyncEventSource events("/events");
const uint32_t interval = 1000;
const int button1Pin = 4;
uint32_t lastSend = 0;
void prepareJson(String& buffer) {
buffer.reserve(512);
buffer.concat("{\"button1\":");
buffer.concat(digitalRead(button1Pin) == LOW);
buffer.concat(",\"1234567890abcdefghij1234567890abcdefghij1234567890abcdefghij1234567890abcdefghij1234567890abcdefghij1234567890abcdefghij\":");
buffer.concat(random(0, 999999999));
buffer.concat("}");
}
void setup() {
Serial.begin(115200);
#if ARDUINO_USB_CDC_ON_BOOT
Serial.setTxTimeoutMs(0);
delay(100);
#else
while (!Serial)
yield();
#endif
randomSeed(micros());
pinMode(button1Pin, OUTPUT);
digitalWrite(button1Pin, HIGH);
WiFi.softAP("esp-captive");
server.on("/", HTTP_GET, [](AsyncWebServerRequest* request) {
request->send(200, "text/html", appWebPage);
});
server.on("/button1", HTTP_GET, [](AsyncWebServerRequest* request) {
request->send(200, "text/plain", "OK");
digitalWrite(button1Pin, digitalRead(button1Pin) == LOW ? HIGH : LOW);
String buffer;
prepareJson(buffer);
ESP_LOGI("async_tcp", "Sending from handler...");
events.send(buffer.c_str(), "state", millis());
ESP_LOGI("async_tcp", "Sent from handler!");
});
events.onConnect([](AsyncEventSourceClient* client) {
String buffer;
prepareJson(buffer);
ESP_LOGI("async_tcp", "Sending from onConnect...");
client->send(buffer.c_str(), "state", millis(), 5000);
ESP_LOGI("async_tcp", "Sent from onConnect!");
});
server.addHandler(&events);
DefaultHeaders::Instance().addHeader("Access-Control-Allow-Origin", "*");
server.begin();
}
void loop() {
if (millis() - lastSend >= interval) {
String buffer;
prepareJson(buffer);
ESP_LOGI("loop", "Sending...");
events.send(buffer.c_str(), "state", millis());
ESP_LOGI("loop", "Sent!");
lastSend = millis();
}
}

View File

@ -1,6 +1,6 @@
{
"name": "ESP Async WebServer",
"version": "3.0.6",
"name": "ESPAsyncWebServer",
"version": "3.1.1",
"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",
@ -27,8 +27,8 @@
"dependencies": [
{
"owner": "mathieucarbou",
"name": "Async TCP",
"version": "^3.1.4",
"name": "AsyncTCP",
"version": "^3.2.3",
"platforms": "espressif32"
},
{

View File

@ -1,5 +1,5 @@
name=ESP Async WebServer
version=3.0.6
name=ESPAsyncWebServer
version=3.1.1
author=Me-No-Dev
maintainer=Mathieu Carbou <mathieu.carbou@gmail.com>
sentence=Asynchronous HTTP and WebSocket Server Library for ESP32, ESP8266 and RP2040

View File

@ -4,6 +4,11 @@ build_flags =
-Wall -Wextra
-D CONFIG_ARDUHAL_LOG_COLORS
-D CORE_DEBUG_LEVEL=ARDUHAL_LOG_LEVEL_VERBOSE
-D CONFIG_ASYNC_TCP_MAX_ACK_TIME=3000
-D CONFIG_ASYNC_TCP_PRIORITY=10
-D CONFIG_ASYNC_TCP_QUEUE_SIZE=128
-D CONFIG_ASYNC_TCP_RUNNING_CORE=1
-D CONFIG_ASYNC_TCP_STACK_SIZE=4096
upload_protocol = esptool
monitor_speed = 115200
monitor_filters = esp32_exception_decoder, log2file
@ -12,33 +17,34 @@ monitor_filters = esp32_exception_decoder, log2file
lib_dir = .
; src_dir = examples/CaptivePortal
; src_dir = examples/SimpleServer
src_dir = examples/StreamFiles
; src_dir = examples/StreamFiles
; src_dir = examples/Filters
; src_dir = examples/Draft
src_dir = examples/issues/Issue14
[env:arduino]
platform = espressif32
board = esp32dev
lib_deps =
bblanchon/ArduinoJson @ 7.1.0
mathieucarbou/Async TCP @ ^3.1.4
mathieucarbou/AsyncTCP @ 3.2.3
[env:arduino-2]
platform = espressif32@6.7.0
board = esp32dev
lib_deps =
bblanchon/ArduinoJson @ 7.1.0
mathieucarbou/Async TCP @ ^3.1.4
mathieucarbou/AsyncTCP @ 3.2.3
[env:arduino-3]
platform = espressif32
platform_packages=
platformio/framework-arduinoespressif32 @ https://github.com/espressif/arduino-esp32.git#3.0.2
platformio/framework-arduinoespressif32-libs @ https://github.com/espressif/arduino-esp32/releases/download/3.0.2/esp32-arduino-libs-3.0.2.zip
platformio/framework-arduinoespressif32 @ https://github.com/espressif/arduino-esp32.git#3.0.3
platformio/framework-arduinoespressif32-libs @ https://github.com/espressif/arduino-esp32/releases/download/3.0.3/esp32-arduino-libs-3.0.3.zip
board = esp32dev
lib_deps =
bblanchon/ArduinoJson @ 7.1.0
mathieucarbou/Async TCP @ ^3.1.4
mathieucarbou/AsyncTCP @ 3.2.3
[env:esp8266]
platform = espressif8266

View File

@ -22,26 +22,29 @@
#include <rom/ets_sys.h>
#endif
#include "AsyncEventSource.h"
#include "literals.h"
using namespace asyncsrv;
static String generateEventMessage(const char* message, const char* event, uint32_t id, uint32_t reconnect) {
String ev;
if (reconnect) {
ev += F("retry: ");
ev += T_retry_;
ev += reconnect;
ev += F("\r\n");
ev += T_rn;
}
if (id) {
ev += F("id: ");
ev += String(id);
ev += F("\r\n");
ev += T_id__;
ev += id;
ev += T_rn;
}
if (event != NULL) {
ev += F("event: ");
ev += String(event);
ev += F("\r\n");
ev += T_event_;
ev += event;
ev += T_rn;
}
if (message != NULL) {
@ -57,9 +60,9 @@ static String generateEventMessage(const char* message, const char* event, uint3
if (ldata != NULL) {
memcpy(ldata, lineStart, llen);
ldata[llen] = 0;
ev += F("data: ");
ev += T_data_;
ev += ldata;
ev += F("\r\n\r\n");
ev += T_rnrn;
free(ldata);
}
lineStart = (char*)message + messageLen;
@ -92,14 +95,14 @@ static String generateEventMessage(const char* message, const char* event, uint3
if (ldata != NULL) {
memcpy(ldata, lineStart, llen);
ldata[llen] = 0;
ev += F("data: ");
ev += T_data_;
ev += ldata;
ev += F("\r\n");
ev += T_rn;
free(ldata);
}
lineStart = nextLine;
if (lineStart == ((char*)message + messageLen))
ev += F("\r\n");
ev += T_rn;
}
} while (lineStart < ((char*)message + messageLen));
}
@ -158,8 +161,8 @@ AsyncEventSourceClient::AsyncEventSourceClient(AsyncWebServerRequest* request, A
_client = request->client();
_server = server;
_lastId = 0;
if (request->hasHeader(F("Last-Event-ID")))
_lastId = atoi(request->getHeader(F("Last-Event-ID"))->value().c_str());
if (request->hasHeader(T_Last_Event_ID))
_lastId = atoi(request->getHeader(T_Last_Event_ID)->value().c_str());
_client->setRxTimeout(0);
_client->onError(NULL, NULL);
@ -360,8 +363,8 @@ bool AsyncEventSource::canHandle(AsyncWebServerRequest* request) {
if (request->method() != HTTP_GET || !request->url().equals(_url)) {
return false;
}
request->addInterestingHeader(F("Last-Event-ID"));
request->addInterestingHeader("Cookie");
request->addInterestingHeader(T_Last_Event_ID);
request->addInterestingHeader(T_Cookie);
return true;
}
@ -382,10 +385,10 @@ void AsyncEventSource::handleRequest(AsyncWebServerRequest* request) {
AsyncEventSourceResponse::AsyncEventSourceResponse(AsyncEventSource* server) {
_server = server;
_code = 200;
_contentType = F("text/event-stream");
_contentType = T_text_event_stream;
_sendContentLength = false;
addHeader(F("Cache-Control"), F("no-cache"));
addHeader(F("Connection"), F("keep-alive"));
addHeader(T_Cache_Control, T_no_cache);
addHeader(T_Connection, T_keep_alive);
}
void AsyncEventSourceResponse::_respond(AsyncWebServerRequest* request) {

View File

@ -38,6 +38,9 @@
#define MAX_PRINTF_LEN 64
using namespace asyncsrv;
size_t webSocketSendFrameWindow(AsyncClient* client) {
if (!client->canSend())
return 0;
@ -613,7 +616,7 @@ size_t AsyncWebSocketClient::printf(const char* format, ...) {
return len;
}
#ifndef ESP32
#ifdef ESP8266
size_t AsyncWebSocketClient::printf_P(PGM_P formatP, ...) {
va_list arg;
va_start(arg, formatP);
@ -680,7 +683,7 @@ void AsyncWebSocketClient::text(const String& message) {
text(message.c_str(), message.length());
}
#ifndef ESP32
#ifdef ESP8266
void AsyncWebSocketClient::text(const __FlashStringHelper* data) {
PGM_P p = reinterpret_cast<PGM_P>(data);
@ -699,7 +702,7 @@ void AsyncWebSocketClient::text(const __FlashStringHelper* data) {
free(message);
}
}
#endif // ESP32
#endif // ESP8266
void AsyncWebSocketClient::binary(AsyncWebSocketMessageBuffer* buffer) {
if (buffer) {
@ -728,7 +731,7 @@ void AsyncWebSocketClient::binary(const String& message) {
binary(message.c_str(), message.length());
}
#ifndef ESP32
#ifdef ESP8266
void AsyncWebSocketClient::binary(const __FlashStringHelper* data, size_t len) {
PGM_P p = reinterpret_cast<PGM_P>(data);
char* message = (char*)malloc(len);
@ -739,6 +742,7 @@ void AsyncWebSocketClient::binary(const __FlashStringHelper* data, size_t len) {
}
}
#endif
IPAddress AsyncWebSocketClient::remoteIP() const {
if (!_client)
return IPAddress((uint32_t)0U);
@ -838,7 +842,8 @@ void AsyncWebSocket::text(uint32_t id, const char* message) {
void AsyncWebSocket::text(uint32_t id, const String& message) {
text(id, message.c_str(), message.length());
}
#ifndef ESP32
#ifdef ESP8266
void AsyncWebSocket::text(uint32_t id, const __FlashStringHelper* data) {
PGM_P p = reinterpret_cast<PGM_P>(data);
@ -857,7 +862,8 @@ void AsyncWebSocket::text(uint32_t id, const __FlashStringHelper* data) {
free(message);
}
}
#endif // ESP32
#endif // ESP8266
void AsyncWebSocket::text(uint32_t id, AsyncWebSocketMessageBuffer* buffer) {
if (buffer) {
text(id, std::move(buffer->_buffer));
@ -881,7 +887,7 @@ void AsyncWebSocket::textAll(const char* message) {
void AsyncWebSocket::textAll(const String& message) {
textAll(message.c_str(), message.length());
}
#ifndef ESP32
#ifdef ESP8266
void AsyncWebSocket::textAll(const __FlashStringHelper* data) {
PGM_P p = reinterpret_cast<PGM_P>(data);
@ -900,7 +906,7 @@ void AsyncWebSocket::textAll(const __FlashStringHelper* data) {
free(message);
}
}
#endif // ESP32
#endif // ESP8266
void AsyncWebSocket::textAll(AsyncWebSocketMessageBuffer* buffer) {
if (buffer) {
textAll(std::move(buffer->_buffer));
@ -927,7 +933,8 @@ void AsyncWebSocket::binary(uint32_t id, const char* message) {
void AsyncWebSocket::binary(uint32_t id, const String& message) {
binary(id, message.c_str(), message.length());
}
#ifndef ESP32
#ifdef ESP8266
void AsyncWebSocket::binary(uint32_t id, const __FlashStringHelper* data, size_t len) {
PGM_P p = reinterpret_cast<PGM_P>(data);
char* message = (char*)malloc(len);
@ -937,7 +944,8 @@ void AsyncWebSocket::binary(uint32_t id, const __FlashStringHelper* data, size_t
free(message);
}
}
#endif // ESP32
#endif // ESP8266
void AsyncWebSocket::binary(uint32_t id, AsyncWebSocketMessageBuffer* buffer) {
if (buffer) {
binary(id, std::move(buffer->_buffer));
@ -961,7 +969,8 @@ void AsyncWebSocket::binaryAll(const char* message) {
void AsyncWebSocket::binaryAll(const String& message) {
binaryAll(message.c_str(), message.length());
}
#ifndef ESP32
#ifdef ESP8266
void AsyncWebSocket::binaryAll(const __FlashStringHelper* data, size_t len) {
PGM_P p = reinterpret_cast<PGM_P>(data);
char* message = (char*)malloc(len);
@ -971,7 +980,8 @@ void AsyncWebSocket::binaryAll(const __FlashStringHelper* data, size_t len) {
free(message);
}
}
#endif // ESP32
#endif // ESP8266
void AsyncWebSocket::binaryAll(AsyncWebSocketMessageBuffer* buffer) {
if (buffer) {
binaryAll(std::move(buffer->_buffer));
@ -1017,7 +1027,7 @@ size_t AsyncWebSocket::printfAll(const char* format, ...) {
return len;
}
#ifndef ESP32
#ifdef ESP8266
size_t AsyncWebSocket::printf_P(uint32_t id, PGM_P formatP, ...) {
AsyncWebSocketClient* c = client(id);
if (c != NULL) {
@ -1108,7 +1118,7 @@ void AsyncWebSocket::handleRequest(AsyncWebServerRequest* request) {
const AsyncWebHeader* version = request->getHeader(WS_STR_VERSION);
if (version->value().toInt() != 13) {
AsyncWebServerResponse* response = request->beginResponse(400);
response->addHeader(WS_STR_VERSION, F("13"));
response->addHeader(WS_STR_VERSION, T_13);
request->send(response);
return;
}
@ -1173,7 +1183,7 @@ AsyncWebSocketResponse::AsyncWebSocketResponse(const String& key, AsyncWebSocket
int len = base64_encode_block((const char*)hash, 20, buffer, &_state);
len = base64_encode_blockend((buffer + len), &_state);
addHeader(WS_STR_CONNECTION, WS_STR_UPGRADE);
addHeader(WS_STR_UPGRADE, F("websocket"));
addHeader(WS_STR_UPGRADE, T_WS);
addHeader(WS_STR_ACCEPT, buffer);
}

View File

@ -306,19 +306,19 @@ class AsyncWebSocket : public AsyncWebHandler {
void text(uint32_t id, const char* message, size_t len);
void text(uint32_t id, const char* message);
void text(uint32_t id, const String& message);
#ifndef ESP32
void text(uint32_t id, const __FlashStringHelper* message);
#endif // ESP32
void text(uint32_t id, AsyncWebSocketMessageBuffer* buffer);
void text(uint32_t id, AsyncWebSocketSharedBuffer buffer);
#ifdef ESP8266
void text(uint32_t id, const __FlashStringHelper* message);
#endif // ESP8266
void textAll(const uint8_t* message, size_t len);
void textAll(const char* message, size_t len);
void textAll(const char* message);
void textAll(const String& message);
#ifndef ESP32
#ifdef ESP8266
void textAll(const __FlashStringHelper* message);
#endif // ESP32
#endif // ESP8266
void textAll(AsyncWebSocketMessageBuffer* buffer);
void textAll(AsyncWebSocketSharedBuffer buffer);
@ -326,9 +326,9 @@ class AsyncWebSocket : public AsyncWebHandler {
void binary(uint32_t id, const char* message, size_t len);
void binary(uint32_t id, const char* message);
void binary(uint32_t id, const String& message);
#ifndef ESP32
#ifdef ESP8266
void binary(uint32_t id, const __FlashStringHelper* message, size_t len);
#endif // ESP32
#endif // ESP8266
void binary(uint32_t id, AsyncWebSocketMessageBuffer* buffer);
void binary(uint32_t id, AsyncWebSocketSharedBuffer buffer);
@ -336,16 +336,16 @@ class AsyncWebSocket : public AsyncWebHandler {
void binaryAll(const char* message, size_t len);
void binaryAll(const char* message);
void binaryAll(const String& message);
#ifndef ESP32
#ifdef ESP8266
void binaryAll(const __FlashStringHelper* message, size_t len);
#endif // ESP32
#endif // ESP8266
void binaryAll(AsyncWebSocketMessageBuffer* buffer);
void binaryAll(AsyncWebSocketSharedBuffer buffer);
size_t printf(uint32_t id, const char* format, ...) __attribute__((format(printf, 3, 4)));
size_t printfAll(const char* format, ...) __attribute__((format(printf, 2, 3)));
#ifndef ESP32
#ifdef ESP8266
size_t printf_P(uint32_t id, PGM_P formatP, ...) __attribute__((format(printf, 3, 4)));
size_t printfAll_P(PGM_P formatP, ...) __attribute__((format(printf, 2, 3)));
#endif

View File

@ -43,10 +43,12 @@
#error Platform not supported
#endif
#define ASYNCWEBSERVER_VERSION "3.0.6"
#include "literals.h"
#define ASYNCWEBSERVER_VERSION "3.1.1"
#define ASYNCWEBSERVER_VERSION_MAJOR 3
#define ASYNCWEBSERVER_VERSION_MINOR 0
#define ASYNCWEBSERVER_VERSION_REVISION 6
#define ASYNCWEBSERVER_VERSION_MINOR 1
#define ASYNCWEBSERVER_VERSION_REVISION 1
#define ASYNCWEBSERVER_FORK_mathieucarbou
#ifdef ASYNCWEBSERVER_REGEX
@ -151,7 +153,7 @@ class AsyncWebHeader {
const String& name() const { return _name; }
const String& value() const { return _value; }
String toString() const { return _name + F(": ") + _value + F("\r\n"); }
String toString() const { return _name + (char)0x3a + (char)0x20 /*": "*/ + _value + asyncsrv::T_rn; }
};
/*
@ -347,7 +349,9 @@ class AsyncWebServerRequest {
size_t params() const; // get arguments count
bool hasParam(const String& name, bool post = false, bool file = false) const;
bool hasParam(const __FlashStringHelper* data, bool post = false, bool file = false) const;
#ifdef ESP8266
bool hasParam(const __FlashStringHelper* data, bool post = false, bool file = false) const { return hasParam(String(data).c_str(), post, file); };
#endif
/**
* @brief Get the Request parameter by name
@ -509,10 +513,13 @@ class AsyncWebServerResponse {
size_t _ackedLength;
size_t _writtenLength;
WebResponseState _state;
const char* _responseCodeToString(int code);
public:
#ifndef ESP8266
static const char* responseCodeToString(int code);
#else
static const __FlashStringHelper* responseCodeToString(int code);
#endif
public:
AsyncWebServerResponse();

View File

@ -1,2 +0,0 @@
// to please Arduino Lint
#include "ESPAsyncWebServer.h"

View File

@ -25,6 +25,9 @@
#else
#include "md5.h"
#endif
#include "literals.h"
using namespace asyncsrv;
// Basic Auth hash = base64("username:password")
@ -133,16 +136,16 @@ String generateDigestHash(const char* username, const char* password, const char
}
String requestDigestAuthentication(const char* realm) {
String header = F("realm=\"");
String header(T_realm__);
if (realm == NULL)
header.concat(F("asyncesp"));
header.concat(T_asyncesp);
else
header.concat(realm);
header.concat(F("\", qop=\"auth\", nonce=\""));
header.concat(T_auth_nonce);
header.concat(genRandomMD5());
header.concat(F("\", opaque=\""));
header.concat(T__opaque);
header.concat(genRandomMD5());
header += '"';
header += (char)0x22; // '"'
return header;
}
@ -173,7 +176,8 @@ bool checkDigestAuthentication(const char* header, const __FlashStringHelper* me
String myNc;
String myCnonce;
myHeader += F(", ");
myHeader += (char)0x2c; // ','
myHeader += (char)0x20; // ' '
do {
String avLine(myHeader.substring(0, nextBreak));
avLine.trim();
@ -191,42 +195,42 @@ bool checkDigestAuthentication(const char* header, const __FlashStringHelper* me
avLine = avLine.substring(1, avLine.length() - 1);
}
if (varName.equals(F("username"))) {
if (varName.equals(T_username)) {
if (!avLine.equals(username)) {
// os_printf("AUTH FAIL: username\n");
return false;
}
myUsername = avLine;
} else if (varName.equals(F("realm"))) {
} else if (varName.equals(T_realm)) {
if (realm != NULL && !avLine.equals(realm)) {
// os_printf("AUTH FAIL: realm\n");
return false;
}
myRealm = avLine;
} else if (varName.equals(F("nonce"))) {
} else if (varName.equals(T_nonce)) {
if (nonce != NULL && !avLine.equals(nonce)) {
// os_printf("AUTH FAIL: nonce\n");
return false;
}
myNonce = avLine;
} else if (varName.equals(F("opaque"))) {
} else if (varName.equals(T_opaque)) {
if (opaque != NULL && !avLine.equals(opaque)) {
// os_printf("AUTH FAIL: opaque\n");
return false;
}
} else if (varName.equals(F("uri"))) {
} else if (varName.equals(T_uri)) {
if (uri != NULL && !avLine.equals(uri)) {
// os_printf("AUTH FAIL: uri\n");
return false;
}
myUri = avLine;
} else if (varName.equals(F("response"))) {
} else if (varName.equals(T_response)) {
myResponse = avLine;
} else if (varName.equals(F("qop"))) {
} else if (varName.equals(T_qop)) {
myQop = avLine;
} else if (varName.equals(F("nc"))) {
} else if (varName.equals(T_nc)) {
myNc = avLine;
} else if (varName.equals(F("cnonce"))) {
} else if (varName.equals(T_cnonce)) {
myCnonce = avLine;
}
} while (nextBreak > 0);

View File

@ -21,6 +21,9 @@
#include "ESPAsyncWebServer.h"
#include "WebHandlerImpl.h"
using namespace asyncsrv;
AsyncStaticWebHandler::AsyncStaticWebHandler(const char* uri, FS& fs, const char* path, const char* cache_control)
: _fs(fs), _uri(uri), _path(path), _default_file(F("index.htm")), _cache_control(cache_control), _last_modified(), _callback(nullptr) {
// Ensure leading '/'
@ -222,22 +225,22 @@ void AsyncStaticWebHandler::handleRequest(AsyncWebServerRequest* request) {
} else {
etag = String(request->_tempFile.size());
}
if (_last_modified.length() && _last_modified == request->header(F("If-Modified-Since"))) {
if (_last_modified.length() && _last_modified == request->header(T_IMS)) {
request->_tempFile.close();
request->send(304); // Not modified
} else if (_cache_control.length() && request->hasHeader(F("If-None-Match")) && request->header(F("If-None-Match")).equals(etag)) {
} else if (_cache_control.length() && request->hasHeader(T_INM) && request->header(T_INM).equals(etag)) {
request->_tempFile.close();
AsyncWebServerResponse* response = new AsyncBasicResponse(304); // Not modified
response->addHeader(F("Cache-Control"), _cache_control);
response->addHeader(F("ETag"), etag);
response->addHeader(T_Cache_Control, _cache_control);
response->addHeader(T_ETag, etag);
request->send(response);
} else {
AsyncWebServerResponse* response = new AsyncFileResponse(request->_tempFile, filename, String(), false, _callback);
if (_last_modified.length())
response->addHeader(F("Last-Modified"), _last_modified);
response->addHeader(T_Last_Modified, _last_modified);
if (_cache_control.length()) {
response->addHeader(F("Cache-Control"), _cache_control);
response->addHeader(F("ETag"), etag);
response->addHeader(T_Cache_Control, _cache_control);
response->addHeader(T_ETag, etag);
}
request->send(response);
}

View File

@ -21,13 +21,13 @@
#include "ESPAsyncWebServer.h"
#include "WebAuthentication.h"
#include "WebResponseImpl.h"
#ifndef ESP8266
#define os_strlen strlen
#endif
#include "literals.h"
#include <cstring>
#define __is_param_char(c) ((c) && ((c) != '{') && ((c) != '[') && ((c) != '&') && ((c) != '='))
using namespace asyncsrv;
enum { PARSE_REQ_START,
PARSE_REQ_HEADERS,
PARSE_REQ_BODY,
@ -113,9 +113,9 @@ void AsyncWebServerRequest::_onData(void* buf, size_t len) {
_parsedLength += len;
} else {
if (_parsedLength == 0) {
if (_contentType.startsWith(F("application/x-www-form-urlencoded"))) {
if (_contentType.startsWith(T_app_xform_urlencoded)) {
_isPlainPost = true;
} else if (_contentType == F("text/plain") && __is_param_char(((char*)buf)[0])) {
} else if (_contentType == T_text_plain && __is_param_char(((char*)buf)[0])) {
size_t i = 0;
while (i < len && __is_param_char(((char*)buf)[i++]))
;
@ -153,7 +153,7 @@ void AsyncWebServerRequest::_onData(void* buf, size_t len) {
}
void AsyncWebServerRequest::_removeNotInterestingHeaders() {
if (std::any_of(std::begin(_interestingHeaders), std::end(_interestingHeaders), [](const String& str) { return str.equalsIgnoreCase(F("ANY")); }))
if (std::any_of(std::begin(_interestingHeaders), std::end(_interestingHeaders), [](const String& str) { return str.equalsIgnoreCase(T_ANY); }))
return; // nothing to do
for (auto iter = std::begin(_headers); iter != std::end(_headers);) {
@ -246,19 +246,19 @@ bool AsyncWebServerRequest::_parseReqHead() {
String u = _temp.substring(m.length() + 1, index);
_temp = _temp.substring(index + 1);
if (m == F("GET")) {
if (m == T_GET) {
_method = HTTP_GET;
} else if (m == F("POST")) {
} else if (m == T_POST) {
_method = HTTP_POST;
} else if (m == F("DELETE")) {
} else if (m == T_DELETE) {
_method = HTTP_DELETE;
} else if (m == F("PUT")) {
} else if (m == T_PUT) {
_method = HTTP_PUT;
} else if (m == F("PATCH")) {
} else if (m == T_PATCH) {
_method = HTTP_PATCH;
} else if (m == F("HEAD")) {
} else if (m == T_HEAD) {
_method = HTTP_HEAD;
} else if (m == F("OPTIONS")) {
} else if (m == T_OPTIONS) {
_method = HTTP_OPTIONS;
}
@ -271,67 +271,51 @@ bool AsyncWebServerRequest::_parseReqHead() {
_url = urlDecode(u);
_addGetParams(g);
if (!_temp.startsWith(F("HTTP/1.0")))
if (!_temp.startsWith(T_HTTP_1_0))
_version = 1;
_temp = String();
return true;
}
bool strContains(const String& src, const String& find, bool mindcase = true) {
int pos = 0, i = 0;
const int slen = src.length();
const int flen = find.length();
if (slen < flen)
return false;
while (pos <= (slen - flen)) {
for (i = 0; i < flen; i++) {
if (mindcase) {
if (src[pos + i] != find[i])
i = flen + 1; // no match
} else if (tolower(src[pos + i]) != tolower(find[i])) {
i = flen + 1; // no match
}
}
if (i == flen)
return true;
pos++;
}
return false;
}
bool AsyncWebServerRequest::_parseReqHeader() {
int index = _temp.indexOf(':');
if (index) {
String name = _temp.substring(0, index);
String value = _temp.substring(index + 2);
if (name.equalsIgnoreCase("Host")) {
String name(_temp.substring(0, index));
String value(_temp.substring(index + 2));
if (name.equalsIgnoreCase(T_Host)) {
_host = value;
} else if (name.equalsIgnoreCase(F("Content-Type"))) {
} else if (name.equalsIgnoreCase(T_Content_Type)) {
_contentType = value.substring(0, value.indexOf(';'));
if (value.startsWith(F("multipart/"))) {
if (value.startsWith(T_MULTIPART_)) {
_boundary = value.substring(value.indexOf('=') + 1);
_boundary.replace(String('"'), String());
_isMultipart = true;
}
} else if (name.equalsIgnoreCase(F("Content-Length"))) {
} else if (name.equalsIgnoreCase(T_Content_Length)) {
_contentLength = atoi(value.c_str());
} else if (name.equalsIgnoreCase(F("Expect")) && value == F("100-continue")) {
} else if (name.equalsIgnoreCase(T_EXPECT) && value == T_100_CONTINUE) {
_expectingContinue = true;
} else if (name.equalsIgnoreCase(F("Authorization"))) {
if (value.length() > 5 && value.substring(0, 5).equalsIgnoreCase(F("Basic"))) {
} else if (name.equalsIgnoreCase(T_AUTH)) {
if (value.length() > 5 && value.substring(0, 5).equalsIgnoreCase(T_BASIC)) {
_authorization = value.substring(6);
} else if (value.length() > 6 && value.substring(0, 6).equalsIgnoreCase(F("Digest"))) {
} else if (value.length() > 6 && value.substring(0, 6).equalsIgnoreCase(T_DIGEST)) {
_isDigest = true;
_authorization = value.substring(7);
}
} else {
if (name.equalsIgnoreCase(F("Upgrade")) && value.equalsIgnoreCase(F("websocket"))) {
if (name.equalsIgnoreCase(T_UPGRADE) && value.equalsIgnoreCase(T_WS)) {
// WebSocket request can be uniquely identified by header: [Upgrade: websocket]
_reqconntype = RCT_WS;
} else {
if (name.equalsIgnoreCase(F("Accept")) && strContains(value, F("text/event-stream"), false)) {
} else if (name.equalsIgnoreCase(T_ACCEPT)){
String lowcase(value);
lowcase.toLowerCase();
#ifndef ESP8266
const char* substr = std::strstr(lowcase.c_str(), T_text_event_stream);
#else
const char* substr = std::strstr(lowcase.c_str(), String(T_text_event_stream).c_str());
#endif
if (substr != NULL) {
// WebEvent request can be uniquely identified by header: [Accept: text/event-stream]
_reqconntype = RCT_EVENT;
}
@ -339,7 +323,12 @@ bool AsyncWebServerRequest::_parseReqHeader() {
}
_headers.emplace_back(name, value);
}
#ifndef TARGET_RP2040
_temp.clear();
#else
// Ancient PRI core does not have String::clear() method 8-()
_temp = String();
#endif
return true;
}
@ -347,14 +336,20 @@ void AsyncWebServerRequest::_parsePlainPostChar(uint8_t data) {
if (data && (char)data != '&')
_temp += (char)data;
if (!data || (char)data == '&' || _parsedLength == _contentLength) {
String name = F("body");
String value = _temp;
if (!_temp.startsWith(String('{')) && !_temp.startsWith(String('[')) && _temp.indexOf('=') > 0) {
String name(T_BODY);
String value(_temp);
if (!(_temp.charAt(0) == '{') && !(_temp.charAt(0) == '[') && _temp.indexOf('=') > 0) {
name = _temp.substring(0, _temp.indexOf('='));
value = _temp.substring(_temp.indexOf('=') + 1);
}
_params.emplace_back(urlDecode(name), urlDecode(value), true);
_temp = String();
#ifndef TARGET_RP2040
_temp.clear();
#else
// Ancient PRI core does not have String::clear() method 8-()
_temp = String();
#endif
}
}
@ -430,17 +425,17 @@ void AsyncWebServerRequest::_parseMultipartPostByte(uint8_t data, bool last) {
_temp += (char)data;
if ((char)data == '\n') {
if (_temp.length()) {
if (_temp.length() > 12 && _temp.substring(0, 12).equalsIgnoreCase(F("Content-Type"))) {
if (_temp.length() > 12 && _temp.substring(0, 12).equalsIgnoreCase(T_Content_Type)) {
_itemType = _temp.substring(14);
_itemIsFile = true;
} else if (_temp.length() > 19 && _temp.substring(0, 19).equalsIgnoreCase(F("Content-Disposition"))) {
} else if (_temp.length() > 19 && _temp.substring(0, 19).equalsIgnoreCase(T_Content_Disposition)) {
_temp = _temp.substring(_temp.indexOf(';') + 2);
while (_temp.indexOf(';') > 0) {
String name = _temp.substring(0, _temp.indexOf('='));
String nameVal = _temp.substring(_temp.indexOf('=') + 2, _temp.indexOf(';') - 1);
if (name == F("name")) {
if (name == T_name) {
_itemName = nameVal;
} else if (name == F("filename")) {
} else if (name == T_filename) {
_itemFilename = nameVal;
_itemIsFile = true;
}
@ -448,9 +443,9 @@ void AsyncWebServerRequest::_parseMultipartPostByte(uint8_t data, bool last) {
}
String name = _temp.substring(0, _temp.indexOf('='));
String nameVal = _temp.substring(_temp.indexOf('=') + 2, _temp.length() - 1);
if (name == F("name")) {
if (name == T_name) {
_itemName = nameVal;
} else if (name == F("filename")) {
} else if (name == T_filename) {
_itemFilename = nameVal;
_itemIsFile = true;
}
@ -590,7 +585,7 @@ void AsyncWebServerRequest::_parseLine() {
_server->_attachHandler(this);
_removeNotInterestingHeaders();
if (_expectingContinue) {
String response = F("HTTP/1.1 100 Continue\r\n\r\n");
String response(T_HTTP_100_CONT);
_client->write(response.c_str(), response.length());
}
// check handler for authentication
@ -668,10 +663,6 @@ bool AsyncWebServerRequest::hasParam(const String& name, bool post, bool file) c
return false;
}
bool AsyncWebServerRequest::hasParam(const __FlashStringHelper* data, bool post, bool file) const {
return hasParam(String(data).c_str(), post, file);
}
const AsyncWebParameter* AsyncWebServerRequest::getParam(const char* name, bool post, bool file) const {
for (const auto& p : _params) {
if (p.name() == name && p.isPost() == post && p.isFile() == file) {
@ -711,7 +702,7 @@ AsyncWebServerResponse* AsyncWebServerRequest::beginResponse(int code, const Str
}
AsyncWebServerResponse* AsyncWebServerRequest::beginResponse(FS& fs, const String& path, const String& contentType, bool download, AwsTemplateProcessor callback) {
if (fs.exists(path) || (!download && fs.exists(path + F(".gz"))))
if (fs.exists(path) || (!download && fs.exists(path + T__gz)))
return new AsyncFileResponse(fs, path, contentType, download, callback);
return NULL;
}
@ -770,7 +761,7 @@ void AsyncWebServerRequest::send(int code, const String& contentType, PGM_P cont
}
void AsyncWebServerRequest::send(FS& fs, const String& path, const String& contentType, bool download, AwsTemplateProcessor callback) {
if (fs.exists(path) || (!download && fs.exists(path + F(".gz")))) {
if (fs.exists(path) || (!download && fs.exists(path + T__gz))) {
send(beginResponse(fs, path, contentType, download, callback));
} else
send(404);
@ -797,7 +788,7 @@ void AsyncWebServerRequest::sendChunked(const String& contentType, AwsResponseFi
void AsyncWebServerRequest::redirect(const char* url) {
AsyncWebServerResponse* response = beginResponse(302);
response->addHeader(F("Location"), url);
response->addHeader(T_LOCATION, url);
send(response);
}
@ -838,16 +829,16 @@ bool AsyncWebServerRequest::authenticate(const char* hash) {
void AsyncWebServerRequest::requestAuthentication(const char* realm, bool isDigest) {
AsyncWebServerResponse* r = beginResponse(401);
if (!isDigest && realm == NULL) {
r->addHeader(F("WWW-Authenticate"), F("Basic realm=\"Login Required\""));
r->addHeader(T_WWW_AUTH, T_BASIC_REALM_LOGIN_REQ);
} else if (!isDigest) {
String header = F("Basic realm=\"");
String header(T_BASIC_REALM);
header.concat(realm);
header += '"';
r->addHeader(F("WWW-Authenticate"), header);
r->addHeader(T_WWW_AUTH, header);
} else {
String header = F("Digest ");
String header(T_DIGEST_);
header.concat(requestDigestAuthentication(realm));
r->addHeader(F("WWW-Authenticate"), header);
r->addHeader(T_WWW_AUTH, header);
}
send(r);
}
@ -941,80 +932,80 @@ String AsyncWebServerRequest::urlDecode(const String& text) const {
#ifndef ESP8266
const char* AsyncWebServerRequest::methodToString() const {
if (_method == HTTP_ANY)
return "ANY";
return T_ANY;
if (_method & HTTP_GET)
return "GET";
return T_GET;
if (_method & HTTP_POST)
return "POST";
return T_POST;
if (_method & HTTP_DELETE)
return "DELETE";
return T_DELETE;
if (_method & HTTP_PUT)
return "PUT";
return T_PUT;
if (_method & HTTP_PATCH)
return "PATCH";
return T_PATCH;
if (_method & HTTP_HEAD)
return "HEAD";
return T_HEAD;
if (_method & HTTP_OPTIONS)
return "OPTIONS";
return "UNKNOWN";
return T_OPTIONS;
return T_UNKNOWN;
}
#else // ESP8266
const __FlashStringHelper* AsyncWebServerRequest::methodToString() const {
if (_method == HTTP_ANY)
return FPSTR(T_ANY);
if (_method & HTTP_GET)
return FPSTR(T_GET);
if (_method & HTTP_POST)
return FPSTR(T_POST);
if (_method & HTTP_DELETE)
return FPSTR(T_DELETE);
if (_method & HTTP_PUT)
return FPSTR(T_PUT);
if (_method & HTTP_PATCH)
return FPSTR(T_PATCH);
if (_method & HTTP_HEAD)
return FPSTR(T_HEAD);
if (_method & HTTP_OPTIONS)
return FPSTR(T_OPTIONS);
return FPSTR(T_UNKNOWN);
}
#endif // ESP8266
#ifndef ESP8266
const char* AsyncWebServerRequest::requestedConnTypeToString() const {
switch (_reqconntype) {
case RCT_NOT_USED:
return "RCT_NOT_USED";
return T_RCT_NOT_USED;
case RCT_DEFAULT:
return "RCT_DEFAULT";
return T_RCT_DEFAULT;
case RCT_HTTP:
return "RCT_HTTP";
return T_RCT_HTTP;
case RCT_WS:
return "RCT_WS";
return T_RCT_WS;
case RCT_EVENT:
return "RCT_EVENT";
return T_RCT_EVENT;
default:
return "ERROR";
return T_ERROR;
}
}
#endif
#ifdef ESP8266
const __FlashStringHelper* AsyncWebServerRequest::methodToString() const {
if (_method == HTTP_ANY)
return F("ANY");
else if (_method & HTTP_GET)
return F("GET");
else if (_method & HTTP_POST)
return F("POST");
else if (_method & HTTP_DELETE)
return F("DELETE");
else if (_method & HTTP_PUT)
return F("PUT");
else if (_method & HTTP_PATCH)
return F("PATCH");
else if (_method & HTTP_HEAD)
return F("HEAD");
else if (_method & HTTP_OPTIONS)
return F("OPTIONS");
return F("UNKNOWN");
}
#else // ESP8266
const __FlashStringHelper* AsyncWebServerRequest::requestedConnTypeToString() const {
switch (_reqconntype) {
case RCT_NOT_USED:
return F("RCT_NOT_USED");
return FPSTR(T_RCT_NOT_USED);
case RCT_DEFAULT:
return F("RCT_DEFAULT");
return FPSTR(T_RCT_DEFAULT);
case RCT_HTTP:
return F("RCT_HTTP");
return FPSTR(T_RCT_HTTP);
case RCT_WS:
return F("RCT_WS");
return FPSTR(T_RCT_WS);
case RCT_EVENT:
return F("RCT_EVENT");
return FPSTR(T_RCT_EVENT);
default:
return F("ERROR");
return FPSTR(T_ERROR);
}
}
#endif
#endif // ESP8266
bool AsyncWebServerRequest::isExpectedRequestedConnType(RequestedConnectionType erct1, RequestedConnectionType erct2, RequestedConnectionType erct3) {
bool res = false;

View File

@ -22,6 +22,8 @@
#include "WebResponseImpl.h"
#include "cbuf.h"
using namespace asyncsrv;
// Since ESP8266 does not link memchr by default, here's its implementation.
void* memchr(void* ptr, int ch, size_t count) {
unsigned char* p = static_cast<unsigned char*>(ptr);
@ -33,97 +35,185 @@ void* memchr(void* ptr, int ch, size_t count) {
/*
* Abstract Response
* */
const char* AsyncWebServerResponse::_responseCodeToString(int code) {
return reinterpret_cast<const char*>(responseCodeToString(code));
}
*
*/
const __FlashStringHelper* AsyncWebServerResponse::responseCodeToString(int code) {
#ifndef ESP8266
const char* AsyncWebServerResponse::responseCodeToString(int code) {
switch (code) {
case 100:
return F("Continue");
return T_HTTP_CODE_100;
case 101:
return F("Switching Protocols");
return T_HTTP_CODE_101;
case 200:
return F("OK");
return T_HTTP_CODE_200;
case 201:
return F("Created");
return T_HTTP_CODE_201;
case 202:
return F("Accepted");
return T_HTTP_CODE_202;
case 203:
return F("Non-Authoritative Information");
return T_HTTP_CODE_203;
case 204:
return F("No Content");
return T_HTTP_CODE_204;
case 205:
return F("Reset Content");
return T_HTTP_CODE_205;
case 206:
return F("Partial Content");
return T_HTTP_CODE_206;
case 300:
return F("Multiple Choices");
return T_HTTP_CODE_300;
case 301:
return F("Moved Permanently");
return T_HTTP_CODE_301;
case 302:
return F("Found");
return T_HTTP_CODE_302;
case 303:
return F("See Other");
return T_HTTP_CODE_303;
case 304:
return F("Not Modified");
return T_HTTP_CODE_304;
case 305:
return F("Use Proxy");
return T_HTTP_CODE_305;
case 307:
return F("Temporary Redirect");
return T_HTTP_CODE_307;
case 400:
return F("Bad Request");
return T_HTTP_CODE_400;
case 401:
return F("Unauthorized");
return T_HTTP_CODE_401;
case 402:
return F("Payment Required");
return T_HTTP_CODE_402;
case 403:
return F("Forbidden");
return T_HTTP_CODE_403;
case 404:
return F("Not Found");
return T_HTTP_CODE_404;
case 405:
return F("Method Not Allowed");
return T_HTTP_CODE_405;
case 406:
return F("Not Acceptable");
return T_HTTP_CODE_406;
case 407:
return F("Proxy Authentication Required");
return T_HTTP_CODE_407;
case 408:
return F("Request Time-out");
return T_HTTP_CODE_408;
case 409:
return F("Conflict");
return T_HTTP_CODE_409;
case 410:
return F("Gone");
return T_HTTP_CODE_410;
case 411:
return F("Length Required");
return T_HTTP_CODE_411;
case 412:
return F("Precondition Failed");
return T_HTTP_CODE_412;
case 413:
return F("Request Entity Too Large");
return T_HTTP_CODE_413;
case 414:
return F("Request-URI Too Large");
return T_HTTP_CODE_414;
case 415:
return F("Unsupported Media Type");
return T_HTTP_CODE_415;
case 416:
return F("Requested range not satisfiable");
return T_HTTP_CODE_416;
case 417:
return F("Expectation Failed");
return T_HTTP_CODE_417;
case 500:
return F("Internal Server Error");
return T_HTTP_CODE_500;
case 501:
return F("Not Implemented");
return T_HTTP_CODE_501;
case 502:
return F("Bad Gateway");
return T_HTTP_CODE_502;
case 503:
return F("Service Unavailable");
return T_HTTP_CODE_503;
case 504:
return F("Gateway Time-out");
return T_HTTP_CODE_504;
case 505:
return F("HTTP Version not supported");
return T_HTTP_CODE_505;
default:
return F("");
return T_HTTP_CODE_ANY;
}
}
#else // ESP8266
const __FlashStringHelper* AsyncWebServerResponse::responseCodeToString(int code)
{
switch (code) {
case 100:
return FPSTR(T_HTTP_CODE_100);
case 101:
return FPSTR(T_HTTP_CODE_101);
case 200:
return FPSTR(T_HTTP_CODE_200);
case 201:
return FPSTR(T_HTTP_CODE_201);
case 202:
return FPSTR(T_HTTP_CODE_202);
case 203:
return FPSTR(T_HTTP_CODE_203);
case 204:
return FPSTR(T_HTTP_CODE_204);
case 205:
return FPSTR(T_HTTP_CODE_205);
case 206:
return FPSTR(T_HTTP_CODE_206);
case 300:
return FPSTR(T_HTTP_CODE_300);
case 301:
return FPSTR(T_HTTP_CODE_301);
case 302:
return FPSTR(T_HTTP_CODE_302);
case 303:
return FPSTR(T_HTTP_CODE_303);
case 304:
return FPSTR(T_HTTP_CODE_304);
case 305:
return FPSTR(T_HTTP_CODE_305);
case 307:
return FPSTR(T_HTTP_CODE_307);
case 400:
return FPSTR(T_HTTP_CODE_400);
case 401:
return FPSTR(T_HTTP_CODE_401);
case 402:
return FPSTR(T_HTTP_CODE_402);
case 403:
return FPSTR(T_HTTP_CODE_403);
case 404:
return FPSTR(T_HTTP_CODE_404);
case 405:
return FPSTR(T_HTTP_CODE_405);
case 406:
return FPSTR(T_HTTP_CODE_406);
case 407:
return FPSTR(T_HTTP_CODE_407);
case 408:
return FPSTR(T_HTTP_CODE_408);
case 409:
return FPSTR(T_HTTP_CODE_409);
case 410:
return FPSTR(T_HTTP_CODE_410);
case 411:
return FPSTR(T_HTTP_CODE_411);
case 412:
return FPSTR(T_HTTP_CODE_412);
case 413:
return FPSTR(T_HTTP_CODE_413);
case 414:
return FPSTR(T_HTTP_CODE_414);
case 415:
return FPSTR(T_HTTP_CODE_415);
case 416:
return FPSTR(T_HTTP_CODE_416);
case 417:
return FPSTR(T_HTTP_CODE_417);
case 500:
return FPSTR(T_HTTP_CODE_500);
case 501:
return FPSTR(T_HTTP_CODE_501);
case 502:
return FPSTR(T_HTTP_CODE_502);
case 503:
return FPSTR(T_HTTP_CODE_503);
case 504:
return FPSTR(T_HTTP_CODE_504);
case 505:
return FPSTR(T_HTTP_CODE_505);
default:
return FPSTR(T_HTTP_CODE_ANY);
}
}
#endif // ESP8266
AsyncWebServerResponse::AsyncWebServerResponse()
: _code(0), _contentType(), _contentLength(0), _sendContentLength(true), _chunked(false), _headLength(0), _sentLength(0), _ackedLength(0), _writtenLength(0), _state(RESPONSE_SETUP) {
@ -155,15 +245,19 @@ void AsyncWebServerResponse::addHeader(const String& name, const String& value)
String AsyncWebServerResponse::_assembleHead(uint8_t version) {
if (version) {
addHeader(F("Accept-Ranges"), F("none"));
addHeader(T_Accept_Ranges, T_none);
if (_chunked)
addHeader(F("Transfer-Encoding"), F("chunked"));
addHeader(Transfer_Encoding, T_chunked);
}
String out = String();
String out;
int bufSize = 300;
char buf[bufSize];
snprintf_P(buf, bufSize, PSTR("HTTP/1.%d %d %s\r\n"), version, _code, _responseCodeToString(_code));
#ifndef ESP8266
snprintf(buf, bufSize, "HTTP/1.%d %d %s\r\n", version, _code, responseCodeToString(_code));
#else
snprintf_P(buf, bufSize, PSTR("HTTP/1.%d %d %s\r\n"), version, _code, String(responseCodeToString(_code)).c_str());
#endif
out.concat(buf);
if (_sendContentLength) {
@ -181,7 +275,7 @@ String AsyncWebServerResponse::_assembleHead(uint8_t version) {
}
_headers.clear();
out.concat(F("\r\n"));
out.concat(T_rn);
_headLength = out.length();
return out;
}
@ -211,9 +305,9 @@ AsyncBasicResponse::AsyncBasicResponse(int code, const String& contentType, cons
if (_content.length()) {
_contentLength = _content.length();
if (!_contentType.length())
_contentType = F("text/plain");
_contentType = T_text_plain;
}
addHeader(F("Connection"), F("close"));
addHeader(T_Connection, T_close);
}
void AsyncBasicResponse::_respond(AsyncWebServerRequest* request) {
@ -291,7 +385,7 @@ AsyncAbstractResponse::AsyncAbstractResponse(AwsTemplateProcessor callback) : _c
}
void AsyncAbstractResponse::_respond(AsyncWebServerRequest* request) {
addHeader(F("Connection"), F("close"));
addHeader(T_Connection, T_close);
_head = _assembleHead(request->version());
_state = RESPONSE_HEADERS;
_ack(request, 0, 0);
@ -514,48 +608,52 @@ AsyncFileResponse::~AsyncFileResponse() {
}
void AsyncFileResponse::_setContentType(const String& path) {
#if HAVE_EXTERN_GET_CONTENT_TYPE_FUNCTION
extern const __FlashStringHelper* getContentType(const String& path);
#if HAVE_EXTERN_GET_Content_Type_FUNCTION
#ifndef ESP8266
extern const char* getContentType(const String& path);
#else
extern const __FlashStringHelper* getContentType(const String& path);
#endif
_contentType = getContentType(path);
#else
if (path.endsWith(F(".html")))
_contentType = F("text/html");
else if (path.endsWith(F(".htm")))
_contentType = F("text/html");
else if (path.endsWith(F(".css")))
_contentType = F("text/css");
else if (path.endsWith(F(".json")))
_contentType = F("application/json");
else if (path.endsWith(F(".js")))
_contentType = F("application/javascript");
else if (path.endsWith(F(".png")))
_contentType = F("image/png");
else if (path.endsWith(F(".gif")))
_contentType = F("image/gif");
else if (path.endsWith(F(".jpg")))
_contentType = F("image/jpeg");
else if (path.endsWith(F(".ico")))
_contentType = F("image/x-icon");
else if (path.endsWith(F(".svg")))
_contentType = F("image/svg+xml");
else if (path.endsWith(F(".eot")))
_contentType = F("font/eot");
else if (path.endsWith(F(".woff")))
_contentType = F("font/woff");
else if (path.endsWith(F(".woff2")))
_contentType = F("font/woff2");
else if (path.endsWith(F(".ttf")))
_contentType = F("font/ttf");
else if (path.endsWith(F(".xml")))
_contentType = F("text/xml");
else if (path.endsWith(F(".pdf")))
_contentType = F("application/pdf");
else if (path.endsWith(F(".zip")))
_contentType = F("application/zip");
else if (path.endsWith(F(".gz")))
_contentType = F("application/x-gzip");
if (path.endsWith(T__html))
_contentType = T_text_html;
else if (path.endsWith(T__htm))
_contentType = T_text_html;
else if (path.endsWith(T__css))
_contentType = T_text_css;
else if (path.endsWith(T__json))
_contentType = T_application_json;
else if (path.endsWith(T__js))
_contentType = T_application_javascript;
else if (path.endsWith(T__png))
_contentType = T_image_png;
else if (path.endsWith(T__gif))
_contentType = T_image_gif;
else if (path.endsWith(T__jpg))
_contentType = T_image_jpeg;
else if (path.endsWith(T__ico))
_contentType = T_image_x_icon;
else if (path.endsWith(T__svg))
_contentType = T_image_svg_xml;
else if (path.endsWith(T__eot))
_contentType = T_font_eot;
else if (path.endsWith(T__woff))
_contentType = T_font_woff;
else if (path.endsWith(T__woff2))
_contentType = T_font_woff2;
else if (path.endsWith(T__ttf))
_contentType = T_font_ttf;
else if (path.endsWith(T__xml))
_contentType = T_text_xml;
else if (path.endsWith(T__pdf))
_contentType = T_application_pdf;
else if (path.endsWith(T__zip))
_contentType = T_application_zip;
else if (path.endsWith(T__gz))
_contentType = T_application_x_gzip;
else
_contentType = F("text/plain");
_contentType = T_text_plain;
#endif
}
@ -563,9 +661,9 @@ AsyncFileResponse::AsyncFileResponse(FS& fs, const String& path, const String& c
_code = 200;
_path = path;
if (!download && !fs.exists(_path) && fs.exists(_path + F(".gz"))) {
_path = _path + F(".gz");
addHeader(F("Content-Encoding"), F("gzip"));
if (!download && !fs.exists(_path) && fs.exists(_path + T__gz)) {
_path = _path + T__gz;
addHeader(T_Content_Encoding, T_gzip);
_callback = nullptr; // Unable to process zipped templates
_sendContentLength = true;
_chunked = false;
@ -590,15 +688,15 @@ AsyncFileResponse::AsyncFileResponse(FS& fs, const String& path, const String& c
// set filename and force rendering
snprintf_P(buf, sizeof(buf), PSTR("inline"));
}
addHeader(F("Content-Disposition"), buf);
addHeader(T_Content_Disposition, buf);
}
AsyncFileResponse::AsyncFileResponse(File content, const String& path, const String& contentType, bool download, AwsTemplateProcessor callback) : AsyncAbstractResponse(callback) {
_code = 200;
_path = path;
if (!download && String(content.name()).endsWith(F(".gz")) && !path.endsWith(F(".gz"))) {
addHeader(F("Content-Encoding"), F("gzip"));
if (!download && String(content.name()).endsWith(T__gz) && !path.endsWith(T__gz)) {
addHeader(T_Content_Encoding, T_gzip);
_callback = nullptr; // Unable to process gzipped templates
_sendContentLength = true;
_chunked = false;
@ -621,7 +719,7 @@ AsyncFileResponse::AsyncFileResponse(File content, const String& path, const Str
} else {
snprintf_P(buf, sizeof(buf), PSTR("inline"));
}
addHeader(F("Content-Disposition"), buf);
addHeader(T_Content_Disposition, buf);
}
size_t AsyncFileResponse::_fillBuffer(uint8_t* data, size_t len) {

View File

@ -21,6 +21,8 @@
#include "ESPAsyncWebServer.h"
#include "WebHandlerImpl.h"
using namespace asyncsrv;
bool ON_STA_FILTER(AsyncWebServerRequest* request) {
return WiFi.localIP() == request->client()->localIP();
}
@ -145,7 +147,7 @@ void AsyncWebServer::_attachHandler(AsyncWebServerRequest* request) {
}
}
request->addInterestingHeader(F("ANY"));
request->addInterestingHeader(T_ANY);
request->setHandler(_catchAllHandler);
}

341
src/literals.h Normal file
View File

@ -0,0 +1,341 @@
#pragma once
namespace asyncsrv {
#ifndef ESP8622
static constexpr const char* T_100_CONTINUE = "100-continue";
static constexpr const char* T_ACCEPT = "Accept";
static constexpr const char* T_Accept_Ranges = "Accept-Ranges";
static constexpr const char* T_app_xform_urlencoded = "application/x-www-form-urlencoded";
static constexpr const char* T_AUTH = "Authorization";
static constexpr const char* T_BASIC = "Basic";
static constexpr const char* T_BASIC_REALM = "Basic realm=\"";
static constexpr const char* T_BASIC_REALM_LOGIN_REQ = "Basic realm=\"Login Required\"";
static constexpr const char* T_BODY = "body";
static constexpr const char* T_Cache_Control = "Cache-Control";
static constexpr const char* T_chunked = "chunked";
static constexpr const char* T_close = "close";
static constexpr const char* T_Connection = "Connection";
static constexpr const char* T_Content_Disposition = "Content-Disposition";
static constexpr const char* T_Content_Encoding = "Content-Encoding";
static constexpr const char* T_Content_Length = "Content-Length";
static constexpr const char* T_Content_Type = "Content-Type";
static constexpr const char* T_Cookie = "Cookie";
static constexpr const char* T_DIGEST = "Digest";
static constexpr const char* T_DIGEST_ = "Digest ";
static constexpr const char* T_ETag = "ETag";
static constexpr const char* T_EXPECT = "Expect";
static constexpr const char* T_HTTP_1_0 = "HTTP/1.0";
static constexpr const char* T_HTTP_100_CONT = "HTTP/1.1 100 Continue\r\n\r\n";
static constexpr const char* T_IMS = "If-Modified-Since";
static constexpr const char* T_INM = "If-None-Match";
static constexpr const char* T_keep_alive = "keep-alive";
static constexpr const char* T_Last_Event_ID = "Last-Event-ID";
static constexpr const char* T_Last_Modified = "Last-Modified";
static constexpr const char* T_LOCATION = "Location";
static constexpr const char* T_MULTIPART_ = "multipart/";
static constexpr const char* T_no_cache = "no-cache";
static constexpr const char* T_none = "none";
static constexpr const char* T_UPGRADE = "Upgrade";
static constexpr const char* T_WS = "websocket";
static constexpr const char* T_WWW_AUTH = "WWW-Authenticate";
static constexpr const char* Transfer_Encoding = "Transfer-Encoding";
// HTTP Methods
static constexpr const char* T_ANY = "ANY";
static constexpr const char* T_GET = "GET";
static constexpr const char* T_POST = "POST";
static constexpr const char* T_PUT = "PUT";
static constexpr const char* T_DELETE = "DELETE";
static constexpr const char* T_PATCH = "PATCH";
static constexpr const char* T_HEAD = "HEAD";
static constexpr const char* T_OPTIONS = "OPTIONS";
static constexpr const char* T_UNKNOWN = "UNKNOWN";
// Req content types
static constexpr const char* T_RCT_NOT_USED = "RCT_NOT_USED";
static constexpr const char* T_RCT_DEFAULT = "RCT_DEFAULT";
static constexpr const char* T_RCT_HTTP = "RCT_HTTP";
static constexpr const char* T_RCT_WS = "RCT_WS";
static constexpr const char* T_RCT_EVENT = "RCT_EVENT";
static constexpr const char* T_ERROR = "ERROR";
// extentions & MIME-Types
static constexpr const char* T__css = ".css";
static constexpr const char* T__eot = ".eot";
static constexpr const char* T__gif = ".gif";
static constexpr const char* T__gz = ".gz";
static constexpr const char* T__htm = ".htm";
static constexpr const char* T__html = ".html";
static constexpr const char* T__ico = ".ico";
static constexpr const char* T__jpg = ".jpg";
static constexpr const char* T__js = ".js";
static constexpr const char* T__json = ".json";
static constexpr const char* T__pdf = ".pdf";
static constexpr const char* T__png = ".png";
static constexpr const char* T__svg = ".svg";
static constexpr const char* T__ttf = ".ttf";
static constexpr const char* T__woff = ".woff";
static constexpr const char* T__woff2 = ".woff2";
static constexpr const char* T__xml = ".xml";
static constexpr const char* T__zip = ".zip";
static constexpr const char* T_application_javascript = "application/javascript";
static constexpr const char* T_application_json = "application/json";
static constexpr const char* T_application_pdf = "application/pdf";
static constexpr const char* T_application_x_gzip = "application/x-gzip";
static constexpr const char* T_application_zip = "application/zip";
static constexpr const char* T_font_eot = "font/eot";
static constexpr const char* T_font_ttf = "font/ttf";
static constexpr const char* T_font_woff = "font/woff";
static constexpr const char* T_font_woff2 = "font/woff2";
static constexpr const char* T_image_gif = "image/gif";
static constexpr const char* T_image_jpeg = "image/jpeg";
static constexpr const char* T_image_png = "image/png";
static constexpr const char* T_image_svg_xml = "image/svg+xml";
static constexpr const char* T_image_x_icon = "image/x-icon";
static constexpr const char* T_text_css = "text/css";
static constexpr const char* T_text_event_stream = "text/event-stream";
static constexpr const char* T_text_html = "text/html";
static constexpr const char* T_text_plain = "text/plain";
static constexpr const char* T_text_xml = "text/xml";
// Responce codes
static constexpr const char* T_HTTP_CODE_100 = "Continue";
static constexpr const char* T_HTTP_CODE_101 = "Switching Protocols";
static constexpr const char* T_HTTP_CODE_200 = "OK";
static constexpr const char* T_HTTP_CODE_201 = "Created";
static constexpr const char* T_HTTP_CODE_202 = "Accepted";
static constexpr const char* T_HTTP_CODE_203 = "Non-Authoritative Information";
static constexpr const char* T_HTTP_CODE_204 = "No Content";
static constexpr const char* T_HTTP_CODE_205 = "Reset Content";
static constexpr const char* T_HTTP_CODE_206 = "Partial Content";
static constexpr const char* T_HTTP_CODE_300 = "Multiple Choices";
static constexpr const char* T_HTTP_CODE_301 = "Moved Permanently";
static constexpr const char* T_HTTP_CODE_302 = "Found";
static constexpr const char* T_HTTP_CODE_303 = "See Other";
static constexpr const char* T_HTTP_CODE_304 = "Not Modified";
static constexpr const char* T_HTTP_CODE_305 = "Use Proxy";
static constexpr const char* T_HTTP_CODE_307 = "Temporary Redirect";
static constexpr const char* T_HTTP_CODE_400 = "Bad Request";
static constexpr const char* T_HTTP_CODE_401 = "Unauthorized";
static constexpr const char* T_HTTP_CODE_402 = "Payment Required";
static constexpr const char* T_HTTP_CODE_403 = "Forbidden";
static constexpr const char* T_HTTP_CODE_404 = "Not Found";
static constexpr const char* T_HTTP_CODE_405 = "Method Not Allowed";
static constexpr const char* T_HTTP_CODE_406 = "Not Acceptable";
static constexpr const char* T_HTTP_CODE_407 = "Proxy Authentication Required";
static constexpr const char* T_HTTP_CODE_408 = "Request Time-out";
static constexpr const char* T_HTTP_CODE_409 = "Conflict";
static constexpr const char* T_HTTP_CODE_410 = "Gone";
static constexpr const char* T_HTTP_CODE_411 = "Length Required";
static constexpr const char* T_HTTP_CODE_412 = "Precondition Failed";
static constexpr const char* T_HTTP_CODE_413 = "Request Entity Too Large";
static constexpr const char* T_HTTP_CODE_414 = "Request-URI Too Large";
static constexpr const char* T_HTTP_CODE_415 = "Unsupported Media Type";
static constexpr const char* T_HTTP_CODE_416 = "Requested range not satisfiable";
static constexpr const char* T_HTTP_CODE_417 = "Expectation Failed";
static constexpr const char* T_HTTP_CODE_500 = "Internal Server Error";
static constexpr const char* T_HTTP_CODE_501 = "Not Implemented";
static constexpr const char* T_HTTP_CODE_502 = "Bad Gateway";
static constexpr const char* T_HTTP_CODE_503 = "Service Unavailable";
static constexpr const char* T_HTTP_CODE_504 = "Gateway Time-out";
static constexpr const char* T_HTTP_CODE_505 = "HTTP Version not supported";
static constexpr const char* T_HTTP_CODE_ANY = "Unknown code";
// other
static constexpr const char* T__opaque = "\", opaque=\"";
static constexpr const char* T_13 = "13";
static constexpr const char* T_asyncesp = "asyncesp";
static constexpr const char* T_auth_nonce = "\", qop=\"auth\", nonce=\"";
static constexpr const char* T_cnonce = "cnonce";
static constexpr const char* T_data_ = "data: ";
static constexpr const char* T_event_ = "event: ";
static constexpr const char* T_filename = "filename";
static constexpr const char* T_gzip = "gzip";
static constexpr const char* T_Host = "Host";
static constexpr const char* T_id__ = "id: ";
static constexpr const char* T_name = "name";
static constexpr const char* T_nc = "nc";
static constexpr const char* T_nonce = "nonce";
static constexpr const char* T_opaque = "opaque";
static constexpr const char* T_qop = "qop";
static constexpr const char* T_realm = "realm";
static constexpr const char* T_realm__ = "realm=\"";
static constexpr const char* T_response = "response";
static constexpr const char* T_retry_ = "retry: ";
static constexpr const char* T_rn = "\r\n";
static constexpr const char* T_rnrn = "\r\n\r\n";
static constexpr const char* T_uri = "uri";
static constexpr const char* T_username = "username";
#else // ESP8622
static const char T_100_CONTINUE[] PROGMEM = "100-continue";
static const char T_ACCEPT[] PROGMEM = "Accept";
static const char T_Accept_Ranges[] PROGMEM = "Accept-Ranges";
static const char T_app_xform_urlencoded[] PROGMEM = "application/x-www-form-urlencoded";
static const char T_AUTH[] PROGMEM = "Authorization";
static const char T_BASIC[] PROGMEM = "Basic";
static const char T_BASIC_REALM[] PROGMEM = "Basic realm=\"";
static const char T_BASIC_REALM_LOGIN_REQ[] PROGMEM = "Basic realm=\"Login Required\"";
static const char T_BODY[] PROGMEM = "body";
static const char T_Cache_Control[] PROGMEM = "Cache-Control";
static const char T_chunked[] PROGMEM = "chunked";
static const char T_close[] PROGMEM = "close";
static const char T_Connection[] PROGMEM = "Connection";
static const char T_Content_Disposition[] PROGMEM = "Content-Disposition";
static const char T_Content_Encoding[] PROGMEM = "Content-Encoding";
static const char T_Content_Length[] PROGMEM = "Content-Length";
static const char T_Content_Type[] PROGMEM = "Content-Type";
static const char T_Cookie[] PROGMEM = "Cookie";
static const char T_DIGEST[] PROGMEM = "Digest";
static const char T_DIGEST_[] PROGMEM = "Digest ";
static const char T_ETag[] PROGMEM = "ETag";
static const char T_EXPECT[] PROGMEM = "Expect";
static const char T_HTTP_1_0[] PROGMEM = "HTTP/1.0";
static const char T_HTTP_100_CONT[] PROGMEM = "HTTP/1.1 100 Continue\r\n\r\n";
static const char T_IMS[] PROGMEM = "If-Modified-Since";
static const char T_INM[] PROGMEM = "If-None-Match";
static const char T_keep_alive[] PROGMEM = "keep-alive";
static const char T_Last_Event_ID[] PROGMEM = "Last-Event-ID";
static const char T_Last_Modified[] PROGMEM = "Last-Modified";
static const char T_LOCATION[] PROGMEM = "Location";
static const char T_MULTIPART_[] PROGMEM = "multipart/";
static const char T_no_cache[] PROGMEM = "no-cache";
static const char T_none[] PROGMEM = "none";
static const char T_UPGRADE[] PROGMEM = "Upgrade";
static const char T_WS[] PROGMEM = "websocket";
static const char T_WWW_AUTH[] PROGMEM = "WWW-Authenticate";
static const char Transfer_Encoding[] PROGMEM = "Transfer-Encoding";
// HTTP Methods
static const char T_ANY[] PROGMEM = "ANY";
static const char T_GET[] PROGMEM = "GET";
static const char T_POST[] PROGMEM = "POST";
static const char T_PUT[] PROGMEM = "PUT";
static const char T_DELETE[] PROGMEM = "DELETE";
static const char T_PATCH[] PROGMEM = "PATCH";
static const char T_HEAD[] PROGMEM = "HEAD";
static const char T_OPTIONS[] PROGMEM = "OPTIONS";
static const char T_UNKNOWN[] PROGMEM = "UNKNOWN";
// Req content types
static const char T_RCT_NOT_USED[] PROGMEM = "RCT_NOT_USED";
static const char T_RCT_DEFAULT[] PROGMEM = "RCT_DEFAULT";
static const char T_RCT_HTTP[] PROGMEM = "RCT_HTTP";
static const char T_RCT_WS[] PROGMEM = "RCT_WS";
static const char T_RCT_EVENT[] PROGMEM = "RCT_EVENT";
static const char T_ERROR[] PROGMEM = "ERROR";
// extentions & MIME-Types
static const char T__css[] PROGMEM = ".css";
static const char T__eot[] PROGMEM = ".eot";
static const char T__gif[] PROGMEM = ".gif";
static const char T__gz[] PROGMEM = ".gz";
static const char T__htm[] PROGMEM = ".htm";
static const char T__html[] PROGMEM = ".html";
static const char T__ico[] PROGMEM = ".ico";
static const char T__jpg[] PROGMEM = ".jpg";
static const char T__js[] PROGMEM = ".js";
static const char T__json[] PROGMEM = ".json";
static const char T__pdf[] PROGMEM = ".pdf";
static const char T__png[] PROGMEM = ".png";
static const char T__svg[] PROGMEM = ".svg";
static const char T__ttf[] PROGMEM = ".ttf";
static const char T__woff[] PROGMEM = ".woff";
static const char T__woff2[] PROGMEM = ".woff2";
static const char T__xml[] PROGMEM = ".xml";
static const char T__zip[] PROGMEM = ".zip";
static const char T_application_javascript[] PROGMEM = "application/javascript";
static const char T_application_json[] PROGMEM = "application/json";
static const char T_application_pdf[] PROGMEM = "application/pdf";
static const char T_application_x_gzip[] PROGMEM = "application/x-gzip";
static const char T_application_zip[] PROGMEM = "application/zip";
static const char T_font_eot[] PROGMEM = "font/eot";
static const char T_font_ttf[] PROGMEM = "font/ttf";
static const char T_font_woff[] PROGMEM = "font/woff";
static const char T_font_woff2[] PROGMEM = "font/woff2";
static const char T_image_gif[] PROGMEM = "image/gif";
static const char T_image_jpeg[] PROGMEM = "image/jpeg";
static const char T_image_png[] PROGMEM = "image/png";
static const char T_image_svg_xml[] PROGMEM = "image/svg+xml";
static const char T_image_x_icon[] PROGMEM = "image/x-icon";
static const char T_text_css[] PROGMEM = "text/css";
static const char T_text_event_stream[] PROGMEM = "text/event-stream";
static const char T_text_html[] PROGMEM = "text/html";
static const char T_text_plain[] PROGMEM = "text/plain";
static const char T_text_xml[] PROGMEM = "text/xml";
// Responce codes
static const char T_HTTP_CODE_100[] PROGMEM = "Continue";
static const char T_HTTP_CODE_101[] PROGMEM = "Switching Protocols";
static const char T_HTTP_CODE_200[] PROGMEM = "OK";
static const char T_HTTP_CODE_201[] PROGMEM = "Created";
static const char T_HTTP_CODE_202[] PROGMEM = "Accepted";
static const char T_HTTP_CODE_203[] PROGMEM = "Non-Authoritative Information";
static const char T_HTTP_CODE_204[] PROGMEM = "No Content";
static const char T_HTTP_CODE_205[] PROGMEM = "Reset Content";
static const char T_HTTP_CODE_206[] PROGMEM = "Partial Content";
static const char T_HTTP_CODE_300[] PROGMEM = "Multiple Choices";
static const char T_HTTP_CODE_301[] PROGMEM = "Moved Permanently";
static const char T_HTTP_CODE_302[] PROGMEM = "Found";
static const char T_HTTP_CODE_303[] PROGMEM = "See Other";
static const char T_HTTP_CODE_304[] PROGMEM = "Not Modified";
static const char T_HTTP_CODE_305[] PROGMEM = "Use Proxy";
static const char T_HTTP_CODE_307[] PROGMEM = "Temporary Redirect";
static const char T_HTTP_CODE_400[] PROGMEM = "Bad Request";
static const char T_HTTP_CODE_401[] PROGMEM = "Unauthorized";
static const char T_HTTP_CODE_402[] PROGMEM = "Payment Required";
static const char T_HTTP_CODE_403[] PROGMEM = "Forbidden";
static const char T_HTTP_CODE_404[] PROGMEM = "Not Found";
static const char T_HTTP_CODE_405[] PROGMEM = "Method Not Allowed";
static const char T_HTTP_CODE_406[] PROGMEM = "Not Acceptable";
static const char T_HTTP_CODE_407[] PROGMEM = "Proxy Authentication Required";
static const char T_HTTP_CODE_408[] PROGMEM = "Request Time-out";
static const char T_HTTP_CODE_409[] PROGMEM = "Conflict";
static const char T_HTTP_CODE_410[] PROGMEM = "Gone";
static const char T_HTTP_CODE_411[] PROGMEM = "Length Required";
static const char T_HTTP_CODE_412[] PROGMEM = "Precondition Failed";
static const char T_HTTP_CODE_413[] PROGMEM = "Request Entity Too Large";
static const char T_HTTP_CODE_414[] PROGMEM = "Request-URI Too Large";
static const char T_HTTP_CODE_415[] PROGMEM = "Unsupported Media Type";
static const char T_HTTP_CODE_416[] PROGMEM = "Requested range not satisfiable";
static const char T_HTTP_CODE_417[] PROGMEM = "Expectation Failed";
static const char T_HTTP_CODE_500[] PROGMEM = "Internal Server Error";
static const char T_HTTP_CODE_501[] PROGMEM = "Not Implemented";
static const char T_HTTP_CODE_502[] PROGMEM = "Bad Gateway";
static const char T_HTTP_CODE_503[] PROGMEM = "Service Unavailable";
static const char T_HTTP_CODE_504[] PROGMEM = "Gateway Time-out";
static const char T_HTTP_CODE_505[] PROGMEM = "HTTP Version not supported";
static const char T_HTTP_CODE_ANY[] PROGMEM = "Unknown code";
// other
static const char T__opaque[] PROGMEM = "\", opaque=\"";
static const char T_13[] PROGMEM = "13";
static const char T_asyncesp[] PROGMEM = "asyncesp";
static const char T_auth_nonce[] PROGMEM = "\", qop=\"auth\", nonce=\"";
static const char T_cnonce[] PROGMEM = "cnonce";
static const char T_data_[] PROGMEM = "data: ";
static const char T_event_[] PROGMEM = "event: ";
static const char T_filename[] PROGMEM = "filename";
static const char T_gzip[] PROGMEM = "gzip";
static const char T_Host[] PROGMEM = "Host";
static const char T_id__[] PROGMEM = "id: ";
static const char T_name[] PROGMEM = "name";
static const char T_nc[] PROGMEM = "nc";
static const char T_nonce[] PROGMEM = "nonce";
static const char T_opaque[] PROGMEM = "opaque";
static const char T_qop[] PROGMEM = "qop";
static const char T_realm[] PROGMEM = "realm";
static const char T_realm__[] PROGMEM = "realm=\"";
static const char T_response[] PROGMEM = "response";
static const char T_retry_[] PROGMEM = "retry: ";
static const char T_rn[] PROGMEM = "\r\n";
static const char T_rnrn[] PROGMEM = "\r\n\r\n";
static const char T_uri[] PROGMEM = "uri";
static const char T_username[] PROGMEM = "username";
#endif // ESP8622
} // namespace asyncsrv {}