HTTP Client Release 5.0.0: Structured Responses, Typed Errors, and Full Streaming Playback#52
Merged
Conversation
…, and full streaming playback ## Why This Change Was Made - `send()` returned `Result(String, String)` in 4.x, which made HTTP errors invisible (a 404 looked identical to a 200), discarded status codes and headers, and forced callers to parse error strings. This made downstream consumers like proxy_request unable to properly map upstream failures. - `start_stream()` could record streaming responses but could NOT play them back from fixtures, forcing callback-based streaming tests to hit real endpoints on every run. This blocked reliable CI testing for the proxy pipeline. ## What Was Changed - **`send()` return type**: `Result(String, String)` → `Result(HttpResponse, SendError)` where `HttpResponse` carries status/headers/body and `SendError` distinguishes `ResponseError` (4xx/5xx with full response) from `RequestError` (transport failures) - **`start_stream()` playback**: Added `replay_recorded_stream()` and `maybe_replay_from_recording()` private functions that replay recorded chunks directly via callbacks (`on_stream_start`, `on_stream_chunk`, `on_stream_end`) — no network calls during playback - **Recording/playback parity**: All three execution modes (`send()`, `stream_yielder()`, `start_stream()`) now fully support both recording and playback with shared `StreamingResponse` fixture format - **Hexdocs**: Added "Recording and Playback" sections to `send()`, `stream_yielder()`, and `start_stream()` documenting the behavior in each mode - **README**: Added recording support table showing all modes, plus two new snippet references - **Snippets**: Added `recording_stream_yielder.gleam` and `recording_start_stream.gleam` — tested examples proving streaming record/playback works end-to-end - **Tests**: 134 tests total (up from 127). Added: start_stream playback with StreamingResponse, start_stream playback with BlockingResponse, start_stream playback miss fallthrough, transform_response direct tests - **Release notes**: `releases/release-5.0.0.md` with migration guide, breaking changes, and streaming playback documentation - **Downstream**: Updated `dream_opensearch` 2.1.0 to adapt to the new `send()` return type, updated examples ## Note to Future Engineer - The `StreamingResponse` fixture format is shared between `stream_yielder()` and `start_stream()` — a recording made by one can be played back by either. This is intentional and tested. - `stream_messages_with_recorder()` still has an error path for "recording found in stream_messages path" — this is a safety net. `run_stream_process()` handles playback via `maybe_replay_from_recording()` before `stream_messages()` is ever called, so this error should never fire in practice. If you see it, something changed the call order. - The `internal.gleam` functions are `pub` only because Gleam requires FFI functions to be public. They're not part of the consumer API and are tested indirectly through higher-level functions. Don't feel guilty about not unit-testing them directly. - If you're wondering why there are 134 tests for an HTTP client: because 2.1.0 shipped with streaming recording that was "fundamentally broken" and "tests were rigged." We learned our lesson. Every public function gets tested. Trust but verify. Then verify again.
…hangelog ## Why This Change Was Made - The 5.0.0 release notes and changelog framed everything as "features" and "breaking changes" but never explicitly called out the bugs that were fixed. Three real bugs were buried under feature descriptions: silent 4xx/5xx success, start_stream playback errors, and stale opensearch syntax. ## What Was Changed - Added a "Bug Fixes" section to release-5.0.0.md with three numbered items: (1) HTTP 4xx/5xx no longer silently succeed, (2) start_stream() playback no longer errors, (3) dream_opensearch client.new syntax - Added a "### Fixed" section to CHANGELOG.md covering the same three bugs - Restructured the "### Added" section in CHANGELOG to separately list HttpResponse type, SendError type, and start_stream playback as distinct additions - Applied gleam format to test files (auto-formatting from pre-commit hook) ## Note to Future Engineer - If you fix a bug, call it a bug fix. Don't dress it up as a feature — future you reading the changelog at 2am during an incident will thank present you for the honesty.
…onse HTTP Client 5.0.0: Structured responses, typed errors, and full streaming playback
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
send()returnsHttpResponse— status, headers, and body instead of just the body stringResponseErrorfor HTTP 4xx/5xx (with full response),RequestErrorfor transport failuresOkalways means success — HTTP error responses moved fromOktoError, eliminating silent failuresstart_stream()playback support — all three execution modes (send(),stream_yielder(),start_stream()) now fully support recording and playbackdream_opensearchupdated from pre-4.0client.newtoclient.new()Breaking Changes
send()return type:Result(String, String)→Result(HttpResponse, SendError)Ok(body)→Error(ResponseError(response))Error(message)→Error(RequestError(message: message))Test Coverage
All 134 tests pass. See release notes for full details.