Retrofit — Add Custom Request Header

You’ve already learned how to integrate authentication with Retrofit, how to pass multiple query parameter values for the same identifier. Additionally, if you read the previously published articles within this series, you know how to create your own custom response converter and register it into the Retrofit instance.

This post shows you how to add custom headers to your requests by using the @Header annotation within your interface definition or by intercepting the request and add defined header fields with their values.


Retrofit Series Overview

  1. Getting Started and Creating an Android Client
  2. Retrofit 2 — Basics of API Description
  3. Retrofit 2 — Creating a Sustainable Android Client
  4. Synchronous and Asynchronous Requests
  5. Send Objects in Request Body
  6. Add Custom Request Header
  7. Retrofit 2 — Manage Request Headers in OkHttp Interceptor
  8. Retrofit 2 — Dynamic Request Headers with @HeaderMap
  9. Multiple Query Parameters of Same Name
  10. Optional Query Parameters
  11. Using the Log Level to Debug Requests
  12. Retrofit 2 — Log Requests and Responses
  13. Retrofit 2 — Enable Logging for Development Builds Only
  14. How to Upload Files to Server
  15. Retrofit 2 — How to Upload Files to Server
  16. Retrofit 2 — How to Upload Multiple Files to Server
  17. Retrofit 2 — Passing Multiple Parts Along a File with @PartMap
  18. Basic Authentication on Android
  19. Token Authentication on Android
  20. OAuth on Android
  21. Retrofit 2 — Hawk Authentication on Android
  22. How to Refresh an Access Token
  23. Retrofit 2 — Upgrade Guide from 1.9
  24. Retrofit 2 — Simple Error Handling
  25. How to use OkHttp 3 with Retrofit 1
  26. Send Data Form-Urlencoded
  27. Send Data Form-Urlencoded Using FieldMap
  28. Retrofit 2 — How to Add Query Parameters to Every Request
  29. Retrofit 2 — Add Multiple Query Parameter With QueryMap
  30. Retrofit 2 — How to Use Dynamic Urls for Requests
  31. Retrofit 2 — URL Handling, Resolution and Parsing
  32. Retrofit 2 — Constant, Default and Logic Values for POST and PUT Requests
  33. Retrofit 2 — How to Download Files from Server
  34. Retrofit 2 — Cancel Requests
  35. Retrofit 2 — Reuse and Analyze Requests
  36. Retrofit 2 — How to Change API Base Url at Runtime
  37. Optional Path Parameters
  38. Retrofit 2 — How to Send Plain Text Request Body
  39. Retrofit 2 — Pagination Using Query Parameter
  40. Retrofit 2 — Pagination Using Link Header and Dynamic Urls (Like GitHub)
  41. Retrofit 2 — Pagination Using Range Header Fields (Like Heroku)
  42. How to Integrate XML Converter
  43. Define a Custom Response Converter
  44. Retrofit 2 — Introduction to (Multiple) Converters
  45. Retrofit 2 — Adding & Customizing the Gson Converter
  46. Retrofit 2 — Implementing Custom Converters
  47. Retrofit 2 — Basics of Mocking Server Responses
  48. Retrofit 2 — Customizing Network Behavior of Mocked Server Responses (soon)
  49. Java Basics for Retrofit — Callbacks (soon)
  50. Java Basics for Retrofit — Annotations (soon)
  51. Java Basics for Retrofit — Fluent Interface with Builders (soon)

Define Custom Request Headers

Retrofit provides two options to define HTTP request header fields: static and dynamic. Static headers can’t be changed for different requests. The header’s key and value are fixed and initiated with the app startup.

In contrast, dynamic headers must be set for each request.

Static Request Header

The first option to add a static header is to define the header and respective value for your API method as an annotation. The header gets automatically added by Retrofit for every request using this method. The annotation can be either key-value-pair as one string or as a list of strings. Let's face two concrete examples which illustrate the definition options:

Retrofit 1.9

public interface UserService {  
    @Headers("Cache-Control: max-age=640000")
    @GET("/tasks")
    List<Task> getTasks();
}

Retrofit 2

public interface UserService {  
    @Headers("Cache-Control: max-age=640000")
    @GET("/tasks")
    Call<List<Task>> getTasks();
}

The example above shows the key-value-definition for the static header. Further, you can pass multiple key-value-strings as a list encapsulated in curly brackets {} to the @Headers annotation.

Retrofit 1.9

public interface UserService {  
    @Headers({
        "Accept: application/vnd.yourapi.v1.full+json",
        "User-Agent: Your-App-Name"
    })
    @GET("/tasks/{task_id}")
    Task getTask(@Path("task_id") long taskId);
}

Retrofit 2

public interface UserService {  
    @Headers({
        "Accept: application/vnd.yourapi.v1.full+json",
        "User-Agent: Your-App-Name"
    })
    @GET("/tasks/{task_id}")
    Call<Task> getTask(@Path("task_id") long taskId);
}

Additionally, you can define static headers via the intercept method of Retrofits RequestInterceptor (customized implementation of the Interceptor interface in Retrofit 2). We already used the RequestInterceptor within the previous posts (Basic and Token Auth, OAuth) and of course you can enhance it by setting header fields.

Retrofit 1.9

RequestInterceptor requestInterceptor = new RequestInterceptor() {  
    @Override
    public void intercept(RequestFacade request) {
        request.addHeader("User-Agent", "Your-App-Name");
        request.addHeader("Accept", "application/vnd.yourapi.v1.full+json");
    }
};

RestAdapter restAdapter = new RestAdapter.Builder()  
    .setEndpoint("https://api.github.com")
    .setRequestInterceptor(requestInterceptor)
    .build();

Retrofit 2

In Retrofit 2, you need to intercept the request on the network layer provided by OkHttp.

OkHttpClient.Builder httpClient = new OkHttpClient.Builder();  
httpClient.addInterceptor(new Interceptor() {  
    @Override
    public Response intercept(Interceptor.Chain chain) throws IOException {
        Request original = chain.request();

        Request request = original.newBuilder()
            .header("User-Agent", "Your-App-Name")
            .header("Accept", "application/vnd.yourapi.v1.full+json")
            .method(original.method(), original.body())
            .build();

        return chain.proceed(request);
    }
}

OkHttpClient client = httpClient.build();  
Retrofit retrofit = new Retrofit.Builder()  
    .baseUrl(API_BASE_URL)
    .addConverterFactory(GsonConverterFactory.create())
    .client(client)
    .build();

As you can see, the example above sets the User-Agent and Accept header fields with respective values. These values are passed with every request which is executed using the RestAdapter (Retrofit in Retrofit 2) and the integrated RequestInterceptor (Interceptor in Retrofit 2).

Dynamic Header

A more customizable approach are dynamic headers. A dynamic header is passed like a parameter to the method. The provided parameter value gets mapped by Retrofit before executing the request. Let's look at the code example:

Retrofit 1.9

public interface UserService {  
    @GET("/tasks")
    List<Task> getTasks(@Header("Content-Range") String contentRange);
}

Retrofit 2

public interface UserService {  
    @GET("/tasks")
    Call<List<Task>> getTasks(@Header("Content-Range") String contentRange);
}

Define dynamic headers where you might pass different values for each request. The example illustrates the dynamic header with Content-Range definition.

No Header Override in Retrofit 1

Remember: Retrofit doesn't override header definitions with the same name. Every defined header is added to the request.

That's it. Retrofit simplifies header manipulation and allows to simply change them for separated requests when necessary.

In case things went south, give us a shot on twitter @futurestud_io.

Override Existing Headers in Retrofit 2

As opposed to Retrofit v1, you can override the values of existing header fields. You can override the values within the Interceptor implementation passed to the used OkHttp client. The Request.Builder offers two methods to add headers:

  1. .header(key, value): overrides the respective header key with value if there is already an existing header identified by key
  2. .addHeader(key, value): adds the respective header key and value even if there is an existing header field with the same key

Additional Resources


Explore the Library

Find interesting tutorials and solutions for your problems.

Miscellaneous