I'm using Polly to retry HttpClient attemnpts :
services.AddHttpClient<JoinPackageApiClient>(jp => { jp.BaseAddress = new Uri(appSettings.JoinPackageWS.BaseUrl); })
.AddPolicyHandler(GetRetryPolicy(appSettings, serviceProvider))
Where GetRetryPolicy
is :
private static IAsyncPolicy<HttpResponseMessage> GetRetryPolicy(AppSettings appSettings, ServiceProvider serviceProvider)
{
return HttpPolicyExtensions
.HandleTransientHttpError()
.OrResult(msg => msg.StatusCode != HttpStatusCode.OK)
.Or<TimeoutRejectedException>()
.Or<TaskCanceledException>()
.Or<OperationCanceledException>()
.WaitAndRetryAsync(appSettings.PollySettings.RetryAttempts, (retryAttempt, c) =>
{
return TimeSpan.FromSeconds(2);
}, onRetry: (response, delay, retryCount, context) =>
{
//█how can I access the full(!) HttpClient's URI here ?
//e.g. : https://a.com/b/c?d=1
});
}
Question:
Looking at the onRetry
parameter, I want to log the full URL attempt in the onRetry
section.
How can I get the full URI in that section ?
I was wrong when I have stated in my comment that this is not possible.
I have to correct myself: Yes, it is doable and it is actually pretty easy. :)
All you need to do is to use a different overload of AddPolicyHandler
public static IHttpClientBuilder AddPolicyHandler (this IHttpClientBuilder builder, Func<IServiceProvider,HttpRequestMessage,IAsyncPolicy<HttpResponseMessage>> policySelector);
So, whenever you call the AddPolicyHandler
you have to provide a function, which
IServiceProvider
instance to be able to access to any DI registered serviceRequestUri
propertyIAsyncPolicy<HttpResponseMessage>
So, you have to modify the registration code like this:
services.AddHttpClient<JoinPackageApiClient>(jp => ...)
.AddPolicyHandler((provider, request) => GetRetryPolicy(appSettings, provider, request));
and the GetRetryPolicy
method like this:
private static IAsyncPolicy<HttpResponseMessage> GetRetryPolicy(
AppSettings appSettings,
IServiceProvider serviceProvider,
HttpRequestMessage request)
=> HttpPolicyExtensions
.HandleTransientHttpError()
...
.WaitAndRetryAsync(appSettings.PollySettings.RetryAttempts,
(_, __) => TimeSpan.FromSeconds(2),
(response, delay, retryCount, context) =>
{
var url = request.RequestUri;
// ...
});
The good news is that the url will change whenever you issue a new request.
(In my test client I have set the BaseAddress to http://httpstat.us
)
When I run this test
await client.GetAsync("/200");
try
{
await client.GetAsync("/401");
}
catch { }
await client.GetAsync("/403");
then the retry triggered 4 times (2x for 401 and 2x for 403). The onRetry
received the related HttpRequestMessage
so, the logging was accurate.