Max
Max

Reputation: 1612

Is there a way to add query parameter to every request with Retrofit 2?

I need to add a query parameter to every request made by Retrofit 2.0.0-beta2 library. I found this solution for Retrofit 1.9, but how to add RequestInterceptor in newest library version?

My 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);

Upvotes: 77

Views: 44605

Answers (7)

Kidus Tekeste
Kidus Tekeste

Reputation: 661

For a cleaner code approach have a separate class for the interceptor chain like this:

    public class LanguageInterceptor implements Interceptor {
        @Override
        public Response intercept(Chain chain) throws IOException {
            HttpUrl url = chain.request()
                    .url()
                    .newBuilder()
                    .addQueryParameter("name","value")
                    .build();

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

Then in the class where you defined your retrofit instance you add the instance object to it with .addInterceptor(new LanguageInterceptor()) like this:

public static Retrofit getClient() {
        HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
        interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
        OkHttpClient client = new OkHttpClient.Builder()
                .connectTimeout(30, TimeUnit.SECONDS)
                .readTimeout(30, TimeUnit.SECONDS)
                .addInterceptor(new LanguageInterceptor())
                .addInterceptor(interceptor)
                .build();

        if (retrofit == null) {
            retrofit = new Retrofit.Builder()
                    .baseUrl(BASE_URL)
                    .client(client)
                    .addConverterFactory(ScalarsConverterFactory.create())
                    .addConverterFactory(GsonConverterFactory.create())
                    .build();
            Log.e(TAG, "getClient: base url " + retrofit.baseUrl());
        }
        return retrofit;
    }

Upvotes: 2

Achraf Amil
Achraf Amil

Reputation: 1375

In kotlin, add the following interceptor to the OkHttpClient you set in Retrofit builder :

Retrofit.Builder()
    .baseUrl("...")
    .client(
        OkHttpClient.Builder()
            .addInterceptor { chain ->
                val url = chain
                    .request()
                    .url()
                    .newBuilder()
                    .addQueryParameter("key", "value")
                    .build()
                chain.proceed(chain.request().newBuilder().url(url).build())
            }
            .build()
    )
    .build()
    .create(FooService::class.java)

And, of course, extracting the OkHttpClient building into a val or an injection dependency would make it even more modular and lisible.

Upvotes: 8

zenghui.wang
zenghui.wang

Reputation: 131

now the Retrofit has release 2.0.0 and this is my 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);

Upvotes: 13

isakbob
isakbob

Reputation: 1539

A lot of these answers are similar, but an issue I came accross is the chaining of functions inside the Interceptor which led it to fail for me. Changes cannot be made directly to a url according to the linked video. Rather, a copy of the url must be made and then reassigned back to the original url as shown below:

{

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();
}

While the functions called are identical to the first answer, this answer partitions the function calls out. Namely, the original url as well as the new url are stored in separate local variables. This prevents overwriting the original url until you want the OkHttpClient to do so.

Upvotes: 2

sebastian
sebastian

Reputation: 2880

You have to switch to an Interceptor from OkHttp. Create an OkHttpClient, add the Interceptor to it an pass that client in the Retrofit 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();

You can then adjust the request to your needs using chain.request().newBuilder(). See the documentation for details.

Upvotes: 3

Sergey Nikitin
Sergey Nikitin

Reputation: 827

In 3.2.0 and higher you should use addInterceptor() in OkHttpClient.Builder instead.

For example, with 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();

Upvotes: 6

Lukas Lechner
Lukas Lechner

Reputation: 8181

For the sake of completeness, here is the full code you need to add a parameter to every Retrofit 2.x request using a 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();

Upvotes: 159

Related Questions