[Android] OkHttpで共通ヘッダーを付与する方法をまとめてみた

AndroidアプリでAPI通信をしていると、ほぼ必ず「このヘッダーは全リクエストにつけたいな」というケースが出てきます。例えばログイン済みのトークンを入れるAuthorizationヘッダーや、アプリの種類を判別するUser-Agentなどですね。これを毎回のリクエストで書いていたらミスも増えるし、コードもごちゃつきます。

そこで役立つのがOkHttpのInterceptorです。これを使えば、すべてのリクエストに共通ヘッダーを自動で付与できるようになります。今回は、実装方法をステップごとに紹介していきます。

スポンサーリンク

そもそもInterceptorって何?

Interceptorは、OkHttpがリクエストやレスポンスを処理する途中に割り込んで、内容を書き換えたり、ログを取ったりできる仕組みです。簡単にいうと「リクエストとレスポンスを横からチェックできるフック」みたいなものですね。

これを使えば「リクエストに毎回同じヘッダーを追加する」なんて処理も自然に実現できます。ログ出力やエラー処理でもよく使われるので、覚えておいて損はありません。

共通ヘッダー用のInterceptorを作る

まずはシンプルに、固定のヘッダーを追加するInterceptorを書いてみます。

class HeaderInterceptor : Interceptor {
    override fun intercept(chain: Interceptor.Chain): Response {
        val original = chain.request()
        val request = original.newBuilder()
            .header("Authorization", "Bearer xxxxx")
            .header("User-Agent", "MyApp/1.0.0")
            .method(original.method, original.body)
            .build()
        return chain.proceed(request)
    }
}

ポイントはoriginal.newBuilder()でリクエストをコピーして、その上にヘッダーを追加しているところです。chain.proceed()に渡すのは新しく作ったリクエストになります。

OkHttpClientにセットする

Interceptorを書いただけではまだ動きません。これをOkHttpClientに登録してあげる必要があります。

val client = OkHttpClient.Builder()
    .addInterceptor(HeaderInterceptor())
    .build()

これで完成です。このclientをRetrofitのインスタンス作成時に渡すか、直接OkHttpでリクエストすると、すべての通信に共通ヘッダーが入るようになります。

動的にトークンを設定したい場合

実際の開発では、ログインして得られるトークンを共通ヘッダーに設定するケースが多いと思います。その場合は、Interceptorにトークンを渡せるようにしてあげましょう。

class HeaderInterceptor(
    private val tokenProvider: () -> String?
) : Interceptor {
    override fun intercept(chain: Interceptor.Chain): Response {
        val original = chain.request()
        val builder = original.newBuilder()
            .header("User-Agent", "MyApp/1.0.0")

        tokenProvider()?.let {
            builder.header("Authorization", "Bearer $it")
        }

        val request = builder
            .method(original.method, original.body)
            .build()
        return chain.proceed(request)
    }
}

tokenProviderは関数型で渡しておくと便利です。SharedPreferencesやDataStoreから現在のトークンを返すようにしておけば、常に最新のトークンを使えます。

注意点

  • トークンが切れているときは401エラーになるので、Interceptorでエラーハンドリングするのもアリ
  • addInterceptor()addNetworkInterceptor()の違いに注意(基本はaddInterceptor()でOK)
  • ログ用のInterceptorを同時に入れると、通信の挙動がデバッグしやすくなる

まとめ

  • OkHttpのInterceptorを使えば共通ヘッダーを一括管理できる
  • 固定値のヘッダーはもちろん、ログイントークンなど動的な値も追加可能
  • 認証やユーザー識別に必要な情報はここでまとめて設定しておくとコードがすっきりする

共通ヘッダーをInterceptorにまとめると、API通信まわりのコードがとてもシンプルになります。もしまだリクエストごとにヘッダーを書いているなら、ぜひ試してみてください。

コメント

タイトルとURLをコピーしました