Skip to content

Commit c7ba47a

Browse files
committed
chore: Switch legacy redirect handling to new pattern (google#4161)
1 parent c44d7dd commit c7ba47a

4 files changed

Lines changed: 45 additions & 45 deletions

File tree

github/github.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ var ErrPathForbidden = errors.New("path must not contain '..' due to auth vulner
164164

165165
// A Client manages communication with the GitHub API.
166166
type Client struct {
167-
clientMu sync.Mutex // clientMu protects the client during calls that modify the CheckRedirect func.
167+
clientMu sync.Mutex // clientMu protects the client fields during copy and Client calls.
168168
client *http.Client // HTTP client used to communicate with the API.
169169
clientIgnoreRedirects *http.Client // HTTP client used to communicate with the API on endpoints where we don't want to follow redirects.
170170

github/migrations.go

Lines changed: 6 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,6 @@ import (
99
"context"
1010
"errors"
1111
"fmt"
12-
"net/http"
13-
"strings"
1412
)
1513

1614
// MigrationService provides access to the migration related functions
@@ -186,29 +184,18 @@ func (s *MigrationService) MigrationArchiveURL(ctx context.Context, org string,
186184
if err != nil {
187185
return "", err
188186
}
189-
190187
req.Header.Set("Accept", mediaTypeMigrationsPreview)
191188

192-
s.client.clientMu.Lock()
193-
defer s.client.clientMu.Unlock()
194-
195-
// Disable the redirect mechanism because AWS fails if the GitHub auth token is provided.
196-
var loc string
197-
saveRedirect := s.client.client.CheckRedirect
198-
s.client.client.CheckRedirect = func(req *http.Request, _ []*http.Request) error {
199-
loc = req.URL.String()
200-
return errors.New("disable redirect")
189+
loc, _, err := s.client.bareDoUntilFound(ctx, req, 10)
190+
if err != nil {
191+
return "", err
201192
}
202-
defer func() { s.client.client.CheckRedirect = saveRedirect }()
203193

204-
_, err = s.client.Do(ctx, req, nil) // expect error from disable redirect
205-
if err == nil {
194+
if loc == nil {
206195
return "", errors.New("expected redirect, none provided")
207196
}
208-
if !strings.Contains(err.Error(), "disable redirect") {
209-
return "", err
210-
}
211-
return loc, nil
197+
198+
return loc.String(), nil
212199
}
213200

214201
// DeleteMigration deletes a previous migration archive.

github/migrations_test.go

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ func TestMigrationService_MigrationStatus(t *testing.T) {
128128
})
129129
}
130130

131-
func TestMigrationService_MigrationArchiveURL(t *testing.T) {
131+
func TestMigrationService_MigrationArchiveURL_Redirect(t *testing.T) {
132132
t.Parallel()
133133
client, mux, _ := setup(t)
134134

@@ -161,6 +161,28 @@ func TestMigrationService_MigrationArchiveURL(t *testing.T) {
161161
})
162162
}
163163

164+
func TestMigrationService_MigrationArchiveURL_NoRedirect(t *testing.T) {
165+
t.Parallel()
166+
client, mux, _ := setup(t)
167+
168+
mux.HandleFunc("/orgs/o/migrations/1/archive", func(w http.ResponseWriter, r *http.Request) {
169+
testMethod(t, r, "GET")
170+
testHeader(t, r, "Accept", mediaTypeMigrationsPreview)
171+
172+
w.WriteHeader(http.StatusOK)
173+
assertWrite(t, w, []byte("0123456789abcdef"))
174+
})
175+
176+
ctx := t.Context()
177+
got, err := client.Migrations.MigrationArchiveURL(ctx, "o", 1)
178+
if err == nil {
179+
t.Error("Migrations.MigrationArchiveURL did not return expected error")
180+
}
181+
if got != "" {
182+
t.Errorf("MigrationArchiveURL = %+v, want %+v", got, "")
183+
}
184+
}
185+
164186
func TestMigrationService_DeleteMigration(t *testing.T) {
165187
t.Parallel()
166188
client, mux, _ := setup(t)

github/repos_releases.go

Lines changed: 15 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -365,36 +365,27 @@ func (s *RepositoriesService) DownloadReleaseAsset(ctx context.Context, owner, r
365365
}
366366
req.Header.Set("Accept", defaultMediaType)
367367

368-
s.client.clientMu.Lock()
369-
defer s.client.clientMu.Unlock()
370-
371-
var loc string
372-
saveRedirect := s.client.client.CheckRedirect
373-
s.client.client.CheckRedirect = func(req *http.Request, _ []*http.Request) error {
374-
loc = req.URL.String()
375-
return errors.New("disable redirect")
368+
loc, resp, err := s.client.bareDoUntilFound(ctx, req, 10)
369+
if err != nil {
370+
return nil, "", err
376371
}
377-
defer func() { s.client.client.CheckRedirect = saveRedirect }()
378372

379-
req = withContext(ctx, req)
380-
resp, err := s.client.client.Do(req)
381-
if err != nil {
382-
if !strings.Contains(err.Error(), "disable redirect") {
383-
return nil, "", err
384-
}
385-
if followRedirectsClient != nil {
386-
rc, err := s.downloadReleaseAssetFromURL(ctx, followRedirectsClient, loc)
387-
return rc, "", err
388-
}
389-
return nil, loc, nil // Intentionally return no error with valid redirect URL.
373+
// No redirect, stream the response body directly.
374+
if loc == nil {
375+
return resp.Body, "", nil
390376
}
391377

392-
if err := CheckResponse(resp); err != nil {
393-
_ = resp.Body.Close()
394-
return nil, "", err
378+
// Close body as it's not needed when following redirects or returning the redirect URL.
379+
_ = resp.Body.Close()
380+
381+
// Got a redirect URL.
382+
redirectStr := loc.String()
383+
if followRedirectsClient != nil {
384+
rc, err := s.downloadReleaseAssetFromURL(ctx, followRedirectsClient, redirectStr)
385+
return rc, "", err
395386
}
396387

397-
return resp.Body, "", nil
388+
return nil, redirectStr, nil
398389
}
399390

400391
func (s *RepositoriesService) downloadReleaseAssetFromURL(ctx context.Context, followRedirectsClient *http.Client, url string) (rc io.ReadCloser, err error) {

0 commit comments

Comments
 (0)