2019-08-29 Retrofit + OkHttp で Authorization ヘッダーを設定する
Retrofit で一部のメソッドだけに Authorization ヘッダーとトークンをつけるには……。以下のソースコードは Kotlin でコンパイルも通していない雰囲気だけのもの。
バージョンは↓。
- Retrofit 2.6.x
- OkHttp 4.0.x
↓にある方法のひとつを紹介する。
https://stackoverflow.com/questions/41078866/retrofit-authorization-bearer-token
まず単純な方法はメソッドの引数に @Headder("Authorization") token
という引数を追加すること。
interface RetrofitService {
@GET("users")
suspend fun getUserList(@Header("Authorization") token: String): List<User>
}
Bearer
をつけたければ OkHttp の Interceptor
で header を書き換える。
val httpClient = OkHttpClient.Builder().addInterceptor(object : Interceptor {
override fun intercept(chain: Interceptor.Chain): Response {
val request = chain.request()
var newRequest = request.headers["Authorization"]?.let { token ->
request.newBuilder().header("Authorization", "Bearer $token").build()
} ?: request
return chain.proceed(newRequest)
}
}).build()
// httpClient を Retrofit の client に設定する
// ...
これで動くのだけど認証の必要なメソッド (例ではgetUserList
) が token
を取るのも何だかなあと。 token
はわざわざ引数で取らなくても良いこともあるので……。
そこである種のマーカーとして Retrofit の @Headers
を使う。
interface RetrofitService {
@GET("/users")
@Headers(AuthorizationInterceptor.placeholder)
suspend fun getUserList(): List<User>
}
あとはだいたい同じで OkHttp の Interceptor
で書き換える。
class AuthorizationInterceptor: Interceptor {
companion oboject {
val headerName = "Authorization"
val headerValue = "DUMMY"
val placeholder = "$headerName: $headerValue"
}
override fun intercept(chain: Interceptor.Chain): Response {
// token はどこかから得る
// 例えばコンストラクタに context をとって SharedPreferences から……とか
val token = // ...
val request = chain.request()
var newRequest =
if (request.header(headerName) == headerValue)
request.newBuilder().header("Authorization", "Bearer $token").build()
else
request
return chain.proceed(newRequest)
}
}
// ...
val httpClient =
OkHttpClient.Builder().addInterceptor(AuthorizationInterceptor()).build()
// httpClient を Retrofit の client に設定する
// ...
どうするのが良いのかは知らないけど一応こんな感じで動く。