A simple HttpClientHandler which handles HTTP 429 (TooManyRequest) and also allows parallel pausing.
IHost host = Host.CreateDefaultBuilder()
.ConfigureAppConfiguration( /* Configure your app-config */)
.ConfigureLogging(/* Configure your logging */)
.ConfigureServices(services =>
services
.AddHttpClient()
// Here is where you add the handler
.ConfigurePrimaryHttpMessageHandler(_ => new TooManyRequestsHandler
{
// Any settings you want (since HttpClientHandler is derived from)
})
.ConfigureHttpClient((_, client) =>
{
client.DefaultRequestHeaders.Accept.Add(new("application/json"));
// might also add other settings
}))
.Services
.Build();
Simply provide the TooManyRequestsHandler
when constructing a new HttpClient
:
TooManyRequestsHandler handler = new
{
// Any settings you want (since HttpClientHandler is derived from)
};
HttpClient client = new(handler);
The library supports the following .NET versions:
- .NET 5+
- .NET Standard 2.1+
All other versions StatusCode.TooManyRequests
is not avaliable, therefore the library will not be supported for those versions.
This explains why you might get "The request was canceled due to the configured HttpClient.Timeout of 100 seconds elapsing." exception messages.
To fix the problem, simply set the HttpClient.Timeout
property to a greated value or infinite (TimeSpan.InfiniteTimeSpan
, or for < .NET 7 TimeSpan.FromMilliseconds(-1)
;
// For >= .NET 7
TimeSpan timeout = TimeSpan.InfiniteTimeSpan;
// For < .NET 7
TimeSpan timeout = TimeSpan.FromMilliseconds(-1);
// Using IHttpClientFactory
.ConfigureHttpClient((_, client) =>
{
client.Timeout = timeout;
})
// Or using constructor
HttpClient client = new(handler)
{
Timeout = timeout
};
The HttpClient
class holds a Timeout
property, which by default is set to 100 seconds. (More about it here)
That Timeout has nothing to do with requests directly, but rather with how long the HttpClient
s underlying HttpMessageHandler
takes. And since that handler in our case asynchronously waits until the time in the HttpResponseMessage.Headers.RetryAfter.Date
is reached, the time for a request will rise with each retry.
It's a very unfortunate problem and I haven't found a good fix for it yet (not setting the Timeout to infinite), but I would be glad if someone could help me fix it!