feat: add rp2040 support

This commit is contained in:
Ayush Sharma
2024-06-14 01:34:29 +05:30
committed by Mathieu Carbou
parent e3eb2b1044
commit 1af677d88b
20 changed files with 114 additions and 30 deletions

View File

@ -28,7 +28,10 @@ jobs:
- core: esp8266:esp8266 - core: esp8266:esp8266
board: esp8266:esp8266:huzzah board: esp8266:esp8266:huzzah
index_url: https://arduino.esp8266.com/stable/package_esp8266com_index.json index_url: https://arduino.esp8266.com/stable/package_esp8266com_index.json
- name: package_rp2040_index.json
core: rp2040:rp2040
board: rp2040:rp2040:rpipicow
index_url: https://github.com/earlephilhower/arduino-pico/releases/download/global/package_rp2040_index.json
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v4 uses: actions/checkout@v4
@ -55,6 +58,10 @@ jobs:
if: ${{ matrix.core == 'esp8266:esp8266' }} if: ${{ matrix.core == 'esp8266:esp8266' }}
run: ARDUINO_LIBRARY_ENABLE_UNSAFE_INSTALL=true arduino-cli lib install --git-url https://github.com/mathieucarbou/esphome-ESPAsyncTCP#v2.0.0 run: ARDUINO_LIBRARY_ENABLE_UNSAFE_INSTALL=true arduino-cli lib install --git-url https://github.com/mathieucarbou/esphome-ESPAsyncTCP#v2.0.0
- name: Install AsyncTCP (RP2040)
if: ${{ matrix.core == 'rp2040:rp2040' }}
run: ARDUINO_LIBRARY_ENABLE_UNSAFE_INSTALL=true arduino-cli lib install --git-url https://github.com/khoih-prog/AsyncTCP_RP2040W#v1.2.0
- name: Build CaptivePortal - name: Build CaptivePortal
run: arduino-cli compile --library . --warnings none -b ${{ matrix.board }} "examples/CaptivePortal/CaptivePortal.ino" run: arduino-cli compile --library . --warnings none -b ${{ matrix.board }} "examples/CaptivePortal/CaptivePortal.ino"

View File

@ -4,13 +4,14 @@
[![Continuous Integration](https://github.com/mathieucarbou/ESPAsyncWebServer/actions/workflows/ci.yml/badge.svg)](https://github.com/mathieucarbou/ESPAsyncWebServer/actions/workflows/ci.yml) [![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/ESP%20Async%20WebServer.svg)](https://registry.platformio.org/libraries/mathieucarbou/ESP%20Async%20WebServer)
Asynchronous HTTP and WebSocket Server Library for ESP32, ESP8266 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. Supports: WebSocket, SSE, Authentication, Arduino Json 7, File Upload, Static File serving, URL Rewrite, URL Redirect, etc.
This fork is based on [yubox-node-org/ESPAsyncWebServer](https://github.com/yubox-node-org/ESPAsyncWebServer) and includes all the concurrency fixes. This fork is based on [yubox-node-org/ESPAsyncWebServer](https://github.com/yubox-node-org/ESPAsyncWebServer) and includes all the concurrency fixes.
## Changes in this fork ## Changes in this fork
- [@ayushsharma82](https://github.com/ayushsharma82) and [@mathieucarbou](https://github.com/mathieucarbou): Add RP2040 support ([#31](https://github.com/mathieucarbou/ESPAsyncWebServer/pull/31))
- [@mathieucarbou](https://github.com/mathieucarbou): `SSE_MAX_QUEUED_MESSAGES` to control the maximum number of messages that can be queued for a SSE client - [@mathieucarbou](https://github.com/mathieucarbou): `SSE_MAX_QUEUED_MESSAGES` to control the maximum number of messages that can be queued for a SSE client
- [@mathieucarbou](https://github.com/mathieucarbou): `write()` function public in `AsyncEventSource.h` - [@mathieucarbou](https://github.com/mathieucarbou): `write()` function public in `AsyncEventSource.h`
- [@mathieucarbou](https://github.com/mathieucarbou): `WS_MAX_QUEUED_MESSAGES`: control the maximum number of messages that can be queued for a Websocket client - [@mathieucarbou](https://github.com/mathieucarbou): `WS_MAX_QUEUED_MESSAGES`: control the maximum number of messages that can be queued for a Websocket client

View File

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

View File

@ -4,13 +4,14 @@
[![Continuous Integration](https://github.com/mathieucarbou/ESPAsyncWebServer/actions/workflows/ci.yml/badge.svg)](https://github.com/mathieucarbou/ESPAsyncWebServer/actions/workflows/ci.yml) [![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/ESP%20Async%20WebServer.svg)](https://registry.platformio.org/libraries/mathieucarbou/ESP%20Async%20WebServer)
Asynchronous HTTP and WebSocket Server Library for ESP32, ESP8266 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. Supports: WebSocket, SSE, Authentication, Arduino Json 7, File Upload, Static File serving, URL Rewrite, URL Redirect, etc.
This fork is based on [yubox-node-org/ESPAsyncWebServer](https://github.com/yubox-node-org/ESPAsyncWebServer) and includes all the concurrency fixes. This fork is based on [yubox-node-org/ESPAsyncWebServer](https://github.com/yubox-node-org/ESPAsyncWebServer) and includes all the concurrency fixes.
## Changes in this fork ## Changes in this fork
- [@ayushsharma82](https://github.com/ayushsharma82) and [@mathieucarbou](https://github.com/mathieucarbou): Add RP2040 support ([#31](https://github.com/mathieucarbou/ESPAsyncWebServer/pull/31))
- [@mathieucarbou](https://github.com/mathieucarbou): `SSE_MAX_QUEUED_MESSAGES` to control the maximum number of messages that can be queued for a SSE client - [@mathieucarbou](https://github.com/mathieucarbou): `SSE_MAX_QUEUED_MESSAGES` to control the maximum number of messages that can be queued for a SSE client
- [@mathieucarbou](https://github.com/mathieucarbou): `write()` function public in `AsyncEventSource.h` - [@mathieucarbou](https://github.com/mathieucarbou): `write()` function public in `AsyncEventSource.h`
- [@mathieucarbou](https://github.com/mathieucarbou): `WS_MAX_QUEUED_MESSAGES`: control the maximum number of messages that can be queued for a Websocket client - [@mathieucarbou](https://github.com/mathieucarbou): `WS_MAX_QUEUED_MESSAGES`: control the maximum number of messages that can be queued for a Websocket client

View File

@ -5,6 +5,9 @@
#elif defined(ESP8266) #elif defined(ESP8266)
#include <ESP8266WiFi.h> #include <ESP8266WiFi.h>
#include <ESPAsyncTCP.h> #include <ESPAsyncTCP.h>
#elif defined(TARGET_RP2040)
#include <WebServer.h>
#include <WiFi.h>
#endif #endif
#include "ESPAsyncWebServer.h" #include "ESPAsyncWebServer.h"

View File

@ -7,6 +7,9 @@
#elif defined(ESP8266) #elif defined(ESP8266)
#include <ESP8266WiFi.h> #include <ESP8266WiFi.h>
#include <ESPAsyncTCP.h> #include <ESPAsyncTCP.h>
#elif defined(TARGET_RP2040)
#include <WebServer.h>
#include <WiFi.h>
#endif #endif
#include "ESPAsyncWebServer.h" #include "ESPAsyncWebServer.h"

View File

@ -12,6 +12,9 @@
#elif defined(ESP8266) #elif defined(ESP8266)
#include <ESP8266WiFi.h> #include <ESP8266WiFi.h>
#include <ESPAsyncTCP.h> #include <ESPAsyncTCP.h>
#elif defined(TARGET_RP2040)
#include <WebServer.h>
#include <WiFi.h>
#endif #endif
#include <ESPAsyncWebServer.h> #include <ESPAsyncWebServer.h>

View File

@ -17,7 +17,11 @@ class StreamConcat : public Stream {
return c != -1 ? c : _s2->read(); return c != -1 ? c : _s2->read();
} }
#if defined(TARGET_RP2040)
size_t readBytes(char* buffer, size_t length) {
#else
size_t readBytes(char* buffer, size_t length) override { size_t readBytes(char* buffer, size_t length) override {
#endif
size_t count = _s1->readBytes(buffer, length); size_t count = _s1->readBytes(buffer, length);
return count > 0 ? count : _s2->readBytes(buffer, length); return count > 0 ? count : _s2->readBytes(buffer, length);
} }

View File

@ -6,6 +6,9 @@
#elif defined(ESP8266) #elif defined(ESP8266)
#include <ESP8266WiFi.h> #include <ESP8266WiFi.h>
#include <ESPAsyncTCP.h> #include <ESPAsyncTCP.h>
#elif defined(TARGET_RP2040)
#include <WebServer.h>
#include <WiFi.h>
#endif #endif
#include "StreamConcat.h" #include "StreamConcat.h"
#include "StreamString.h" #include "StreamString.h"
@ -42,7 +45,11 @@ void setup() {
StreamConcat stream1(&header, &body); StreamConcat stream1(&header, &body);
StreamString content; StreamString content;
#if defined(TARGET_RP2040)
content.printf("FreeHeap: %d", rp2040.getFreeHeap());
#else
content.printf("FreeHeap: %" PRIu32, ESP.getFreeHeap()); content.printf("FreeHeap: %" PRIu32, ESP.getFreeHeap());
#endif
StreamConcat stream2 = StreamConcat(&stream1, &content); StreamConcat stream2 = StreamConcat(&stream1, &content);
File footer = LittleFS.open("/footer.html", "r"); File footer = LittleFS.open("/footer.html", "r");
@ -67,7 +74,11 @@ void loop() {
// dnsServer.processNextRequest(); // dnsServer.processNextRequest();
if (millis() - last > 2000) { if (millis() - last > 2000) {
#if defined(TARGET_RP2040)
Serial.printf("FreeHeap: %d", rp2040.getFreeHeap());
#else
Serial.printf("FreeHeap: %" PRIu32, ESP.getFreeHeap()); Serial.printf("FreeHeap: %" PRIu32, ESP.getFreeHeap());
#endif
last = millis(); last = millis();
} }
} }

View File

@ -18,7 +18,11 @@ class StreamString : public Stream {
return c; return c;
} }
#if defined(TARGET_RP2040)
size_t readBytes(char* buffer, size_t length) {
#else
size_t readBytes(char* buffer, size_t length) override { size_t readBytes(char* buffer, size_t length) override {
#endif
if (length > _buffer.length()) if (length > _buffer.length())
length = _buffer.length(); length = _buffer.length();
// Don't use _str.ToCharArray() because it inserts a terminator // Don't use _str.ToCharArray() because it inserts a terminator

View File

@ -1,7 +1,7 @@
{ {
"name": "ESP Async WebServer", "name": "ESP Async WebServer",
"version": "2.10.8", "version": "2.10.8",
"description": "Asynchronous HTTP and WebSocket Server Library for ESP32, ESP8266. Supports: WebSocket, SSE, Authentication, Arduino Json 7, File Upload, Static File serving, URL Rewrite, URL Redirect, etc.", "description": "Asynchronous HTTP and WebSocket Server Library for ESP32, ESP8266 and RP2040. Supports: WebSocket, SSE, Authentication, Arduino Json 7, File Upload, Static File serving, URL Rewrite, URL Redirect, etc.",
"keywords": "http,async,websocket,webserver", "keywords": "http,async,websocket,webserver",
"homepage": "https://github.com/mathieucarbou/ESPAsyncWebServer", "homepage": "https://github.com/mathieucarbou/ESPAsyncWebServer",
"repository": { "repository": {
@ -21,7 +21,8 @@
"frameworks": "arduino", "frameworks": "arduino",
"platforms": [ "platforms": [
"espressif32", "espressif32",
"espressif8266" "espressif8266",
"raspberrypi"
], ],
"dependencies": [ "dependencies": [
{ {
@ -39,6 +40,12 @@
{ {
"name": "Hash", "name": "Hash",
"platforms": "espressif8266" "platforms": "espressif8266"
},
{
"owner": "khoih-prog",
"name": "AsyncTCP_RP2040W",
"version": "^1.2.0",
"platforms": "raspberrypi"
} }
], ],
"export": { "export": {

View File

@ -2,9 +2,9 @@ name=ESP Async WebServer
version=2.10.8 version=2.10.8
author=Me-No-Dev author=Me-No-Dev
maintainer=Mathieu Carbou <mathieu.carbou@gmail.com> maintainer=Mathieu Carbou <mathieu.carbou@gmail.com>
sentence=Asynchronous HTTP and WebSocket Server Library for ESP32, ESP8266 sentence=Asynchronous HTTP and WebSocket Server Library for ESP32, ESP8266 and RP2040
paragraph=Supports: WebSocket, SSE, Authentication, Arduino Json 7, File Upload, Static File serving, URL Rewrite, URL Redirect, etc paragraph=Supports: WebSocket, SSE, Authentication, Arduino Json 7, File Upload, Static File serving, URL Rewrite, URL Redirect, etc
category=Other category=Other
url=https://github.com/mathieucarbou/ESPAsyncWebServer url=https://github.com/mathieucarbou/ESPAsyncWebServer
architectures=esp8266,esp32 architectures=*
license=LGPL-3.0 license=LGPL-3.0

View File

@ -46,3 +46,15 @@ board = huzzah
lib_deps = lib_deps =
bblanchon/ArduinoJson @ 7.0.4 bblanchon/ArduinoJson @ 7.0.4
esphome/ESPAsyncTCP-esphome @ 2.0.0 esphome/ESPAsyncTCP-esphome @ 2.0.0
; PlatformIO support for Raspberry Pi Pico is not official
; https://github.com/platformio/platform-raspberrypi/pull/36
; https://github.com/earlephilhower/arduino-pico/blob/master/docs/platformio.rst
; board settings: https://github.com/earlephilhower/arduino-pico/blob/master/tools/json/rpipico.json
[env:rpipicow]
upload_protocol = picotool
platform = https://github.com/maxgerhardt/platform-raspberrypi.git
board = rpipicow
lib_deps =
bblanchon/ArduinoJson @ 7.0.4
khoih-prog/AsyncTCP_RP2040W @ 1.2.0

View File

@ -18,7 +18,7 @@
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/ */
#include "Arduino.h" #include "Arduino.h"
#ifndef ESP8266 #if defined(ESP32)
#include <rom/ets_sys.h> #include <rom/ets_sys.h>
#endif #endif
#include "AsyncEventSource.h" #include "AsyncEventSource.h"
@ -190,7 +190,7 @@ void AsyncEventSourceClient::_queueMessage(const char* message, size_t len) {
if (_messageQueue.size() >= SSE_MAX_QUEUED_MESSAGES) { if (_messageQueue.size() >= SSE_MAX_QUEUED_MESSAGES) {
#ifdef ESP8266 #ifdef ESP8266
ets_printf(String(F("ERROR: Too many messages queued\n")).c_str()); ets_printf(String(F("ERROR: Too many messages queued\n")).c_str());
#else #elif defined(ESP32)
log_e("Too many messages queued: deleting message"); log_e("Too many messages queued: deleting message");
#endif #endif
return; return;

View File

@ -28,11 +28,16 @@
#ifndef SSE_MAX_QUEUED_MESSAGES #ifndef SSE_MAX_QUEUED_MESSAGES
#define SSE_MAX_QUEUED_MESSAGES 32 #define SSE_MAX_QUEUED_MESSAGES 32
#endif #endif
#else // esp8266 #elif defined(ESP8266)
#include <ESPAsyncTCP.h> #include <ESPAsyncTCP.h>
#ifndef SSE_MAX_QUEUED_MESSAGES #ifndef SSE_MAX_QUEUED_MESSAGES
#define SSE_MAX_QUEUED_MESSAGES 8 #define SSE_MAX_QUEUED_MESSAGES 8
#endif #endif
#elif defined(TARGET_RP2040)
#include <AsyncTCP_RP2040W.h>
#ifndef SSE_MAX_QUEUED_MESSAGES
#define SSE_MAX_QUEUED_MESSAGES 32
#endif
#endif #endif
#include <ESPAsyncWebServer.h> #include <ESPAsyncWebServer.h>

View File

@ -25,14 +25,14 @@
#include <libb64/cencode.h> #include <libb64/cencode.h>
#ifndef ESP8266 #if defined(ESP32)
#if ESP_IDF_VERSION_MAJOR < 5 #if ESP_IDF_VERSION_MAJOR < 5
#include "./port/SHA1Builder.h" #include "./port/SHA1Builder.h"
#else #else
#include <SHA1Builder.h> #include <SHA1Builder.h>
#endif #endif
#include <rom/ets_sys.h> #include <rom/ets_sys.h>
#else #elif defined(TARGET_RP2040) || defined(ESP8266)
#include <Hash.h> #include <Hash.h>
#endif #endif
@ -417,7 +417,7 @@ void AsyncWebSocketClient::_queueMessage(AsyncWebSocketSharedBuffer buffer, uint
if (closeWhenFull) { if (closeWhenFull) {
#ifdef ESP8266 #ifdef ESP8266
ets_printf("AsyncWebSocketClient::_queueMessage: Too many messages queued: closing connection\n"); ets_printf("AsyncWebSocketClient::_queueMessage: Too many messages queued: closing connection\n");
#else #elif defined(ESP32)
log_e("Too many messages queued: closing connection"); log_e("Too many messages queued: closing connection");
#endif #endif
_status = WS_DISCONNECTED; _status = WS_DISCONNECTED;
@ -426,7 +426,7 @@ void AsyncWebSocketClient::_queueMessage(AsyncWebSocketSharedBuffer buffer, uint
} else { } else {
#ifdef ESP8266 #ifdef ESP8266
ets_printf("AsyncWebSocketClient::_queueMessage: Too many messages queued: discarding new message\n"); ets_printf("AsyncWebSocketClient::_queueMessage: Too many messages queued: discarding new message\n");
#else #elif defined(ESP32)
log_e("Too many messages queued: discarding new message"); log_e("Too many messages queued: discarding new message");
#endif #endif
} }
@ -1155,7 +1155,7 @@ AsyncWebSocketResponse::AsyncWebSocketResponse(const String& key, AsyncWebSocket
uint8_t hash[20]; uint8_t hash[20];
char buffer[33]; char buffer[33];
#ifdef ESP8266 #if defined(ESP8266) || defined(TARGET_RP2040)
sha1(key + WS_STR_UUID, hash); sha1(key + WS_STR_UUID, hash);
#else #else
String k; String k;

View File

@ -28,12 +28,18 @@
#ifndef WS_MAX_QUEUED_MESSAGES #ifndef WS_MAX_QUEUED_MESSAGES
#define WS_MAX_QUEUED_MESSAGES 32 #define WS_MAX_QUEUED_MESSAGES 32
#endif #endif
#else #elif defined(ESP8266)
#include <ESPAsyncTCP.h> #include <ESPAsyncTCP.h>
#ifndef WS_MAX_QUEUED_MESSAGES #ifndef WS_MAX_QUEUED_MESSAGES
#define WS_MAX_QUEUED_MESSAGES 8 #define WS_MAX_QUEUED_MESSAGES 8
#endif #endif
#elif defined(TARGET_RP2040)
#include <AsyncTCP_RP2040W.h>
#ifndef WS_MAX_QUEUED_MESSAGES
#define WS_MAX_QUEUED_MESSAGES 32
#endif
#endif #endif
#include <ESPAsyncWebServer.h> #include <ESPAsyncWebServer.h>
#include <deque> #include <deque>

View File

@ -34,6 +34,11 @@
#elif defined(ESP8266) #elif defined(ESP8266)
#include <ESP8266WiFi.h> #include <ESP8266WiFi.h>
#include <ESPAsyncTCP.h> #include <ESPAsyncTCP.h>
#elif defined(TARGET_RP2040)
#include <WiFi.h>
#include <AsyncTCP_RP2040W.h>
#include <http_parser.h>
#include <HTTP_Method.h>
#else #else
#error Platform not supported #error Platform not supported
#endif #endif
@ -61,17 +66,21 @@ class AsyncStaticWebHandler;
class AsyncCallbackWebHandler; class AsyncCallbackWebHandler;
class AsyncResponseStream; class AsyncResponseStream;
#ifndef WEBSERVER_H #if defined (TARGET_RP2040)
typedef enum { typedef enum http_method WebRequestMethod;
HTTP_GET = 0b00000001, #else
HTTP_POST = 0b00000010, #ifndef WEBSERVER_H
HTTP_DELETE = 0b00000100, typedef enum {
HTTP_PUT = 0b00001000, HTTP_GET = 0b00000001,
HTTP_PATCH = 0b00010000, HTTP_POST = 0b00000010,
HTTP_HEAD = 0b00100000, HTTP_DELETE = 0b00000100,
HTTP_OPTIONS = 0b01000000, HTTP_PUT = 0b00001000,
HTTP_ANY = 0b01111111, HTTP_PATCH = 0b00010000,
} WebRequestMethod; HTTP_HEAD = 0b00100000,
HTTP_OPTIONS = 0b01000000,
HTTP_ANY = 0b01111111,
} WebRequestMethod;
#endif
#endif #endif
#ifndef HAVE_FS_FILE_OPEN_MODE #ifndef HAVE_FS_FILE_OPEN_MODE

View File

@ -20,7 +20,7 @@
*/ */
#include "WebAuthentication.h" #include "WebAuthentication.h"
#include <libb64/cencode.h> #include <libb64/cencode.h>
#ifdef ESP32 #if defined(ESP32) || defined(TARGET_RP2040)
#include <MD5Builder.h> #include <MD5Builder.h>
#else #else
#include "md5.h" #include "md5.h"
@ -64,7 +64,7 @@ bool checkBasicAuthentication(const char* hash, const char* username, const char
} }
static bool getMD5(uint8_t* data, uint16_t len, char* output) { // 33 bytes or more static bool getMD5(uint8_t* data, uint16_t len, char* output) { // 33 bytes or more
#ifdef ESP32 #if defined(ESP32) || defined(TARGET_RP2040)
MD5Builder md5; MD5Builder md5;
md5.begin(); md5.begin();
md5.add(data, len); md5.add(data, len);

View File

@ -210,7 +210,15 @@ void AsyncStaticWebHandler::handleRequest(AsyncWebServerRequest* request) {
String etag; String etag;
if (lw) { if (lw) {
setLastModified(gmtime(&lw)); setLastModified(gmtime(&lw));
#if defined(TARGET_RP2040)
// time_t == long long int
const size_t len = 1 + 8 * sizeof(time_t);
char buf[len];
char* ret = lltoa(lw, buf, len, 10);
etag = ret ? String(ret) : String(request->_tempFile.size());
#else
etag = String(lw); etag = String(lw);
#endif
} else { } else {
etag = String(request->_tempFile.size()); etag = String(request->_tempFile.size());
} }