Skip to content

Commit 1bf9172

Browse files
Merge pull request #148 from ESP32Async/timeout
Reverted AsyncResponseStream buffer to cbuf which is considerably faster than StreamString
2 parents 8d712ea + bc81189 commit 1bf9172

File tree

4 files changed

+61
-6
lines changed

4 files changed

+61
-6
lines changed
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
// SPDX-License-Identifier: LGPL-3.0-or-later
2+
// Copyright 2016-2025 Hristo Gochkov, Mathieu Carbou, Emil Muratov
3+
4+
#include <DNSServer.h>
5+
#ifdef ESP32
6+
#include <AsyncTCP.h>
7+
#include <WiFi.h>
8+
#elif defined(ESP8266)
9+
#include <ESP8266WiFi.h>
10+
#include <ESPAsyncTCP.h>
11+
#elif defined(TARGET_RP2040) || defined(TARGET_RP2350) || defined(PICO_RP2040) || defined(PICO_RP2350)
12+
#include <RPAsyncTCP.h>
13+
#include <WiFi.h>
14+
#endif
15+
16+
#include <ESPAsyncWebServer.h>
17+
18+
static AsyncWebServer server(80);
19+
20+
void setup() {
21+
Serial.begin(115200);
22+
23+
#ifndef CONFIG_IDF_TARGET_ESP32H2
24+
WiFi.mode(WIFI_AP);
25+
WiFi.softAP("esp-captive");
26+
#endif
27+
28+
// Shows how to use AsyncResponseStream.
29+
// The internal buffer will be allocated and data appended to it,
30+
// until the response is sent, then this buffer is read and committed on the network.
31+
//
32+
// curl -v http://192.168.4.1/
33+
//
34+
server.on("/", HTTP_GET, [](AsyncWebServerRequest *request) {
35+
AsyncResponseStream *response = request->beginResponseStream("plain/text", 40 * 1024);
36+
for (int i = 0; i < 32 * 1024; i++) {
37+
response->write('a');
38+
}
39+
request->send(response);
40+
});
41+
42+
server.begin();
43+
}
44+
45+
void loop() {
46+
delay(100);
47+
}

platformio.ini

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
[platformio]
22
default_envs = arduino-2, arduino-3, esp8266, raspberrypi
33
lib_dir = .
4+
; src_dir = examples/AsyncResponseStream
45
; src_dir = examples/Auth
56
; src_dir = examples/CaptivePortal
67
; src_dir = examples/CatchAllHandler
@@ -49,6 +50,7 @@ build_flags =
4950
-D CONFIG_ASYNC_TCP_QUEUE_SIZE=64
5051
-D CONFIG_ASYNC_TCP_RUNNING_CORE=1
5152
-D CONFIG_ASYNC_TCP_STACK_SIZE=4096
53+
; -D CONFIG_ASYNC_TCP_USE_WDT=0
5254
upload_protocol = esptool
5355
monitor_speed = 115200
5456
monitor_filters = esp32_exception_decoder, log2file

src/WebResponseImpl.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
#undef max
1111
#endif
1212
#include "literals.h"
13-
#include <StreamString.h>
13+
#include <cbuf.h>
1414
#include <memory>
1515
#include <vector>
1616

@@ -157,7 +157,7 @@ class AsyncProgmemResponse : public AsyncAbstractResponse {
157157

158158
class AsyncResponseStream : public AsyncAbstractResponse, public Print {
159159
private:
160-
StreamString _content;
160+
std::unique_ptr<cbuf> _content;
161161

162162
public:
163163
AsyncResponseStream(const char *contentType, size_t bufferSize);
@@ -172,7 +172,7 @@ class AsyncResponseStream : public AsyncAbstractResponse, public Print {
172172
* @brief Returns the number of bytes available in the stream.
173173
*/
174174
size_t available() const {
175-
return _content.length(); // note: _content.available() is not const
175+
return _content->available();
176176
}
177177
using Print::write;
178178
};

src/WebResponses.cpp

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -820,22 +820,28 @@ AsyncResponseStream::AsyncResponseStream(const char *contentType, size_t bufferS
820820
_code = 200;
821821
_contentLength = 0;
822822
_contentType = contentType;
823-
if (!_content.reserve(bufferSize)) {
823+
// internal buffer will be null on allocation failure
824+
_content = std::unique_ptr<cbuf>(new cbuf(bufferSize));
825+
if (_content->size() != bufferSize) {
824826
#ifdef ESP32
825827
log_e("Failed to allocate");
826828
#endif
827829
}
828830
}
829831

830832
size_t AsyncResponseStream::_fillBuffer(uint8_t *buf, size_t maxLen) {
831-
return _content.readBytes((char *)buf, maxLen);
833+
return _content->read((char *)buf, maxLen);
832834
}
833835

834836
size_t AsyncResponseStream::write(const uint8_t *data, size_t len) {
835837
if (_started()) {
836838
return 0;
837839
}
838-
size_t written = _content.write(data, len);
840+
if (len > _content->room()) {
841+
size_t needed = len - _content->room();
842+
_content->resizeAdd(needed);
843+
}
844+
size_t written = _content->write((const char *)data, len);
839845
_contentLength += written;
840846
return written;
841847
}

0 commit comments

Comments
 (0)