Re-authorization and onRetry with Polly
Full source code available here.
Want to learn more about Polly? Check out my Pluralsight course on it.
In a previous post I showed how to use Polly to make a simple call, retrying in the event of failure. In another I showed how to let a request fail and process the response.
In this post I will show a retry where a delegate is called as part of the retry. A common use case for this is reauthorizing after an Unauthorized
response.
The difference between this policy and the ones in my previous posts is very small.
1public class ValuesController : ApiController
2{
3 readonly RetryPolicy<HttpResponseMessage> _httpRequestPolicy;
4 private HttpClient _httpClient;
5 public ValuesController()
6 {
7 _httpRequestPolicy = Policy.HandleResult<HttpResponseMessage>(
8 r => r.StatusCode == HttpStatusCode.InternalServerError ||
9 r.StatusCode == HttpStatusCode.Unauthorized)
10 .WaitAndRetryAsync(3, retryAttempt => TimeSpan.FromSeconds(retryAttempt), onRetry: (response, timespan) =>
11 {
12 if (response.Result.StatusCode == HttpStatusCode.Unauthorized)
13 {
14 PerformReauthorization();
15 }
16 });
17 }
The onRetry delegate is the new part -
1onRetry: (response, timespan) =>
2{
3 if (response.Result.StatusCode == HttpStatusCode.Unauthorized)
4 {
5 PerformReauthorization();
6 }
7}
In my PerformReauthorization
I create a new HttpClient
and pass it the new authorization code. For simplicity I am passing a code in the cookie of my request, you could of course use Basic Authentication or any another technique.
1private void PerformReauthorization()
2{
3 // here you would get a new token, call some other service, etc.
4 _httpClient = GetHttpClient("GoodAuthCode"); // pass in the good auth token
5}
The important thing to note is that my HttpClient instance is class level, meaning it can be accessed from PerformReauthorization
.
The call to the web service remains the same.
HttpResponseMessage httpResponse = await _httpRequestPolicy.ExecuteAsync(() => _httpClient.GetAsync(requestEndpoint))
I’ll post of fallbacks soon, they allow a default value to be returned in the event of repeated failures.
For completeness here is GetHttpClient
.
1private HttpClient GetHttpClient(string authCookieValue)
2{
3 var cookieContainer = new CookieContainer();
4 var handler = new HttpClientHandler() {CookieContainer = cookieContainer};
5 cookieContainer.Add(new Uri("http://localhost"),new Cookie("Auth", authCookieValue));
6 _httpClient = new HttpClient(handler);
7 _httpClient.BaseAddress = new Uri(@"http://localhost:2629/api/");
8
9 _httpClient.DefaultRequestHeaders.Accept.Clear();
10 _httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
11 return _httpClient;
12}
Full source code available here.