Skip to content

Instantly share code, notes, and snippets.

@dmitryshliugaev
Last active May 8, 2018 19:00
Show Gist options
  • Save dmitryshliugaev/cd14420e1884677263b5d5d3032e242e to your computer and use it in GitHub Desktop.
Save dmitryshliugaev/cd14420e1884677263b5d5d3032e242e to your computer and use it in GitHub Desktop.
RXMoya renew token
MyMoyaProvider.rx.request(.requestMessages)
.filterSuccessfulStatusCodes()
.retryWithAuthIfNeeded()
.mapObject(MapToMyObject.self)
.subscribe { event in
switch event {
case .success(let mapObject):
//do something
case .error(let error):
//send to error observer
self.error.onNext(error)
}
}
//MARK: – Renew token
public extension PrimitiveSequence where TraitType == SingleTrait, ElementType == Response {
public func retryWithAuthIfNeeded() -> Single<ElementType> {
return catchError { error -> PrimitiveSequence<SingleTrait, Response> in
if let moyaError: MoyaError = error as? MoyaError, let response: Response = moyaError.response {
if response.statusCode == 401 {
let user: User = AccountService.getUser()
guard let password = SAMKeychain.password(forService: kPasswordAccessKey, account: user.login) else {
return Single.error(error)
}
let account = Account.init(login: user.login, password: password)
return self.retryAuth(account)
}
}
return Single.error(error)
}
}
private func retryAuth(_ account: Account) -> Single<ElementType> {
return retryWhen { errorObservable in
Observable.zip(errorObservable, Observable.range(start: 1, count: 3), resultSelector: { $1 })
.flatMap { i -> PrimitiveSequence<SingleTrait, Response> in
return AuthProvider.rx.request(.signIn(account: account))
.filterSuccessfulStatusCodes()
.catchError { error in
if case MoyaError.statusCode(let response) = error {
if response.statusCode > 399 && response.statusCode < 500 {
self.authError()
}
}
return Single.error(error)
}.flatMap({ event -> PrimitiveSequence<SingleTrait, Response> in
if let resp: HTTPURLResponse = event.response, let cookie = HTTPCookie.cookies(withResponseHeaderFields: resp.allHeaderFields as! [String: String], for: resp.url!).first {
SAMKeychain.setPassword(cookie.value, forService: kTokenAccessKey, account: account.login)
return Single.just(event)
}
return Single.just(event)
})
}
}
}
private func authError() {
Utils.resetToLoginScreen()
let ac = UIAlertController(title: NSLocalizedString("common.error", comment: ""), message: NSLocalizedString("auth.error", comment: ""), preferredStyle: .alert)
ac.addAction(UIAlertAction(title: NSLocalizedString("common.ok", comment: ""), style: .default))
DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) {
UIApplication.shared.keyWindow?.rootViewController?.present(ac, animated: true, completion: nil)
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment