Uso de retryWhen para actualizar tokens basados en el código de error http
Encontré este ejemplo enCómo actualizar el token oauth usando moya y rxswift que tuve que modificar ligeramente para poder compilar. Este código funciona 80% para mi escenario. El problema es que se ejecutará para todos los errores http, y no solo para los errores 401. Lo que quiero es que todos mis otros errores http pasen como errores, para que pueda manejarlos en otro lugar y no tragarlos aquí.
Con este código, si obtengo unHttpStatus 500
, ejecutará el código de autenticación 3 veces, lo que obviamente no es lo que quiero.
He tratado de alterar este código para manejar solo manejar401
errores, pero parece que no importa lo que haga, no puedo obtener el código para compilar. Siempre se queja del tipo de devolución incorrecto,"Cannot convert return expression of type Observable<Response> to return type Observable<Response>"
lo cual no tiene sentido para mí ..
Lo que quiero: manejar 401, pero detener todos los demás errores
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)
})
}
}
}
}