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