You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
When configuring a timeout for HttpClient with AddPolicyHandler, then using the HttpClient to download a file, the policy is ignored.
Expected behavior:
With a large download that normally takes n>100 seconds and setting a long timeout x>n seconds, the download should succeed.
With a smaller download that normally takes n<100 seconds, and setting a short timeout x<n seconds, the request should fail, throwing a Timeout or TaskCanceled exception after x seconds.
Actual behavior:
The client throws a TaskCanceled exception after approx, 100 seconds (which is the default HttpClient timeout).
The download succeeds.
Code to reproduce the problem:
Program.cs
using Microsoft.Extensions.DependencyInjection;using Polly;using System;using System.Diagnostics;using System.Net.Http;using System.Threading.Tasks;namespaceTimeoutTest{classProgram{staticIHttpClientFactoryfactory;staticinti=0;staticasync Task Main(string[]args){varservices=new ServiceCollection();//setting timeout via policy
services.AddHttpClient("p200").AddPolicyHandler(Policy.TimeoutAsync<HttpResponseMessage>(TimeSpan.FromMilliseconds(200)));
services.AddHttpClient("p2000").AddPolicyHandler(Policy.TimeoutAsync<HttpResponseMessage>(TimeSpan.FromMilliseconds(2000)));
services.AddHttpClient("p200_000").AddPolicyHandler(Policy.TimeoutAsync<HttpResponseMessage>(TimeSpan.FromMilliseconds(200_000)));//setting timeout via config
services.AddHttpClient("c200",config => config.Timeout = TimeSpan.FromMilliseconds(200));
services.AddHttpClient("c2000",config => config.Timeout = TimeSpan.FromMilliseconds(2000));
services.AddHttpClient("c200_000",config => config.Timeout = TimeSpan.FromMilliseconds(200_000));varserviceProvider= services.BuildServiceProvider();factory= serviceProvider.GetService<IHttpClientFactory>();
Console.WriteLine("Using policy-based timeout:");await TestDownload("http://download.inspire.net.nz/data/200MB.zip","p200_000");await TestDownload("http://download.inspire.net.nz/data/20MB.zip","p2000");await TestDownload("http://download.inspire.net.nz/data/20MB.zip","p200");
Console.WriteLine("\nUsing config-based timeout:");await TestDownload("http://download.inspire.net.nz/data/200MB.zip","c200_000");await TestDownload("http://download.inspire.net.nz/data/20MB.zip","c2000");
Console.WriteLine("\nUsing policy-based timeout for a long running request with a small response:");await TestDownload("http://httpbin.org/delay/5","p2000");}staticasync Task TestDownload(stringurl,stringclientName){varwatch=new Stopwatch();
watch.Start();try{
Console.WriteLine($"#{++i} Url: {url}, Timeout: {clientName.Substring(1)}ms");await factory.CreateClient(clientName).GetAsync(url).Result.Content.ReadAsByteArrayAsync();
watch.Stop();
Console.WriteLine($" Result: Success, Elapsed: {watch.ElapsedMilliseconds}ms");}catch(AggregateExceptionex)when(ex.InnerException is Polly.Timeout.TimeoutRejectedException){
Console.WriteLine($" Result: TimeoutRejected, Elapsed: {watch.ElapsedMilliseconds}ms");}catch(AggregateExceptionex)when(ex.InnerException is TaskCanceledException){
Console.WriteLine($" Result: TaskCanceled, Elapsed: {watch.ElapsedMilliseconds}ms");}catch(Exceptionex){
Console.WriteLine(ex.ToString());throw;}}}}
Using policy-based timeout:
#1 Url: http://download.inspire.net.nz/data/512MB.zip, Timeout: 300_000ms
Result: TaskCanceled, Elapsed: 100379ms
#2 Url: http://download.inspire.net.nz/data/20MB.zip, Timeout: 3000ms
Result: Success, Elapsed: 11079ms
Using config-based timeout:
#3 Url: http://download.inspire.net.nz/data/512MB.zip, Timeout: 300_000ms
Result: Success, Elapsed: 193739ms
#4 Url: http://download.inspire.net.nz/data/20MB.zip, Timeout: 3000ms
Result: TaskCanceled, Elapsed: 3044ms
Using policy-based timeout for a long running request with a small response:
#5 Url: http://httpbin.org/delay/5, Timeout: 3000ms
Result: TimeoutRejected, Elapsed: 3016ms
Using policy-based timeout with a very short timeout:
#6 Url: http://download.inspire.net.nz/data/20MB.zip, Timeout: 300ms
Result: TimeoutRejected, Elapsed: 327ms
Remarks:
Attempts 1 & 2 demonstrate the unexpected behavior described above.
3 & 4 demonstrate how similar requests, using a config-based timeout, behave as expected.
5 & 6 are sanity checks that demonstrate cases where policy-based timeouts do behave as expected
Of course the actual download times may vary according to your internet speed, so you may have to download different sized files, and/or specify different timeout values in order to reproduce the problem.
The text was updated successfully, but these errors were encountered:
Summary:
When configuring a timeout for HttpClient with AddPolicyHandler, then using the HttpClient to download a file, the policy is ignored.
Expected behavior:
Actual behavior:
Code to reproduce the problem:
Program.cs
TimeoutTest.csproj
Output:
Remarks:
Attempts 1 & 2 demonstrate the unexpected behavior described above.
3 & 4 demonstrate how similar requests, using a config-based timeout, behave as expected.
5 & 6 are sanity checks that demonstrate cases where policy-based timeouts do behave as expected
Of course the actual download times may vary according to your internet speed, so you may have to download different sized files, and/or specify different timeout values in order to reproduce the problem.
The text was updated successfully, but these errors were encountered: