diff --git a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/feign/FeignConfiguration.java b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/feign/FeignConfiguration.java index e975200b..f00eb939 100644 --- a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/feign/FeignConfiguration.java +++ b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/feign/FeignConfiguration.java @@ -16,21 +16,18 @@ package org.springframework.cloud.netflix.feign; -import feign.slf4j.Slf4jLogger; +import java.util.List; + import org.springframework.beans.factory.annotation.Autowired; import org.springframework.cloud.netflix.archaius.ConfigurableEnvironmentConfiguration; import org.springframework.context.annotation.Configuration; -import feign.Client; -import feign.Contract; -import feign.Feign; -import feign.Logger; -import feign.Request; -import feign.Retryer; +import feign.*; import feign.codec.Decoder; import feign.codec.Encoder; import feign.codec.ErrorDecoder; import feign.ribbon.LoadBalancingTarget; +import feign.slf4j.Slf4jLogger; /** * @author Spencer Gibb @@ -68,6 +65,9 @@ public class FeignConfiguration { @Autowired(required = false) private Client ribbonClient; + @Autowired(required = false) + private List requestInterceptors; + protected Feign.Builder feign() { Feign.Builder builder = Feign.builder() // required values @@ -87,6 +87,9 @@ public class FeignConfiguration { if (this.options != null) { builder.options(this.options); } + if (this.requestInterceptors != null) { + builder.requestInterceptors(requestInterceptors); + } return builder; } @@ -96,7 +99,7 @@ public class FeignConfiguration { } protected T loadBalance(Feign.Builder builder, Class type, String schemeName) { - builder.logger(new Slf4jLogger(type)); //TODO: how to have choice here? + builder.logger(new Slf4jLogger(type)); // TODO: how to have choice here? if (this.ribbonClient != null) { return builder.client(this.ribbonClient).target(type, schemeName); } diff --git a/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/feign/FeignClientTests.java b/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/feign/FeignClientTests.java index 9728ab21..56d9d67d 100644 --- a/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/feign/FeignClientTests.java +++ b/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/feign/FeignClientTests.java @@ -16,9 +16,13 @@ package org.springframework.cloud.netflix.feign; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + import java.lang.reflect.InvocationHandler; import java.lang.reflect.Proxy; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import lombok.AllArgsConstructor; @@ -33,16 +37,25 @@ import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.builder.SpringApplicationBuilder; import org.springframework.boot.test.IntegrationTest; import org.springframework.boot.test.SpringApplicationConfiguration; +import org.springframework.cloud.netflix.ribbon.RibbonClient; +import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.test.annotation.DirtiesContext; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.context.web.WebAppConfiguration; +import org.springframework.web.bind.annotation.RequestHeader; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; +import com.netflix.loadbalancer.BaseLoadBalancer; +import com.netflix.loadbalancer.ILoadBalancer; +import com.netflix.loadbalancer.Server; + +import feign.RequestInterceptor; +import feign.RequestTemplate; + +import static org.junit.Assert.*; /** * @author Spencer Gibb @@ -61,7 +74,7 @@ public class FeignClientTests extends FeignConfiguration { private TestClient testClient; // @FeignClient(value = "http://localhost:9876", loadbalance = false) - @FeignClient("feignclienttest") + @FeignClient("localapp") protected static interface TestClient { @RequestMapping(method = RequestMethod.GET, value = "/hello") public Hello getHello(); @@ -71,14 +84,38 @@ public class FeignClientTests extends FeignConfiguration { @RequestMapping(method = RequestMethod.GET, value = "/hellostrings") public List getHelloStrings(); + + @RequestMapping(method = RequestMethod.GET, value = "/helloheaders") + public List getHelloHeaders(); } @Configuration @EnableAutoConfiguration @RestController @FeignClientScan + @RibbonClient(name = "localapp", configuration = LocalRibbonClientConfiguration.class) protected static class Application { + @Bean + public RequestInterceptor interceptor1() { + return new RequestInterceptor() { + @Override + public void apply(RequestTemplate template) { + template.header("myheader1", "myheader1value"); + } + }; + } + + @Bean + public RequestInterceptor interceptor2() { + return new RequestInterceptor() { + @Override + public void apply(RequestTemplate template) { + template.header("myheader2", "myheader2value"); + } + }; + } + @RequestMapping(method = RequestMethod.GET, value = "/hello") public Hello getHello() { return new Hello("hello world 1"); @@ -86,9 +123,7 @@ public class FeignClientTests extends FeignConfiguration { @RequestMapping(method = RequestMethod.GET, value = "/hellos") public List getHellos() { - ArrayList hellos = new ArrayList<>(); - hellos.add(new Hello("hello world 1")); - hellos.add(new Hello("oi terra 2")); + ArrayList hellos = getHelloList(); return hellos; } @@ -100,6 +135,15 @@ public class FeignClientTests extends FeignConfiguration { return hellos; } + @RequestMapping(method = RequestMethod.GET, value = "/helloheaders") + public List getHelloHeaders(@RequestHeader("myheader1") String myheader1, + @RequestHeader("myheader2") String myheader2) { + ArrayList headers = new ArrayList<>(); + headers.add(myheader1); + headers.add(myheader2); + return headers; + } + public static void main(String[] args) { new SpringApplicationBuilder(Application.class).properties( "spring.application.name=feignclienttest", @@ -107,6 +151,13 @@ public class FeignClientTests extends FeignConfiguration { } } + private static ArrayList getHelloList() { + ArrayList hellos = new ArrayList<>(); + hellos.add(new Hello("hello world 1")); + hellos.add(new Hello("oi terra 2")); + return hellos; + } + @Test public void testClient() { assertNotNull("testClient was null", this.testClient); @@ -116,13 +167,27 @@ public class FeignClientTests extends FeignConfiguration { assertNotNull("invocationHandler was null", invocationHandler); } - // TODO: only works if port is hardcoded cant resolve ${local.server.port} in - // annotation - /* - * @Test public void testSimpleType() { Hello hello = testClient.getHello(); - * assertNotNull("hello was null", hello); assertEquals("first hello didn't match", - * new Hello("hello world 1"), hello); } - */ + @Test + public void testSimpleType() { + Hello hello = testClient.getHello(); + assertNotNull("hello was null", hello); + assertEquals("first hello didn't match", new Hello("hello world 1"), hello); + } + + @Test + public void testGenericType() { + List hellos = testClient.getHellos(); + assertNotNull("hellos was null", hellos); + assertEquals("hellos didn't match", hellos, getHelloList()); + } + + @Test + public void testRequestInterceptors() { + List headers = testClient.getHelloHeaders(); + assertNotNull("headers was null", headers); + assertTrue("headers didn't contain myheader1value", headers.contains("myheader1value")); + assertTrue("headers didn't contain myheader2value", headers.contains("myheader2value")); + } @Data @AllArgsConstructor @@ -131,3 +196,19 @@ public class FeignClientTests extends FeignConfiguration { private String message; } } + +// Load balancer with fixed server list for "local" pointing to localhost +@Configuration +class LocalRibbonClientConfiguration { + + @Value("${local.server.port}") + private int port = 0; + + @Bean + public ILoadBalancer ribbonLoadBalancer() { + BaseLoadBalancer balancer = new BaseLoadBalancer(); + balancer.setServersList(Arrays.asList(new Server("localhost", port))); + return balancer; + } + +}