Android Retrofit Parameterized @Headers
I am using OAuth and I need to put the OAuth token in my header every time I make a request. I see the @Header
annotation, but is there a way to make it parameterized so i can pass in at run time?
Here is the concept
@Header({Authorization:'OAuth {var}', api_version={var} })
Can you pass them in at Runtime?
@GET("/users")
void getUsers(
@Header("Authorization") String auth,
@Header("X-Api-Version") String version,
Callback<User> callback
)
Solution 1:
Besides using @Header parameter, I'd rather use RequestInterceptor to update all your request without changing your interface. Using something like:
RestAdapter.Builder builder = new RestAdapter.Builder()
.setRequestInterceptor(new RequestInterceptor() {
@Override
public void intercept(RequestFacade request) {
request.addHeader("Accept", "application/json;versions=1");
if (isUserLoggedIn()) {
request.addHeader("Authorization", getToken());
}
}
});
p/s : If you are using Retrofit2, you should use Interceptor
instead of RequestInterceptor
Since RequestInterceptor
is not longer available in Retrofit 2.0
Solution 2:
Yes, you can pass them in runtime. As a matter of fact, pretty much exactly as you typed it out. This would be in your API interface class, named say SecretApiInterface.java
public interface SecretApiInterface {
@GET("/secret_things")
SecretThing.List getSecretThings(@Header("Authorization") String token)
}
Then you pass the parameters to this interface from your request, something along those lines: (this file would be for example SecretThingRequest.java)
public class SecretThingRequest extends RetrofitSpiceRequest<SecretThing.List, SecretApiInteface>{
private String token;
public SecretThingRequest(String token) {
super(SecretThing.List.class, SecretApiInterface.class);
this.token = token;
}
@Override
public SecretThing.List loadDataFromNetwork() {
SecretApiInterface service = getService();
return service.getSecretThings(Somehow.Magically.getToken());
}
}
Where Somehow.Magically.getToken()
is a method call that returns a token, it is up to you where and how you define it.
You can of course have more than one @Header("Blah") String blah
annotations in the interface implementation, as in your case!
I found it confusing too, the documentation clearly says it replaces the header, but it DOESN'T!
It is in fact added as with @Headers("hardcoded_string_of_liited_use")
annotation
Hope this helps ;)
Solution 3:
The accepted answer is for an older version of Retrofit. For future viewers the way to do this with Retrofit
2.0 is using a custom OkHttp client:
OkHttpClient httpClient = new OkHttpClient.Builder()
.addInterceptor(new Interceptor() {
@Override
public Response intercept(Chain chain) throws IOException {
Builder ongoing = chain.request().newBuilder();
ongoing.addHeader("Accept", "application/json;versions=1");
if (isUserLoggedIn()) {
ongoing.addHeader("Authorization", getToken());
}
return chain.proceed(ongoing.build());
}
})
.build();
Retrofit retrofit = new Retrofit.Builder()
// ... extra config
.client(httpClient)
.build();
Hope it helps someone. :)
Solution 4:
Retrofit 2.3.0
OkHttpClient.Builder okHttpClientBuilder = new OkHttpClient.Builder();
okHttpClientBuilder
.addInterceptor(new Interceptor() {
@Override
public okhttp3.Response intercept(Chain chain) throws IOException {
Request request = chain.request();
Request.Builder newRequest = request.newBuilder().header("Authorization", accessToken);
return chain.proceed(newRequest.build());
}
});
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(GithubService.BASE_URL)
.client(okHttpClientBuilder.build())
.addConverterFactory(GsonConverterFactory.create())
.build();
I am using this to connect to GitHub.