@@ -34,7 +34,13 @@ pub mod solvers;
34
34
pub mod types;
35
35
36
36
const DEFAULT_RETRY_INTERVAL : Duration = Duration :: from_secs ( 1 ) ;
37
- const MAX_RETRY_INTERVAL : Duration = Duration :: from_secs ( 8 ) ;
37
+
38
+ /// Upper limit for locally generated increasing backoff interval.
39
+ const MAX_BACKOFF_INTERVAL : Duration = Duration :: from_secs ( 8 ) ;
40
+
41
+ /// Upper limit for server-generated retry intervals (Retry-After).
42
+ const MAX_SERVER_RETRY_INTERVAL : Duration = Duration :: from_secs ( 60 ) ;
43
+
38
44
static REPLAY_NONCE : http:: HeaderName = http:: HeaderName :: from_static ( "replay-nonce" ) ;
39
45
40
46
pub enum NewAccountOutput < ' a > {
@@ -232,10 +238,22 @@ where
232
238
233
239
let err: types:: Problem = deserialize_body ( res. body ( ) ) ?;
234
240
235
- let retriable = matches ! (
236
- err. kind,
237
- types:: ErrorKind :: BadNonce | types:: ErrorKind :: RateLimited
238
- ) ;
241
+ let retriable = match err. kind {
242
+ types:: ErrorKind :: RateLimited => {
243
+ // The server may ask us to retry in several hours or days.
244
+ if let Some ( val) = res
245
+ . headers ( )
246
+ . get ( http:: header:: RETRY_AFTER )
247
+ . and_then ( parse_retry_after)
248
+ . filter ( |x| x > & MAX_SERVER_RETRY_INTERVAL )
249
+ {
250
+ return Err ( RequestError :: RateLimited ( val) ) ;
251
+ }
252
+ true
253
+ }
254
+ types:: ErrorKind :: BadNonce => true ,
255
+ _ => false ,
256
+ } ;
239
257
240
258
if retriable && wait_for_retry ( & res, & mut tries) . await {
241
259
ngx_log_debug ! ( self . log. as_ptr( ) , "retrying failed request ({err})" ) ;
@@ -416,7 +434,7 @@ where
416
434
_ => order. status = OrderStatus :: Processing ,
417
435
} ;
418
436
419
- let mut tries = backoff ( MAX_RETRY_INTERVAL , self . finalize_timeout ) ;
437
+ let mut tries = backoff ( MAX_BACKOFF_INTERVAL , self . finalize_timeout ) ;
420
438
421
439
while order. status == OrderStatus :: Processing && wait_for_retry ( & res, & mut tries) . await {
422
440
drop ( order) ;
@@ -466,7 +484,7 @@ where
466
484
return Err ( NewCertificateError :: ChallengeStatus ( result. status ) ) ;
467
485
}
468
486
469
- let mut tries = backoff ( MAX_RETRY_INTERVAL , self . authorization_timeout ) ;
487
+ let mut tries = backoff ( MAX_BACKOFF_INTERVAL , self . authorization_timeout ) ;
470
488
wait_for_retry ( & res, & mut tries) . await ;
471
489
472
490
let result = loop {
@@ -552,7 +570,8 @@ async fn wait_for_retry<B>(
552
570
. headers ( )
553
571
. get ( http:: header:: RETRY_AFTER )
554
572
. and_then ( parse_retry_after)
555
- . unwrap_or ( interval) ;
573
+ . unwrap_or ( interval)
574
+ . min ( MAX_SERVER_RETRY_INTERVAL ) ;
556
575
557
576
sleep ( retry_after) . await ;
558
577
true
0 commit comments