Сочетание перехвата переходных неисправностей с повторной авторизацией в Polly

Я пишу мобильное приложение с 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));
}

person vaindil    schedule 30.05.2018    source источник
comment
Возможно ли, что на самом деле повторная аутентификация не работает? И что возвращается не исходный ответ 401, а второй ответ 401? Тогда этот второй ответ 401 не будет обрабатываться внутренним ReAuthPolicy (он повторяет аутентификацию только один раз; разумная практика). А внешний WaitAndRetryPolicy (намеренно) не обрабатывает 401. Поэтому я ожидаю, что он будет возвращен вызывающей стороне, если это то, что происходит. Стоит внимательно проверить, с пошаговой отладкой и точкой останова на _client.SendAsync(request). Просто возможность.   -  person mountain traveller    schedule 30.05.2018
comment
@mountaintraveller Вот и все. Я сделал шаг вперед, чтобы убедиться, что этого не произошло, до того, как опубликовал это, но, похоже, я сделал это неправильно. Большое спасибо!   -  person vaindil    schedule 31.05.2018


Ответы (1)


Оказывается, мой код в конце концов был правильным, я просто неправильно установил учетные данные для авторизации в своей функции LogInWithSavedCredentials.

person vaindil    schedule 31.05.2018