Skip to content

refactor!: align request bodies with ht - #74

Merged
medz merged 8 commits into
mainfrom
refactor/73-body-extends-ht-body
Jun 23, 2026
Merged

refactor!: align request bodies with ht#74
medz merged 8 commits into
mainfrom
refactor/73-body-extends-ht-body

Conversation

@medz

@medz medz commented Jun 23, 2026

Copy link
Copy Markdown
Owner

Summary

  • Upgrade to ht ^0.6.0 and make Oxy request Body extend ht.Body directly.
  • Remove Oxy-specific request BodyKind, Body.from*, Body.open(), contentLength, and BodyStreamFactory surface in favor of upstream ht.Body APIs.
  • Clone replayable request bodies for retry attempts and preserved-method redirects so each attempt consumes an independent ht.Body.

Breaking Changes

  • Request Body now uses the ht.Body primitive API: stream(), bytes(), arrayBuffer(), text(), json(), blob(), slice(), clone(), bodyUsed, size, type, and contentType.
  • Raw Stream<List> inputs remain one-shot; pass ht.Body(stream) when upstream clone semantics are desired.

Validation

  • dart run patchwork apply
  • dart format --output=none --set-exit-if-changed .
  • dart analyze
  • dart test test/core_test.dart -p vm
  • dart test test/client_vm_test.dart -p vm
  • dart test -p vm -p node -p chrome

Fixes #73

Summary by CodeRabbit

  • Breaking Changes
    • Removed Oxy-specific request-body APIs; use upstream ht.Body behavior/APIs instead.
    • package:oxy/oxy.dart now only re-exports Body and ResponseBody.
    • Upgraded dependency to ht ^0.6.0.
  • Changed
    • Replayable request bodies are cloned for retries and method-redirect attempts.
    • Redirects now explicitly preserve or clear request bodies when methods change (e.g., to GET).
    • Improved request upload handling: content-length and progress now use known body length; native/web transports updated for streaming decisions.
  • Tests
    • Updated and added native and browser coverage for request replay and streaming behavior.

@medz medz added dependencies Dependency updates refactor Internal restructuring without intended behavior change type:feature area:core labels Jun 23, 2026
@coderabbitai

coderabbitai Bot commented Jun 23, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 574e76c5-39cd-4e00-9516-00621f4a1cb2

📥 Commits

Reviewing files that changed from the base of the PR and between 9796aab and fe9560a.

📒 Files selected for processing (6)
  • lib/src/client.dart
  • lib/src/core/body.dart
  • lib/src/transport/transport.web.dart
  • test/client_browser_test.dart
  • test/core_test.dart
  • test/pipeline_test.dart
💤 Files with no reviewable changes (1)
  • test/core_test.dart
🚧 Files skipped from review as they are similar to previous changes (2)
  • lib/src/client.dart
  • lib/src/core/body.dart

📝 Walkthrough

Walkthrough

Body is reworked from a standalone class to final class Body extends ht.Body, removing Oxy-specific BodyKind, static constructors, open(), and contentLength. New top-level helpers (requestBodyFrom, requestJsonBody, knownBodyLength, streamsRequestBody) replace the old factory/property API. Per-attempt body cloning is added for retries and redirects. Both transports are updated to use upstream body primitives. The ht dependency is upgraded to ^0.6.0.

Changes

Body Refactor to ht.Body Subclass

Layer / File(s) Summary
Body class redesign and public API surface
lib/src/core/body.dart, lib/oxy.dart, pubspec.yaml
Body is redesigned as final class Body extends ht.Body with replayable and _streamUpload computed from the initializer. clone() throws BodyStateError when not replayable. Top-level helpers requestBodyFrom, requestJsonBody, knownBodyLength, and streamsRequestBody replace old factory/property APIs. ResponseBody internal typedef updated to private _BodyStreamFactory. oxy.dart export narrowed to Body and ResponseBody. ht bumped to ^0.6.0.
Request construction and body resolution
lib/src/core/request.dart, lib/src/client/request_resolution.dart
Request constructor uses requestBodyFrom(body) instead of Body.from(body). resolveRequestBody uses requestJsonBody/requestBodyFrom. resolveClientRequest uses knownBodyLength(body) for the content-length header. Doc example updated to use Blob.
Per-attempt body cloning for retries and redirects
lib/src/client.dart, lib/src/client/redirects.dart
New _requestForAttempt and _mayNeedBodyReplay helpers clone the body when body.replayable is true before each attempt. _redirectRequest explicitly sets body: nextBody (null or cloned) in the redirect copy.
Native transport layer updates
lib/src/transport/transport.native.dart
Native transport uses knownBodyLength and body.stream() instead of body.contentLength/body.open() for header setting, progress totals, and chunk iteration.
Web transport layer updates
lib/src/transport/transport.web.dart
Web transport extends JS interop for feature detection (JSObjectStatic.defineProperty, PropertyDescriptor). WebTransport accepts optional requestStreamsSupported override and lazily detects browser streaming support via _detectRequestStreamsSupported(). shouldStreamRequestBody replaces the kind-switch. Uses knownBodyLength for content-length and progress; logs fallback warning in debug mode when streaming is unsupported.
Test coverage and changelog updates
test/core_test.dart, test/client_vm_test.dart, test/client_browser_test.dart, test/pipeline_test.dart, CHANGELOG.md
Core tests assert ht.Body-style APIs (replayable, bodyUsed, contentType, clone isolation, UnsupportedError). VM test switches to Body(...) with async generator. Browser tests validate shouldStreamRequestBody decisions across request-body inputs and streaming support. Pipeline test verifies body preservation when replay disabled. Changelog documents breaking removals and ht ^0.6.0 upgrade.

Sequence Diagram(s)

sequenceDiagram
  participant Caller
  participant Client
  participant _requestForAttempt
  participant _redirectRequest
  participant Body
  participant Transport

  Caller->>Client: send(request)
  Client->>_requestForAttempt: request (each attempt)
  _requestForAttempt->>Body: body.replayable?
  alt replayable and replay needed
    Body-->>_requestForAttempt: body.clone()
    _requestForAttempt-->>Client: request with cloned body
  else
    _requestForAttempt-->>Client: original request
  end
  Client->>Transport: send(attemptRequest)
  Transport->>Body: body.stream()
  Transport->>Body: knownBodyLength(body)
  Transport-->>Client: response
  alt redirect with body clear
    Client->>_redirectRequest: attemptRequest
    _redirectRequest->>Body: clearBody ? null : body.clone()
    _redirectRequest-->>Client: redirected request
  end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

Possibly related PRs

  • medz/oxy#72: Previous step that made Body a metadata view over ht.Body; this PR completes the migration by making Body a direct subclass.
  • medz/oxy#34: Earlier redesign of the retry/redirect architecture in lib/src/client.dart and lib/src/client/redirects.dart that this PR extends with per-attempt body cloning.
  • medz/oxy#66: Modifies lib/src/client/request_resolution.dart content-length header handling; this PR refactors it to use knownBodyLength(body) instead of body?.contentLength.

🐇 Hop, hop, the old Body's gone,
ht.Body carries the stream along.
replayable guards each retry's clone,
redirects clear or clone on their own.
The rabbit cheers: cleaner code is sewn! 🎉

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main refactoring objective: aligning request bodies with the upstream ht package by collapsing the Oxy-specific Body API onto ht.Body.
Linked Issues check ✅ Passed All acceptance criteria from issue #73 are met: BodyKind and Body.kind removed, Body.contentLength removed, Body.open() removed, Body.from* factories removed, and retry/redirect/timeout/progress/web upload behavior preserved across platforms.
Out of Scope Changes check ✅ Passed All changes are scoped to the Body refactoring objective. Updates to test files, transports, client logic, and pubspec.yaml directly support the alignment with ht ^0.6.0 and Body API changes, with no unrelated alterations.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch refactor/73-body-extends-ht-body

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot added the feature New capability or public behavior label Jun 23, 2026

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 0b848c97af

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread pubspec.yaml
@medz

medz commented Jun 23, 2026

Copy link
Copy Markdown
Owner Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 0b848c97af

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread lib/src/core/body.dart Outdated

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 9796aab8eb

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread lib/src/core/body.dart Outdated
@medz medz changed the title feat!: collapse Body onto ht Body feat!: make Body extend ht.Body Jun 23, 2026
@medz medz changed the title feat!: make Body extend ht.Body refactor!: align request bodies with ht Jun 23, 2026

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 5a33d2ba31

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread lib/src/core/body.dart Outdated
Comment thread lib/src/core/body.dart Outdated

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 1c39646951

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread lib/src/client.dart

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 42cd67c4e9

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread lib/src/core/body.dart Outdated

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 5b505c0ca2

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread lib/src/core/body.dart Outdated
@medz
medz merged commit 72ed7b4 into main Jun 23, 2026
3 checks passed
@medz
medz deleted the refactor/73-body-extends-ht-body branch June 23, 2026 12:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:core dependencies Dependency updates feature New capability or public behavior refactor Internal restructuring without intended behavior change type:feature

Projects

None yet

Development

Successfully merging this pull request may close these issues.

refactor: collapse Body onto subclassable ht.Body

1 participant