Skip to content

Commit

Permalink
adds support for response interceptor configuration. Fixes spring-clo…
Browse files Browse the repository at this point in the history
  • Loading branch information
doumdoum committed Dec 9, 2022
1 parent 9354054 commit 821b6cd
Show file tree
Hide file tree
Showing 6 changed files with 71 additions and 2 deletions.
1 change: 1 addition & 0 deletions docs/src/main/asciidoc/spring-cloud-openfeign.adoc
Expand Up @@ -206,6 +206,7 @@ spring:
requestInterceptors:
- com.example.FooRequestInterceptor
- com.example.BarRequestInterceptor
responseInterceptor: com.example.BazResponseInterceptor
dismiss404: false
encoder: com.example.SimpleEncoder
decoder: com.example.SimpleDecoder
Expand Down
Expand Up @@ -32,6 +32,7 @@
import feign.QueryMapEncoder;
import feign.Request;
import feign.RequestInterceptor;
import feign.ResponseInterceptor;
import feign.Retryer;
import feign.Target.HardCodedTarget;
import feign.codec.Decoder;
Expand Down Expand Up @@ -219,6 +220,10 @@ protected void configureUsingConfiguration(FeignClientFactory context, Feign.Bui
AnnotationAwareOrderComparator.sort(interceptors);
builder.requestInterceptors(interceptors);
}
ResponseInterceptor responseInterceptor = getInheritedAwareOptional(context, ResponseInterceptor.class);
if (responseInterceptor != null) {
builder.responseInterceptor(responseInterceptor);
}
QueryMapEncoder queryMapEncoder = getInheritedAwareOptional(context, QueryMapEncoder.class);
if (queryMapEncoder != null) {
builder.queryMapEncoder(queryMapEncoder);
Expand Down Expand Up @@ -277,6 +282,10 @@ protected void configureUsingProperties(FeignClientProperties.FeignClientConfigu
}
}

if (config.getResponseInterceptor() != null) {
builder.responseInterceptor(getOrInstantiate(config.getResponseInterceptor()));
}

if (config.getDismiss404() != null) {
if (config.getDismiss404()) {
builder.dismiss404();
Expand Down
Expand Up @@ -28,6 +28,7 @@
import feign.Logger;
import feign.QueryMapEncoder;
import feign.RequestInterceptor;
import feign.ResponseInterceptor;
import feign.Retryer;
import feign.codec.Decoder;
import feign.codec.Encoder;
Expand Down Expand Up @@ -126,6 +127,8 @@ public static class FeignClientConfiguration {

private List<Class<RequestInterceptor>> requestInterceptors;

private Class<ResponseInterceptor> responseInterceptor;

private Map<String, Collection<String>> defaultRequestHeaders;

private Map<String, Collection<String>> defaultQueryParameters;
Expand Down Expand Up @@ -202,6 +205,14 @@ public void setRequestInterceptors(List<Class<RequestInterceptor>> requestInterc
this.requestInterceptors = requestInterceptors;
}

public Class<ResponseInterceptor> getResponseInterceptor() {
return responseInterceptor;
}

public void setResponseInterceptor(Class<ResponseInterceptor> responseInterceptor) {
this.responseInterceptor = responseInterceptor;
}

public Map<String, Collection<String>> getDefaultRequestHeaders() {
return defaultRequestHeaders;
}
Expand Down Expand Up @@ -311,6 +322,7 @@ public boolean equals(Object o) {
&& Objects.equals(readTimeout, that.readTimeout) && Objects.equals(retryer, that.retryer)
&& Objects.equals(errorDecoder, that.errorDecoder)
&& Objects.equals(requestInterceptors, that.requestInterceptors)
&& Objects.equals(responseInterceptor, that.responseInterceptor)
&& Objects.equals(dismiss404, that.dismiss404) && Objects.equals(encoder, that.encoder)
&& Objects.equals(decoder, that.decoder) && Objects.equals(contract, that.contract)
&& Objects.equals(exceptionPropagationPolicy, that.exceptionPropagationPolicy)
Expand All @@ -325,8 +337,9 @@ public boolean equals(Object o) {
@Override
public int hashCode() {
return Objects.hash(loggerLevel, connectTimeout, readTimeout, retryer, errorDecoder, requestInterceptors,
dismiss404, encoder, decoder, contract, exceptionPropagationPolicy, defaultQueryParameters,
defaultRequestHeaders, capabilities, queryMapEncoder, micrometer, followRedirects, url);
responseInterceptor, dismiss404, encoder, decoder, contract, exceptionPropagationPolicy,
defaultQueryParameters, defaultRequestHeaders, capabilities, queryMapEncoder, micrometer,
followRedirects, url);
}

}
Expand Down
Expand Up @@ -27,6 +27,7 @@
import feign.Logger;
import feign.QueryMapEncoder;
import feign.RequestInterceptor;
import feign.ResponseInterceptor;
import feign.Retryer;
import feign.codec.Decoder;
import feign.codec.Encoder;
Expand Down Expand Up @@ -60,6 +61,7 @@ void shouldDefaultToValuesWhenFieldsNotSet() {
assertThat(config.getRetryer()).isNull();
assertThat(config.getErrorDecoder()).isNull();
assertThat(config.getRequestInterceptors()).isNull();
assertThat(config.getResponseInterceptor()).isNull();
assertThat(config.getDefaultRequestHeaders()).isNull();
assertThat(config.getDefaultQueryParameters()).isNull();
assertThat(config.getDismiss404()).isNull();
Expand All @@ -82,6 +84,8 @@ void shouldReturnValuesWhenSet() {
config.setErrorDecoder(ErrorDecoder.class);
List<Class<RequestInterceptor>> requestInterceptors = Lists.list(RequestInterceptor.class);
config.setRequestInterceptors(requestInterceptors);
Class<ResponseInterceptor> responseInterceptor = ResponseInterceptor.class;
config.setResponseInterceptor(responseInterceptor);
Map<String, Collection<String>> defaultRequestHeaders = Maps.newHashMap("default", Collections.emptyList());
config.setDefaultRequestHeaders(defaultRequestHeaders);
Map<String, Collection<String>> defaultQueryParameters = Maps.newHashMap("default", Collections.emptyList());
Expand All @@ -103,6 +107,7 @@ void shouldReturnValuesWhenSet() {
assertThat(config.getRetryer()).isSameAs(Retryer.class);
assertThat(config.getErrorDecoder()).isSameAs(ErrorDecoder.class);
assertThat(config.getRequestInterceptors()).isSameAs(requestInterceptors);
assertThat(config.getResponseInterceptor()).isSameAs(responseInterceptor);
assertThat(config.getDefaultRequestHeaders()).isSameAs(defaultRequestHeaders);
assertThat(config.getDefaultQueryParameters()).isSameAs(defaultQueryParameters);
assertThat(config.getDismiss404()).isTrue();
Expand Down
Expand Up @@ -34,11 +34,13 @@

import feign.Capability;
import feign.Feign;
import feign.InvocationContext;
import feign.InvocationHandlerFactory;
import feign.QueryMapEncoder;
import feign.Request;
import feign.RequestInterceptor;
import feign.RequestTemplate;
import feign.ResponseInterceptor;
import feign.RetryableException;
import feign.Retryer;
import feign.codec.EncodeException;
Expand Down Expand Up @@ -99,6 +101,8 @@ public class FeignClientUsingPropertiesTests {

private FeignClientFactoryBean barFactoryBean;

private FeignClientFactoryBean bazFactoryBean;

private FeignClientFactoryBean unwrapFactoryBean;

private FeignClientFactoryBean formFactoryBean;
Expand All @@ -116,6 +120,10 @@ public FeignClientUsingPropertiesTests() {
barFactoryBean.setContextId("bar");
barFactoryBean.setType(FeignClientFactoryBean.class);

bazFactoryBean = new FeignClientFactoryBean();
bazFactoryBean.setContextId("baz");
bazFactoryBean.setType(FeignClientFactoryBean.class);

unwrapFactoryBean = new FeignClientFactoryBean();
unwrapFactoryBean.setContextId("unwrap");
unwrapFactoryBean.setType(FeignClientFactoryBean.class);
Expand Down Expand Up @@ -143,6 +151,11 @@ public BarClient barClient() {
return barFactoryBean.feign(context).target(BarClient.class, "http://localhost:" + port);
}

public PingClient pingClient() {
bazFactoryBean.setApplicationContext(applicationContext);
return bazFactoryBean.feign(context).target(PingClient.class, "http://localhost:" + port);
}

public UnwrapClient unwrapClient() {
unwrapFactoryBean.setApplicationContext(applicationContext);
return unwrapFactoryBean.feign(context).target(UnwrapClient.class, "http://localhost:" + port);
Expand All @@ -164,6 +177,12 @@ public void testBar() {
assertThatThrownBy(() -> barClient().bar()).isInstanceOf(RetryableException.class);
}

@Test
public void testBaz() {
String response = pingClient().ping();
assertThat(response).isEqualTo("baz");
}

@Test
public void testUnwrap() throws Exception {
assertThatThrownBy(() -> unwrapClient().unwrap()).isInstanceOf(SocketTimeoutException.class);
Expand Down Expand Up @@ -298,6 +317,13 @@ protected interface BarClient {

}

protected interface PingClient {

@GetMapping(path = "/ping")
String ping();

}

protected interface UnwrapClient {

@GetMapping(path = "/bar") // intentionally /bar
Expand Down Expand Up @@ -355,6 +381,11 @@ public String bar() throws InterruptedException {
return "OK";
}

@GetMapping(path = "/ping")
public String ping() {
return "pong";
}

@PostMapping(path = "/form", consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
public String form(HttpServletRequest request) {
return request.getParameter("form");
Expand Down Expand Up @@ -394,6 +425,15 @@ public void apply(RequestTemplate template) {

}

public static class BazResponseInterceptor implements ResponseInterceptor {

@Override
public Object aroundDecode(InvocationContext invocationContext) {
return "baz";
}

}

public static class NoRetryer implements Retryer {

@Override
Expand Down
Expand Up @@ -12,6 +12,7 @@ spring.cloud.openfeign.client.config.default.capabilities=org.springframework.cl
spring.cloud.openfeign.client.config.default.queryMapEncoder=org.springframework.cloud.openfeign.FeignClientUsingPropertiesTests.NoOpQueryMapEncoder
spring.cloud.openfeign.client.config.foo.requestInterceptors[0]=org.springframework.cloud.openfeign.FeignClientUsingPropertiesTests.FooRequestInterceptor
spring.cloud.openfeign.client.config.foo.requestInterceptors[1]=org.springframework.cloud.openfeign.FeignClientUsingPropertiesTests.BarRequestInterceptor
spring.cloud.openfeign.client.config.baz.responseInterceptor=org.springframework.cloud.openfeign.FeignClientUsingPropertiesTests.BazResponseInterceptor
spring.cloud.openfeign.client.config.singleValue.defaultRequestHeaders[singleValueHeaders]=header
spring.cloud.openfeign.client.config.singleValue.defaultQueryParameters[singleValueParameters]=parameter
spring.cloud.openfeign.client.config.multipleValue.defaultRequestHeaders[multipleValueHeaders]=header1,header2
Expand Down

0 comments on commit 821b6cd

Please sign in to comment.