Skip to content

feat(http-request): add throwOnError, onRetry, streaming body, parseRetryAfter, sanitizeHeaders#146

Merged
John-David Dalton (jdalton) merged 1 commit intomainfrom
feat/http-request-enhancements
Apr 6, 2026
Merged

feat(http-request): add throwOnError, onRetry, streaming body, parseRetryAfter, sanitizeHeaders#146
John-David Dalton (jdalton) merged 1 commit intomainfrom
feat/http-request-enhancements

Conversation

@jdalton
Copy link
Copy Markdown
Collaborator

Summary

  • HttpResponseError class: thrown on non-2xx when throwOnError is enabled, carries full HttpResponse
  • throwOnError option on HttpRequestOptions: makes non-2xx responses throw (enabling retry via retries)
  • onRetry callback on HttpRequestOptions: customize retry behavior per-attempt (return false to stop, number to override delay, undefined for default)
  • Streaming body: body accepts Readable streams (incl. form-data npm package), auto-merges getHeaders() when present
  • parseRetryAfter(): standalone RFC 7231 §7.1.3 Retry-After parser (strict integer seconds + HTTP-date)
  • sanitizeHeaders(): redact sensitive headers (authorization, cookie, etc.) for safe logging/telemetry

Safety hardening

  • Stream bodies rejected with retries > 0 (one-shot, not replayable)
  • followRedirects disabled for stream bodies (consumed on first request)
  • settled/resolveOnce/rejectOnce guards prevent double-settle on all 10+ event paths
  • rejectOnce destroys stream body to avoid descriptor leaks
  • res.resume() drains redirect response bodies to free sockets
  • emitResponse wrapped in try/catch — user hook errors can't leave promises pending
  • onRetry delay clamped (negative → 0, NaN → default)
  • maxResponseSize cleanup destroys both response and request

Motivation

Enables the socket-sdk-js PR #556 to deduplicate with lib — these helpers replace SDK-local implementations of retry logic, header sanitization, Retry-After parsing, and FormData upload plumbing.

Test plan

  • 60 new tests added (136 → 196 total) covering all new features and edge cases
  • 9 rounds of adversarial review with Codex caught and fixed 10 bugs before shipping
  • All 196 tests pass, TypeScript checks pass, lint passes

…etryAfter, sanitizeHeaders

Add new HTTP helpers to enable SDK deduplication:

- HttpResponseError class: thrown on non-2xx when throwOnError is enabled
- throwOnError option: makes non-2xx responses throw (enabling retry)
- onRetry callback: customize retry behavior per-attempt (skip 4xx, honor Retry-After)
- Streaming body support: body accepts Readable/FormData, auto-merges getHeaders()
- parseRetryAfter(): RFC 7231 Retry-After header parser (strict integer + HTTP-date)
- sanitizeHeaders(): redact sensitive headers for safe logging

Safety:
- Stream bodies rejected with retries > 0 (one-shot, not replayable)
- Redirects disabled for stream bodies
- settled/resolveOnce/rejectOnce guards prevent double-settle on all paths
- rejectOnce destroys stream body to avoid descriptor leaks
- res.resume() drains redirect response bodies
- emitResponse wrapped in try/catch for hook error resilience
- onRetry delay clamped (negative → 0, NaN → default)
- maxResponseSize cleanup destroys both response and request
@jdalton John-David Dalton (jdalton) merged commit ec1d199 into main Apr 6, 2026
12 checks passed
@jdalton John-David Dalton (jdalton) deleted the feat/http-request-enhancements branch April 6, 2026 18:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant