Skip to content

Let clients configure a redirect policy - #277

Closed
williammartin wants to merge 1 commit into
trunkfrom
williammartin-check-redirect-trunk
Closed

Let clients configure a redirect policy#277
williammartin wants to merge 1 commit into
trunkfrom
williammartin-check-redirect-trunk

Conversation

@williammartin

Copy link
Copy Markdown
Member

NewHTTPClient builds an http.Client from ClientOptions but never sets
CheckRedirect, so a caller has no way to control redirect handling and always
gets Go's default policy.

That default is not always what a caller wants. Go converts a DELETE into a
GET when it follows a 301, so a client deleting a resource that has been
renamed receives a success response having deleted nothing.

This adds a CheckRedirect field to ClientOptions and threads it through, in
the same shape as http.Client's field of the same name. Behaviour is unchanged
when it is nil.

Why now

cli/cli is migrating its remaining raw httpClient.Do call sites onto its
api.Client, so that all API traffic honours the per-host api_host config
added in #275. gh repo delete was the one site that could not migrate: it
needs this policy, and because go-gh discarded it, the command had to build its
own client and hold an absolute api.github.com URL, which meant it silently
ignored api_host.

With this change it migrates, and an end-to-end test that routes every request
through a gateway with api.github.com blackholed passes in full. That test is
what surfaced this: gh repo delete was the last command still reaching
GitHub directly.

Together with #275, this is everything go-gh needs for that work. Draft because
#275 should land first.

Testing

TestNewHTTPClientCheckRedirect covers both the default policy and a custom one
that stops at the redirect. It uses the package's existing tripper stub;
redirect policy lives on http.Client above the transport, so a stubbed
transport still exercises the real policy.

Verified the test detects the bug: reverting the one-line change to
NewHTTPClient fails it with expected: 301, actual: 204.

NewHTTPClient built its http.Client from the transport alone, so a
CheckRedirect supplied by the caller was silently discarded. There was no
way to express a redirect policy through this package.

That silence has teeth. Go's default policy converts a DELETE into a GET
when it follows a 301, so deleting a resource that has since been renamed
follows the redirect, issues a GET against the new location, and returns
its success status. The caller is told the delete succeeded when nothing
was deleted. cli/cli hits exactly this in `gh repo delete`, and works
around it today by building its own client and bypassing this package.

Add CheckRedirect to ClientOptions and pass it through, mirroring the
field of the same name on http.Client. Leaving it nil keeps the existing
behaviour of following up to 10 redirects.

The test drives a stub transport that answers the first request with a
301. Redirect handling belongs to http.Client rather than the transport,
so the stub still exercises the real policy: the client only asks it for
the redirected request if the policy allows the redirect. Without the
change, the second case sees the DELETE arrive as a GET and reports 204.
@williammartin

Copy link
Copy Markdown
Member Author

Folded into #275 so there is a single PR carrying everything go-gh needs for the cli/cli api_host migration. The change itself is unmodified.

@williammartin
williammartin deleted the williammartin-check-redirect-trunk branch August 7, 2026 08:45
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