Skip to content

Commit ad33253

Browse files
authored
fix(client): fix content type selection in the runtime client. (#435)
* fixes #386 * fixes #387 * fixes #32 * test(client): behavioral harness for content-type selection * fix(client): honor stream payload's declared Content-Type * feat(client): name ContentTyper as an exported interface that Producers may implement * feat(client): payload-aware two-stage Content-Type selection * feat(client): honor SetHeader Content-Type as escape hatch for streams * feat(client): producer-capability filter in pickConsumesMediaType * feat: ContentTyper as a new exported interface * docs: describe two-stage client Content-Type selection * docs: summarise v0.30 client-negotiation deltas vs v0.29 Additional tests for client-side content negotiation ==================================================== Captures the current behavior of (*request).buildHTTP and Runtime.Submit across (consumes, payload, fields) combinations. FIXME-#387 so subsequent fixes produce visible deltas in the harness. Coverage on negotiation paths: buildHTTP 76.3 → 78.6%, createHttpRequest 81.0 → 85.7%. Fix: client-side content type selection ==================================================== Stream payloads (io.Reader, io.ReadCloser) bypass the producer in buildHTTP — their bytes flow through verbatim. The picker's chosen mediaType therefore only describes the operation's intent, not the body. * "infer Content-Type from payload" (#387) Payloads that implement runtime.ContentTyper may override this pick. with a non-empty result now overrides the picked mediaType for the header. This addresses the "infer Content-Type from payload" half of issue #387. * pick the right consumes entry (#386) The picker-side counterpart (choosing the right consumes entry up front when the payload is a raw stream and no ContentType() is declared) requires payload-aware two-stage selection. Non-stream (struct, []byte) payloads are unchanged: producer runs and the header reflects the picker. The picker (pickConsumesMediaType) runs in createHttpRequest before the writer populates the payload. It cannot see whether the payload is a stream, so its choice may misrepresent the body — e.g. picking application/json for a request whose payload is a raw byte stream. This change introduces a Stage-2 fallback inside buildHTTP that runs *after* the writer has populated r.payload. For stream payloads (io.Reader / io.ReadCloser) that do not declare their own type via `ContentType() string`: - if application/octet-stream is also offered in the operation's consumes list AND a producer is registered for it, the wire Content-Type advertises octet-stream — a safer claim than the picker's structural mime; - otherwise the picker's choice is preserved (we cannot infer something better without more information from the caller). This addresses the picker-side counterpart of issue #386. Combined with the previous step (#387 — payload-declared ContentType() override), the wire Content-Type now matches the body in every case where the runtime has enough information to know. * honor SetHeader Content-Type as escape hatch for streams 1. SetHeaderParam("Content-Type", X) — user's explicit assertion; 2. runtime.ContentTyper on the payload — value declares its type; 3. Stage-2 octet-stream upgrade — stream with neither of the above; 4. Stage-1 picker mediaType — final fallback. Non-stream paths (struct/[]byte payloads, form fields, multipart) are deliberately not honored. * producer-capability filter in pickConsumesMediaType The selection rules become: 1. multipart/form-data preference (issue #286, unchanged); 2. first non-empty entry that is structural OR has a registered producer in r.Producers — closes the gap; 3. first non-empty entry overall (preserves the historical "none of producers" diagnostic when nothing is registered); 4. DefaultMediaType when consumes is empty. Signed-off-by: Frederic BIDON <fredbi@yahoo.com>
1 parent 2b5a6dd commit ad33253

7 files changed

Lines changed: 1164 additions & 202 deletions

File tree

.claude/plans/track-b2-docui-extraction.md

Lines changed: 0 additions & 149 deletions
This file was deleted.

0 commit comments

Comments
 (0)