[iOS][Alamofire] RequestAdapterを使用して、APIリクエスト前に任意の処理を実行する

Alamofireを使用したAPIリクエストにおいて、リクエスト前に任意の処理を実行する方法を解説します。
2022.03.29

はじめに

こんにちは。モバイル事業部の平屋です。

HTTPネットワーキングライブラリAlamofireにはRequestAdapterという仕組みがあり、リクエスト前に任意の処理を実行することができます。例えば、以下の処理を共通処理として追加できます。

  • リクエストにAuthorizationヘッダーを追加する

本記事ではこのRequestAdapterの使い方を解説します。

検証環境

  • macOS Monterey 12.2
  • Xcode Version 13.1

(1) RequestAdapterを実装する

任意のクラスをRequestAdapterプロトコルに適合させ、adapt(_:session:completion:)を実装します。

このメソッド内では、引数で渡されたURLRequestに対して任意の処理を行い、completionを呼びます。

以下の例では、リクエストにAuthorizationヘッダーを追加しています。

class Adapter: RequestAdapter {
    let accessToken = "xxxxx"

    func adapt(_ urlRequest: URLRequest, for session: Session, completion: @escaping (Result<URLRequest, Error>) -> Void) {
        var urlRequest = urlRequest

        // Authorizationヘッダーを追加
        urlRequest.headers.add(.authorization(bearerToken: accessToken))

        // 処理を行った結果を渡す
        completion(.success(urlRequest))
    }
}

(2) RequestAdapterを使う

(1)で実装したRequestAdapterを使うには、以下を実装します。

  • (2-1) AdapterからInterceptorを生成
  • (2-2) Interceptorと共にSessionを生成
  • (2-3) Sessionを使ってリクエストを実行
class ViewController: UIViewController {
    let session: Session = {
        // (2-1)
        let interceptor = Interceptor(adapters: [Adapter()])

        // (2-2)
        let session = Session(interceptor: interceptor)
        return session
    }()

    override func viewDidLoad() {
        super.viewDidLoad()

        // (2-3)
        let request = try! URLRequest(url: "https://httpbin.org/get", method: .get)
        session.request(request).responseDecodable(of: Response.self) { response in
            switch response.result {
            case .success(let res):
                print("res:", res)
            case .failure(let error):
                print("error:", error)
            }
        }
    }
}

struct Response: Decodable {
    let headers: [String: String]
    let origin: String
    let url: String
}

extension Response: CustomDebugStringConvertible {
    var debugDescription: String {
        "headers: \(headers), origin:\(origin), url:\(url)"
    }
}

(3) 動作確認

今回はhttps://httpbin.org/を使って動作確認しました。リクエスト内容をそのまま返してくれるエンドポイント(/get)などがあります。(Alamofire付属のサンプルコードで使われていました)

RequestAdapterを使った場合

RequestAdapterを使ったサンプルコードを実行すると以下のレスポンスを取得できました。(Authorizationヘッダーが入っている)

headers: [
    "Accept-Encoding": "br;q=1.0, gzip;q=0.9, deflate;q=0.8",
    "Host": "httpbin.org",
    "Authorization": "Bearer xxxxx",
    "Accept-Language": "en;q=1.0, ja-US;q=0.9"
    ...
    ],
...

RequestAdapterを使わない場合

また、RequestAdapterを使わないようにサンプルコードを修正すると、

class ViewController: UIViewController {
    let session = Session()

    // ...
}

以下のレスポンスを取得できました。(Authorizationヘッダーが入っていない)

headers: [
     "Accept-Encoding": "br;q=1.0, gzip;q=0.9, deflate;q=0.8",
     "Host": "httpbin.org",
     "Accept-Language": "en;q=1.0, ja-US;q=0.9"
     ...
    ],
...