Headers
Feign supports settings headers on requests either as part of the api or as part of the client depending on the use case.
Set headers using apis
In cases where specific interfaces or calls should always have certain header values set, it makes sense to define headers as part of the api.
Static headers can be set on an api interface or method using the @Headers annotation.
@Headers(“Accept: application/json”)
interface BaseApi {
@Headers(“Content-Type: application/json”)
@RequestLine(“PUT /api/{key}”)
void put(@Param(“key”) String key, V value);
}
Methods can specify dynamic content for static headers using variable expansion in @Headers.
public interface Api {
@RequestLine(“POST /”)
@Headers(“X-Ping: {token}”)
void post(@Param(“token”) String token);
}
In cases where both the header field keys and values are dynamic and the range of possible keys cannot be known ahead of time and may vary between different method calls in the same api/client (e.g. custom metadata header fields such as “x-amz-meta-" or "x-goog-meta-”), a Map parameter can be annotated with HeaderMap to construct a query that uses the contents of the map as its header parameters.
public interface Api {
@RequestLine(“POST /”)
void post(@HeaderMap Map<String, Object> headerMap);
}
These approaches specify header entries as part of the api and do not require any customizations when building the Feign client.
Setting headers per target
To customize headers for each request method on a Target, a RequestInterceptor can be used. RequestInterceptors can be shared across Target instances and are expected to be thread-safe. RequestInterceptors are applied to all request methods on a Target.
If you need per method customization, a custom Target is required, as the a RequestInterceptor does not have access to the current method metadata.
For an example of setting headers using a RequestInterceptor, see the Request Interceptors section.
Headers can be set as part of a custom Target.
static class DynamicAuthTokenTarget implements Target {
public DynamicAuthTokenTarget(Class clazz,
UrlAndTokenProvider provider,
ThreadLocal requestIdProvider);
@Override
public Request apply(RequestTemplate input) {
TokenIdAndPublicURL urlAndToken = provider.get();
if (input.url().indexOf("http") != 0) {
input.insert(0, urlAndToken.publicURL);
}
input.header("X-Auth-Token", urlAndToken.tokenId);
input.header("X-Request-ID", requestIdProvider.get());
return input.request();
}
}
public class Example {
public static void main(String[] args) {
Bank bank = Feign.builder()
.target(new DynamicAuthTokenTarget(Bank.class, provider, requestIdProvider));
}
}
These approaches depend on the custom RequestInterceptor or Target being set on the Feign client when it is built and can be used as a way to set headers on all api calls on a per-client basis. This can be useful for doing things such as setting an authentication token in the header of all api requests on a per-client basis. The methods are run when the api call is made on the thread that invokes the api call, which allows the headers to be set dynamically at call time and in a context-specific manner – for example, thread-local storage can be used to set different header values depending on the invoking thread, which can be useful for things such as setting thread-specific trace identifiers for requests.