Skip to content

feat: keep the response metadata reachable - #16

Draft
simonx1 wants to merge 1 commit into
obie:mainfrom
simonx1:feat/expose-response-metadata
Draft

simonx1 wants to merge 1 commit into
obie:mainfrom
simonx1:feat/expose-response-metadata

Conversation

@simonx1

@simonx1 simonx1 commented Sep 18, 2026

Copy link
Copy Markdown

The README says to quote response.request_id when reporting a problem to Typesafe. It was only ever set on a successful response. On a failure — the case you'd actually report — the header sat in ApiError#headers and nothing pointed at it, so the one identifier support asks for was the one thing the error didn't surface.

Everything else on a successful response was dropped too. The client scanned the headers for the request id and discarded the rest, so rate-limit counters — which it has no opinion about and no business consuming — were gone by the time anything could read them.

The fix

ApiError gains #request_id and #endpoint. Response gains #headers and #header(name). The case-insensitive lookup that Client and RetryPolicy had each written for themselves becomes Headers.fetch, in one place, still taking the first value of an Array the way Net::HTTP hands back a repeated header.

Response.new takes headers: where it took request_id:; #request_id reads the same value out of them.

Tests

test/metadata_test.rb, 11 cases.


Draft: part of a security and API-coverage audit, opened for reference rather than as a request for immediate review. Independent of the other branches, each off main. Suite green on Ruby 3.2.11, 3.3.8 and 3.4.8.

🤖 Generated with Claude Code

The README says to quote `response.request_id` when reporting a problem to
Typesafe. It was only ever set on a successful response. On a failure --
the case you would actually report -- the header was in ApiError#headers
and nothing pointed at it, so the one identifier support asks for was the
one thing the error did not surface.

Everything else on a successful response was dropped too. The client
scanned the headers for the request id and discarded the rest, so
rate-limit counters, which it has no opinion about and no business
consuming, were gone by the time anything could read them.

ApiError gains #request_id and #endpoint. Response gains #headers and
#header(name). The case-insensitive lookup that Client and RetryPolicy had
each written for themselves is now Headers.fetch, in one place, still
taking the first value of an Array the way Net::HTTP hands back a repeated
header.

Response.new takes headers: where it took request_id:; #request_id reads
the same value out of them.

Co-Authored-By: Claude Opus 5 (1M context) <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