gpt4 book ai didi

swift - RxSwift 更新身份验证 token

转载 作者:可可西里 更新时间:2023-11-01 01:49:26 34 4
gpt4 key购买 nike

Hy 我正在尝试使用 Moya 和 RxSwift 来更新身份验证 token 并重试请求。

问题是我有多个请求同时进行,假设在身份验证 token 过期时触发了 10 个请求,我将尝试更新所有请求的 token ,并在第一个请求更新后立即更新其他的将失败,因为他们使用了错误的 token 来更新。

我想做的只是构建一个(可能)请求队列,然后重试这些请求。不确定这是否是最佳方案。

这是我目前所拥有的:

final class NetworkOnlineProvider {

fileprivate let database = DatabaseClient(database: DatabaseRealm()).database
fileprivate let provider: MoyaProvider<NetworkAPI>

init(endpointClosure: @escaping MoyaProvider<NetworkAPI>.EndpointClosure = MoyaProvider<NetworkAPI>.defaultEndpointMapping,
requestClosure: @escaping MoyaProvider<NetworkAPI>.RequestClosure = MoyaProvider<NetworkAPI>.defaultRequestMapping,
stubClosure: @escaping MoyaProvider<NetworkAPI>.StubClosure = MoyaProvider.neverStub,
manager: Manager = MoyaProvider<NetworkAPI>.defaultAlamofireManager(),
plugins: [PluginType] = [],
trackInflights: Bool = false) {

self.provider = MoyaProvider(endpointClosure: endpointClosure, requestClosure: requestClosure, stubClosure: stubClosure, manager: manager, plugins: plugins, trackInflights: trackInflights)
}

fileprivate func getJWTRenewRequest() -> Single<Response>? {
if let token = JWTManager.sharedInstance.token {

return provider.rx.request(.renew(token: token))
}

return nil
}

func tokenRequest() -> Single<String> {
let errorSingle = Single<String>.create { single in
single(.error(APIError.failure))

return Disposables.create()
}

let emptyJWTSingle = Single<String>.create { single in
single(.success(""))

return Disposables.create()
}

// Return if no token found
guard let appToken = JWTManager.sharedInstance.getJWT() else {
return refreshToken() ?? emptyJWTSingle
}

// If we have a valid token, just return it
if !appToken.hasTokenExpired {
return Single<String>.create { single in
single(.success(appToken.token))

return Disposables.create()
}
}

// Token has expired
let newTokenRequest = refreshToken()
return newTokenRequest ?? errorSingle
}

func refreshToken() -> Single<String>? {
return getJWTRenewRequest()?
.debug("Renewing JWT")
.filterSuccessfulStatusCodes()
.map { (response: Response) -> (token: String, expiration: Double) in
guard let json = try? JSON(data: response.data) else { throw RxError.unknown }

let success = json["success"]

guard
let jwt = success["jwt"].string,
let jwt_expiration = success["jwt_expiration"].double,
let valid_login = success["valid_login"].bool, valid_login
else { throw RxError.unknown }

return (token: jwt, expiration: jwt_expiration)
}
.do(onSuccess: { (token: String, expiration: Double) in
JWTManager.sharedInstance.save(token: JWT(token: token, expiration: String(expiration)))
})
.map { (token: String, expiration: Double) in
return token
}
.catchError { e -> Single<String> in
print("Failed to Renew JWT")
JWTManager.sharedInstance.delete()

UIApplication.shared.appDelegate.cleanPreviousContext(jwt: true)
let loginVC = UIStoryboard(storyboard: .login).instantiateViewController(vc: LoginViewController.self)
UIApplication.shared.appDelegate.window?.setRootViewController(UINavigationController(rootViewController: loginVC))

throw e
}
}

func request(_ target: NetworkAPI) -> Single<Response> {
let actualRequest = provider.rx.request(target)

if target.isAuthenticatedCall {
return tokenRequest().flatMap { _ in
actualRequest
}
}


return actualRequest
}
}

最佳答案

解决方案在这里:RxSwift and Retrying a Network Request Despite Having an Invalid Token

关键是使用 flatMapFirst,这样您只对第一个 401 发出一个请求,并在该请求运行期间忽略其他 401。

与文章相关的要点包括证明它有效的单元测试。

关于swift - RxSwift 更新身份验证 token ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55733968/

34 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com