How to dynamically set headers in Retrofit (Android)

前端 未结 4 676
无人及你
无人及你 2020-11-29 01:07

I am using an API that uses an authorization scheme that requires a special \"X-Authorization\" header to be set to authenticate the request. For example, this Retrofit setu

相关标签:
4条回答
  • 2020-11-29 01:45

    A request Header can be updated dynamically using the @Header annotation. A corresponding parameter must be provided to the @Header. If the value is null, the header will be omitted. Otherwise, toString will be called on the value, and the result used.

    @GET("user")
    Call<User> getUser(@Header("Authorization") String authorization)
    
    0 讨论(0)
  • 2020-11-29 01:49

    Passing header in parameter would be helpful. Look to the following code;

     @GET("/posts")
    Observable<JsonElement> getDataFromService(
            @HeaderMap Map<String, String> headers,
            @QueryMap HashMap<String, Object> queryParams
    );
    
            hashMap1.put("Authorization", token);
        return ApiService.getAPI_test().getDataFromService(hashMap1, url, hashMap)
                .observeOn(AndroidSchedulers.mainThread())
                .subscribeOn(Schedulers.io());
    

    Update:

    More better would be

     @GET("/posts")
    Observable<JsonElement> getDataFromService(
            @Header("Authorization") token: String = "Bearer " + PreferenceUtils.getToken(),
            @QueryMap HashMap<String, Object> queryParams
    );
    
    0 讨论(0)
  • 2020-11-29 01:52

    Since Retrofit 2.0 you have two options


    1) Using OkHttp 2.2+ use Interceptor

    At the Http level, you have more control over the request, so you could do things like applying headers only to a specific request made to a specific endpoint, and so on.

    public class MyOkHttpInterceptor implements Interceptor {
    
    @Override
    public Response intercept(Chain chain) throws IOException {
        Request originalRequest = chain.request();
        if (!"/posts".contains(originalRequest.url()) ) {
            return chain.proceed(originalRequest);
        }
    
        String token = // get token logic 
    
        Request newRequest = originalRequest.newBuilder()
            .header("X-Authorization", token)
            .build();
    
        return chain.proceed(newRequest);
    }
    
    [...]
    
    OkHttpClient okHttpClient = new OkHttpClient();
    okHttpClient.networkInterceptors().add(new MyOkHttpInterceptor());
    OkClient okClient = new OkClient(okHttpClient);
    YourApi api = new RestAdapter.Builder()
                .setEndpoint(url)
                .setClient(okClient)
                .build()
                .create(YourApi.class);
    

    Edit: Adding @JakeWarthon comment as another option as is also valid.

    2) Put @Header on a method parameter and pass it as a value when invoking.

    From the docs:

    // Replaces the header with the the value of its target.
    @GET("/")
    void foo(@Header("Accept-Language") String lang, Callback<Response> cb);
    

    Header parameters may be null which will omit them from the request. Passing a List or array will result in a header for each non-null item.

    Note: Headers do not overwrite each other. All headers with the same name will be included in the request.


    EDIT: This option should not be considered as Retrofit 2.* dropped support for interceptors.

    3) User retrofit RequestInterceptor

    From the docs: Intercept every request before it is executed in order to add additional data.

    You could do something like

    public class MyRetrofitInterceptor implements RequestInterceptor {
    
    @Override
    public void intercept(RequestFacade req) {
        String token = // get token logic 
        if (token != null) {
            req.addHeader("X-Authorization", token);
        }
    }
    
    [...]
    
    YourApi api = new RestAdapter.Builder()
                .setEndpoint(url)
                .setRequestInterceptor(new MyRetrofitInterceptor())
                .build()
                .create(YourApi.class);
    

    The "problem" with this approach is that the interceptor will get executed on all the endpoints, as it's set at the RestAdapter level, and not per endpoint. Also, the RequestFacade doesn't expose much information about the request, so no chance to add much logic around it.

    0 讨论(0)
  • 2020-11-29 02:03

    Dynamic Header In Retrofit 2

    I have struggled too much to add Dynamic Header In Retrofit 2.

    I have gone through so many blogs and StackOver flow. Everyone has shown example with Interceptor.

    And it’s not a wise thing ,just for one API call we need to do that much work.

    You just have to add @HeaderMap as argument of fun. I have done in very simple way :-

    In Kotlin

        val headers = HashMap<String, String>()
        headers["KEY_AUTHORIZATION"] = "paste AUTHORIZATION value here"
        headers["KEY_TOKEN"] = "paste TOKEN value here"
    
        val jsonObject= JsonObject()
    
    I am passing here header and other data also
    Calling of fun:-
    
    postEvent(headers,jsonObject)
    
    API Declaration 
    
        @POST("/v1/post_data")
        fun postEvent(@HeaderMap headers: Map<String, String>, @Body jsonObject: JsonObject): Call<JsonObject>
    
    API Declaration with RxAndroid
    
        @POST("/v1/post_data")
        fun postEvent(@HeaderMap headers: Map<String, String>, @Body jsonObject: JsonObject): Single<JsonObject>
    

    2nd argument here i have JsonObject. You can replace with anything whatever you need to pass or you can remove it also.

    In Java

     HashMap<String, String> headers = new HashMap<String, String>();
        headers.put("KEY_AUTHORIZATION","paste AUTHORIZATION value here");
        headers.put("KEY_TOKEN", "paste TOKEN value here");
    
        JsonObject jsonObject= new JsonObject();
    
    I am passing here header and other data also
    
    Calling of fun:-
    postEvent(headers,jsonObject);
    
        API Declaration 
        @POST("/v1/post_data")
        Call<JsonObject> postEvent(@HeaderMap Map<String, String> headers, @Body JsonObject jsonObject);
    
    API Declaration with RxAndroid
    
        @POST("/v1/post_data")
        Single<JsonObject> postEvent(@HeaderMap Map<String, String> headers, @Body JsonObject jsonObject);
    

    2nd argument here i have JsonObject. You can replace with anything whatever you need to pass or you can remove it also.

    0 讨论(0)
提交回复
热议问题