TooManyRequestsHandler 1.0.0

dotnet add package TooManyRequestsHandler --version 1.0.0                
NuGet\Install-Package TooManyRequestsHandler -Version 1.0.0                
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="TooManyRequestsHandler" Version="1.0.0" />                
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add TooManyRequestsHandler --version 1.0.0                
#r "nuget: TooManyRequestsHandler, 1.0.0"                
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
// Install TooManyRequestsHandler as a Cake Addin
#addin nuget:?package=TooManyRequestsHandler&version=1.0.0

// Install TooManyRequestsHandler as a Cake Tool
#tool nuget:?package=TooManyRequestsHandler&version=1.0.0                

TooManyRequestsHandler

A simple HttpClientHandler which handles HTTP 429 (TooManyRequest) and also allows parallel pausing.

How to Use

Using IHttpClientFactory

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();

In HttpClient-Constructor

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);

Compatibility

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.

Inconveniences

This explains why you might get "The request was canceled due to the configured HttpClient.Timeout of 100 seconds elapsing." exception messages.

Fix

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
};

Explanation

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 HttpClients 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!

Product Compatible and additional computed target framework versions.
.NET net5.0 is compatible.  net5.0-windows was computed.  net6.0 is compatible.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 was computed.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed. 
.NET Core netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard2.1 is compatible. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last updated
1.0.0 198 2/9/2023

Initial release