Retry transient HTTP errors with a handler
C#
using System;
using System.Net;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
/// <summary>Retries idempotent requests on 429, 5xx or network errors.</summary>
public sealed class RetryHandler : DelegatingHandler
{
private const int MaxAttempts = 4;
public RetryHandler(HttpMessageHandler inner) : base(inner) { }
protected override async Task<HttpResponseMessage> SendAsync(
HttpRequestMessage request, CancellationToken cancellationToken)
{
for (var attempt = 1; ; attempt++)
{
try
{
var response = await base.SendAsync(request, cancellationToken);
if (!ShouldRetry(response.StatusCode) || attempt == MaxAttempts)
{
return response;
}
response.Dispose();
}
catch (HttpRequestException) when (attempt < MaxAttempts)
{
// Network error: fall through to the backoff below.
}
var delay = TimeSpan.FromMilliseconds(200 * Math.Pow(2, attempt - 1));
await Task.Delay(delay, cancellationToken);
}
}
private static bool ShouldRetry(HttpStatusCode code) =>
code == HttpStatusCode.TooManyRequests || (int)code >= 500;
}