The solution is to use @RequestHeader annotation instead of feign specific annotations
@FeignClient(name="Simple-Gateway")
interface GatewayClient {
@RequestMapping(method = RequestMethod.GET, value = "/gateway/test")
String getSessionId(@RequestHeader("X-Auth-Token") String token);
}
Answer from Hasnain on Stack OverflowThe solution is to use @RequestHeader annotation instead of feign specific annotations
@FeignClient(name="Simple-Gateway")
interface GatewayClient {
@RequestMapping(method = RequestMethod.GET, value = "/gateway/test")
String getSessionId(@RequestHeader("X-Auth-Token") String token);
}
The @RequestHeader did not work for me. What did work was:
@Headers("X-Auth-Token: {access_token}")
@RequestLine("GET /orders/{id}")
Order get(@Param("id") String id, @Param("access_token") String accessToken);
You can create an interceptor that'd inject headers in all requests as below:
@Bean
public RequestInterceptor requestInterceptor() {
return requestTemplate -> {
requestTemplate.header("user", username);
requestTemplate.header("password", password);
requestTemplate.header("Accept", ContentType.APPLICATION_JSON.getMimeType());
};
}
Also it provides a way to set interceptor using property files as below:
feign:
client:
config:
default:
requestInterceptors:
com.baeldung.cloud.openfeign.JSONPlaceHolderInterceptor
we can create the configuration with default as the client name to configure all @FeignClient objects, or we can declare the feign client name for a configuration
Reference: https://www.baeldung.com/spring-cloud-openfeign
EDIT: Another way is to set headers in yml as below:
feign:
client:
config:
default:
defaultRequestHeaders:
Authorization:
- Basic dXNlcjpwYXNzd29yZA==
SomeOtherHeader:
- Value1
- Value2
we have used below for kotlin to make sure we add proper headers to all the request sent :
Feign client with configuration setup
@FeignClient(name = "YourClient", url = "\${base-url}", configuration = [FeignHeaderConfiguration::class])
interface YourClient
Header configuration
@Configuration
class FeignHeaderConfiguration {
@Bean
fun clientHeaderInterceptor(): ClientHeaderInterceptor {
return ClientHeaderInterceptor()
}
}
and interceptor where we added the header
class ClientHeaderInterceptor : RequestInterceptor {
override fun apply(requestTemplate: RequestTemplate) {
requestTemplate.header("Accept", MediaType.APPLICATION_JSON_VALUE)
}
}
Custom decoder
You could use a custom decoder:
public class CustomDecoder extends GsonDecoder {
private Map<String, Collection<String>> headers;
@Override
public Object decode(Response response, Type type) throws IOException {
headers = response.headers();
return super.decode(response, type);
}
public Map<String, Collection<String>> getHeaders() {
return headers;
}
}
Return Response
Other solution could be return Response instead of List<Dto>:
@Headers({
"Content-Type: " + MediaType.APPLICATION_JSON_UTF8_VALUE
})
@RequestLine("GET Dto/")
Response search();
Then deserialize body and get headers:
Response response = Client.search();
response.headers();
Gson gson = new Gson();
gson.fromJson(response.body().asReader(), Dto.class);
I'm getting late to the party, but I know for someone in the future it could help
We can wrap our response into a ResponseEntity<SomePojo>, by doing that we can access as the headers object as the body with type SomePojo.
...
import org.springframework.http.ResponseEntity;
...
public ResponseEntity<List<Dto>> search() {
DtoClient client = DtoClient.connect();
return client.search();
}
You can also achieve this by adding header to individual methods as follows:
@RequestMapping(method = RequestMethod.GET, path = "/resource", headers = {"myHeader=value"})
Using @Headers with dynamic values in Feign client + Spring Cloud (Brixton RC2) discusses a solution for dynamic values using @RequestHeader.
You can set a specific configuration class on your feign interface and define a RequestInterceptor bean in there. For example:
@FeignClient(name = "foo", url = "http://localhost:4444/feign",
configuration = FeignConfiguration.class)
public interface LocalhostClient {
}
@Configuration
public class FeignConfiguration {
@Bean
public RequestInterceptor requestTokenBearerInterceptor() {
return new RequestInterceptor() {
@Override
public void apply(RequestTemplate requestTemplate) {
// Do what you want to do
}
};
}
}