There is a few use cases where we need to add different headers or authentication mechanisms on a per client basis. Currently the FeignClientFactoryBean appears to apply its configuration to all feign clients that it constructs. This was problematic in that some services that we want to use feign for require a different set of RequestInterceptors to one set of clients verse another. Is there a way to accomplish this today? We were able to work around this issue by using the feign builder directly, with the only thing we are customizing is the list RequestInterceptor from the other FeignClients.
Comment From: spencergibb
Good idea. We have a similar mechanism for @RibbonClient we could reuse.
Comment From: theevangelista
Maybe we could register the RequestInterceptors through a value in @RibbonClient ? So it's clear which client use which interceptor
Comment From: spencergibb
@joaoevangelista we need to maintain separation between Feign and Ribbon. I'm imagining the same type of facility that @RibbonClient uses for @FeignClient. We could probably generalize it for use with other annotations.
Comment From: theevangelista
@spencergibb Really sorry! I meant @FeignClient, I got confused a bit, but yea, a generalized way would be nice too
Comment From: marcosbarbero
Hi everybody, how is this issue going?
Comment From: dwelch2344
Just wanted to throw in my vote on this. We've got a mixture of some ribbon backed FeignClients and a few that are hard coded to 3rd party APIs, so this would be a major win.
Comment From: spencergibb
Yeah, I see this as our biggest feature for feign. I'm working on getting ready for a conference week after next, so it might not get started until after OSCON.
Comment From: sbuettner
Same as @dwelch2344. Would really like to see support for that. Maybe by leveraging springs @Qualifier annotation.
Comment From: lpborges
This is exactly what I need. I need to setup a FeignClient that use Basic Authentication, and this feature can help to setup a Feign BasicAuthRequestInterceptor different for each client. Maybe some options for authentication on the FeignClient annotation can help too.
I figured to setup Authentication using headers in the RequestMapping:
@FeignClient(url="${service.url}")
public interface ProductsClient {
@RequestMapping(method = RequestMethod.GET, value = "/item/{idProduct}", consumes = "application/json",
headers="Authorization: Basic ${service.auth}")
public ProductDTO getProduct(@PathVariable("idProduct") long idProduct);
}
But the problem is that the headers parameter don't apply the Spring value properties ( ${service.auth} ), so you need to hard code the authentication value.
Comment From: theevangelista
For now, you can create a bean of feign.RequestInterceptor returning a BasicAuthRequestInterceptor or implement your own, like I did for OAuth2 here. It will be applied to all requests using feign
Comment From: lpborges
Yes, but the problem is that the same Interceptor is used for all FeignClient, and I have 3 differents clients each one with different authentication user and password.
Comment From: spencergibb
@xyloman @lpborges @joaoevangelista @marcosbarbero @dwelch2344 @sbuettner I have submitted PR #572 for review.
Comment From: sbuettner
I think there is still an issue. It seems that RequestInterceptors are currently only retrieved from the application context but not from the @Configuration defined in the @FeignClient configuration property.
Comment From: spencergibb
@sbuettner If you think there's an issue with the new functionality, please open a new issue, don't comment on an old one.
Comment From: choelea
One page helped me here is: http://stackoverflow.com/questions/37066331/using-headers-with-dynamic-values-in-feign-client-spring-cloud-brixton-rc2. Even though RequestInterceptor works fine for me but it's hard to set the header dynamically. I I am using spring boot 1.4.0
Comment From: subodhkarwa
Is there any inbuild solution, if parameters in headers differ based on URL. Let's say, one client only expects - autheticationToken while other excepts token along with "someSectetKey"
I am overriding interceptors but would welcome if there is something else which can support this
Comment From: ryanjbaxter
@subodhkarwa not sure I understand your question. In any case please open an issue in the Open Feign project https://github.com/spring-cloud/spring-cloud-openfeign
Comment From: damianw345
Hello I found a way to configure two independent interceptors on two different feign clients. I just specified two configuration classes without spring @Configuration annotation. So I have: ` @RequiredArgsConstructor public class FeignOauthClientConfiguration {
private final UploadConfiguration uploadConfiguration;
private final AuthorizationHeaderService authorizationHeaderService;
@Bean
public JiraOauthFeignClientInterceptor jiraOauthFeignClientInterceptor() {
return new JiraOauthFeignClientInterceptor(uploadConfiguration, authorizationHeaderService);
}
} `
and
` public class FeignBasicAuthClientConfiguration {
@Value("${jira.user}")
private String user;
@Value("${jira.password}")
private String password;
@Bean
public RequestInterceptor basicAuthFeignClientInterceptor() {
return new BasicAuthRequestInterceptor(user, password);
}
} ` With @Configuration annotation two interceptors were applied. It is connected to @Bean Lite Mode
https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/context/annotation/Bean.html
Configuration classes are then specified in @FeignClient configuration property
Comment From: mxmlnglt
OK great @damianw345 but now how do you instantiate those configurations...?
I can see you have a Lombok-specific @RequiredArgsConstructor annotation on the first one, so how do you specify it in your @FeignClient configuration annotation?
Comment From: herrsorgenfrei
@mxmlnglt Try the following steps: 1. Reference a configuration class on your client's interface:
@FeignClient(name = "clientOne", configuration = ConfigOne.class)
public interface ClientOne { ... }
- Create your specific interceptor annotated with @Bean inside the configuration:
public class ConfigOne {
@Bean
public InterceptorOne interceptorOne(AdditionalDependency ad) {
return new InterceptorOne(ad);
}
}
- Make sure your ConfigOne-class is not annotated with any @Component/... annotations or is found by component scan.
Does it work for you?
Comment From: ayoubgdah
Thanks @mxmlnglt . It worked like a charm when you remove the @Configuration from the Configuration
Comment From: ethfun
cause BasicAuthRequestInterceptor implements RequestInterceptor , you can check all feign client by diff feign name,this is my solution:
`
@Configuration
public class FeignClientConfiguration {
@Bean
public RequestInterceptor requestInterceptor() {
return requestTemplate -> {
Target target = requestTemplate.feignTarget();
String feignName = target.name();
if ("oneFeign".equals(feignName)) {
template.header("Authorization", headerValue);
} else if (!"twoFeign".equals(feignName)) {
template.header("Authorization", headerValue);
}
};
}
}
`