My Retrofit 2 (2.0.2
currently) client needs to add custom headers to requests.
I\'m using an Interceptor
to add these headers to all request
I came up with a very simple and elegant (in my opinion) solution to my problem, and probably for other scenarios.
I use the Headers
annotation to pass my custom annotations, and since OkHttp requires that they follow the Name: Value
format, I decided that my format will be: @: ANNOTATION_NAME
.
So basically:
public interface MyApi {
@POST("register")
@HEADERS("@: NoAuth")
Call<RegisterResponse> register(@Body RegisterRequest data);
@GET("user/{userId}")
Call<GetUserResponse> getUser(@Path("userId") String userId);
}
Then I can intercept the request, check whether I have an annotation with name @
. If so, I get the value and remove the header from the request.
This works well even if you want to have more than one "custom annotation":
@HEADERS({
"@: NoAuth",
"@: LogResponseCode"
})
Here's how to extract all of these "custom annotations" and remove them from the request:
new OkHttpClient.Builder().addNetworkInterceptor(new Interceptor() {
@Override
public okhttp3.Response intercept(Chain chain) throws IOException {
Request request = chain.request();
List<String> customAnnotations = request.headers().values("@");
// do something with the "custom annotations"
request = request.newBuilder().removeHeader("@").build();
return chain.proceed(request);
}
});
Maybe you can do that by creating different Retrofit object factory method like this.
public class RestClient {
public static <S> S createService(Class<S> serviceClass) {
OkHttpClient.Builder httpClient = new OkHttpClient.Builder();
OkHttpClient client = httpClient.build();
Retrofit retrofit = new Retrofit.Builder().baseUrl(APIConfig.BASE_URL)
.client(client)
.build();
return retrofit.create(serviceClass);
}
public static <S> S createServiceWithAuth(Class<S> serviceClass) {
Interceptor interceptor = new Interceptor() {
@Override
public Response intercept(Chain chain) throws IOException {
final Request request = chain.request().newBuilder()
.addHeader("CUSTOM_HEADER_NAME_1", "CUSTOM_HEADER_VALUE_1")
.addHeader("CUSTOM_HEADER_NAME_2", "CUSTOM_HEADER_VALUE_2")
.build();
return chain.proceed(request);
}
};
OkHttpClient.Builder httpClient = new OkHttpClient.Builder();
httpClient.addInterceptor(interceptor);
OkHttpClient client = httpClient.build();
Retrofit retrofit = new Retrofit.Builder().baseUrl(APIConfig.BASE_URL)
.client(client)
.build();
return retrofit.create(serviceClass);
}
}
if you want to call api without header auth, you can just call createService method:
YourApi api = RestClient.createService(YourApi.class);
And use createServiceWithAuth method if you want to call api with authentication:
YourApiWithAuth api = RestClient.createServiceWithAuth(YourApiWithAuth.class);