Я нашел этот пример на Как обновить токен oauth с помощью moya и rxswift, который мне пришлось немного изменить, чтобы скомпилировать. Этот код работает на 80% для моего сценария. Проблема заключается в том, что он будет работать для всех ошибок HTTP, а не только 401 ошибок. Я хочу, чтобы все мои другие HTTP-ошибки передавались как ошибки, так что я могу обрабатывать их где-то там, а не проглатывать их здесь.
С помощью этого кода, если я получу HttpStatus 500
, он будет запускать код аутентификации 3 раза, что явно не то, что я хочу.
Ive попытался изменить этот код, чтобы обрабатывать только дескрипторы 401
, но кажется, что независимо от того, что я делаю, я не могу получить код для компиляции. Он всегда жалуется на неправильный тип возврата, "Cannot convert return expression of type Observable<Response> to return type Observable<Response>"
, который не имеет для меня никакого смысла.
Что я хочу: обрабатывать 401, но останавливаться на всех других ошибках
import RxSwift
import KeychainAccess
import Moya
public extension ObservableType where E == Response {
/// Tries to refresh auth token on 401 errors and retry the request.
/// If the refresh fails, the signal errors.
public func retryWithAuthIfNeeded() -> Observable<E> {
return self.retryWhen {
(e: Observable<ErrorType>) in
return Observable.zip(e, Observable.range(start: 1, count: 3), resultSelector: { $1 })
.flatMap { i in
return AuthProvider.sharedInstance.request(
.LoginFacebookUser(
accessToken: AuthenticationManager.defaultInstance().getLoginTokenFromKeyChain(),
useFaceBookLogin: AuthenticationManager.defaultInstance().isFacebookLogin())
)
.filterSuccessfulStatusCodes()
.mapObject(Accesstoken.self)
.catchError {
error in
log.debug("ReAuth error: \(error)")
if case Error.StatusCode(let response) = error {
if response.statusCode == 401 {
// Force logout after failed attempt
log.debug("401:, force user logout")
NSNotificationCenter.defaultCenter().postNotificationName(Constants.Notifications.userNotAuthenticated, object: nil, userInfo: nil)
}
}
return Observable.error(error)
}.flatMapLatest({
token -> Observable<Accesstoken> in
AuthenticationManager.defaultInstance().storeServiceTokenInKeychain(token)
return Observable.just(token)
})
}
}
}
}