Alamofire5のRequestInterceptorを試す
背景
- Alamofireを使ってAPI通信していると、アクセストークンのリフレッシュを共通化したくなる
- そこで使えるのがRequestInterceptor
- RequestAdapter, RequestRetrierについての日本語記事はあったがRequestInterceptorの日本語記事は見当たらなかったため情報提供する
説明
- RequestInterceptorにはAdaptとRetryという2つのプロトコルが存在する
- Adaptは毎回実行される処理(たとえばアクセストークンのセットなど)、RetryはAPIをリトライ実行するための条件(たとえば401のときのみアクセストークンを更新してリトライするなど)およびリトライ前に実行したい処理を記述する
コード
import Foundation import Alamofire import SwiftyJSON final class AppRequestInterceptor: Alamofire.RequestInterceptor { private var accessToken: String = "" init () {} func adapt(_ urlRequest: URLRequest, for session: Session, completion: @escaping (Result<URLRequest, Error>) -> Void) { // accessToken取得処理(省略) var urlRequest = urlRequest urlRequest.setValue("Bearer " + self.accessToken, forHTTPHeaderField: "Authorization") completion(.success(urlRequest)) } 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 { return completion(.doNotRetryWithError(error)) } // 401になったらここにくる // アクセストークン更新処理(仮) AF.request("/refresh/token", method: .get, parameters: parameters, encoding: URLEncoding(destination: .queryString) ).responseJSON {response in switch response.result { case .success(let value): let json = JSON(value) guard let accessToken = json["access_token"].string else { return } self.accessToken = accessToken completion(.retry) case .failure(let error): completion(.doNotRetryWithError(error)) } } } }
参考
Alamofire/AdvancedUsage.md at master · Alamofire/Alamofire · GitHub
Authentication with signed requests in Alamofire 5 - SwiftLee