Skip to content

Instantly share code, notes, and snippets.

@davidebettio
Forked from dmitryshliugaev/RXMoya.swift
Created September 8, 2017 20:11
Show Gist options
  • Save davidebettio/01448bcf33d28a92cba4dd47d75ba5fb to your computer and use it in GitHub Desktop.
Save davidebettio/01448bcf33d28a92cba4dd47d75ba5fb to your computer and use it in GitHub Desktop.
RXMoya renew token
provider.request(.requestMessages)
.filterSuccessfulStatusCodes()
.retryWithAuthIfNeeded()
.subscribe { ev in
switch ev {
case .next(let r):
print(r)
case .error(let e):
self.showFailAlertForOperation(error: e)
default:
break
}
}
//MARK: – Renew token
public extension ObservableType where E == Response {
/// Tries to refresh auth token on 401, 403 errors and retry the request.
/// If the refresh fails, the signal errors.
public func retryWithAuthIfNeeded() -> Observable<E> {
return catchError { error -> Observable<Response> in
if let moyaError: MoyaError = error as? MoyaError {
if let response:Response = moyaError.response {
if (response.statusCode == 403 || response.statusCode == 401) {
return self.retryAuth()
}
}
}
return Observable.error(error)
}
}
private func retryAuth() -> Observable<E> {
return self.retryWhen { errorObservable -> Observable<Response> in
Observable.zip(errorObservable, Observable.range(start: 1, count: 1), resultSelector: { $1 }).flatMap { event -> Observable<Response> in
guard let login: String = AccountManager.getLogin(), let password: String = AccountManager.getPassword() else {
self.authError()
return errorObservable.flatMap { Observable.error($0) }
}
return provider.request(.login(login: login, password: password))
.filterSuccessfulStatusCodes()
.catchError { error -> Observable<Response> in
self.authError()
return errorObservable.flatMap { Observable.error($0) }
}
.flatMapLatest { event -> Observable<Response> in
if let resp: HTTPURLResponse = event.response as! HTTPURLResponse? {
let cookie = HTTPCookie.cookies(withResponseHeaderFields: resp.allHeaderFields as! [String : String], for: resp.url!)
if (cookie.count > 0) && AccountManager.saveToken(cookie[0].value) {
return Observable.just(event)
} else {
self.authError()
return errorObservable.flatMap { Observable.error($0) }
}
}
self.authError()
return errorObservable.flatMap { Observable.error($0) }
}
}
}
}
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