1、设置在Moya的API文件中添加validationType,设置为successCodes,不设置的话401会被Moya识别为正常网络请求,无法触发func retry(_ request: Request, for session: Session, dueTo error: Error, completion: @escaping (RetryResult) -> Void)
public var validationType: ValidationType {
return .successCodes
}
2、设置拦截器 设置401为failure触发func retry(_ request: Request, for session: Session, dueTo error: Error, completion: @escaping (RetryResult) -> Void)
import UIKit
import Moya
import SwiftyJSON
import Alamofire
class OAuthPluginType: PluginType {
// 准备发起请求。我们可以在这里对请求进行修改,比如再增加一些额外的参数。
func prepare(_ request: URLRequest, target: TargetType) -> URLRequest {
return request
}
// 开始发起请求。我们可以在这里显示网络状态指示器。
func willSend(_ request: RequestType, target: TargetType) {
}
// 收到请求响应。我们可以在这里根据结果自动进行一些处理,比如请求失败时将失败信息告诉用户,或者记录到日志中。
func didReceive(_ result: Result<Response, MoyaError>, target: TargetType) {
}
// 处理请求结果。我们可以在 completion 前对结果进行进一步处理。
func process(_ result: Result<Response, MoyaError>, target: TargetType) -> Result<Response, MoyaError> {
switch result {
case .success(let response):
let newResponse = getResponse(response: response)
if newResponse.statusCode == 401 {
return .failure(MoyaError.jsonMapping(newResponse))
} else {
return .success(newResponse)
}
case .failure(_):
break
}
return result
}
// 非标准rest返回需要加工一下
func getResponse(response: Response) -> Response {
let json = JSON(response.data)
do {
let data = try json["data"].rawData()
return Response(statusCode: json["code"].intValue, data: data, request: response.request, response: response.response)
} catch {
return Response(statusCode: json["code"].intValue, data: Data(), request: response.request, response: response.response)
}
}
}
3、设置RequestInterceptor
let requestInterceptor = RequestInterceptor()
let session = Session(interceptor: requestInterceptor)
class RequestInterceptor: RequestInterceptor {
let disposeBag = DisposeBag()
func adapt(_ urlRequest: URLRequest, for session: Session, completion: @escaping (Result<URLRequest, Error>) -> Void) {
var request = urlRequest
if let token = AuthManager.shared.token?.token {
request.setValue("Bearer \(token)", forHTTPHeaderField: "Authorization")
print(request.headers)
}
completion(.success(request))
}
func retry(_ request: Request, for session: Session, dueTo error: Error, completion: @escaping (RetryResult) -> Void) {
guard let response = request.task?.response as? HTTPURLResponse, response.statusCode == 401 else {
completion(.doNotRetry)
return
}
// 确保只重试一次,否则就无限重试下去了
guard request.retryCount == 0 else { return completion(.doNotRetry) }
if let refreshToken = AuthManager.shared.token?.refreshToken {
let restApi = RestApi(provider: Networking.defaultNetworking())
restApi.refreshToken(refreshToken: refreshToken).asObservable().subscribe(onNext: { token in
AuthManager.setToken(token: token)
completion(.retry)
}).disposed(by: disposeBag)
} else {
completion(.doNotRetry)
}
}
}