Обработка повторной аутентификации с помощью RxSwift и Moya

У меня есть проект, в котором я использую Moya с расширениями RxSwift. Простые варианты использования работают нормально, я могу выполнять запросы и получать ответы в виде Observables.

public func test() -> Observable<Response> {
    return provider
    .request(.test)
    .retry(5)
}

Затем я могу подписаться на наблюдаемое и без проблем распечатать ответ.

Но теперь мне нужно обработать логику аутентификации. Это работает так: я запускаю вышеуказанный запрос с токеном, добавленным в качестве поля заголовка HTTP. Moya позволяет мне сделать это прозрачно, используя endpointByAddingHTTPHeaderFields в endpointClosure. Пока проблем нет.

Проблема возникает, когда запрос не выполняется со статусом HTTP 401, это означает, что мне нужно повторно пройти аутентификацию, вызвав другую конечную точку.

provider.request(.auth(user, pass)).retry(5)

Это возвращает другой Observable, который я могу легко сопоставить с JSON, чтобы получить новый токен.

Затем мне просто нужно снова вызвать test ()!

Итак, мой вопрос ... Как я могу добавить эту логику аутентификации внутри функции test () выше, чтобы Observable возвращал test () уже гарантированно запускает логику повторной аутентификации в случае сбоя и является результатом второго запроса с повторной аутентификацией.

Я новичок в RXSwift и RX в целом, поэтому я немного не понимаю, какие операторы я бы использовал для этого.

Спасибо!


person genericperson    schedule 09.12.2015    source источник
comment
Вы когда-нибудь решали это?   -  person tskulbru    schedule 02.07.2016
comment
Ошибка 401 или действительный объект ответа?   -  person Daniel T.    schedule 17.07.2016
comment
В первом случае вам может помочь следующий ответ: stackoverflow.com/questions/35841054/   -  person Daniel T.    schedule 17.07.2016


Ответы (1)


public func test(with authToken: String) -> Observable<Response> {
    return provider
      .request(.test)
      .endpointByAddingHTTPHeaderFields(["Authorization": authToken])
      .catchError { error in
        if needsReauth(error) {
          return provider.request(.auth(user, pass)).map { parseToken($0) }
            .flatMap { token in
              return test(with: token)
            }
        } else {
          return .error(error)
        }
      }
}

catchError позволяет продолжить выполнение наблюдаемого с использованием другого наблюдаемого. Наблюдаемая, которую мы здесь определяем, делает следующее:

  1. Сначала он запросит конечную точку .auth.
  2. Затем он читает из ответа, чтобы получить новый токен аутентификации.
  3. Наконец, мы рекурсивно вызываем test(with authToken: String), чтобы повторить запрос тестовой точки.
person tomahh    schedule 25.01.2017