Retrofit 2 - Elegant way of adding headers in the api level

梦想与她 提交于 2019-12-02 18:45:39
Nitzan Tomer

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

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);
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!