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通信まわりのコードがとてもシンプルになります。もしまだリクエストごとにヘッダーを書いているなら、ぜひ試してみてください。
コメント