Skip to content
This repository was archived by the owner on Aug 3, 2026. It is now read-only.

Commit d0536cc

Browse files
committed
staged stream execution path
1 parent 8e2f652 commit d0536cc

5 files changed

Lines changed: 334 additions & 36 deletions

File tree

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@ All notable changes to this project will be documented in this file.
88
- Streaming download API via `getStream()` for binary or arbitrary content (no JSON handling).
99
- Chunk-based delivery using `FetchChunkCallback` to process large payloads incrementally (files, firmware, blobs).
1010
- Completion callback with `StreamResult` containing transport error, HTTP status code, and total received byte count.
11+
- Status-gated streaming overloads with `FetchStreamStartCallback` and
12+
`StreamStartInfo` so callers can reject non-`2xx` responses before any body
13+
chunk is processed.
1114
- Per-request streaming size limits via `FetchRequestOptions::maxBodyBytes` (default: unlimited for streams).
1215
- Added global (`FetchConfig`) and per-request (`FetchRequestOptions`) TX/RX HTTP client buffer sizing controls.
1316
- Added explicit HTTPS trust-source configuration to `FetchConfig` and per-request TLS overrides to `FetchRequestOptions` (`caCertPem`, `useTlsCertBundle`, `useGlobalCaStore`, `skipTlsServerCertValidation`, `skipTlsCommonNameCheck`).
@@ -18,6 +21,9 @@ All notable changes to this project will be documented in this file.
1821
- Added `isInitialized()` as the public runtime-state contract accessor.
1922

2023
### Fixed
24+
- Stream requests can now resolve HTTP status, content length, and chunked mode
25+
before chunk delivery when callers use the new status-aware overload, which
26+
prevents OTA/file consumers from processing HTML or error bodies as payload.
2127
- Normalize malformed `http:/` or `https:/` URLs to `http://`/`https://` to avoid DNS failures with parsed hosts like `:example.com`.
2228
- Collapse extra slashes (`https:///`) and strip a leading `://:` host typo before handing URLs to esp_http_client.
2329
- HTTPS requests now default to ESP certificate-bundle verification, matching the expected mixed Arduino + ESP-IDF transport behavior for public endpoints.

README.md

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,44 @@ if (!started) {
201201
}
202202
```
203203

204+
### Status-Gated Streaming Example
205+
206+
Use the status-aware overload when you must reject non-`2xx` responses before
207+
processing any body bytes, for example during OTA or direct-to-flash writes.
208+
209+
```cpp
210+
const char* exampleURL = "https://example.com/firmware.bin";
211+
212+
bool handleStart(const StreamStartInfo& info){
213+
if (info.statusCode < 200 || info.statusCode >= 300) {
214+
ESP_LOGW("FETCH", "Rejecting response with HTTP %d", info.statusCode);
215+
return false;
216+
}
217+
return true;
218+
}
219+
220+
bool handleChunk(const void* data, size_t size){
221+
return true;
222+
}
223+
224+
void handleDone(StreamResult result){
225+
ESP_LOGI("FETCH", "Finished: status=%d error=%s bytes=%u",
226+
result.statusCode,
227+
esp_err_to_name(result.error),
228+
result.receivedBytes
229+
);
230+
}
231+
232+
fetch.getStream(exampleURL, handleStart, handleChunk, handleDone);
233+
```
234+
235+
If `handleStart(...)` returns `false`:
236+
237+
* no chunk callback is invoked
238+
* `StreamResult.error == ESP_OK`
239+
* `StreamResult.statusCode` contains the resolved HTTP status
240+
* `StreamResult.receivedBytes == 0`
241+
204242
---
205243
206244
### Streaming Size Limits
@@ -370,11 +408,33 @@ bool getStream(const String& url,
370408
FetchStreamCallback onDone = nullptr,
371409
const FetchRequestOptions& opts = {}
372410
);
411+
412+
bool getStream(const char* url,
413+
FetchStreamStartCallback onStart,
414+
FetchChunkCallback onChunk,
415+
FetchStreamCallback onDone = nullptr,
416+
const FetchRequestOptions& opts = {}
417+
);
418+
419+
bool getStream(const String& url,
420+
FetchStreamStartCallback onStart,
421+
FetchChunkCallback onChunk,
422+
FetchStreamCallback onDone = nullptr,
423+
const FetchRequestOptions& opts = {}
424+
);
373425
```
374426

375427
#### Callbacks
376428

377429
```cpp
430+
struct StreamStartInfo {
431+
int statusCode;
432+
int64_t contentLength;
433+
bool isChunked;
434+
};
435+
436+
using FetchStreamStartCallback = std::function<bool(const StreamStartInfo& info)>;
437+
378438
using FetchChunkCallback = std::function<bool(const void* data, size_t size)>;
379439

380440
using FetchStreamCallback = std::function<void(StreamResult result)>;
@@ -386,6 +446,10 @@ struct StreamResult {
386446
};
387447
```
388448
449+
Use `FetchStreamStartCallback` when the caller needs to validate HTTP status
450+
before processing any response body bytes. Legacy `getStream(...)` overloads
451+
without `onStart` remain available for existing callers.
452+
389453
---
390454
391455
## Result Shape (JSON Mode)

0 commit comments

Comments
 (0)