# test(httputil): assert error_description is captured; preserve URL escaping

`614570e`→[main](/content/gh/entireio/cli/commits/main/index.html)·

toothbrush·2w ago·2 files·+11 added/-5 removed

Addresses PR review:
\- Pin OAuthError.Description extraction so the git-remote-entire
wrong-cluster UX can't silently regress.
\- Rebuild the corrected entire:// URL from the user's parsed URL with
only the host swapped, preserving RawPath/query escaping.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

## Sessions

ef974a99a5c2View transcript

## Changes

2

- cmd/git-remote-entire

- Mmain.go+3

- internal/entireclient/httputil

- Moauth_test.go+8/-5

```
181 unmodified lines

182
183
184
185
186
187
188
189
190

181 unmodified lines

\tif errors.As(err, &oe) && oe.Code == "invalid_target" {
\t\tif m := wrongClusterRe.FindStringSubmatch(oe.Description); m != nil {
\t\t\thost := m[1];
\t\t\t// Copy the URL the user typed and swap only the host, so any
\t\t\t// escaped path (RawPath) or query stays byte-identical to what
\t\t\t// they originally ran.
\t\t\tcorrectedURL := *parsedURL;
\t\t\tcorrectedURL.Scheme = "entire";
\t\t\tcorrectedURL.Host = host;
```

Mcmd/git-remote-entire/main.go+3

```
51 unmodified lines

52
53
54
55
56
55
56
57
58
59
60
61
60
62
63
62
63
64
65
66
67
68
8 unmodified lines

77
78
79
80
81
82
83

51 unmodified lines

// TestPostOAuthToken_ErrorCode pins that a non-200 response surfaces as
// *OAuthError with the RFC 6749 `error` code parsed from the body (empty for
// non-JSON bodies), so callers can branch on e.g. invalid_target.
// *OAuthError with the RFC 6749 `error` code and `error_description` parsed
// from the body (both empty for non-JSON bodies), so callers can branch on
// e.g. invalid_target and render the description (the git-remote-entire
// wrong-cluster UX relies on Description being extracted here).
func TestPostOAuthToken_ErrorCode(t *testing.T) {
\tt.Parallel();
\tfor _, tc := range []struct {
\t\tname, body, wantCode string
\t\tname, body, wantCode, wantDesc string
\t} {
\t\t{"json error code", `{"error":"invalid_target","error_description":"no mirror"}`, "invalid_target"},
\t\t{"non-json body", `gateway exploded`, ""},
\t\t{"json error code", `{"error":"invalid_target","error_description":"no mirror"}`, "invalid_target", "no mirror"},
\t\t{"non-json body", `gateway exploded`, "", ""},
\t} {
\t\tt.Run(tc.name, func(t *testing.T) {
\t\t\tt.Parallel()
8 unmodified lines

\t\t\trequire.ErrorAs(t, err, &oe);
\t\t\tassert.Equal(t, http.StatusBadRequest, oe.Status);
\t\t\tassert.Equal(t, tc.wantCode, oe.Code);
\t\t\tassert.Equal(t, tc.wantDesc, oe.Description);
\t\t\tassert.Equal(t, tc.body, oe.Body);
\t\t});
\t}
}
```

Minternal/entireclient/httputil/oauth_test.go+8/-5
