From 66c047e6d508adb9425f6251f2aa82adce654549 Mon Sep 17 00:00:00 2001 From: hscholz Date: Fri, 18 Dec 2015 09:11:13 +0100 Subject: [PATCH] fixes gh-716 adds option to decode 404s --- .../cloud/netflix/feign/FeignClient.java | 5 ++++ .../netflix/feign/FeignClientFactoryBean.java | 6 ++++ .../netflix/feign/FeignClientsRegistrar.java | 1 + .../netflix/feign/SpringDecoderTests.java | 13 +++++++++ .../netflix/feign/valid/FeignClientTests.java | 28 +++++++++++++++++-- 5 files changed, 51 insertions(+), 2 deletions(-) diff --git a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/feign/FeignClient.java b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/feign/FeignClient.java index 365d76b2..422fc4f9 100644 --- a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/feign/FeignClient.java +++ b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/feign/FeignClient.java @@ -63,6 +63,11 @@ public @interface FeignClient { */ String url() default ""; + /** + * Whether 404s should be decoded instead of throwing FeignExceptions + */ + boolean decode404() default false; + /** * A custom @Configuration for the feign client. Can contain override * @Bean definition for the pieces that make up the client, for instance diff --git a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/feign/FeignClientFactoryBean.java b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/feign/FeignClientFactoryBean.java index 8124201b..c024f875 100644 --- a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/feign/FeignClientFactoryBean.java +++ b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/feign/FeignClientFactoryBean.java @@ -55,6 +55,8 @@ class FeignClientFactoryBean implements FactoryBean, InitializingBean, A private String url; + private boolean decode404; + private ApplicationContext context; @Override @@ -105,6 +107,10 @@ class FeignClientFactoryBean implements FactoryBean, InitializingBean, A builder.requestInterceptors(requestInterceptors.values()); } + if (decode404) { + builder.decode404(); + } + return builder; } diff --git a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/feign/FeignClientsRegistrar.java b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/feign/FeignClientsRegistrar.java index e5496024..f1cdf717 100644 --- a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/feign/FeignClientsRegistrar.java +++ b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/feign/FeignClientsRegistrar.java @@ -173,6 +173,7 @@ public class FeignClientsRegistrar implements ImportBeanDefinitionRegistrar, definition.addPropertyValue("url", getUrl(attributes)); definition.addPropertyValue("name", getServiceId(attributes)); definition.addPropertyValue("type", className); + definition.addPropertyValue("decode404", attributes.get("decode404")); definition.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_BY_TYPE); String beanName = StringUtils diff --git a/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/feign/SpringDecoderTests.java b/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/feign/SpringDecoderTests.java index 53c852ea..b718b3e3 100644 --- a/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/feign/SpringDecoderTests.java +++ b/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/feign/SpringDecoderTests.java @@ -43,6 +43,7 @@ import org.springframework.web.bind.annotation.RestController; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; /** * @author Spencer Gibb @@ -66,7 +67,12 @@ public class SpringDecoderTests extends FeignClientFactoryBean { } public TestClient testClient() { + return testClient(false); + } + + public TestClient testClient(boolean decode404) { setType(this.getClass()); + setDecode404(decode404); return feign(factory).target(TestClient.class, "http://localhost:" + this.port); } @@ -120,6 +126,13 @@ public class SpringDecoderTests extends FeignClientFactoryBean { testClient().getNotFound(); } + @Test + public void testDecodes404() { + final ResponseEntity response = testClient(true).getNotFound(); + assertNotNull("response was null", response); + assertNull("response body was not null", response.getBody()); + } + @Data @AllArgsConstructor @NoArgsConstructor diff --git a/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/feign/valid/FeignClientTests.java b/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/feign/valid/FeignClientTests.java index 22fbe7dc..9c382685 100644 --- a/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/feign/valid/FeignClientTests.java +++ b/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/feign/valid/FeignClientTests.java @@ -20,6 +20,7 @@ import static org.hamcrest.Matchers.instanceOf; import static org.hamcrest.Matchers.is; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; import static org.junit.Assert.assertThat; import static org.junit.Assert.assertTrue; @@ -90,6 +91,9 @@ public class FeignClientTests { @Autowired private TestClientServiceId testClientServiceId; + @Autowired + private DecodingTestClient decodingTestClient; + @Autowired private Client feignClient; @@ -149,14 +153,21 @@ public class FeignClientTests { Hello getHello(); } + @FeignClient(name = "localapp2", decode404 = true) + protected interface DecodingTestClient { + @RequestMapping(method = RequestMethod.GET, value = "/notFound") + ResponseEntity notFound(); + } + @Configuration @EnableAutoConfiguration @RestController - @EnableFeignClients(clients = {TestClientServiceId.class, TestClient.class}, + @EnableFeignClients(clients = {TestClientServiceId.class, TestClient.class, DecodingTestClient.class}, defaultConfiguration = TestDefaultFeignConfig.class) @RibbonClients({ @RibbonClient(name = "localapp", configuration = LocalRibbonClientConfiguration.class), - @RibbonClient(name = "localapp1", configuration = LocalRibbonClientConfiguration.class) + @RibbonClient(name = "localapp1", configuration = LocalRibbonClientConfiguration.class), + @RibbonClient(name = "localapp2", configuration = LocalRibbonClientConfiguration.class) }) protected static class Application { @@ -204,6 +215,11 @@ public class FeignClientTests { return ResponseEntity.ok().build(); } + @RequestMapping(method = RequestMethod.GET, value = "/notFound") + ResponseEntity notFound() { + return ResponseEntity.status(HttpStatus.NOT_FOUND).body((String)null); + } + public static void main(String[] args) { new SpringApplicationBuilder(Application.class).properties( "spring.application.name=feignclienttest", @@ -299,6 +315,14 @@ public class FeignClientTests { assertEquals("status code was wrong", HttpStatus.OK, response.getStatusCode()); } + @Test + public void testDecodeNotFound() { + ResponseEntity response = decodingTestClient.notFound(); + assertNotNull("response was null", response); + assertEquals("status code was wrong", HttpStatus.NOT_FOUND, response.getStatusCode()); + assertNull("response body was not null", response.getBody()); + } + @Data @AllArgsConstructor @NoArgsConstructor