diff --git a/README.md b/README.md index b14d36c..029def8 100644 --- a/README.md +++ b/README.md @@ -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)) diff --git a/docs/_config.yml b/docs/_config.yml index e6d54d2..3636597 100644 --- a/docs/_config.yml +++ b/docs/_config.yml @@ -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: diff --git a/docs/index.md b/docs/index.md index b14d36c..029def8 100644 --- a/docs/index.md +++ b/docs/index.md @@ -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)) diff --git a/examples/issues/Issue14/Issue14.ino b/examples/issues/Issue14/Issue14.ino new file mode 100644 index 0000000..f62084a --- /dev/null +++ b/examples/issues/Issue14/Issue14.ino @@ -0,0 +1,107 @@ +#include +#ifdef ESP32 + #include + #include +#elif defined(ESP8266) + #include + #include +#elif defined(TARGET_RP2040) + #include + #include +#endif + +#include "ESPAsyncWebServer.h" + +const char appWebPage[] PROGMEM = R"rawliteral( + + + + +)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(); + } +} diff --git a/library.json_ b/library.json_ index 4e089ba..4d322f2 100644 --- a/library.json_ +++ b/library.json_ @@ -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" }, { diff --git a/library.properties b/library.properties index e0265c3..f3647ad 100644 --- a/library.properties +++ b/library.properties @@ -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 sentence=Asynchronous HTTP and WebSocket Server Library for ESP32, ESP8266 and RP2040 diff --git a/platformio.ini b/platformio.ini index 0c85cfe..01110bf 100644 --- a/platformio.ini +++ b/platformio.ini @@ -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 diff --git a/src/AsyncEventSource.cpp b/src/AsyncEventSource.cpp index 4cafdae..639fd56 100644 --- a/src/AsyncEventSource.cpp +++ b/src/AsyncEventSource.cpp @@ -22,26 +22,29 @@ #include #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) { diff --git a/src/AsyncWebSocket.cpp b/src/AsyncWebSocket.cpp index e978afc..88d88ec 100644 --- a/src/AsyncWebSocket.cpp +++ b/src/AsyncWebSocket.cpp @@ -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(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(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(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(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(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(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); } diff --git a/src/AsyncWebSocket.h b/src/AsyncWebSocket.h index 77bf7ee..ee7bde1 100644 --- a/src/AsyncWebSocket.h +++ b/src/AsyncWebSocket.h @@ -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 diff --git a/src/ESPAsyncWebServer.h b/src/ESPAsyncWebServer.h index 77c5de7..73a2c36 100644 --- a/src/ESPAsyncWebServer.h +++ b/src/ESPAsyncWebServer.h @@ -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(); diff --git a/src/ESP_Async_WebServer.h b/src/ESP_Async_WebServer.h deleted file mode 100644 index ca6a112..0000000 --- a/src/ESP_Async_WebServer.h +++ /dev/null @@ -1,2 +0,0 @@ -// to please Arduino Lint -#include "ESPAsyncWebServer.h" diff --git a/src/WebAuthentication.cpp b/src/WebAuthentication.cpp index abd74b8..b5962fc 100644 --- a/src/WebAuthentication.cpp +++ b/src/WebAuthentication.cpp @@ -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); diff --git a/src/WebHandlers.cpp b/src/WebHandlers.cpp index d740d86..580ceba 100644 --- a/src/WebHandlers.cpp +++ b/src/WebHandlers.cpp @@ -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); } diff --git a/src/WebRequest.cpp b/src/WebRequest.cpp index 2331b13..f0d6bdf 100644 --- a/src/WebRequest.cpp +++ b/src/WebRequest.cpp @@ -21,13 +21,13 @@ #include "ESPAsyncWebServer.h" #include "WebAuthentication.h" #include "WebResponseImpl.h" - -#ifndef ESP8266 - #define os_strlen strlen -#endif +#include "literals.h" +#include #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; diff --git a/src/WebResponses.cpp b/src/WebResponses.cpp index 1fd41fa..86aa947 100644 --- a/src/WebResponses.cpp +++ b/src/WebResponses.cpp @@ -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(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(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) { diff --git a/src/WebServer.cpp b/src/WebServer.cpp index 9d78e02..0e29a54 100644 --- a/src/WebServer.cpp +++ b/src/WebServer.cpp @@ -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); } diff --git a/src/literals.h b/src/literals.h new file mode 100644 index 0000000..145d69b --- /dev/null +++ b/src/literals.h @@ -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 {}