Skip to content

refactor: collapse Body onto subclassable ht.Body #73

Description

@medz

Context

#72 made Oxy request bodies a metadata view over ht.Body, which fixed the immediate support gap: ht.Body and ht body primitives can be passed directly through Body.from(...).

After reviewing the direction in medz/ht#51, the better long-term model is simpler:

  • ht.Body owns the public body primitive API.
  • Oxy only adds request policy where it is genuinely needed.

The ideal public API should not keep Oxy-only body concepts such as BodyKind, kind, contentLength, open(), or the fromBytes / fromText / fromJson / fromBlob / fromFormData / fromUrlSearchParams factory set.

Target Shape

Once upstream ht.Body is subclassable, Oxy Body should move toward:

final class Body extends ht.Body {
  Body([ht.BodyInit? init]) : super(init);

  @override
  Body clone() {
    return Body._fromHt(super.clone());
  }
}

The user-facing body API should come from ht.Body:

  • stream()
  • listen
  • bytes()
  • arrayBuffer()
  • text()
  • json()
  • blob()
  • slice()
  • clone()
  • bodyUsed
  • size
  • type / contentType

Oxy internals can still maintain private request policy:

  • map body.size to nullable Content-Length by catching UnsupportedError
  • preserve one-shot semantics for raw stream request bodies
  • keep retry and redirect checks for non-replayable bodies
  • keep web upload mode as a private transport policy, not a public kind
  • encode request json: through an internal helper instead of exposing Body.fromJson

Acceptance Criteria

  • Remove public BodyKind and Body.kind.
  • Remove public Body.contentLength; internal request preparation uses Body.size.
  • Remove public Body.open(); transports use stream() / listen from the body primitive.
  • Remove or deprecate the public Body.fromX factory set.
  • Request(body: ht.Body(...)) and Request(body: Body(...)) keep working naturally.
  • Retry, redirect, timeout, progress, and web upload behavior remain covered by VM, Node, and browser tests.

Depends On

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions