fix: error on CLI HTTP redirects instead of following them - #29104
Merged
Merged
Conversation
Go's default redirect handling follows a 301/302/303 by downgrading the request to a GET with no body. With a stale deployment URL that redirects to the new host, this silently turned "coder tokens create" into a list request and surfaced a confusing JSON decode error. Reject redirects in the CLI HTTP client and return a typed error that names the original and target URLs and suggests "coder login <new URL>" when the redirect changes host or scheme.
…rects Rejecting redirects is a breaking change for anyone who was relying on the old follow-with-downgrade behavior. Add a global --allow-redirects flag (CODER_ALLOW_REDIRECTS) that restores it, and mention the flag in the redirect error suggestion.
Contributor
Docs previewCheck off each page once it's been reviewed. If a page changes in a later push, its checkbox clears automatically so it gets a fresh look. Pages not yet wired into the docs navigation aren't listed here. |
f0ssel
marked this pull request as ready for review
September 8, 2026 16:24
aslilac
approved these changes
Sep 8, 2026
Comment on lines
+907
to
+912
| // rejectRedirect is an http.Client CheckRedirect hook that refuses to | ||
| // follow any redirect. Go's default behavior would follow a 301, 302, or | ||
| // 303 by downgrading the request to a GET with no body, silently turning | ||
| // a POST into a read of the same path. A redirect from the API almost | ||
| // always means the configured deployment URL is stale, so surface that | ||
| // instead. The --allow-redirects flag restores the old behavior. |
ethanndickson
approved these changes
Sep 9, 2026
ethanndickson
left a comment
Member
There was a problem hiding this comment.
One comment re: flag wording otherwise lgtm
|
|
||
| --allow-redirects bool, $CODER_ALLOW_REDIRECTS | ||
| Follow HTTP redirects from the server instead of returning an error. | ||
| Following a redirect downgrades POST requests to GET and may cause |
Member
There was a problem hiding this comment.
This is a bit too specific. Perhaps best to say "Following redirects may alter the request method and/or drop its body"
Member
There was a problem hiding this comment.
I agree, AFAIK 307 and 308 preserves the request. And in other scenarios it's often client-specific.
mafredri
approved these changes
Sep 9, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to subscribe to this conversation on GitHub.
Already have an account?
Sign in.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
codersdk.Clientuses anhttp.Clientwith noCheckRedirect, so Go's default applies: a 301/302/303 is followed by downgrading the request to a GET with no body. When~/.config/coderv2/urlpoints at a stale host that redirects to the new deployment,coder tokens createsilently becomes aGET /api/v2/users/{user}/keys/tokens(the list endpoint, same path) and fails with:Fix
Set
CheckRedirecton the HTTP client built incli/root.go(createHTTPClient, used by every CLI command includingcoder login) to refuse redirects and return a typedredirectError. The CLI error formatter prints the original and target URLs plus a suggestion to runcoder login <new URL>when the redirect changes host or scheme, or a proxy/path-rewrite hint when it stays within the same deployment.The
codersdk.Newdefaulthttp.Clientis intentionally left unchanged to avoid altering behavior for agents, provisioner daemons, and external SDK consumers.Breaking change
The CLI previously followed redirects silently. Any workflow that depended on that, for example a stale URL config that "worked" through a host redirect, or an http-to-https redirect in front of a deployment, will now fail with the error above until the stored URL is updated with
coder login.To keep the old behavior, opt in with the new global flag
--allow-redirectsorCODER_ALLOW_REDIRECTS=true. The flag help text notes that following redirects may alter the request method or drop its body, so this is a compatibility escape hatch rather than a recommended setting.Tests
Test_createHTTPClientRedirects/RejectedByDefault: a stale server redirects to a target serving[]on GET; assertsCreateTokenfails with*redirectErrorcarrying the correct URLs and that the formatted output includes the login suggestion and the flag name.Test_createHTTPClientRedirects/AllowRedirects: withallowRedirectsset, GET requests follow the redirect successfully and the POST reproduces the legacy downgrade behavior without aredirectError.Test_redirectErrorHelper: host change, http-to-https upgrade, and same-deployment cases.Golden help files and
docs/reference/cli/index.mdregenerated withmake gen.Generated by Coder Agents on behalf of @f0ssel.