Skip to content

Commit d28c578

Browse files
authored
Merge pull request #107 from cli/babakks/handle-slow-down
fix: handle `slow_down` error
2 parents 6c44f68 + 5ffd590 commit d28c578

File tree

4 files changed

+414
-23
lines changed

4 files changed

+414
-23
lines changed

.github/workflows/ci.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ jobs:
55
test:
66
strategy:
77
matrix:
8-
go: [ '1.21', '1.22', '1.23' ]
8+
go: [ '1.21', '1.22', '1.23', '1.24', '1.25' ]
99
os: [ ubuntu-latest, macos-latest, windows-latest ]
1010
fail-fast: false
1111

@@ -15,7 +15,7 @@ jobs:
1515
steps:
1616
- uses: actions/checkout@v2
1717
- name: Setup Go
18-
uses: actions/setup-go@v1
18+
uses: actions/setup-go@v6
1919
with:
2020
go-version: ${{ matrix.go }}
2121
- name: Run tests

device/device_flow.go

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ type WaitOptions struct {
148148

149149
// Wait polls the server at uri until authorization completes.
150150
func Wait(ctx context.Context, c httpClient, uri string, opts WaitOptions) (*api.AccessToken, error) {
151-
checkInterval := time.Duration(opts.DeviceCode.Interval) * time.Second
151+
baseCheckInterval := time.Duration(opts.DeviceCode.Interval) * time.Second
152152
expiresIn := time.Duration(opts.DeviceCode.ExpiresIn) * time.Second
153153
grantType := opts.GrantType
154154
if opts.GrantType == "" {
@@ -159,7 +159,7 @@ func Wait(ctx context.Context, c httpClient, uri string, opts WaitOptions) (*api
159159
if makePoller == nil {
160160
makePoller = newPoller
161161
}
162-
_, poll := makePoller(ctx, checkInterval, expiresIn)
162+
_, poll := makePoller(ctx, baseCheckInterval, expiresIn)
163163

164164
for {
165165
if err := poll.Wait(); err != nil {
@@ -187,8 +187,35 @@ func Wait(ctx context.Context, c httpClient, uri string, opts WaitOptions) (*api
187187
token, err := resp.AccessToken()
188188
if err == nil {
189189
return token, nil
190-
} else if !(errors.As(err, &apiError) && apiError.Code == "authorization_pending") {
190+
}
191+
192+
if !errors.As(err, &apiError) {
191193
return nil, err
192194
}
195+
196+
if apiError.Code == "authorization_pending" {
197+
// Keep polling
198+
continue
199+
}
200+
201+
if apiError.Code == "slow_down" {
202+
// Based on the RFC spec, we must add 5 seconds to our current polling interval.
203+
// (See https://www.rfc-editor.org/rfc/rfc8628#section-3.5)
204+
newInterval := poll.GetInterval() + 5*time.Second
205+
206+
// GitHub OAuth API returns the new interval in seconds in the response.
207+
// We should try to use that if provided. It's okay if we couldn't find
208+
// it as we have already increased our interval as of the RFC spec.
209+
if s := resp.Get("interval"); s != "" {
210+
if v, err := strconv.ParseInt(s, 10, 64); err == nil && v > 0 {
211+
newInterval = time.Duration(v) * time.Second
212+
}
213+
}
214+
215+
poll.SetInterval(newInterval)
216+
continue
217+
}
218+
219+
return nil, err
193220
}
194221
}

0 commit comments

Comments
 (0)