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

后端 未结 2 643
轻奢々
轻奢々 2021-01-31 05:28

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

相关标签:
2条回答
  • 2021-01-31 06:11

    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);
        }
    });
    
    0 讨论(0)
  • 2021-01-31 06:17

    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);
    
    0 讨论(0)
提交回复
热议问题