Retrofitでヘッダーを動的に設定する方法 (Android)
質問
私は、リクエストを認証するために特別な "X-Authorization" ヘッダーを設定する必要がある認証スキームを使用する API を使用しています。たとえば、この Retrofit の設定は、認証トークンが次のようなユーザーに対して完全に機能します。
abc123
:
@Headers("X-Authorization: abc123")
@GET("/posts")
Observable<List<Post>> get_posts();
ユーザーのX-Authorizationトークンをキャッシュしているので、それにアクセスすることは可能ですが、@Headers宣言にそれをドロップすることはできません。
@Headers("X-Authorization: " + token)
@GET("/posts")
Observable<List<Post>> get_posts();
ここでコンパイルエラーになります。
Error:(41, 34) error: element value must be a constant expression
これを回避する方法について何かアイデアはありますか?
どのように解決するのですか?
Retrofit 2.0以降では、次の2つの方法があります。
1) OkHttp 2.2+ を使用する場合 インターセプター
Httpレベルでは、リクエストに対してより多くの制御が可能です。そのため、特定のエンドポイントに対して行われた特定のリクエストにのみヘッダを適用する、といったようなことが可能です。
public class MyOkHttpInterceptor implements Interceptor {
@Override
public Response intercept(Chain chain) throws IOException {
Request originalRequest = chain.request();
if (!"/posts".contains(originalRequest.url()) ) {
return chain.proceed(originalRequest);
}
String token = // get token logic
Request newRequest = originalRequest.newBuilder()
.header("X-Authorization", token)
.build();
return chain.proceed(newRequest);
}
[...]
OkHttpClient okHttpClient = new OkHttpClient();
okHttpClient.networkInterceptors().add(new MyOkHttpInterceptor());
OkClient okClient = new OkClient(okHttpClient);
YourApi api = new RestAdapter.Builder()
.setEndpoint(url)
.setClient(okClient)
.build()
.create(YourApi.class);
編集 : 追加 ジェイク・ウォーソン のコメントを追加するのも有効です。
2) 置く ヘッダ をメソッドのパラメータにつけて、起動時に値として渡します。
から ドキュメント :
// Replaces the header with the the value of its target.
@GET("/")
void foo(@Header("Accept-Language") String lang, Callback<Response> cb);
ヘッダーパラメータに null を指定すると、リクエストからそれらを省略することができます。リストや配列を渡すと、NULLでない各項目のヘッダが生成されます。
注意: ヘッダは互いに上書きされません。同じ名前のヘッダはすべてリクエストに含まれます。
EDITです。 Retrofit 2.*ではインターセプターのサポートがなくなったため、このオプションは考慮しないでください。
3) ユーザーによるRequestInterceptorの後付け
ドキュメントから 追加データを追加するために、実行される前にすべてのリクエストをインターセプトします。
のようなことができます。
public class MyRetrofitInterceptor implements RequestInterceptor {
@Override
public void intercept(RequestFacade req) {
String token = // get token logic
if (token != null) {
req.addHeader("X-Authorization", token);
}
}
[...]
YourApi api = new RestAdapter.Builder()
.setEndpoint(url)
.setRequestInterceptor(new MyRetrofitInterceptor())
.build()
.create(YourApi.class);
この方法の問題点は、インターセプターがエンドポイントごとではなくRestAdapterレベルで設定されているため、すべてのエンドポイントで実行されることです。また
RequestFacade
はリクエストに関する情報をあまり公開しないので、 それに関するロジックをあまり追加する機会がありません。
関連
-
[解決済み] Androidのソフトキーボードをプログラムで閉じる/隠すにはどうすればよいですか?
-
[解決済み] Androidでアクティビティ起動時にEditTextにフォーカスが当たらないようにする方法
-
[解決済み] Androidの「コンテキスト」とは何ですか?
-
[解決済み] AndroidのListViewで画像を遅延ロードする方法
-
[解決済み] EclipseのAndroidプラグインで "Debug certificate expired "エラーが発生する。
-
[解決済み] Androidで画面の大きさをピクセル単位で取得する方法
-
[解決済み】Android UserManager.isUserAGoat()の正しい使用例?)
-
[解決済み] edittextのテキストがメールアドレスかどうかを確認するには?
-
[解決済み] Android APKファイルの中身を見るには?
-
[解決済み] アンドロイドボタンセレクター
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み] RecyclerView.Stateを使って、RecyclerViewのスクロール位置を保存するには?
-
[解決済み] プログラムでソフトキーボードを開く
-
[解決済み] getApplication()、getApplicationContext()、getBaseContext()、someClass.thisの違いと使い分け。
-
[解決済み] Android ConstraintLayout - あるビューを別のビューの上に配置する
-
[解決済み] AppCompat-v7 21でアクションバー/ツールバーにアイコンを表示する。
-
[解決済み] 通知をクリックした後にアプリケーションを開く
-
[解決済み] Gradleでビルドタイプを使用し、ContentProviderを使用する同じアプリを1つのデバイスで実行する。
-
[解決済み] グリッドビューの高さが削減される
-
[解決済み] Androidでツールバーの戻るボタンの色を変えるには?
-
[解決済み] サポートライブラリのアクションバーをPreferenceActivityに追加するには?