Я пишу мобильное приложение с Xamarin, поэтому мне нужна политика для повторных сетевых запросов. API, который вызывает мое приложение, предоставляет JWT, срок действия которого истекает, поэтому мне нужно автоматически повторно аутентифицироваться, если получен соответствующий ответ. Похоже, это должно быть тривиально с Полли, и в вики Полли даже говорится, что это тривиально, но я не могу заставить его работать.
Конечная цель:
- Запросы на повторную попытку 4 раза с интервалом в 2 секунды в случае сбоя в сети
- Если запрос когда-либо будет успешным и вернет действительный ответ, то полностью откажитесь от Полли, потому что мы получили то, что нам нужно.
- If the request succeeds but returns a 401 (meaning we need to reauthenticate):
- Use saved credentials and reauthenticate automatically
- Если учетные данные действительны, вернитесь к внешней политике повторных попыток при сбоях сети.
- Если учетные данные недействительны (конечная точка аутентификации возвращает 401), затем прервите работу и выйдите из системы.
Вот мой код. Если ответ успешен, это работает правильно. Он также повторяет попытки по мере необходимости при сбоях сети. Проблема в том, что когда получено 401, этот ответ всегда возвращается из политики. Повторная аутентификация вызывается и возвращается успешно, но Полли прерывается - исходный запрос не повторяется, и возвращается исходный ответ 401.
// example
var result = await RetryPolicy.ExecuteAndCaptureAsync(() => _client.SendAsync(request));
// policies
public static PolicyWrap<HttpResponseMessage> RetryPolicy
{
get => WaitAndRetryPolicy.WrapAsync(ReAuthPolicy);
}
private static IAsyncPolicy WaitAndRetryPolicy
{
get => Policy
.Handle<WebException>()
.Or<HttpRequestException>()
.WaitAndRetryAsync(4, _ => TimeSpan.FromSeconds(2));
}
private static IAsyncPolicy<HttpResponseMessage> ReAuthPolicy
{
get => Policy
.HandleResult<HttpResponseMessage>(x => x.StatusCode == HttpStatusCode.Unauthorized)
.RetryAsync(retryCount: 1, onRetryAsync: (_, __) => App.CoreService.LogInWithSavedCredsAsync(true));
}
ReAuthPolicy
(он повторяет аутентификацию только один раз; разумная практика). А внешнийWaitAndRetryPolicy
(намеренно) не обрабатывает 401. Поэтому я ожидаю, что он будет возвращен вызывающей стороне, если это то, что происходит. Стоит внимательно проверить, с пошаговой отладкой и точкой останова на_client.SendAsync(request)
. Просто возможность. - person mountain traveller   schedule 30.05.2018