web-dev-qa-db-fra.com

Existe-t-il un moyen d’ajouter un paramètre de requête à chaque requête avec Retrofit 2?

J'ai besoin d'ajouter un paramètre de requête à chaque requête de la bibliothèque Retrofit 2.0.0-beta2. J'ai trouvé cette solution pour Retrofit 1.9, mais comment ajouter RequestInterceptor dans la version la plus récente de la bibliothèque?

Mon interface:

@GET("user/{id}")
Call<User> getUser(@Path("id")long id);

@GET("users/")
Call<List<User>> getUser();

Client:

Retrofit retrofit = new Retrofit.Builder()
                    .baseUrl(BASE_URL)
                    .addConverterFactory(GsonConverterFactory.create())
                    .client(CLIENT)  // custom OkHTTP Client
                    .build();
service = retrofit.create(userService.class);
48
Max

Par souci d'exhaustivité, voici le code complet dont vous avez besoin d'ajouter un paramètre à chaque demande Retrofit 2.x à l'aide d'un OkHttp-Interceptor:

OkHttpClient client = new OkHttpClient();

client.interceptors().add(new Interceptor() {
    @Override
    public Response intercept(Chain chain) throws IOException {
        Request request = chain.request();
        HttpUrl url = request.url().newBuilder().addQueryParameter("name","value").build();
        request = request.newBuilder().url(url).build();
        return chain.proceed(request);
    }
});

Retrofit retrofit = new Retrofit.Builder()
        .baseUrl("...")
        .client(client)
        .build();
94
lukle

maintenant, Retrofit a la version 2.0.0 et voici ma solution:

OkHttpClient client = new OkHttpClient.Builder()
        .addInterceptor(new Interceptor() {
            @Override
            public Response intercept(Chain chain) throws IOException {

                String uid = "0";
                long timestamp = (int) (Calendar.getInstance().getTimeInMillis() / 1000);
                String signature = MD5Util.crypt(timestamp + "" + uid + MD5_SIGN);
                String base64encode = signature + ":" + timestamp + ":" + uid;
                base64encode = Base64.encodeToString(base64encode.getBytes(), Base64.NO_WRAP | Base64.URL_SAFE);

                Request request = chain.request();
                HttpUrl url = request.url()
                        .newBuilder()
                        .addQueryParameter("pageSize", "2")
                        .addQueryParameter("method", "getAliasList")
                        .build();

                request = request
                        .newBuilder()
                        .addHeader("Authorization", "zui " + base64encode)
                        .addHeader("from_client", "ZuiDeer")
                        .url(url)
                        .build();

                Response response = chain.proceed(request);
                return response;
            }
        }).build();


Retrofit retrofit = new Retrofit.Builder()
        .baseUrl(ApiConstants.API_BASE_URL)
        .client(client)
        .addConverterFactory(GsonConverterFactory.create())
        .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
        .build();

mRestfulService = retrofit.create(RestfulService.class);
7
zenghui.wang

Vous devez passer à Interceptor à partir de OkHttp. Créez une OkHttpClient, ajoutez-y une Interceptor et transmettez-lui le passage du client dans la modification Builder.

OkHttpClient client = new OkHttpClient();
client.interceptors().add(new Interceptor() {
    @Override
    public Response intercept(Chain chain) throws IOException {
        ...
    }
});

Retrofit retrofit = new Retrofit.Builder()
        .baseUrl("...")
        .client(client)
        .build();

Vous pouvez ensuite adapter la demande à vos besoins à l’aide de chain.request().newBuilder(). Voir documentation pour plus de détails.

4
sebastian

Dans 3.2.0 et supérieur, vous devriez utiliser addInterceptor() dans OkHttpClient.Builder à la place.

Par exemple, avec Retrolambda :

HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor()
        .setLevel(HttpLoggingInterceptor.Level.BASIC);

Interceptor clientInterceptor = chain -> {
    Request request = chain.request();
    HttpUrl url = request.url().newBuilder().addQueryParameter("name", "value").build();
    request = request.newBuilder().url(url).build();
    return chain.proceed(request);
};

OkHttpClient client = new OkHttpClient.Builder()
        .addNetworkInterceptor(clientInterceptor)
        .addInterceptor(loggingInterceptor)
        .build();

Retrofit retrofit = new Retrofit.Builder()
        .baseUrl(BASE_URL)
        .addConverterFactory(GsonConverterFactory.create())
        .client(client)
        .build();
3
Sergey Nikitin

Beaucoup de ces réponses sont similaires, mais un problème que j'ai découvert est l'enchaînement de fonctions dans la variable Interceptor qui l'a conduit à échouer. Les modifications ne peuvent pas être effectuées directement sur une URL en fonction de la vidéo liée. Au lieu de cela, une copie de l'URL doit être créée puis réaffectée à l'URL d'origine, comme indiqué ci-dessous:

{

public method(){
    final String api_key = "key";

    OkHttpClient client = new OkHttpClient.Builder()
                          .addInterceptor(new Interceptor() {
                              @Override
                              public Response intercept(Chain chain) throws IOException {
                                    Request original = chain.request();
                                    HttpUrl httpUrl = original.url();

                                    HttpUrl newHttpUrl = httpUrl
                                                        .newBuilder()
                                                        .addQueryParameter("api_key", api_key)
                                                        .build();

                                    Request.Builder requestBuilder = original
                                                                 .newBuilder()
                                                             .url(newHttpUrl);

                                    Request request = requestBuilder
                                                      .build();
                                    return chain.proceed(request);
                              }
                          }).build();


    retrofit = new Retrofit.Builder()
            .baseUrl("https://base.url.ext/")
            .client(client)
            .addConverterFactory(GsonConverterFactory.create())
            .build();
}

Bien que les fonctions appelées soient identiques à la première réponse, cette réponse partitionne les appels de fonction. À savoir, l'URL d'origine ainsi que la nouvelle URL sont stockés dans des variables locales distinctes. Cela empêche de remplacer l'URL d'origine tant que vous ne souhaitez pas que OkHttpClient le fasse. 

0
isakbob