I'm trying to implement retry using DelegatingHandler but I also want to set HttpCompletionOption.
My code looks like following :
public class RetryHandler : DelegatingHandler
{
private readonly int MaxRetries;
public RetryHandler(HttpMessageHandler innerHandler, int retryCount = 3)
: base(innerHandler)
{
MaxRetries = retryCount;
}
protected override async Task<HttpResponseMessage> SendAsync(
HttpRequestMessage request,
CancellationToken cancellationToken)
{
HttpResponseMessage response = null;
for (var i = 0; i < MaxRetries; i++)
{
response = await base.SendAsync(request, cancellationToken);
if (response.IsSuccessStatusCode)
{
return response;
}
}
return response;
}
}
static void Main(string[] args)
{
using (var client = new HttpClient(new RetryHandler(new HttpClientHandler())))
{
var request = new HttpRequestMessage(HttpMethod.Post, "https://ptsv2.com/t/smz9v-1564979884/post");
var myResult = client.SendAsync(request).Result;
Console.WriteLine(myResult.ToString());
}
Console.ReadLine();
}
As you can see there is no option to set HttpCompletionOption by inheriting DelegatingHandler, I tried creating CustomDelegatinghandler but in that case I'm unable to use new RetryHandler(new HttpClientHandler()) as I have used in the main method.
Is there any way to implement DelegatingHandler(or custom) that has/ supports following signature?
protected override async Task<HttpResponseMessage> SendAsync(
HttpRequestMessage request, HttpCompletionOption option,
CancellationToken cancellationToken)
Any help would be appreciated. Thanks,
You don't need to include HttpCompletionOption
in the message handler signature, because handling HttpCompletionOption
is responsibility of HttpClient
, not of HttpMessageHandler
.
An HttpMessageHandler
must initiate a task of sending a request and return a Task<HttpResponseMessage>
as early as possible. In general, it should not perform any buffering of the response content (well, unless it's a middleware created for the purpose of buffering), and that's why it doesn't receive HttpCompletionOption
. It should always act as if it was passed HttpCompletionOption.ResponseHeadersRead
.
The intended way to specify HttpCompletionOption
is include it in a call to an overload of HttpClient
method such as GetAsync
or SendAsync
:
client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead);
Roughly speaking, HttpClient
handles HttpCompletionOption
as follows:
Task<HttpResponseMessage>
(see code)HttpCompletionOption.ResponseHeadersRead
is specified, then done: return the task to the caller (see code)HttpCompletionOption.ResponseContentRead
is specified, then instead, return the task of HttpContent.LoadIntoBufferAsync
, as a continuation of the original Task<HttpResponseMessage>
(see code)