5

I have a Typed Client which i have configured in the services and i am using Polly to make retries for transient faults.

Aim: I want to make use of Polly to implement refresh token, whenever there is a 401 response from the target site, i want Polly to refresh the token and continue the initial request again.

The problem is the typed client has all the api methods and the refresh token method, when the request is initiated from the typed client how do i access the typed client again to call the refresh token and continue the initial request?

The 'Context' in onRetry provides some support to add any object to the dictionary, but i am unable to access the SetPolicyExecutionContext('someContext') method and i do not want to add this on all the methods before initiating the call as there's whole lot of API.

// In Service Configuration

// Refresh token policy

var refreshTokenPolicy = Polly.Policy.HandleResult<HttpResponseMessage>(r => r.StatusCode == HttpStatusCode.Unauthorized)
.RetryAsync(1, (response, retrycount, context)) =>
{
    if(response.Result.StatusCode == HttpStatusCode.Unauthorized)
    {
         // Perform refresh token
    }
}

// Typed Client 
services.AddHttpClient<TypedClient>();

public class TypedClient
{
    private static HttpClient _client;
    public TypedClient(HttpClient client)
    {
        _client = client;
    }

    public string ActualCall()
    {
        // some action
    }

    public string RefreshToken()
    {
        // Refresh the token and return
    }
}
Peter Csala
  • 17,736
  • 16
  • 35
  • 75
kartik rajan
  • 115
  • 1
  • 5
  • Do any of these three blog posts covering the topic help? 1) https://nodogmablog.bryanhogan.net/2017/05/re-authorization-and-onretry-with-polly/ ; 2) https://diaryofadev.net/2017/05/oath-with-polly/ ; 3) https://www.jerriepelser.com/blog/refresh-google-access-token-with-polly/ . Number 3) sounds very similar. – mountain traveller Jul 10 '19 at 18:22
  • @mountaintraveller None of these are what OP is doing specifically. OP has proper separation of concerns; all of these sources shove polly right into the actions of the HttpClient instead of wrapping Polly around the Typed HttpClient – 8protons Nov 19 '20 at 00:52

1 Answers1

8

You can useAddPolicyHandler which has an overload that passesIServiceProvider. So all you need to do is something like:

services.AddHttpClient<TypedClient>()
    .AddPolicyHandler((provider, request) =>
    {
        return Policy.HandleResult<HttpResponseMessage>(r => r.StatusCode == HttpStatusCode.Unauthorized)
            .RetryAsync(1, (response, retryCount, context) =>
            {
                var client = provider.GetRequiredService<TypedClient>();
                // refresh auth token.
            });
        });
    });
Chris Pratt
  • 232,153
  • 36
  • 385
  • 444
  • This was very helpful. I ended up keeping an AccessToken private property with the most current token received. It worked out well. – Yehuda Makarov Mar 09 '20 at 18:58
  • 2
    Isn't it asking for trouble to call the same get service from Polly? TypeClient.Get falls into Polly, Polly then calls TypedClient.Get, which then fails and falls into Polly again... – 8protons Nov 19 '20 at 18:56
  • How do I update Authorization header in HttpClient which will retry a request? provider.GetRequiredService() will return a new instance of HttpClient and retry will still fail as far as I understand – Maksim Ramanovich Jul 08 '22 at 08:23
  • This does not address the original question: how do you change the default header authentication token from here? This will get a new token just for the current request. So this answer will fail every time you try to contact the server, then find a token, then try again. Very, very inefficient. – Quark Soup Oct 04 '22 at 23:34