'How to dynamically set headers in Retrofit (Android)
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 setup works perfectly for the user whose auth token is abc123:
@Headers("X-Authorization: abc123")
@GET("/posts")
Observable<List<Post>> get_posts();
I cache the user's X-Authorization token, so I have access to that, however, I can't just drop it in the @Headers declaration.
@Headers("X-Authorization: " + token)
@GET("/posts")
Observable<List<Post>> get_posts();
I get a compile error here: Error:(41, 34) error: element value must be a constant expression
Any ideas on how I could get around this?
Solution 1:[1]
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
);
Solution 2:[2]
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.
Solution 3:[3]
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)
Solution 4:[4]
When the last part of this answer How to dynamically set headers in Retrofit (Android) did not work for me (halfway of the project), I improved it:-
public class MyRetrofitInterceptor implements RequestInterceptor {
// volatile variable
public static String token = null; //change at start of app
@Override
public void intercept(RequestFacade req) {
// change token from outside the class.
if (token != null) {
req.addHeader("X-Authorization", token);
}
}
It worked as soon as the token was updated from the response from the server API.
I think it worked as the string variable 'token' was used as the reference to its value, in global terms (being public static).
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | |
| Solution 2 | |
| Solution 3 | zeusboy |
| Solution 4 |
