Below is a sample code to implement ResponseInterceptor for openfeign with spring-boot.
import feign.InvocationContext;
import feign.ResponseInterceptor;
import org.springframework.stereotype.Component;
@Component
public class FeignClientInterceptor implements ResponseInterceptor {
@Override
public Object aroundDecode(InvocationContext invocationContext) {
feign.Response response= invocationContext.response();
feign.Request request=response.request();
//Do something with request and response
return invocationContext.proceed();
}
}
Dependency used for this example:
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>2022.0.1</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
</dependencies>
Answer from zenuve on Stack Overflowjava - Feign response interceptor using Spring Cloud OpenFeign - Stack Overflow
Support Response Interceptors
Response interceptor is not intercepting response
Response interceptor not getting picked from Capability
Below is a sample code to implement ResponseInterceptor for openfeign with spring-boot.
import feign.InvocationContext;
import feign.ResponseInterceptor;
import org.springframework.stereotype.Component;
@Component
public class FeignClientInterceptor implements ResponseInterceptor {
@Override
public Object aroundDecode(InvocationContext invocationContext) {
feign.Response response= invocationContext.response();
feign.Request request=response.request();
//Do something with request and response
return invocationContext.proceed();
}
}
Dependency used for this example:
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>2022.0.1</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
</dependencies>
I dit not succeeded in using the ResponseInterceptor.
But I've found an alternative using the feign.codec.Decoder.
In this example, I'm reading the Content-Language of every Feign client responses :
public class ClientResponseInterceptor implements Decoder {
private final JacksonDecoder delegate;
public ClientResponseInterceptor(JacksonDecoder delegate) {
this.delegate = delegate;
}
@Override
public Object decode(Response response, Type type) throws IOException, FeignException {
String contentLanguageFromFeignResponse;
Collection<String> contentLanguage = response.headers().get(HttpHeaders.CONTENT_LANGUAGE);
// Extract this part in another method
if (contentLanguage != null && !contentLanguage.isEmpty()) {
Optional<String> attributeOpt = contentLanguage.stream().findFirst();
if (attributeOpt.isPresent()) {
contentLanguageFromFeignResponse = attributeOpt.get();
}
}
// Do something with contentLanguageFromFeignResponse
return delegate.decode(response, type);
}
}
And declaring it in your feign config file :
@Bean
public ClientResponseInterceptor responseInterceptor() {
return new ClientResponseInterceptor(new JacksonDecoder(/*objectMapper*/));
}
(You can use another Decoder, JacksonDecoder is just an example)
You don't really need your own implementation of the FeignRequestInterceptor as there is already BasicAuthRequestInterceptor in the feign.auth package that does exactly the same.
That being said, you basically have almost everything set up already. All is left to do is to define the basicAuthRequestInterceptor bean with specific username and password:
@Bean
public RequestInterceptor basicAuthRequestInterceptor() {
return new BasicAuthRequestInterceptor("username", "password");
}
I know the thread is a bit old but wanted to give some explanation on what's happening here.
If you'd like to customize your Feign requests, you can use a RequestInterceptor. This can be a custom implementation or you can reuse what's available in the Feign library, e.g. BasicAuthRequestInterceptor.
How to register it? Well, there are 2 ways to do it depending on how you use Feign.
If you're using plain Feign without Spring, then you gotta set the interceptor to the Feign builder. An example is here.
Feign.builder()
.requestInterceptor(new MyCustomInterceptor())
.target(MyClient.class, "http://localhost:8081");
If you're using Spring Cloud OpenFeign and you use the @FeignClient annotation to construct your clients, then you have to create a bean from your RequestInterceptor by either defining it as a @Component or as a @Bean in one of your @Configuration classes. Example here.
@Component
public class MyCustomInterceptor implements RequestInterceptor {
@Override
public void apply(RequestTemplate template) {
// do something
}
}
Also, you can check out one of my articles in this topic, maybe that clears it up better: Customizing each request with Spring Cloud Feign
A practical example of how to intercept the response in a Spring Cloud OpenFeign.
- Create a custom
Clientby extendingClient.Defaultas shown below:
public class CustomFeignClient extends Client.Default {
public CustomFeignClient(SSLSocketFactory sslContextFactory, HostnameVerifier hostnameVerifier) {
super(sslContextFactory, hostnameVerifier);
}
@Override
public Response execute(Request request, Request.Options options) throws IOException {
Response response = super.execute(request, options);
InputStream bodyStream = response.body().asInputStream();
String responseBody = StreamUtils.copyToString(bodyStream, StandardCharsets.UTF_8);
//TODO do whatever you want with the responseBody - parse and modify it
return response.toBuilder().body(responseBody, StandardCharsets.UTF_8).build();
}
}
- Then use the custom
Clientin a configuration class:
public class FeignClientConfig {
public FeignClientConfig() { }
@Bean
public Client client() {
return new CustomFeignClient(null, null);
}
}
- Finally, use the configuration class in a FeignClient:
@FeignClient(name = "api-client", url = "${api.base-url}", configuration = FeignClientConfig.class)
public interface ApiClient {
}
Good luck
If you want to use feign from spring cloud, use org.springframework.cloud:spring-cloud-starter-feign as your dependency coordinates. Currently the only way to modify the response is to implement your own feign.Client.