diff --git a/digicert-certcentral-caplugin/Client/CertCentralClient.cs b/digicert-certcentral-caplugin/Client/CertCentralClient.cs index 753f54f..9060b22 100644 --- a/digicert-certcentral-caplugin/Client/CertCentralClient.cs +++ b/digicert-certcentral-caplugin/Client/CertCentralClient.cs @@ -73,7 +73,14 @@ private CertCentralResponse Request(CertCentralBaseRequest request) private static int RequestIDCounter = 1; + private const int MaxRateLimitRetries = 3; + private CertCentralResponse Request(CertCentralBaseRequest request, string parameters) + { + return Request(request, parameters, 1); + } + + private CertCentralResponse Request(CertCentralBaseRequest request, string parameters, int attempt) { //set in config files //ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12; @@ -129,10 +136,28 @@ private CertCentralResponse Request(CertCentralBaseRequest request, string param { if (errorResponse.StatusCode == (HttpStatusCode)429/*Too Many Requests*/) { - Logger.LogInformation($"Request ID: {reqID} was rate-limited. Trying again in 5 seconds"); - // TODO - Figure out how long to wait, then wait that long - System.Threading.Thread.Sleep(5000); - return Request(request, parameters); + // DigiCert's documented limits are 1000 requests / 3 minutes AND 100 / 5 + // seconds, rolling, per API key, and its guidance is exponential backoff + // with a default maximum of 3 retries. A fixed 5-second wait only ever + // clears the burst window, never the 3-minute one, and the retry was + // unbounded, so a genuine rate-limit became an endless 5-second poll with a + // growing stack rather than an error the caller could report. + if (attempt >= MaxRateLimitRetries) + { + Logger.LogWarning($"Request ID: {reqID} was rate-limited by DigiCert and has exhausted {MaxRateLimitRetries} attempts. Giving up."); + using (var limitReader = new StreamReader(errorResponse.GetResponseStream())) + { + oCertCertResponse.Success = false; + oCertCertResponse.Response = limitReader.ReadToEnd(); + } + } + else + { + int waitSeconds = 5 * (int)Math.Pow(2, attempt - 1); + Logger.LogInformation($"Request ID: {reqID} was rate-limited. Retry {attempt} of {MaxRateLimitRetries - 1} in {waitSeconds} seconds"); + System.Threading.Thread.Sleep(waitSeconds * 1000); + return Request(request, parameters, attempt + 1); + } } else {