Usando retryWhen para atualizar tokens com base no código de erro http
Encontrei este exemplo emComo atualizar o token oauth usando moya e rxswift que tive que alterar um pouco para compilar. Este código funciona 80% para o meu cenário. O problema é que ele será executado para todos os erros http, e não apenas para erros 401. O que eu quero é que todos os meus outros erros http sejam passados como erros, para que eu possa lidar com eles em outros lugares e não engoli-los aqui.
Com esse código, se eu receber umHttpStatus 500
, ele executará o código de autenticação três vezes, o que obviamente não é o que eu quero.
Eu tentei alterar esse código para lidar apenas com identificador401
erros, mas parece que não importa o que eu faça, não consigo compilar o código. Está sempre reclamando sobre o tipo de retorno errado,"Cannot convert return expression of type Observable<Response> to return type Observable<Response>"
o que não faz sentido para mim ..
O que eu quero: lidar com 401, mas parar com todos os outros erros
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)
})
}
}
}
}