Skip to content

Commit ca91fe7

Browse files
author
Adam Talbot
committed
acme: add RetryAfter field to the Authorization object returned by GetAuthorization.
When using WaitAuthorization is not practical due to its blocking, for example in Kubernetes controllers, the GetAuthorization can be used. This change adds the RetryAfter field to the Authorization object returned by GetAuthorization so it can be used by these implementations that use their own polling mechanism. The new RetryAfter field is populated by the "Retry-After" header in the HTTP response. The WaitAuthorization method will never set this new field, since it does not return while the challenges are still pending. Signed-off-by: Adam Talbot <[email protected]>
1 parent b3790b8 commit ca91fe7

File tree

2 files changed

+14
-4
lines changed

2 files changed

+14
-4
lines changed

acme/acme.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -381,7 +381,7 @@ func (c *Client) authorize(ctx context.Context, typ, val string) (*Authorization
381381
if v.Status != StatusPending && v.Status != StatusValid {
382382
return nil, fmt.Errorf("acme: unexpected status: %s", v.Status)
383383
}
384-
return v.authorization(res.Header.Get("Location")), nil
384+
return v.authorization(res.Header.Get("Location"), 0), nil
385385
}
386386

387387
// GetAuthorization retrieves an authorization identified by the given URL.
@@ -402,7 +402,8 @@ func (c *Client) GetAuthorization(ctx context.Context, url string) (*Authorizati
402402
if err := json.NewDecoder(res.Body).Decode(&v); err != nil {
403403
return nil, fmt.Errorf("acme: invalid response: %v", err)
404404
}
405-
return v.authorization(url), nil
405+
d := retryAfter(res.Header.Get("Retry-After"))
406+
return v.authorization(url, d), nil
406407
}
407408

408409
// RevokeAuthorization relinquishes an existing authorization identified
@@ -460,7 +461,7 @@ func (c *Client) WaitAuthorization(ctx context.Context, url string) (*Authorizat
460461
case err != nil:
461462
// Skip and retry.
462463
case raw.Status == StatusValid:
463-
return raw.authorization(url), nil
464+
return raw.authorization(url, 0), nil
464465
case raw.Status == StatusInvalid:
465466
return nil, raw.error(url)
466467
}

acme/types.go

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -426,6 +426,14 @@ type Authorization struct {
426426
//
427427
// This field is unused in RFC 8555.
428428
Combinations [][]int
429+
430+
// RetryAfter specifies how long the client should wait before polling the
431+
// authorization resource again, if indicated by the server.
432+
// This corresponds to the optional Retry-After HTTP header included in a
433+
// 200 (OK) response when the authorization is still StatusPending.
434+
//
435+
// See RFC 8555 Section 7.5.1.
436+
RetryAfter time.Duration
429437
}
430438

431439
// AuthzID is an identifier that an account is authorized to represent.
@@ -471,7 +479,7 @@ type wireAuthz struct {
471479
Error *wireError
472480
}
473481

474-
func (z *wireAuthz) authorization(uri string) *Authorization {
482+
func (z *wireAuthz) authorization(uri string, retryAfter time.Duration) *Authorization {
475483
a := &Authorization{
476484
URI: uri,
477485
Status: z.Status,
@@ -480,6 +488,7 @@ func (z *wireAuthz) authorization(uri string) *Authorization {
480488
Wildcard: z.Wildcard,
481489
Challenges: make([]*Challenge, len(z.Challenges)),
482490
Combinations: z.Combinations, // shallow copy
491+
RetryAfter: retryAfter,
483492
}
484493
for i, v := range z.Challenges {
485494
a.Challenges[i] = v.challenge()

0 commit comments

Comments
 (0)