Skip to content

fix(data): respect caller Content-Type; clean up source comments#51

Open
wenchy wants to merge 7 commits into
masterfrom
docs/improve-options-comments
Open

fix(data): respect caller Content-Type; clean up source comments#51
wenchy wants to merge 7 commits into
masterfrom
docs/improve-options-comments

Conversation

@wenchy

@wenchy wenchy commented Jul 16, 2026

Copy link
Copy Markdown
Owner

Summary

A doc-cleanup pass surfaced a real regression, which is fixed here alongside the comment work.

Behavior fix — Content-Type handling

Since 13db74d (auto-deduce content type), requestData unconditionally ran opts.Headers.Set("Content-Type", ...), overwriting any Content-Type the caller set via Headers/HeaderPairs. Pre-13db74d, Data never touched Content-Type, so Data(x) + a custom Content-Type worked. This restores that capability for Data.

The split is now principled — based on whether the body format is known or guessed:

Option Body format Content-Type
Data deduced (guessed) respects a caller-supplied value; deduces only when unset
JSON / Form / Files known (marshal/encode/multipart) forces (overrides any caller value)

Form/Files must force because their Content-Type carries the boundary the body depends on. JSON forces for the same reason the body format is known — and because custom JSON media types (application/ld+json, application/problem+json, …) are already covered by Data + an explicit Content-Type (Data marshals structs/maps via json.Marshal just like JSON). So only Data needs to defer to the caller.

Net behavior delta vs master: only Data changes (regains override support). JSON/Form/Files keep their existing force behavior.

Comment cleanup across source files

Standardized doc comments for clarity/conciseness (wraps [http.X], sends an HTTP GET request, sets/forces Content-Type to, etc.) and corrected a few misleading comments. The Data comment now accurately describes deduceContentTypeAndBody's real evaluation order (io.Reader first, then pointer deref, then kind rules), the *[]byte raw-bytes case, and the typed-nil-pointer ((*T)(nil)"<nil>") footgun.

Files

request.go, options.go, response.go, client.go, method.go, interceptor.go, default.go, request_test.go

Verification

  • go build ./...
  • go vet ./...
  • go test ./... ✅ — including TestContentTypeOverride: Data deduces when unset and respects a caller value; JSON/Form force their Content-Type.

🤖 Generated with Claude Code

Tighten and standardize the doc comments across options.go: fix
grammar, use concise phrasing ('from key-value pairs', 'sets
Content-Type to'), name the actual parameter where it clarifies
behavior, and add doc links matching the existing style. Behavior is
unchanged.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@codecov

codecov Bot commented Jul 16, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 83.19%. Comparing base (c3ec67b) to head (908249b).

Additional details and impacted files
@@            Coverage Diff             @@
##           master      #51      +/-   ##
==========================================
+ Coverage   83.05%   83.19%   +0.14%     
==========================================
  Files           7        7              
  Lines         360      363       +3     
==========================================
+ Hits          299      302       +3     
  Misses         38       38              
  Partials       23       23              

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Extend the comment cleanup beyond options.go to the rest of the
package: request.go, response.go, client.go, method.go,
interceptor.go, and default.go. Tighten prose, fix grammar, and
standardize phrasing ('wraps [http.X]', 'sends an HTTP GET request',
'sets Content-Type to'). Also correct a couple of misleading inline
comments (e.g. the do() body-close note, the StatusText return).
Behavior is unchanged.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@wenchy wenchy changed the title docs: improve options.go function comments for clarity docs: improve comments across source files for clarity Jul 16, 2026
wenchy and others added 2 commits July 16, 2026 21:15
Reflect the actual evaluation order: io.Reader is matched first (on
the value as passed), non-reader pointers are dereferenced, then the
[]byte/struct-map-slice/default rules apply. Document the *[]byte raw
case and the typed-nil-pointer footgun ((*T)(nil) is sent as "<nil>").

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Since 13db74d, requestData unconditionally called
opts.Headers.Set("Content-Type", ...), overwriting any Content-Type
the caller set via Headers/HeaderPairs. JSON already had the same
force-override behavior. This restores the pre-13db74d capability for
Data and aligns JSON with it: Content-Type is only set when the caller
has not provided one.

Form and Files keep forced override, since their Content-Type carries
the boundary the body actually depends on.

Adds setContentTypeIfAbsent helper, documents the precedence in the
Data/JSON/Form/Files option comments, and pins the behavior with
TestContentTypeOverride.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@wenchy wenchy changed the title docs: improve comments across source files for clarity fix(data): respect caller Content-Type; clean up source comments Jul 17, 2026
wenchy and others added 2 commits July 17, 2026 14:16
JSON, Form, and Files all produce a body of known format, so they
force their Content-Type (overriding any caller value) for consistency
and to prevent a caller from declaring a mismatched type. Only Data
respects a caller-supplied Content-Type, since its body format is
deduced (guessed) and the caller may know better.

For custom JSON-based media types (e.g. application/ld+json), Data
with an explicit Content-Type covers it — Data marshals structs/maps
the same way JSON does.

Reverts the JSON respect-override added in the previous commit; JSON
keeps its pre-existing force behavior. Updates the JSON comment and
TestContentTypeOverride accordingly.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Frame Data's behavior around issue #48's two cases: a caller-supplied
Content-Type (via Headers/HeaderPairs) is used as-is; otherwise it is
deduced from the data type. Note the deduction is a heuristic (e.g.
XML is detected as text/xml, not application/xml), so set it explicitly
when the exact type matters. Document Body as the raw/streamed path
that sets no Content-Type, and add a README example for sending
xml/octet-stream with an explicit Content-Type.

Add TestDataStringVsBytesEquivalent to pin #48's requirement that
Data(string) and Data([]byte) with the same content produce the same
HTTP request.

No behavior change.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@wenchy

wenchy commented Jul 17, 2026

Copy link
Copy Markdown
Owner Author

Follow-up tying this work to #48: issue #48's two-case model (caller-supplied Content-Type wins; otherwise deduce from type) is now both implemented and documented.

  • Case 1 (caller supplies Content-Type): was broken on masterrequestData unconditionally overwrote it. Fixed here via setContentTypeIfAbsent, so a Headers/HeaderPairs Content-Type now wins for Data.
  • Case 2 (no Content-Type): unchanged type-based deduction.
  • Data: handle any type gracefully based on "Content-Type" of headers #48's equivalence test (Data(string) == Data([]byte) for the same content) is now pinned by TestDataStringVsBytesEquivalent — verified to pass (both yield text/plain; charset=utf-8 + identical body).
  • Data/Body doc comments and a README example spell out the two cases and the sniff heuristic caveat (XML → text/xml/text/plain, so set application/xml explicitly).

Refs #48.

Prefer HeaderPairs("Content-Type", "application/xml") over
Headers(map[string]string{"Content-Type": "..."}) when setting a
single Content-Type, in the README example and TestContentTypeOverride.
Cleaner and consistent with the existing HeaderPairs idiom.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
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