[英]iOS rxSwift: retryWhen updating refresh token
我有一個靜態函數調用網絡服務。 當400響應代碼發生時,我想重做網絡呼叫。
當前代碼正常工作,只是頭文件中的refreshToken在一次嘗試之間不會更新。
我認為問題是因為創建了Observable,但是請求函數在重試時未更新。
我騎車上網,應該在Observable上使用延遲的方法,但是我不知道怎么做。
我試過將代碼移動到: headers = [HeaderKeys.refreshToken.rawValue: "test test"]
任何地方,但它始終不會使用“ test test”刷新令牌進行調用。 它總是使用舊的。
我怎樣才能解決這個問題?
static func getAccessToken() -> Observable<GetAccessTokenResponse> {
var retryCounter = 0
let maxRetryCounter = 3
let delayRetry = 10.0
guard let refreshToken = NetworkHelper.shared.refreshToken else {
return Observable.error(AuthenticationError.networkError)
}
var headers = [HeaderKeys.refreshToken.rawValue: refreshToken]
return NetworkHelper.shared
.request(url: CoreAPI.accessToken.url, request: nil, headers: headers, responseType: GetAccessTokenResponse.self, method: .get, encoding: nil)
.catchError({ (error) -> Observable<(GetAccessTokenResponse?, Int)> in
return Observable.error(AuthenticationError.networkError)
})
.flatMap({ (response) -> Observable<GetAccessTokenResponse> in
// check http status code
switch response.1 {
case 200:
guard response.0?.accessToken != nil else {
return Observable.error(AuthenticationError.genericError)
}
// success
return Observable.just(response.0!)
case 400:
// invalid parameters, refresh token not existing
return Observable.error(AuthenticationError.invalidParameters)
case 404:
// user not existing
return Observable.error(AuthenticationError.userDoesntExist)
default:
// by default return network error
return Observable.error(AuthenticationError.networkError)
}
})
.retryWhen({ (errors) -> Observable<Void> in
return errors
.do(onNext: { (error) in
headers = [HeaderKeys.refreshToken.rawValue: "test test"]
})
.flatMap({error -> Observable<Int> in
debugLog("Retrying get refresh token")
if retryCounter >= maxRetryCounter {
let authError = error as? AuthenticationError ?? .genericError
if authError == AuthenticationError.invalidParameters {
// publish logged false on subject
VDAAuthenticationManager.shared.logged.onNext(false)
}
return Observable.error(error)
}
// increase the retry counter and retry
retryCounter += 1
return Observable<Int>.timer(delayRetry, scheduler: MainScheduler.instance)
})
.flatMap ({ (_) -> Observable<Void> in
return Observable.just(())
})
})
}
在RxSwift中,盡管令牌無效,但重試網絡請求一文中,我解釋了當出現401錯誤時如何保留和更新令牌以及如何處理重試。 使用延遲是答案的一部分。
在您的特定情況下。 看來您可以像這樣使用我的服務:
func getToken(lastResponse: GetAccessTokenResponse?) -> Observable<(response: HTTPURLResponse, data: Data)> {
guard let refreshToken = lastResponse?.refreshToken else { return Observable.error(AuthenticationError.networkError) }
var request = URLRequest(url: CoreAPI.accessToken.url)
request.addValue(refreshToken, forHTTPHeaderField: HeaderKeys.refreshToken.rawValue)
return URLSession.shared.rx.response(request: request)
}
func extractToken(data: Data) throws -> GetAccessTokenResponse {
return try JSONDecoder().decode(GetAccessTokenResponse.self, from: data)
}
let tokenService = TokenAcquisitionService(initialToken: nil, getToken: getToken, extractToken: extractToken(data:))
在上面的代碼中,您將必須傳遞一個有效的initialToken而不是nil
或者必須修改getToken
以便即使它沒有刷新令牌也可以獲取令牌。
下面是一個如何使用deferred的示例:
let response = Observable
.deferred { tokenAcquisitionService.token.take(1) }
.flatMap { makeRequest(withToken: $0) }
.map { response in
guard response.response.statusCode != 401 else { throw ResponseError.unauthorized }
return response
}
.retryWhen { $0.renewToken(with: tokenAcquisitionService) }
我在文章中解釋了每一行代碼的用途以及工作方式。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.