Androidレトロフィットパラメータ化@ヘッダー


85

OAuthを使用していますが、リクエストを行うたびにヘッダーにOAuthトークンを挿入する必要があります。@Headerアノテーションが表示されますが、実行時に渡すことができるようにパラメーター化する方法はありますか?

これがコンセプトです

@Header({Authorization:'OAuth {var}', api_version={var} })

ランタイムでそれらを渡すことができますか?

@GET("/users")
void getUsers(
    @Header("Authorization") String auth, 
    @Header("X-Api-Version") String version, 
    Callback<User> callback
)

これを理解したことがありますか?ヘッダーにもトークンを渡す必要があります
theSociableme 2013

また、これに対する解決策を探しています。ドキュメントから、メソッドの@Headers()アノテーションがフィールドをヘッダーに1つずつ追加しているように聞こえますが、リテラルのみをサポートしています。また、@ Header( "parameter")文字列文字列パラメータアノテーション、ヘッダーを指定された値に置き換えます。
nana 2013

2
ここでも同じですが、後付けを使用するときにセッションを処理する方法を見つけることができませんでした。
FRR 2014年

すべてのアイテムを渡す必要はありませんでした。後付け自体がすべてを処理します。StackOverflowの回答リンクを確認してください。
スビンバブ2018

回答:


98

@Headerパラメーターを使用する以外に、RequestInterceptorを使用して、インターフェイスを変更せずにすべてのリクエストを更新したいと思います。次のようなものを使用する:

RestAdapter.Builder builder = new RestAdapter.Builder()
    .setRequestInterceptor(new RequestInterceptor() {
        @Override
        public void intercept(RequestFacade request) {
            request.addHeader("Accept", "application/json;versions=1");
            if (isUserLoggedIn()) {
                request.addHeader("Authorization", getToken());
            }                    
        }
    });

p / s:Retrofit2を使用している場合は、Interceptor代わりにを使用する必要がありますRequestInterceptor

RequestInterceptorRetrofit2.0では使用できなくなったため


3
これは直接関係していませんが、Authorizationヘッダーを生成するためにリクエストオブジェクトから値を取得する必要がある場合は、ApacheClientを拡張し、重複してリクエストオブジェクトを実行する必要があります(List <Header> headers = .. .. ;リクエストrequestNew = new Request(request.getMethod()、request.getUrl()、headers、request.getBody()); request = requestNew)。

1
これは、コード化されたものを台無しにするトリックです。@ nanaの回答をより適切に使用してください
Ivan Fazaniuk 2016年

1
RestAdapterRetrofit1に依存し、Retrofit2ではですRetrofit。Retrofit2を使用するのでRequestInterceptor、上記のコードとして使用しても問題はありませんか?
ホイタワー2016

55

はい、実行時にそれらを渡すことができます。実際のところ、入力したとおりです。これは、たとえばSecretApiInterface.javaという名前のAPIインターフェイスクラスにあります。

public interface SecretApiInterface {

    @GET("/secret_things")
    SecretThing.List getSecretThings(@Header("Authorization") String token)

}

次に、リクエストからこのインターフェイスにパラメータを渡します。これらの行に沿ったものです(このファイルはたとえばSecretThingRequest.javaになります)

public class SecretThingRequest extends RetrofitSpiceRequest<SecretThing.List, SecretApiInteface>{

    private String token;

    public SecretThingRequest(String token) {
        super(SecretThing.List.class, SecretApiInterface.class);
        this.token = token;
    }

    @Override
    public SecretThing.List loadDataFromNetwork() {
        SecretApiInterface service = getService();
        return service.getSecretThings(Somehow.Magically.getToken());
    }
}

Somehow.Magically.getToken()トークンを返すメソッド呼び出しはどこにありますか。それをどこでどのように定義するかはあなた次第です。

もちろん@Header("Blah") String blah、あなたの場合のように、インターフェースの実装に複数の注釈を付けることができます!

私も混乱していることわかりました。ドキュメントにはヘッダーが置き換えられると明記されていますが、そうでありません
実際には@Headers("hardcoded_string_of_liited_use")注釈と同様に追加されます

お役に立てれば ;)


1
ドキュメントで、既存のヘッダーが置き換えられていないことがわかりました。「ヘッダーは相互に上書きされないことに注意してください。」square.github.io/retrofitと「HeaderManipulation」を確認してください
Amio.io 2014年

37

受け入れられた答えは、古いバージョンのレトロフィットに対するものです。将来の視聴者にとって、Retrofit2.0でこれを行う方法は、カスタムOkHttpクライアントを使用することです。

OkHttpClient httpClient = new OkHttpClient.Builder()
  .addInterceptor(new Interceptor() {
    @Override
    public Response intercept(Chain chain) throws IOException {
      Builder ongoing = chain.request().newBuilder();
      ongoing.addHeader("Accept", "application/json;versions=1");
      if (isUserLoggedIn()) {
        ongoing.addHeader("Authorization", getToken());
      }
      return chain.proceed(ongoing.build());
    }
  })
  .build();

Retrofit retrofit = new Retrofit.Builder()
  // ... extra config
  .client(httpClient)
  .build();

それが誰かを助けることを願っています。:)


5
dagger2の一般的な使用法では、retrofit2はシングルトンになるため、毎回httpclientが作成されることはありません。その場合、isUserLoggedIn()は意味がありません、私は正しいですか?私が現在見ることができる唯一の解決策は、ユーザーのログインステータスが変更されたときにretrofit2の再初期化を強制することです。これにより、適切なヘッダーがリクエストから追加または削除されます。または、現在私が見ることができない明らかな解決策がありますか?ありがとう。
bajicdusko 2016年

2
@bajicduskoこれは私のまったく同じ難問です。解決策を見つけましたか?以前のバージョンの方が効率的だったので、無駄で奇妙に思えます。
deed02392 2016年

@ deed02392Interceptor後の段階でインターセプターを設定またはリセットできるコンポジットを設定できます。ただし、シングルトンとして後付けすることは、早期の最適化の兆候である可能性があると私は主張します。新しい改造インスタンスを作成するには、オーバーヘッドはありません:github.com/square/retrofit/blob/master/retrofit/src/main/java/...
pablisco

あまり深く考えていませんでした。dagger2で初期化されるApiFactoryクラスがいくつかあり、レトロフィットの初期化を担当します。必要に応じてレトロフィットインスタンスの再初期化を強制するApiFactoryのパブリックメソッドを1つ公開したので、非常に簡単です。私はそれを間違っているかもしれませんが、それは仕事をしました、そして私はそれをAuthorizationヘッダーにのみ使用しているので、ユーザーのログインまたはログアウト時に使用されます。もう1つのオプションは、エンドポイント定義内で@Headerアノテーションを使用することですが、これは私には受け入れられませんでした。実用的ではない各エンドポイントに設定する必要があります。
bajicdusko

@pabliscoああ、私の理解では、Retrofit2Interceptorインスタンスを作成した後は、を追加または削除できませんでした。
deed02392 2016年

7

後付け2.3.0

OkHttpClient.Builder okHttpClientBuilder = new OkHttpClient.Builder();
    okHttpClientBuilder
            .addInterceptor(new Interceptor() {
                @Override
                public okhttp3.Response intercept(Chain chain) throws IOException {
                    Request request = chain.request();
                    Request.Builder newRequest = request.newBuilder().header("Authorization", accessToken);
                    return chain.proceed(newRequest.build());
                }
            });

    Retrofit retrofit = new Retrofit.Builder()
            .baseUrl(GithubService.BASE_URL)
            .client(okHttpClientBuilder.build())
            .addConverterFactory(GsonConverterFactory.create())
            .build();

これを使用してGitHubに接続しています。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.