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
Context
#72 made Oxy request bodies a metadata view over
ht.Body, which fixed the immediate support gap:ht.Bodyand ht body primitives can be passed directly throughBody.from(...).After reviewing the direction in medz/ht#51, the better long-term model is simpler:
ht.Bodyowns the public body primitive API.The ideal public API should not keep Oxy-only body concepts such as
BodyKind,kind,contentLength,open(), or thefromBytes/fromText/fromJson/fromBlob/fromFormData/fromUrlSearchParamsfactory set.Target Shape
Once upstream
ht.Bodyis subclassable, OxyBodyshould move toward:The user-facing body API should come from
ht.Body:stream()listenbytes()arrayBuffer()text()json()blob()slice()clone()bodyUsedsizetype/contentTypeOxy internals can still maintain private request policy:
body.sizeto nullableContent-Lengthby catchingUnsupportedErrorkindjson:through an internal helper instead of exposingBody.fromJsonAcceptance Criteria
BodyKindandBody.kind.Body.contentLength; internal request preparation usesBody.size.Body.open(); transports usestream()/listenfrom the body primitive.Body.fromXfactory set.Request(body: ht.Body(...))andRequest(body: Body(...))keep working naturally.Depends On
Bodyhas the Fetch/Blob/Stream-style public surface