From 0adbd5662f8fb87dd9eaa2dc7af5326eaa8e74f4 Mon Sep 17 00:00:00 2001 From: Spencer Gibb Date: Tue, 4 Oct 2016 18:39:07 -0600 Subject: [PATCH 01/48] polish --- .../cloud/netflix/zuul/filters/ZuulProperties.java | 2 +- .../cloud/netflix/ribbon/RibbonUtilsTests.java | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/filters/ZuulProperties.java b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/filters/ZuulProperties.java index b621f59db..59c37dab0 100644 --- a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/filters/ZuulProperties.java +++ b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/filters/ZuulProperties.java @@ -103,7 +103,7 @@ public class ZuulProperties { private Set ignoredHeaders = new LinkedHashSet<>(); /** - * SECURITY_HEADERS are added to ignored headers if spring security is on the classpath and ignoreSecurityHeaders = true + * Flag to say that SECURITY_HEADERS are added to ignored headers if spring security is on the classpath. * By setting ignoreSecurityHeaders to false we can switch off this default behaviour. This should be used together with * disabling the default spring security headers * see https://docs.spring.io/spring-security/site/docs/current/reference/html/headers.html#default-security-headers diff --git a/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/ribbon/RibbonUtilsTests.java b/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/ribbon/RibbonUtilsTests.java index 53b1bd8d3..92548e7f3 100644 --- a/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/ribbon/RibbonUtilsTests.java +++ b/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/ribbon/RibbonUtilsTests.java @@ -17,9 +17,6 @@ package org.springframework.cloud.netflix.ribbon; -import static org.hamcrest.Matchers.is; -import static org.springframework.cloud.netflix.ribbon.RibbonUtils.*; - import java.net.URI; import java.net.URISyntaxException; import java.util.Map; @@ -31,6 +28,10 @@ import com.netflix.client.config.CommonClientConfigKey; import com.netflix.client.config.DefaultClientConfigImpl; import com.netflix.loadbalancer.Server; +import static org.hamcrest.Matchers.is; +import static org.springframework.cloud.netflix.ribbon.RibbonUtils.isSecure; +import static org.springframework.cloud.netflix.ribbon.RibbonUtils.updateToHttpsIfNeeded; + /** * @author Spencer Gibb * @author Jacques-Etienne Beaudet From 8e18c3d3b64b09b48fb77eda298446ebd5c2a0c1 Mon Sep 17 00:00:00 2001 From: bpicode Date: Wed, 5 Oct 2016 02:46:33 +0200 Subject: [PATCH 02/48] Add support for fallback factories in feign client annotation. (#1373) Adds `@FeignClient.fallbackFactory` to define a `feign.hystrix.FallbackFactory`. fixes gh-1117 --- .../main/asciidoc/spring-cloud-netflix.adoc | 24 ++++ .../cloud/netflix/feign/FeignClient.java | 9 ++ .../netflix/feign/FeignClientFactoryBean.java | 2 + .../netflix/feign/FeignClientsRegistrar.java | 1 + .../cloud/netflix/feign/HystrixTargeter.java | 66 ++++++++-- .../invalid/FeignClientValidationTests.java | 124 +++++++++++++++--- .../netflix/feign/valid/FeignClientTests.java | 47 ++++++- 7 files changed, 242 insertions(+), 31 deletions(-) diff --git a/docs/src/main/asciidoc/spring-cloud-netflix.adoc b/docs/src/main/asciidoc/spring-cloud-netflix.adoc index 539611160..1194d049a 100644 --- a/docs/src/main/asciidoc/spring-cloud-netflix.adoc +++ b/docs/src/main/asciidoc/spring-cloud-netflix.adoc @@ -1012,6 +1012,30 @@ static class HystrixClientFallback implements HystrixClient { } ---- +If one needs access to the cause that made the fallback trigger, one can use the `fallbackFactory` attribute inside `@FeignClient`. + +[source,java,indent=0] +---- +@FeignClient(name = "hello", fallbackFactory = HystrixClientFallbackFactory.class) +protected interface HystrixClient { + @RequestMapping(method = RequestMethod.GET, value = "/hello") + Hello iFailSometimes(); +} + +@Component +static class HystrixClientFallbackFactory implements FallbackFactory { + @Override + public HystrixClient create(Throwable cause) { + return new HystrixClientWithFallBackFactory() { + @Override + public Hello iFailSometimes() { + return new Hello("fallback; reason was: " + cause.getMessage()); + } + }; + } +} +---- + WARNING: There is a limitation with the implementation of fallbacks in Feign and how Hystrix fallbacks work. Fallbacks are currently not supported for methods that return `com.netflix.hystrix.HystrixCommand` and `rx.Observable`. [[spring-cloud-feign-inheritance]] 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 8c2e361f6..86620a928 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 @@ -90,6 +90,15 @@ public @interface FeignClient { */ Class fallback() default void.class; + /** + * Define a fallback factory for the specified Feign client interface. The fallback + * factory must produce instances of fallback classes that implement the interface + * annotated by {@link FeignClient}. + * + * @see feign.hystrix.FallbackFactory for details. + */ + Class fallbackFactory() default void.class; + /** * Path prefix to be used by all method-level mappings. Can be used with or without * @RibbonClient. 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 fa345d88c..18bd5b708 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 @@ -69,6 +69,8 @@ class FeignClientFactoryBean implements FactoryBean, InitializingBean, private Class fallback = void.class; + private Class fallbackFactory = void.class; + @Override public void afterPropertiesSet() throws Exception { Assert.hasText(this.name, "Name must be set"); 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 9020c6e75..53c34ef55 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 @@ -179,6 +179,7 @@ class FeignClientsRegistrar implements ImportBeanDefinitionRegistrar, definition.addPropertyValue("type", className); definition.addPropertyValue("decode404", attributes.get("decode404")); definition.addPropertyValue("fallback", attributes.get("fallback")); + definition.addPropertyValue("fallbackFactory", attributes.get("fallbackFactory")); definition.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_BY_TYPE); String alias = name + "FeignClient"; diff --git a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/feign/HystrixTargeter.java b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/feign/HystrixTargeter.java index 5b9ed8d84..66106c702 100644 --- a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/feign/HystrixTargeter.java +++ b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/feign/HystrixTargeter.java @@ -19,6 +19,9 @@ package org.springframework.cloud.netflix.feign; import feign.Feign; import feign.Target; +import feign.hystrix.FallbackFactory; +import feign.hystrix.HystrixFeign; +import org.springframework.util.Assert; /** * @author Spencer Gibb @@ -29,26 +32,67 @@ class HystrixTargeter implements Targeter { @Override public T target(FeignClientFactoryBean factory, Feign.Builder feign, FeignContext context, Target.HardCodedTarget target) { - if (factory.getFallback() == void.class - || !(feign instanceof feign.hystrix.HystrixFeign.Builder)) { + if (!(feign instanceof feign.hystrix.HystrixFeign.Builder)) { return feign.target(target); } + feign.hystrix.HystrixFeign.Builder builder = (feign.hystrix.HystrixFeign.Builder) feign; + Class fallback = factory.getFallback(); + if (fallback != void.class) { + return targetWithFallback(factory.getName(), context, target, builder, fallback); + } + Class fallbackFactory = factory.getFallbackFactory(); + if (fallbackFactory != void.class) { + return targetWithFallbackFactory(factory.getName(), context, target, builder, fallbackFactory); + } - Object fallbackInstance = context.getInstance(factory.getName(), factory.getFallback()); + return feign.target(target); + } + + private T targetWithFallbackFactory(String feignClientName, FeignContext context, + Target.HardCodedTarget target, + HystrixFeign.Builder builder, + Class fallbackFactoryClass) { + FallbackFactory fallbackFactory = (FallbackFactory) + getFromContext("fallbackFactory", feignClientName, context, fallbackFactoryClass, FallbackFactory.class); + /* We take a sample fallback from the fallback factory to check if it returns a fallback + that is compatible with the annotated feign interface. */ + Object exampleFallback = fallbackFactory.create(new RuntimeException()); + Assert.notNull(exampleFallback, + String.format( + "Incompatible fallbackFactory instance for feign client %s. Factory may not produce null!", + feignClientName)); + if (!target.type().isAssignableFrom(exampleFallback.getClass())) { + throw new IllegalStateException( + String.format( + "Incompatible fallbackFactory instance for feign client %s. Factory produces instances of '%s', but should produce instances of '%s'", + feignClientName, exampleFallback.getClass(), target.type())); + } + return builder.target(target, fallbackFactory); + } + + + private T targetWithFallback(String feignClientName, FeignContext context, + Target.HardCodedTarget target, + HystrixFeign.Builder builder, Class fallback) { + T fallbackInstance = getFromContext("fallback", feignClientName, context, fallback, target.type()); + return builder.target(target, fallbackInstance); + } + + private T getFromContext(String fallbackMechanism, String feignClientName, FeignContext context, + Class beanType, Class targetType) { + Object fallbackInstance = context.getInstance(feignClientName, beanType); if (fallbackInstance == null) { throw new IllegalStateException(String.format( - "No fallback instance of type %s found for feign client %s", - factory.getFallback(), factory.getName())); + "No " + fallbackMechanism + " instance of type %s found for feign client %s", + beanType, feignClientName)); } - if (!target.type().isAssignableFrom(factory.getFallback())) { + if (!targetType.isAssignableFrom(beanType)) { throw new IllegalStateException( String.format( - "Incompatible fallback instance. Fallback of type %s is not assignable to %s for feign client %s", - factory.getFallback(), target.type(), factory.getName())); + "Incompatible " + fallbackMechanism + " instance. Fallback/fallbackFactory of type %s is not assignable to %s for feign client %s", + beanType, targetType, feignClientName)); } - - feign.hystrix.HystrixFeign.Builder builder = (feign.hystrix.HystrixFeign.Builder) feign; - return builder.target(target, (T) fallbackInstance); + return (T) fallbackInstance; } } diff --git a/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/feign/invalid/FeignClientValidationTests.java b/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/feign/invalid/FeignClientValidationTests.java index 178fc6435..bd7d235fd 100644 --- a/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/feign/invalid/FeignClientValidationTests.java +++ b/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/feign/invalid/FeignClientValidationTests.java @@ -16,6 +16,7 @@ package org.springframework.cloud.netflix.feign.invalid; +import feign.hystrix.FallbackFactory; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; @@ -42,10 +43,7 @@ public class FeignClientValidationTests { @Test public void testNameAndValue() { this.expected.expectMessage("only one is permitted"); - AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext( - NameAndValueConfiguration.class); - assertNotNull(context.getBean(NameAndValueConfiguration.Client.class)); - context.close(); + new AnnotationConfigApplicationContext(NameAndValueConfiguration.class); } @Configuration @@ -86,10 +84,7 @@ public class FeignClientValidationTests { @Test public void testNotLegalHostname() { this.expected.expectMessage("not legal hostname (foo_bar)"); - AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext( - BadHostnameConfiguration.class); - assertNotNull(context.getBean(BadHostnameConfiguration.Client.class)); - context.close(); + new AnnotationConfigApplicationContext(BadHostnameConfiguration.class); } @Configuration @@ -107,11 +102,12 @@ public class FeignClientValidationTests { @Test public void testMissingFallback() { - this.expected.expectMessage("No fallback instance of type"); + try ( AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext( - MissingFallbackConfiguration.class); - assertNotNull(context.getBean(MissingFallbackConfiguration.Client.class)); - context.close(); + MissingFallbackConfiguration.class)) { + this.expected.expectMessage("No fallback instance of type"); + assertNotNull(context.getBean(MissingFallbackConfiguration.Client.class)); + } } @Configuration @@ -136,11 +132,11 @@ public class FeignClientValidationTests { @Test public void testWrongFallbackType() { - this.expected.expectMessage("Incompatible fallback instance"); - AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext( - WrongFallbackTypeConfiguration.class); - assertNotNull(context.getBean(WrongFallbackTypeConfiguration.Client.class)); - context.close(); + try (AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext( + WrongFallbackTypeConfiguration.class)) { + this.expected.expectMessage("Incompatible fallback instance"); + assertNotNull(context.getBean(WrongFallbackTypeConfiguration.Client.class)); + } } @Configuration @@ -163,4 +159,98 @@ public class FeignClientValidationTests { } } + + @Test + public void testMissingFallbackFactory() { + try (AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext( + MissingFallbackFactoryConfiguration.class)) { + this.expected.expectMessage("No fallbackFactory instance of type"); + assertNotNull(context.getBean(MissingFallbackFactoryConfiguration.Client.class)); + } + } + + @Configuration + @Import(FeignAutoConfiguration.class) + @EnableFeignClients(clients = MissingFallbackFactoryConfiguration.Client.class) + protected static class MissingFallbackFactoryConfiguration { + + @FeignClient(name = "foobar", url = "http://localhost", fallbackFactory = ClientFallback.class) + interface Client { + @RequestMapping(method = RequestMethod.GET, value = "/") + String get(); + } + + class ClientFallback implements FallbackFactory { + + @Override + public Client create(Throwable cause) { + return null; + } + } + } + + @Test + public void testWrongFallbackFactoryType() { + try (AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext( + WrongFallbackFactoryTypeConfiguration.class)) { + this.expected.expectMessage("Incompatible fallbackFactory instance"); + assertNotNull(context.getBean(WrongFallbackFactoryTypeConfiguration.Client.class)); + } + } + + @Configuration + @Import(FeignAutoConfiguration.class) + @EnableFeignClients(clients = WrongFallbackFactoryTypeConfiguration.Client.class) + protected static class WrongFallbackFactoryTypeConfiguration { + + @FeignClient(name = "foobar", url = "http://localhost", fallbackFactory = Dummy.class) + interface Client { + @RequestMapping(method = RequestMethod.GET, value = "/") + String get(); + } + + @Bean + Dummy dummy() { + return new Dummy(); + } + + class Dummy { + } + + } + + @Test + public void testWrongFallbackFactoryGenericType() { + try (AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext( + WrongFallbackFactoryGenericTypeConfiguration.class)) { + this.expected.expectMessage("Incompatible fallbackFactory instance"); + assertNotNull(context.getBean(WrongFallbackFactoryGenericTypeConfiguration.Client.class)); + } + } + + @Configuration + @Import(FeignAutoConfiguration.class) + @EnableFeignClients(clients = WrongFallbackFactoryGenericTypeConfiguration.Client.class) + protected static class WrongFallbackFactoryGenericTypeConfiguration { + + @FeignClient(name = "foobar", url = "http://localhost", fallbackFactory = ClientFallback.class) + interface Client { + @RequestMapping(method = RequestMethod.GET, value = "/") + String get(); + } + + @Bean + ClientFallback dummy() { + return new ClientFallback(); + } + + class ClientFallback implements FallbackFactory { + + @Override + public String create(Throwable cause) { + return "tryinToTrickYa"; + } + } + + } } 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 49f3b8310..366e64545 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 @@ -74,6 +74,7 @@ import feign.Client; import feign.Logger; import feign.RequestInterceptor; import feign.RequestTemplate; +import feign.hystrix.FallbackFactory; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; @@ -115,6 +116,9 @@ public class FeignClientTests { @Autowired HystrixClient hystrixClient; + @Autowired + private HystrixClientWithFallBackFactory hystrixClientWithFallBackFactory; + @Autowired @Qualifier("localapp3FeignClient") HystrixClient namedHystrixClient; @@ -237,6 +241,27 @@ public class FeignClientTests { Future failFuture(); } + @FeignClient(name = "localapp4", fallbackFactory = HystrixClientFallbackFactory.class) + protected interface HystrixClientWithFallBackFactory { + + @RequestMapping(method = RequestMethod.GET, path = "/fail") + Hello fail(); + } + + static class HystrixClientFallbackFactory implements FallbackFactory { + + @Override + public HystrixClientWithFallBackFactory create(final Throwable cause) { + return new HystrixClientWithFallBackFactory() { + @Override + public Hello fail() { + assertNotNull("Cause was null", cause); + return new Hello("Hello from the fallback side: " + cause.getMessage()); + } + }; + } + } + static class HystrixClientFallback implements HystrixClient { @Override public Hello fail() { @@ -268,13 +293,15 @@ public class FeignClientTests { @EnableAutoConfiguration @RestController @EnableFeignClients(clients = { TestClientServiceId.class, TestClient.class, - DecodingTestClient.class, - HystrixClient.class }, defaultConfiguration = TestDefaultFeignConfig.class) + DecodingTestClient.class, HystrixClient.class, HystrixClientWithFallBackFactory.class }, + defaultConfiguration = TestDefaultFeignConfig.class) @RibbonClients({ @RibbonClient(name = "localapp", configuration = LocalRibbonClientConfiguration.class), @RibbonClient(name = "localapp1", configuration = LocalRibbonClientConfiguration.class), @RibbonClient(name = "localapp2", configuration = LocalRibbonClientConfiguration.class), - @RibbonClient(name = "localapp3", configuration = LocalRibbonClientConfiguration.class), }) + @RibbonClient(name = "localapp3", configuration = LocalRibbonClientConfiguration.class), + @RibbonClient(name = "localapp4", configuration = LocalRibbonClientConfiguration.class) + }) protected static class Application { // needs to be in parent context to test multiple HystrixClient beans @@ -283,6 +310,11 @@ public class FeignClientTests { return new HystrixClientFallback(); } + @Bean + public HystrixClientFallbackFactory hystrixClientFallbackFactory() { + return new HystrixClientFallbackFactory(); + } + @Bean FeignFormatterRegistrar feignFormatterRegistrar() { return new FeignFormatterRegistrar() { @@ -584,6 +616,15 @@ public class FeignClientTests { assertEquals("message was wrong", "fallbackfuture", hello.getMessage()); } + @Test + public void testHystrixClientWithFallBackFactory() throws Exception { + Hello hello = hystrixClientWithFallBackFactory.fail(); + assertNotNull("hello was null", hello); + assertNotNull("hello#message was null", hello.getMessage()); + assertTrue("hello#message did not contain the cause (status code) of the fallback invocation", + hello.getMessage().contains("500")); + } + @Test public void namedFeignClientWorks() { assertNotNull("namedHystrixClient was null", this.namedHystrixClient); From 622cc832044c7dc6165ece59502099936f3fa61f Mon Sep 17 00:00:00 2001 From: Spencer Gibb Date: Tue, 4 Oct 2016 18:48:28 -0600 Subject: [PATCH 03/48] polish --- .../org/springframework/cloud/netflix/feign/FeignClient.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) 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 86620a928..1dc139a16 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 @@ -93,7 +93,8 @@ public @interface FeignClient { /** * Define a fallback factory for the specified Feign client interface. The fallback * factory must produce instances of fallback classes that implement the interface - * annotated by {@link FeignClient}. + * annotated by {@link FeignClient}. The fallback factory must be a valid spring + * bean. * * @see feign.hystrix.FallbackFactory for details. */ From ba3923d70608e695aa7a928eb711e4e5da82897e Mon Sep 17 00:00:00 2001 From: Spencer Gibb Date: Wed, 5 Oct 2016 12:51:28 -0600 Subject: [PATCH 04/48] Fix zuul error when there are colons in request param name. Previously, parameter names with colons (ie foo:bar), caused an IllegalArgumentException because 41c364002fe2e0d9e9c1f59ccf4a9c530dcde04a introduced UriTemplate to properly encode. fixes gh-1193 --- .../zuul/filters/ProxyRequestHelper.java | 23 ++++++++++++++++--- .../zuul/filters/ProxyRequestHelperTests.java | 22 ++++++++++++++++++ ...stClientRibbonCommandIntegrationTests.java | 18 ++++++++++++++- 3 files changed, 59 insertions(+), 4 deletions(-) diff --git a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/filters/ProxyRequestHelper.java b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/filters/ProxyRequestHelper.java index 0f99a99e6..85bdb5997 100644 --- a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/filters/ProxyRequestHelper.java +++ b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/filters/ProxyRequestHelper.java @@ -249,6 +249,12 @@ public class ProxyRequestHelper { MultiValueMap headers) { } + /** + * Get url encoded query string. Pay special attention to single parameters with no values + * and parameter names with colon (:) from use of UriTemplate. + * @param params Un-encoded request parameters + * @return + */ public String getQueryString(MultiValueMap params) { if (params.isEmpty()) { return ""; @@ -260,10 +266,21 @@ public class ProxyRequestHelper { for (String value : params.get(param)) { query.append("&"); query.append(param); - if (!"".equals(value)) { - singles.put(param + i, value); + if (!"".equals(value)) { // don't add =, if original is ?wsdl, output is not ?wsdl= + String key = param; + // if form feed is already part of param name double + // since form feed is used as the colon replacement below + if (key.contains("\f")) { + key = (key.replaceAll("\f", "\f\f")); + } + // colon is special to UriTemplate + if (key.contains(":")) { + key = key.replaceAll(":", "\f"); + } + key = key + i; + singles.put(key, value); query.append("={"); - query.append(param + i); + query.append(key); query.append("}"); } i++; diff --git a/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/zuul/filters/ProxyRequestHelperTests.java b/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/zuul/filters/ProxyRequestHelperTests.java index a3f6f6abb..4d211dc01 100644 --- a/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/zuul/filters/ProxyRequestHelperTests.java +++ b/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/zuul/filters/ProxyRequestHelperTests.java @@ -259,6 +259,28 @@ public class ProxyRequestHelperTests { assertThat(queryString, is("?wsdl")); } + @Test + public void getQueryStringEncoded() { + MultiValueMap params = new LinkedMultiValueMap<>(); + params.add("foo", "weird#chars"); + + String queryString = new ProxyRequestHelper().getQueryString(params); + + assertThat(queryString, is("?foo=weird%23chars")); + } + + @Test + public void getQueryParamNameWithColon() { + MultiValueMap params = new LinkedMultiValueMap<>(); + params.add("foo:bar", "baz"); + params.add("foobar", "bam"); + params.add("foo\fbar", "bat"); // form feed is the colon replacement char + + String queryString = new ProxyRequestHelper().getQueryString(params); + + assertThat(queryString, is("?foo:bar=baz&foobar=bam&foo%0Cbar=bat")); + } + @Test public void buildZuulRequestURIWithUTF8() throws Exception { String encodedURI = "/resource/esp%C3%A9cial-char"; diff --git a/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/zuul/filters/route/restclient/RestClientRibbonCommandIntegrationTests.java b/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/zuul/filters/route/restclient/RestClientRibbonCommandIntegrationTests.java index 826a574b8..7b1a4d8b4 100644 --- a/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/zuul/filters/route/restclient/RestClientRibbonCommandIntegrationTests.java +++ b/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/zuul/filters/route/restclient/RestClientRibbonCommandIntegrationTests.java @@ -186,6 +186,17 @@ public class RestClientRibbonCommandIntegrationTests extends ZuulProxyTestBase { assertEquals("/query?foo=weird#chars", result.getBody()); } + @Test + public void simpleHostRouteWithColonParamNames() { + this.routes.addRoute("/self/**", "http://localhost:" + this.port + "/"); + this.endpoint.reset(); + ResponseEntity result = new TestRestTemplate().exchange( + "http://localhost:" + this.port + "/self/colonquery?foo:bar={foobar0}&foobar={foobar1}", HttpMethod.GET, + new HttpEntity<>((Void) null), String.class, "baz", "bam"); + assertEquals(HttpStatus.OK, result.getStatusCode()); + assertEquals("/colonquery?foo:bar=baz&foobar=bam", result.getBody()); + } + @Test public void simpleHostRouteWithContentType() { this.routes.addRoute("/self/**", "http://localhost:" + this.port + "/"); @@ -295,10 +306,15 @@ public class RestClientRibbonCommandIntegrationTests extends ZuulProxyTestBase { } @RequestMapping("/query") - public String addQuery(HttpServletRequest request, @RequestParam String foo) { + public String query(HttpServletRequest request, @RequestParam String foo) { return request.getRequestURI() + "?foo=" + foo; } + @RequestMapping("/colonquery") + public String colonQuery(HttpServletRequest request, @RequestParam(name = "foo:bar") String foobar0, @RequestParam(name = "foobar") String foobar1) { + return request.getRequestURI() + "?foo:bar=" + foobar0 + "&foobar=" + foobar1; + } + @RequestMapping("/matrix/{name}/{another}") public String matrix(@PathVariable("name") String name, @MatrixVariable(value = "p", pathVar = "name") int p, From f30e8b7b4630db74b1cccf436fb3f50f94618427 Mon Sep 17 00:00:00 2001 From: Spencer Gibb Date: Thu, 6 Oct 2016 10:19:46 -0600 Subject: [PATCH 05/48] Remove @Autowired from FeignClientFactoryBean @Autowired causes NullPointerExceptions because of some unknown lifecycle issues. fixes gh-1366 --- .../cloud/netflix/feign/FeignClientFactoryBean.java | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) 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 18bd5b708..e5fcffc7b 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 @@ -51,9 +51,9 @@ import lombok.EqualsAndHashCode; @EqualsAndHashCode(callSuper = false) class FeignClientFactoryBean implements FactoryBean, InitializingBean, ApplicationContextAware { - - @Autowired - private Targeter targeter; + /*********************************** + * WARNING! Nothing in this class should be @Autowired. It causes NPEs because of some lifecycle race condition. + ***********************************/ private Class type; @@ -146,6 +146,7 @@ class FeignClientFactoryBean implements FactoryBean, InitializingBean, Client client = getOptional(context, Client.class); if (client != null) { builder.client(client); + Targeter targeter = get(context, Targeter.class); return targeter.target(this, builder, context, target); } @@ -183,6 +184,7 @@ class FeignClientFactoryBean implements FactoryBean, InitializingBean, } builder.client(client); } + Targeter targeter = get(context, Targeter.class); return targeter.target(this, builder, context, new HardCodedTarget<>( this.type, this.name, url)); } From dd97b6a4b71fc2612feeb07fabd7872b6d91d50b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20S=C5=82ota?= Date: Fri, 7 Oct 2016 00:11:24 +0200 Subject: [PATCH 06/48] #1376 Register and cancel event sending fix --- .../eureka/server/InstanceRegistry.java | 66 ++++++++++++++----- 1 file changed, 50 insertions(+), 16 deletions(-) diff --git a/spring-cloud-netflix-eureka-server/src/main/java/org/springframework/cloud/netflix/eureka/server/InstanceRegistry.java b/spring-cloud-netflix-eureka-server/src/main/java/org/springframework/cloud/netflix/eureka/server/InstanceRegistry.java index 05c5676f7..fe2090f6f 100644 --- a/spring-cloud-netflix-eureka-server/src/main/java/org/springframework/cloud/netflix/eureka/server/InstanceRegistry.java +++ b/spring-cloud-netflix-eureka-server/src/main/java/org/springframework/cloud/netflix/eureka/server/InstanceRegistry.java @@ -18,6 +18,7 @@ package org.springframework.cloud.netflix.eureka.server; import java.util.List; +import com.netflix.eureka.lease.Lease; import org.springframework.beans.BeansException; import org.springframework.cloud.netflix.eureka.server.event.EurekaInstanceCanceledEvent; import org.springframework.cloud.netflix.eureka.server.event.EurekaInstanceRegisteredEvent; @@ -78,27 +79,23 @@ public class InstanceRegistry extends PeerAwareInstanceRegistryImpl @Override public void register(InstanceInfo info, int leaseDuration, boolean isReplication) { - if (log.isDebugEnabled()) { - log.debug("register " + info.getAppName() + ", vip " + info.getVIPAddress() - + ", leaseDuration " + leaseDuration + ", isReplication " - + isReplication); - } - // TODO: what to publish from info (whole object?) - this.ctxt.publishEvent(new EurekaInstanceRegisteredEvent(this, info, - leaseDuration, isReplication)); - + logRegistration(info, isReplication, leaseDuration); + publishEurekaInstanceRegisteredEvent(info, leaseDuration, isReplication); super.register(info, leaseDuration, isReplication); } @Override - public boolean cancel(String appName, String serverId, boolean isReplication) { - if (log.isDebugEnabled()) { - log.debug("cancel " + appName + " serverId " + serverId + ", isReplication {}" - + isReplication); - } - this.ctxt.publishEvent( - new EurekaInstanceCanceledEvent(this, appName, serverId, isReplication)); + public void register(final InstanceInfo info, final boolean isReplication) { + final int instanceLeaseDuration = resolveInstanceLeaseDuration(info); + logRegistration(info, isReplication, instanceLeaseDuration); + publishEurekaInstanceRegisteredEvent(info, instanceLeaseDuration, isReplication); + super.register(info, isReplication); + } + @Override + public boolean cancel(String appName, String serverId, boolean isReplication) { + logCancelation(appName, serverId, isReplication); + publishEurekaInstanceCanceledEvent(appName, serverId, isReplication); return super.cancel(appName, serverId, isReplication); } @@ -126,4 +123,41 @@ public class InstanceRegistry extends PeerAwareInstanceRegistryImpl } return super.renew(appName, serverId, isReplication); } + + @Override + protected boolean internalCancel(String appName, String id, boolean isReplication) { + logCancelation(appName, id, isReplication); + publishEurekaInstanceCanceledEvent(appName, id, isReplication); + return super.internalCancel(appName, id, isReplication); + } + + private void logRegistration(InstanceInfo info, boolean isReplication, int instanceLeaseDuration) { + if (log.isDebugEnabled()) { + log.debug("register " + info.getAppName() + ", vip " + info.getVIPAddress() + + ", leaseDuration " + instanceLeaseDuration + ", isReplication " + isReplication); + } + } + + private void logCancelation(String appName, String serverId, boolean isReplication) { + if (log.isDebugEnabled()) { + log.debug("cancel " + appName + " serverId " + serverId + ", isReplication " + isReplication); + } + } + + private void publishEurekaInstanceRegisteredEvent(InstanceInfo info, int leaseDuration, boolean isReplication) { + // TODO: what to publish from info (whole object?) + this.ctxt.publishEvent(new EurekaInstanceRegisteredEvent(this, info, leaseDuration, isReplication)); + } + + private void publishEurekaInstanceCanceledEvent(String appName, String serverId, boolean isReplication) { + this.ctxt.publishEvent(new EurekaInstanceCanceledEvent(this, appName, serverId, isReplication)); + } + + private int resolveInstanceLeaseDuration(final InstanceInfo info) { + int leaseDuration = Lease.DEFAULT_DURATION_IN_SECS; + if (info.getLeaseInfo() != null && info.getLeaseInfo().getDurationInSecs() > 0) { + leaseDuration = info.getLeaseInfo().getDurationInSecs(); + } + return leaseDuration; + } } From 151e021ef970c5c01c0efe056736a9e5e593558d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20S=C5=82ota?= Date: Sat, 8 Oct 2016 00:15:47 +0200 Subject: [PATCH 07/48] formatting fixed + tests, fixes #1376 --- .../eureka/server/InstanceRegistry.java | 34 +++- .../eureka/server/InstanceRegistryTest.java | 179 ++++++++++++++++++ 2 files changed, 204 insertions(+), 9 deletions(-) create mode 100644 spring-cloud-netflix-eureka-server/src/test/java/org/springframework/cloud/netflix/eureka/server/InstanceRegistryTest.java diff --git a/spring-cloud-netflix-eureka-server/src/main/java/org/springframework/cloud/netflix/eureka/server/InstanceRegistry.java b/spring-cloud-netflix-eureka-server/src/main/java/org/springframework/cloud/netflix/eureka/server/InstanceRegistry.java index fe2090f6f..7ff9de685 100644 --- a/spring-cloud-netflix-eureka-server/src/main/java/org/springframework/cloud/netflix/eureka/server/InstanceRegistry.java +++ b/spring-cloud-netflix-eureka-server/src/main/java/org/springframework/cloud/netflix/eureka/server/InstanceRegistry.java @@ -89,7 +89,7 @@ public class InstanceRegistry extends PeerAwareInstanceRegistryImpl final int instanceLeaseDuration = resolveInstanceLeaseDuration(info); logRegistration(info, isReplication, instanceLeaseDuration); publishEurekaInstanceRegisteredEvent(info, instanceLeaseDuration, isReplication); - super.register(info, isReplication); + superRegister(info, isReplication); } @Override @@ -128,29 +128,45 @@ public class InstanceRegistry extends PeerAwareInstanceRegistryImpl protected boolean internalCancel(String appName, String id, boolean isReplication) { logCancelation(appName, id, isReplication); publishEurekaInstanceCanceledEvent(appName, id, isReplication); + return superInternalCancel(appName, id, isReplication); + } + + protected boolean superInternalCancel(String appName, String id, + boolean isReplication) { return super.internalCancel(appName, id, isReplication); } - private void logRegistration(InstanceInfo info, boolean isReplication, int instanceLeaseDuration) { + protected void superRegister(InstanceInfo info, boolean isReplication) { + super.register(info, isReplication); + } + + private void logRegistration(InstanceInfo info, boolean isReplication, + int instanceLeaseDuration) { if (log.isDebugEnabled()) { - log.debug("register " + info.getAppName() + ", vip " + info.getVIPAddress() - + ", leaseDuration " + instanceLeaseDuration + ", isReplication " + isReplication); + log.debug("register " + info.getAppName() + ", vip " + info.getVIPAddress() + + ", leaseDuration " + instanceLeaseDuration + ", isReplication " + + isReplication); } } private void logCancelation(String appName, String serverId, boolean isReplication) { if (log.isDebugEnabled()) { - log.debug("cancel " + appName + " serverId " + serverId + ", isReplication " + isReplication); + log.debug("cancel " + appName + " serverId " + serverId + ", isReplication " + + isReplication); } } - private void publishEurekaInstanceRegisteredEvent(InstanceInfo info, int leaseDuration, boolean isReplication) { + private void publishEurekaInstanceRegisteredEvent(InstanceInfo info, + int leaseDuration, boolean isReplication) { // TODO: what to publish from info (whole object?) - this.ctxt.publishEvent(new EurekaInstanceRegisteredEvent(this, info, leaseDuration, isReplication)); + this.ctxt.publishEvent(new EurekaInstanceRegisteredEvent(this, info, + leaseDuration, isReplication)); } - private void publishEurekaInstanceCanceledEvent(String appName, String serverId, boolean isReplication) { - this.ctxt.publishEvent(new EurekaInstanceCanceledEvent(this, appName, serverId, isReplication)); + private void publishEurekaInstanceCanceledEvent(String appName, String serverId, + boolean isReplication) { + this.ctxt.publishEvent( + new EurekaInstanceCanceledEvent(this, appName, serverId, isReplication)); } private int resolveInstanceLeaseDuration(final InstanceInfo info) { diff --git a/spring-cloud-netflix-eureka-server/src/test/java/org/springframework/cloud/netflix/eureka/server/InstanceRegistryTest.java b/spring-cloud-netflix-eureka-server/src/test/java/org/springframework/cloud/netflix/eureka/server/InstanceRegistryTest.java new file mode 100644 index 000000000..4c32ce349 --- /dev/null +++ b/spring-cloud-netflix-eureka-server/src/test/java/org/springframework/cloud/netflix/eureka/server/InstanceRegistryTest.java @@ -0,0 +1,179 @@ +package org.springframework.cloud.netflix.eureka.server; + +import static org.junit.Assert.*; +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.anyBoolean; +import static org.mockito.Matchers.anyString; +import static org.mockito.Mockito.*; + +import java.util.LinkedList; +import java.util.List; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.builder.SpringApplicationBuilder; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.mock.mockito.SpyBean; +import org.springframework.cloud.netflix.eureka.server.InstanceRegistryTest.Application; +import org.springframework.cloud.netflix.eureka.server.event.EurekaInstanceCanceledEvent; +import org.springframework.cloud.netflix.eureka.server.event.EurekaInstanceRegisteredEvent; +import org.springframework.context.ApplicationEvent; +import org.springframework.context.ApplicationListener; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +import com.netflix.appinfo.InstanceInfo; +import com.netflix.appinfo.LeaseInfo; +import com.netflix.eureka.registry.PeerAwareInstanceRegistry; + +/** + * @author Bartlomiej Slota + */ +@RunWith(SpringJUnit4ClassRunner.class) +@SpringBootTest(classes = Application.class, + webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, + value = {"spring.application.name=eureka", "logging.level.org.springframework." + + "cloud.netflix.eureka.server.InstanceRegistry=DEBUG"}) +public class InstanceRegistryTest { + + @SpyBean(PeerAwareInstanceRegistry.class) + private InstanceRegistry instanceRegistry; + + @Autowired + private Listener eurekaEventListener; + + @Before + public void setup() { + eurekaEventListener.getApplicationEvents().clear(); + } + + @Test + public void testRegister() throws Exception { + // stubbing superclass method invocation + doNothing().when(instanceRegistry) + .superRegister(any(InstanceInfo.class), anyBoolean()); + + // creating instance info + LeaseInfo leaseInfo = getLeaseInfo(); + InstanceInfo instanceInfo = getInstanceInfo(leaseInfo); + + // calling tested method + instanceRegistry.register(instanceInfo, false); + + // event of proper type is registered + assertEquals(1, eurekaEventListener.getApplicationEvents().size()); + assertTrue(eurekaEventListener.getApplicationEvents().get(0) + instanceof EurekaInstanceRegisteredEvent); + + // event details are correct + EurekaInstanceRegisteredEvent registeredEvent = (EurekaInstanceRegisteredEvent) + (eurekaEventListener.getApplicationEvents().get(0)); + assertEquals(instanceInfo, registeredEvent.getInstanceInfo()); + assertEquals(leaseInfo.getDurationInSecs(), registeredEvent.getLeaseDuration()); + assertEquals(instanceRegistry, registeredEvent.getSource()); + assertFalse(registeredEvent.isReplication()); + + // superclass method wrapper was successfully invoked + verify(instanceRegistry).superRegister(instanceInfo, false); + } + + @Test + public void testDefaultLeaseDurationRegisterEvent() throws Exception { + // stubbing superclass method invocation + doNothing().when(instanceRegistry) + .superRegister(any(InstanceInfo.class), anyBoolean()); + + // creating instance info + InstanceInfo instanceInfo = getInstanceInfo(null); + + // calling tested method + instanceRegistry.register(instanceInfo, false); + + // instance info duration is set to default + EurekaInstanceRegisteredEvent registeredEvent = (EurekaInstanceRegisteredEvent) + (eurekaEventListener.getApplicationEvents().get(0)); + assertEquals(LeaseInfo.DEFAULT_LEASE_DURATION, registeredEvent.getLeaseDuration()); + } + + @Test + public void testInternalCancel() throws Exception { + // stubbing superclass method invocation + doReturn(Boolean.TRUE).when(instanceRegistry) + .superInternalCancel(anyString(), anyString(), anyBoolean()); + + // calling tested method + boolean cancellationResult = instanceRegistry + .internalCancel("my-app", "appId", false); + + // event of proper type is registered + assertEquals(1, eurekaEventListener.getApplicationEvents().size()); + assertTrue(eurekaEventListener.getApplicationEvents().get(0) + instanceof EurekaInstanceCanceledEvent); + + // event details are correct + EurekaInstanceCanceledEvent registeredEvent = (EurekaInstanceCanceledEvent) + (eurekaEventListener.getApplicationEvents().get(0)); + assertEquals("my-app", registeredEvent.getAppName()); + assertEquals("appId", registeredEvent.getServerId()); + assertEquals(instanceRegistry, registeredEvent.getSource()); + assertFalse(registeredEvent.isReplication()); + + // superclass method wrapper was successfully invoked + verify(instanceRegistry).superInternalCancel("my-app", "appId", false); + assertTrue(cancellationResult); + } + + @Configuration + @EnableAutoConfiguration + @EnableEurekaServer + protected static class Application { + + public static void main(String[] args) { + new SpringApplicationBuilder(Application.class) + .properties("spring.application.name=eureka").run(args); + } + + @Bean + public Listener eurekaEventsListener() { + return new Listener(); + } + } + + private LeaseInfo getLeaseInfo() { + LeaseInfo.Builder leaseBuilder = LeaseInfo.Builder.newBuilder(); + leaseBuilder.setRenewalIntervalInSecs(10); + leaseBuilder.setDurationInSecs(15); + return leaseBuilder.build(); + } + + + private InstanceInfo getInstanceInfo(LeaseInfo leaseInfo) { + InstanceInfo.Builder builder = InstanceInfo.Builder.newBuilder(); + builder.setAppName("my-app-name"); + builder.setHostName("my-host-name"); + builder.setPort(8008); + builder.setLeaseInfo(leaseInfo); + return builder.build(); + } + + private static class Listener implements ApplicationListener { + + private final List applicationEvents = new LinkedList<>(); + + @Override + public void onApplicationEvent(ApplicationEvent event) { + if (event instanceof EurekaInstanceCanceledEvent || + event instanceof EurekaInstanceRegisteredEvent) { + applicationEvents.add(event); + } + } + + public List getApplicationEvents() { + return applicationEvents; + } + } +} \ No newline at end of file From 99b86e7a29e3864a351291e7141750b4b96ec1ba Mon Sep 17 00:00:00 2001 From: Ryan Baxter Date: Mon, 10 Oct 2016 15:31:42 -0400 Subject: [PATCH 08/48] Fixes #1374 --- .../filters/pre/FormBodyWrapperFilter.java | 45 ++++++++++--------- spring-cloud-netflix-dependencies/pom.xml | 2 +- 2 files changed, 24 insertions(+), 23 deletions(-) diff --git a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/filters/pre/FormBodyWrapperFilter.java b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/filters/pre/FormBodyWrapperFilter.java index 226817629..dfe88c7db 100644 --- a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/filters/pre/FormBodyWrapperFilter.java +++ b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/filters/pre/FormBodyWrapperFilter.java @@ -16,22 +16,10 @@ package org.springframework.cloud.netflix.zuul.filters.pre; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.OutputStream; -import java.lang.reflect.Field; -import java.util.HashSet; -import java.util.List; -import java.util.Map.Entry; -import java.util.Set; - -import javax.servlet.ServletInputStream; -import javax.servlet.ServletRequest; -import javax.servlet.ServletRequestWrapper; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.Part; - -import org.apache.commons.lang3.StringUtils; +import com.netflix.zuul.ZuulFilter; +import com.netflix.zuul.context.RequestContext; +import com.netflix.zuul.http.HttpServletRequestWrapper; +import com.netflix.zuul.http.ServletInputStreamWrapper; import org.springframework.core.io.InputStreamResource; import org.springframework.core.io.Resource; import org.springframework.http.HttpEntity; @@ -44,14 +32,23 @@ import org.springframework.util.Assert; import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; import org.springframework.util.ReflectionUtils; +import org.springframework.util.StringUtils; import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartRequest; import org.springframework.web.servlet.DispatcherServlet; -import com.netflix.zuul.ZuulFilter; -import com.netflix.zuul.context.RequestContext; -import com.netflix.zuul.http.HttpServletRequestWrapper; -import com.netflix.zuul.http.ServletInputStreamWrapper; +import javax.servlet.ServletInputStream; +import javax.servlet.ServletRequest; +import javax.servlet.ServletRequestWrapper; +import javax.servlet.http.HttpServletRequest; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.lang.reflect.Field; +import java.util.HashSet; +import java.util.List; +import java.util.Map.Entry; +import java.util.Set; /** * @author Spencer Gibb @@ -232,8 +229,12 @@ public class FormBodyWrapperFilter extends ZuulFilter { private Set findQueryParams() { Set result = new HashSet<>(); String query = this.request.getQueryString(); - if (query != null) { - for (String value : StringUtils.split(query, "&")) { + String[] splitQuery = StringUtils.split(query, "&"); + if(splitQuery == null && query != null) { + splitQuery = new String[]{query}; + } + if (splitQuery != null) { + for (String value : splitQuery) { if (value.contains("=")) { value = value.substring(0, value.indexOf("=")); } diff --git a/spring-cloud-netflix-dependencies/pom.xml b/spring-cloud-netflix-dependencies/pom.xml index 99e3cb2dd..094bee0e0 100644 --- a/spring-cloud-netflix-dependencies/pom.xml +++ b/spring-cloud-netflix-dependencies/pom.xml @@ -17,7 +17,7 @@ 0.7.4 1.4.11 9.3.1 - 1.5.5 + 1.5.6 2.2.0 0.10.1 1.2.2 From 50fac81a30a82648dab82e7e7a5e5a1ae43ad719 Mon Sep 17 00:00:00 2001 From: Ryan Baxter Date: Mon, 10 Oct 2016 15:32:20 -0400 Subject: [PATCH 09/48] Revert "Fixes #1374" This reverts commit 99b86e7a29e3864a351291e7141750b4b96ec1ba. --- .../filters/pre/FormBodyWrapperFilter.java | 45 +++++++++---------- spring-cloud-netflix-dependencies/pom.xml | 2 +- 2 files changed, 23 insertions(+), 24 deletions(-) diff --git a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/filters/pre/FormBodyWrapperFilter.java b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/filters/pre/FormBodyWrapperFilter.java index dfe88c7db..226817629 100644 --- a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/filters/pre/FormBodyWrapperFilter.java +++ b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/filters/pre/FormBodyWrapperFilter.java @@ -16,10 +16,22 @@ package org.springframework.cloud.netflix.zuul.filters.pre; -import com.netflix.zuul.ZuulFilter; -import com.netflix.zuul.context.RequestContext; -import com.netflix.zuul.http.HttpServletRequestWrapper; -import com.netflix.zuul.http.ServletInputStreamWrapper; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.lang.reflect.Field; +import java.util.HashSet; +import java.util.List; +import java.util.Map.Entry; +import java.util.Set; + +import javax.servlet.ServletInputStream; +import javax.servlet.ServletRequest; +import javax.servlet.ServletRequestWrapper; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.Part; + +import org.apache.commons.lang3.StringUtils; import org.springframework.core.io.InputStreamResource; import org.springframework.core.io.Resource; import org.springframework.http.HttpEntity; @@ -32,23 +44,14 @@ import org.springframework.util.Assert; import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; import org.springframework.util.ReflectionUtils; -import org.springframework.util.StringUtils; import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartRequest; import org.springframework.web.servlet.DispatcherServlet; -import javax.servlet.ServletInputStream; -import javax.servlet.ServletRequest; -import javax.servlet.ServletRequestWrapper; -import javax.servlet.http.HttpServletRequest; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.OutputStream; -import java.lang.reflect.Field; -import java.util.HashSet; -import java.util.List; -import java.util.Map.Entry; -import java.util.Set; +import com.netflix.zuul.ZuulFilter; +import com.netflix.zuul.context.RequestContext; +import com.netflix.zuul.http.HttpServletRequestWrapper; +import com.netflix.zuul.http.ServletInputStreamWrapper; /** * @author Spencer Gibb @@ -229,12 +232,8 @@ public class FormBodyWrapperFilter extends ZuulFilter { private Set findQueryParams() { Set result = new HashSet<>(); String query = this.request.getQueryString(); - String[] splitQuery = StringUtils.split(query, "&"); - if(splitQuery == null && query != null) { - splitQuery = new String[]{query}; - } - if (splitQuery != null) { - for (String value : splitQuery) { + if (query != null) { + for (String value : StringUtils.split(query, "&")) { if (value.contains("=")) { value = value.substring(0, value.indexOf("=")); } diff --git a/spring-cloud-netflix-dependencies/pom.xml b/spring-cloud-netflix-dependencies/pom.xml index 094bee0e0..99e3cb2dd 100644 --- a/spring-cloud-netflix-dependencies/pom.xml +++ b/spring-cloud-netflix-dependencies/pom.xml @@ -17,7 +17,7 @@ 0.7.4 1.4.11 9.3.1 - 1.5.6 + 1.5.5 2.2.0 0.10.1 1.2.2 From 279edf0665e4646e8ea633b5468f27f5fb7d097d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20S=C5=82ota?= Date: Mon, 10 Oct 2016 22:54:39 +0200 Subject: [PATCH 10/48] super class method wrappers removal and test update #1376 --- .../eureka/server/InstanceRegistry.java | 11 +- .../eureka/server/InstanceRegistryTest.java | 231 ++++++++---------- 2 files changed, 101 insertions(+), 141 deletions(-) diff --git a/spring-cloud-netflix-eureka-server/src/main/java/org/springframework/cloud/netflix/eureka/server/InstanceRegistry.java b/spring-cloud-netflix-eureka-server/src/main/java/org/springframework/cloud/netflix/eureka/server/InstanceRegistry.java index 7ff9de685..69fe52bae 100644 --- a/spring-cloud-netflix-eureka-server/src/main/java/org/springframework/cloud/netflix/eureka/server/InstanceRegistry.java +++ b/spring-cloud-netflix-eureka-server/src/main/java/org/springframework/cloud/netflix/eureka/server/InstanceRegistry.java @@ -89,7 +89,7 @@ public class InstanceRegistry extends PeerAwareInstanceRegistryImpl final int instanceLeaseDuration = resolveInstanceLeaseDuration(info); logRegistration(info, isReplication, instanceLeaseDuration); publishEurekaInstanceRegisteredEvent(info, instanceLeaseDuration, isReplication); - superRegister(info, isReplication); + super.register(info, isReplication); } @Override @@ -128,18 +128,9 @@ public class InstanceRegistry extends PeerAwareInstanceRegistryImpl protected boolean internalCancel(String appName, String id, boolean isReplication) { logCancelation(appName, id, isReplication); publishEurekaInstanceCanceledEvent(appName, id, isReplication); - return superInternalCancel(appName, id, isReplication); - } - - protected boolean superInternalCancel(String appName, String id, - boolean isReplication) { return super.internalCancel(appName, id, isReplication); } - protected void superRegister(InstanceInfo info, boolean isReplication) { - super.register(info, isReplication); - } - private void logRegistration(InstanceInfo info, boolean isReplication, int instanceLeaseDuration) { if (log.isDebugEnabled()) { diff --git a/spring-cloud-netflix-eureka-server/src/test/java/org/springframework/cloud/netflix/eureka/server/InstanceRegistryTest.java b/spring-cloud-netflix-eureka-server/src/test/java/org/springframework/cloud/netflix/eureka/server/InstanceRegistryTest.java index 4c32ce349..fa740240e 100644 --- a/spring-cloud-netflix-eureka-server/src/test/java/org/springframework/cloud/netflix/eureka/server/InstanceRegistryTest.java +++ b/spring-cloud-netflix-eureka-server/src/test/java/org/springframework/cloud/netflix/eureka/server/InstanceRegistryTest.java @@ -1,10 +1,8 @@ package org.springframework.cloud.netflix.eureka.server; import static org.junit.Assert.*; -import static org.mockito.Matchers.any; -import static org.mockito.Matchers.anyBoolean; -import static org.mockito.Matchers.anyString; -import static org.mockito.Mockito.*; +import static org.mockito.Matchers.isA; +import static org.mockito.Mockito.doAnswer; import java.util.LinkedList; import java.util.List; @@ -12,17 +10,18 @@ import java.util.List; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; -import org.springframework.beans.factory.annotation.Autowired; +import org.mockito.invocation.InvocationOnMock; +import org.mockito.stubbing.Answer; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.builder.SpringApplicationBuilder; import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.boot.test.mock.mockito.SpyBean; import org.springframework.cloud.netflix.eureka.server.InstanceRegistryTest.Application; import org.springframework.cloud.netflix.eureka.server.event.EurekaInstanceCanceledEvent; import org.springframework.cloud.netflix.eureka.server.event.EurekaInstanceRegisteredEvent; import org.springframework.context.ApplicationEvent; import org.springframework.context.ApplicationListener; -import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; @@ -40,140 +39,110 @@ import com.netflix.eureka.registry.PeerAwareInstanceRegistry; + "cloud.netflix.eureka.server.InstanceRegistry=DEBUG"}) public class InstanceRegistryTest { - @SpyBean(PeerAwareInstanceRegistry.class) - private InstanceRegistry instanceRegistry; + private final List applicationEvents = new LinkedList<>(); - @Autowired - private Listener eurekaEventListener; + @SpyBean(PeerAwareInstanceRegistry.class) + private InstanceRegistry instanceRegistry; - @Before - public void setup() { - eurekaEventListener.getApplicationEvents().clear(); - } + @MockBean + private ApplicationListener + instanceRegisteredEventListenerMock; - @Test - public void testRegister() throws Exception { - // stubbing superclass method invocation - doNothing().when(instanceRegistry) - .superRegister(any(InstanceInfo.class), anyBoolean()); + @MockBean + private ApplicationListener + instanceCanceledEventListenerMock; - // creating instance info - LeaseInfo leaseInfo = getLeaseInfo(); - InstanceInfo instanceInfo = getInstanceInfo(leaseInfo); + @Before + public void setup() { + applicationEvents.clear(); + Answer applicationListenerAnswer = prepareListenerMockAnswer(); + doAnswer(applicationListenerAnswer).when(instanceRegisteredEventListenerMock) + .onApplicationEvent(isA(EurekaInstanceRegisteredEvent.class)); + doAnswer(applicationListenerAnswer).when(instanceCanceledEventListenerMock) + .onApplicationEvent(isA(EurekaInstanceCanceledEvent.class)); + } + - // calling tested method - instanceRegistry.register(instanceInfo, false); + @Test + public void testRegister() throws Exception { + // creating instance info + LeaseInfo leaseInfo = getLeaseInfo(); + InstanceInfo instanceInfo = getInstanceInfo(leaseInfo); + // calling tested method + instanceRegistry.register(instanceInfo, false); + // event of proper type is registered + assertEquals(1, applicationEvents.size()); + assertTrue(applicationEvents.get(0) instanceof EurekaInstanceRegisteredEvent); + // event details are correct + EurekaInstanceRegisteredEvent registeredEvent = + (EurekaInstanceRegisteredEvent) (applicationEvents.get(0)); + assertEquals(instanceInfo, registeredEvent.getInstanceInfo()); + assertEquals(leaseInfo.getDurationInSecs(), registeredEvent.getLeaseDuration()); + assertEquals(instanceRegistry, registeredEvent.getSource()); + assertFalse(registeredEvent.isReplication()); + } - // event of proper type is registered - assertEquals(1, eurekaEventListener.getApplicationEvents().size()); - assertTrue(eurekaEventListener.getApplicationEvents().get(0) - instanceof EurekaInstanceRegisteredEvent); + @Test + public void testDefaultLeaseDurationRegisterEvent() throws Exception { + // creating instance info + InstanceInfo instanceInfo = getInstanceInfo(null); + // calling tested method + instanceRegistry.register(instanceInfo, false); + // instance info duration is set to default + EurekaInstanceRegisteredEvent registeredEvent = + (EurekaInstanceRegisteredEvent) (applicationEvents.get(0)); + assertEquals(LeaseInfo.DEFAULT_LEASE_DURATION, + registeredEvent.getLeaseDuration()); + } - // event details are correct - EurekaInstanceRegisteredEvent registeredEvent = (EurekaInstanceRegisteredEvent) - (eurekaEventListener.getApplicationEvents().get(0)); - assertEquals(instanceInfo, registeredEvent.getInstanceInfo()); - assertEquals(leaseInfo.getDurationInSecs(), registeredEvent.getLeaseDuration()); - assertEquals(instanceRegistry, registeredEvent.getSource()); - assertFalse(registeredEvent.isReplication()); + @Test + public void testInternalCancel() throws Exception { + // calling tested method + instanceRegistry.internalCancel("my-app", "appId", false); + // event of proper type is registered + assertEquals(1, applicationEvents.size()); + assertTrue(applicationEvents.get(0) instanceof EurekaInstanceCanceledEvent); + // event details are correct + EurekaInstanceCanceledEvent registeredEvent = + (EurekaInstanceCanceledEvent) (applicationEvents.get(0)); + assertEquals("my-app", registeredEvent.getAppName()); + assertEquals("appId", registeredEvent.getServerId()); + assertEquals(instanceRegistry, registeredEvent.getSource()); + assertFalse(registeredEvent.isReplication()); + } - // superclass method wrapper was successfully invoked - verify(instanceRegistry).superRegister(instanceInfo, false); - } + @Configuration + @EnableAutoConfiguration + @EnableEurekaServer + protected static class Application { + public static void main(String[] args) { + new SpringApplicationBuilder(Application.class).run(args); + } + } - @Test - public void testDefaultLeaseDurationRegisterEvent() throws Exception { - // stubbing superclass method invocation - doNothing().when(instanceRegistry) - .superRegister(any(InstanceInfo.class), anyBoolean()); + private LeaseInfo getLeaseInfo() { + LeaseInfo.Builder leaseBuilder = LeaseInfo.Builder.newBuilder(); + leaseBuilder.setRenewalIntervalInSecs(10); + leaseBuilder.setDurationInSecs(15); + return leaseBuilder.build(); + } - // creating instance info - InstanceInfo instanceInfo = getInstanceInfo(null); + private InstanceInfo getInstanceInfo(LeaseInfo leaseInfo) { + InstanceInfo.Builder builder = InstanceInfo.Builder.newBuilder(); + builder.setAppName("my-app-name"); + builder.setHostName("my-host-name"); + builder.setPort(8008); + builder.setLeaseInfo(leaseInfo); + return builder.build(); + } - // calling tested method - instanceRegistry.register(instanceInfo, false); - - // instance info duration is set to default - EurekaInstanceRegisteredEvent registeredEvent = (EurekaInstanceRegisteredEvent) - (eurekaEventListener.getApplicationEvents().get(0)); - assertEquals(LeaseInfo.DEFAULT_LEASE_DURATION, registeredEvent.getLeaseDuration()); - } - - @Test - public void testInternalCancel() throws Exception { - // stubbing superclass method invocation - doReturn(Boolean.TRUE).when(instanceRegistry) - .superInternalCancel(anyString(), anyString(), anyBoolean()); - - // calling tested method - boolean cancellationResult = instanceRegistry - .internalCancel("my-app", "appId", false); - - // event of proper type is registered - assertEquals(1, eurekaEventListener.getApplicationEvents().size()); - assertTrue(eurekaEventListener.getApplicationEvents().get(0) - instanceof EurekaInstanceCanceledEvent); - - // event details are correct - EurekaInstanceCanceledEvent registeredEvent = (EurekaInstanceCanceledEvent) - (eurekaEventListener.getApplicationEvents().get(0)); - assertEquals("my-app", registeredEvent.getAppName()); - assertEquals("appId", registeredEvent.getServerId()); - assertEquals(instanceRegistry, registeredEvent.getSource()); - assertFalse(registeredEvent.isReplication()); - - // superclass method wrapper was successfully invoked - verify(instanceRegistry).superInternalCancel("my-app", "appId", false); - assertTrue(cancellationResult); - } - - @Configuration - @EnableAutoConfiguration - @EnableEurekaServer - protected static class Application { - - public static void main(String[] args) { - new SpringApplicationBuilder(Application.class) - .properties("spring.application.name=eureka").run(args); - } - - @Bean - public Listener eurekaEventsListener() { - return new Listener(); - } - } - - private LeaseInfo getLeaseInfo() { - LeaseInfo.Builder leaseBuilder = LeaseInfo.Builder.newBuilder(); - leaseBuilder.setRenewalIntervalInSecs(10); - leaseBuilder.setDurationInSecs(15); - return leaseBuilder.build(); - } - - - private InstanceInfo getInstanceInfo(LeaseInfo leaseInfo) { - InstanceInfo.Builder builder = InstanceInfo.Builder.newBuilder(); - builder.setAppName("my-app-name"); - builder.setHostName("my-host-name"); - builder.setPort(8008); - builder.setLeaseInfo(leaseInfo); - return builder.build(); - } - - private static class Listener implements ApplicationListener { - - private final List applicationEvents = new LinkedList<>(); - - @Override - public void onApplicationEvent(ApplicationEvent event) { - if (event instanceof EurekaInstanceCanceledEvent || - event instanceof EurekaInstanceRegisteredEvent) { - applicationEvents.add(event); - } - } - - public List getApplicationEvents() { - return applicationEvents; - } - } + private Answer prepareListenerMockAnswer() { + return new Answer() { + @Override + public Object answer(InvocationOnMock invocation) throws Throwable { + return applicationEvents + .add((ApplicationEvent) invocation.getArguments()[0]); + } + }; + } } \ No newline at end of file From c8829f2aa4ffac27772c4e960ced51a582f38d00 Mon Sep 17 00:00:00 2001 From: Max Ishchenko Date: Tue, 11 Oct 2016 17:19:33 +0300 Subject: [PATCH 11/48] Prevent double url encoding for secure ribbon urls (#1389) Secure ribbon urls were forced to use https scheme via UriComponentsBuilder, that was created from original uri. This transformation url encoded previously encoded url parts that were used to create builder. This was introduced in c883495. This change fixes double url encoding using RibbonUtils.updateToHttpsIfNeeded that fixes double escaping case and corner case with '+' in url as well. Fixes gh-1382 --- .../ribbon/RibbonLoadBalancerClient.java | 9 +++---- .../ribbon/RibbonLoadBalancerClientTests.java | 26 +++++++++++++++++++ 2 files changed, 30 insertions(+), 5 deletions(-) diff --git a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/ribbon/RibbonLoadBalancerClient.java b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/ribbon/RibbonLoadBalancerClient.java index 4d00a9fb8..c9261db56 100644 --- a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/ribbon/RibbonLoadBalancerClient.java +++ b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/ribbon/RibbonLoadBalancerClient.java @@ -52,11 +52,10 @@ public class RibbonLoadBalancerClient implements LoadBalancerClient { RibbonLoadBalancerContext context = this.clientFactory .getLoadBalancerContext(serviceId); Server server = new Server(instance.getHost(), instance.getPort()); - boolean secure = isSecure(server, serviceId); - URI uri = original; - if (secure) { - uri = UriComponentsBuilder.fromUri(uri).scheme("https").build().toUri(); - } + IClientConfig clientConfig = clientFactory.getClientConfig(serviceId); + ServerIntrospector serverIntrospector = serverIntrospector(serviceId); + URI uri = RibbonUtils.updateToHttpsIfNeeded(original, clientConfig, + serverIntrospector, server); return context.reconstructURIWithServer(server, uri); } diff --git a/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/ribbon/RibbonLoadBalancerClientTests.java b/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/ribbon/RibbonLoadBalancerClientTests.java index e224a1342..f2e540cdb 100644 --- a/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/ribbon/RibbonLoadBalancerClientTests.java +++ b/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/ribbon/RibbonLoadBalancerClientTests.java @@ -38,6 +38,7 @@ import com.netflix.loadbalancer.Server; import com.netflix.loadbalancer.ServerStats; import lombok.SneakyThrows; +import org.springframework.web.util.DefaultUriTemplateHandler; import static org.hamcrest.Matchers.instanceOf; import static org.hamcrest.Matchers.is; @@ -107,6 +108,31 @@ public class RibbonLoadBalancerClientTests { assertEquals(server.getPort(), uri.getPort()); } + @Test + public void testReconstructSecureUriWithSpecialCharsPath() { + testReconstructUriWithPath("https", "/foo=|"); + } + + @Test + public void testReconstructUnsecureUriWithSpecialCharsPath() { + testReconstructUriWithPath("http", "/foo=|"); + } + + private void testReconstructUriWithPath(String scheme, String path) { + RibbonServer server = getRibbonServer(); + IClientConfig config = mock(IClientConfig.class); + when(config.get(CommonClientConfigKey.IsSecure)).thenReturn(true); + when(clientFactory.getClientConfig(server.getServiceId())).thenReturn(config); + + RibbonLoadBalancerClient client = getRibbonLoadBalancerClient(server); + ServiceInstance serviceInstance = client.choose(server.getServiceId()); + + URI expanded = new DefaultUriTemplateHandler() + .expand(scheme + "://" + server.getServiceId() + path); + URI reconstructed = client.reconstructURI(serviceInstance, expanded); + assertEquals(expanded.getPath(), reconstructed.getPath()); + } + @Test @SneakyThrows public void testReconstructUriWithSecureClientConfig() { From aa160940df8901bde2d30ad4ac48e868e765e939 Mon Sep 17 00:00:00 2001 From: Spencer Gibb Date: Tue, 11 Oct 2016 10:25:02 -0600 Subject: [PATCH 12/48] import order --- .../cloud/netflix/ribbon/RibbonLoadBalancerClientTests.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/ribbon/RibbonLoadBalancerClientTests.java b/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/ribbon/RibbonLoadBalancerClientTests.java index f2e540cdb..905cc6ac5 100644 --- a/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/ribbon/RibbonLoadBalancerClientTests.java +++ b/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/ribbon/RibbonLoadBalancerClientTests.java @@ -29,6 +29,7 @@ import org.mockito.MockitoAnnotations; import org.springframework.cloud.client.ServiceInstance; import org.springframework.cloud.client.loadbalancer.LoadBalancerRequest; import org.springframework.cloud.netflix.ribbon.RibbonLoadBalancerClient.RibbonServer; +import org.springframework.web.util.DefaultUriTemplateHandler; import com.netflix.client.config.CommonClientConfigKey; import com.netflix.client.config.IClientConfig; @@ -38,7 +39,6 @@ import com.netflix.loadbalancer.Server; import com.netflix.loadbalancer.ServerStats; import lombok.SneakyThrows; -import org.springframework.web.util.DefaultUriTemplateHandler; import static org.hamcrest.Matchers.instanceOf; import static org.hamcrest.Matchers.is; From 5a127d07002daa6e7cb8ef8d4e9ce302aa49e84c Mon Sep 17 00:00:00 2001 From: mg Date: Sun, 2 Oct 2016 13:44:51 -0500 Subject: [PATCH 13/48] Warning for GC Overhead Limit Reached with servo. Fixes gh-947 --- docs/src/main/asciidoc/spring-cloud-netflix.adoc | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/docs/src/main/asciidoc/spring-cloud-netflix.adoc b/docs/src/main/asciidoc/spring-cloud-netflix.adoc index 1194d049a..13d3d4b0a 100644 --- a/docs/src/main/asciidoc/spring-cloud-netflix.adoc +++ b/docs/src/main/asciidoc/spring-cloud-netflix.adoc @@ -1758,6 +1758,18 @@ If Spring AOP is enabled and `org.aspectj:aspectjweaver` is present on your runt 3. URI, sanitized for Atlas 4. Client name +WARNING: Avoid using hardcoded url parameters within `RestTemplate`. When targeting dynamic endpoints use URL variables. This will avoid potential "GC Overhead Limit Reached" issues where `ServoMonitorCache` treats each url as a unique key. + +[source,java,indent=0] +---- +// recommended +String orderid = "1"; +restTemplate.getForObject("http://testeurekabrixtonclient/orders/{orderid}", String.class, orderid) + +// avoid +restTemplate.getForObject("http://testeurekabrixtonclient/orders/1", String.class) +---- + [[netflix-metrics-spectator]] === Metrics Collection: Spectator From 18c4bc060b2b3c19f1ce9b0b1d6f3f1b6cbf85dd Mon Sep 17 00:00:00 2001 From: Ryan Baxter Date: Tue, 11 Oct 2016 13:41:31 -0400 Subject: [PATCH 14/48] Upgrade hystrix 1.5.6 (#1388) Fixes gh-1374 --- .../zuul/filters/pre/FormBodyWrapperFilter.java | 13 ++++++------- spring-cloud-netflix-dependencies/pom.xml | 2 +- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/filters/pre/FormBodyWrapperFilter.java b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/filters/pre/FormBodyWrapperFilter.java index 226817629..500ee5a23 100644 --- a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/filters/pre/FormBodyWrapperFilter.java +++ b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/filters/pre/FormBodyWrapperFilter.java @@ -22,16 +22,14 @@ import java.io.OutputStream; import java.lang.reflect.Field; import java.util.HashSet; import java.util.List; -import java.util.Map.Entry; import java.util.Set; +import java.util.Map.Entry; import javax.servlet.ServletInputStream; import javax.servlet.ServletRequest; import javax.servlet.ServletRequestWrapper; import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.Part; -import org.apache.commons.lang3.StringUtils; import org.springframework.core.io.InputStreamResource; import org.springframework.core.io.Resource; import org.springframework.http.HttpEntity; @@ -44,6 +42,7 @@ import org.springframework.util.Assert; import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; import org.springframework.util.ReflectionUtils; +import org.springframework.util.StringUtils; import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartRequest; import org.springframework.web.servlet.DispatcherServlet; @@ -65,7 +64,7 @@ public class FormBodyWrapperFilter extends ZuulFilter { this.requestField = ReflectionUtils.findField(HttpServletRequestWrapper.class, "req", HttpServletRequest.class); this.servletRequestField = ReflectionUtils.findField(ServletRequestWrapper.class, - "request", ServletRequest.class); + "request", ServletRequest.class); Assert.notNull(this.requestField, "HttpServletRequestWrapper.req field not found"); Assert.notNull(this.servletRequestField, @@ -121,7 +120,7 @@ public class FormBodyWrapperFilter extends ZuulFilter { .getField(this.requestField, request); wrapper = new FormBodyRequestWrapper(wrapped); ReflectionUtils.setField(this.requestField, request, wrapper); - if(request instanceof ServletRequestWrapper) { + if (request instanceof ServletRequestWrapper) { ReflectionUtils.setField(this.servletRequestField, request, wrapper); } } @@ -170,7 +169,7 @@ public class FormBodyWrapperFilter extends ZuulFilter { } return this.contentLength; } - + @Override public long getContentLengthLong() { return getContentLength(); @@ -233,7 +232,7 @@ public class FormBodyWrapperFilter extends ZuulFilter { Set result = new HashSet<>(); String query = this.request.getQueryString(); if (query != null) { - for (String value : StringUtils.split(query, "&")) { + for (String value : StringUtils.tokenizeToStringArray(query, "&")) { if (value.contains("=")) { value = value.substring(0, value.indexOf("=")); } diff --git a/spring-cloud-netflix-dependencies/pom.xml b/spring-cloud-netflix-dependencies/pom.xml index 99e3cb2dd..094bee0e0 100644 --- a/spring-cloud-netflix-dependencies/pom.xml +++ b/spring-cloud-netflix-dependencies/pom.xml @@ -17,7 +17,7 @@ 0.7.4 1.4.11 9.3.1 - 1.5.5 + 1.5.6 2.2.0 0.10.1 1.2.2 From bdf2f25259b9207a4053235f3c95132fc547afe8 Mon Sep 17 00:00:00 2001 From: Ryan Baxter Date: Tue, 11 Oct 2016 14:27:47 -0400 Subject: [PATCH 15/48] Fixes #1306 --- spring-cloud-netflix-dependencies/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-cloud-netflix-dependencies/pom.xml b/spring-cloud-netflix-dependencies/pom.xml index 094bee0e0..8d0a85dae 100644 --- a/spring-cloud-netflix-dependencies/pom.xml +++ b/spring-cloud-netflix-dependencies/pom.xml @@ -20,7 +20,7 @@ 1.5.6 2.2.0 0.10.1 - 1.2.2 + 1.3.0 1.1.10 1.7 1.0.0 From 4aaa7d0555baa0e8ebc5f19238eb0cfd735b4f65 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20S=C5=82ota?= Date: Tue, 11 Oct 2016 21:46:25 +0200 Subject: [PATCH 16/48] InstanceRegistry class refactor + renew method test #1376 --- .../eureka/server/InstanceRegistry.java | 67 ++++++++---------- .../eureka/server/InstanceRegistryTest.java | 68 +++++++++++++++---- 2 files changed, 81 insertions(+), 54 deletions(-) diff --git a/spring-cloud-netflix-eureka-server/src/main/java/org/springframework/cloud/netflix/eureka/server/InstanceRegistry.java b/spring-cloud-netflix-eureka-server/src/main/java/org/springframework/cloud/netflix/eureka/server/InstanceRegistry.java index 69fe52bae..c1ba8b25d 100644 --- a/spring-cloud-netflix-eureka-server/src/main/java/org/springframework/cloud/netflix/eureka/server/InstanceRegistry.java +++ b/spring-cloud-netflix-eureka-server/src/main/java/org/springframework/cloud/netflix/eureka/server/InstanceRegistry.java @@ -36,6 +36,7 @@ import com.netflix.eureka.registry.PeerAwareInstanceRegistryImpl; import com.netflix.eureka.resources.ServerCodecs; import lombok.extern.apachecommons.CommonsLog; +import org.springframework.context.ApplicationEvent; /** * @author Spencer Gibb @@ -79,33 +80,27 @@ public class InstanceRegistry extends PeerAwareInstanceRegistryImpl @Override public void register(InstanceInfo info, int leaseDuration, boolean isReplication) { - logRegistration(info, isReplication, leaseDuration); - publishEurekaInstanceRegisteredEvent(info, leaseDuration, isReplication); + handleRegistration(info, leaseDuration, isReplication); super.register(info, leaseDuration, isReplication); } @Override public void register(final InstanceInfo info, final boolean isReplication) { - final int instanceLeaseDuration = resolveInstanceLeaseDuration(info); - logRegistration(info, isReplication, instanceLeaseDuration); - publishEurekaInstanceRegisteredEvent(info, instanceLeaseDuration, isReplication); + handleRegistration(info, resolveInstanceLeaseDuration(info), isReplication); super.register(info, isReplication); } @Override public boolean cancel(String appName, String serverId, boolean isReplication) { - logCancelation(appName, serverId, isReplication); - publishEurekaInstanceCanceledEvent(appName, serverId, isReplication); + handleCancelation(appName, serverId, isReplication); return super.cancel(appName, serverId, isReplication); } @Override public boolean renew(final String appName, final String serverId, boolean isReplication) { - if (log.isDebugEnabled()) { - log.debug("renew " + appName + " serverId " + serverId + ", isReplication {}" - + isReplication); - } + log("renew " + appName + " serverId " + serverId + ", isReplication {}" + + isReplication); List applications = getSortedApplications(); for (Application input : applications) { if (input.getName().equals(appName)) { @@ -116,8 +111,8 @@ public class InstanceRegistry extends PeerAwareInstanceRegistryImpl break; } } - this.ctxt.publishEvent(new EurekaInstanceRenewedEvent(this, appName, - serverId, instance, isReplication)); + publishEvent(new EurekaInstanceRenewedEvent(this, appName, serverId, + instance, isReplication)); break; } } @@ -126,38 +121,32 @@ public class InstanceRegistry extends PeerAwareInstanceRegistryImpl @Override protected boolean internalCancel(String appName, String id, boolean isReplication) { - logCancelation(appName, id, isReplication); - publishEurekaInstanceCanceledEvent(appName, id, isReplication); + handleCancelation(appName, id, isReplication); return super.internalCancel(appName, id, isReplication); } - private void logRegistration(InstanceInfo info, boolean isReplication, - int instanceLeaseDuration) { - if (log.isDebugEnabled()) { - log.debug("register " + info.getAppName() + ", vip " + info.getVIPAddress() - + ", leaseDuration " + instanceLeaseDuration + ", isReplication " - + isReplication); - } + private void handleCancelation(String appName, String id, boolean isReplication) { + log("cancel " + appName + ", serverId " + id + ", isReplication " + isReplication); + publishEvent(new EurekaInstanceCanceledEvent(this, appName, id, isReplication)); } - private void logCancelation(String appName, String serverId, boolean isReplication) { - if (log.isDebugEnabled()) { - log.debug("cancel " + appName + " serverId " + serverId + ", isReplication " - + isReplication); - } - } - - private void publishEurekaInstanceRegisteredEvent(InstanceInfo info, - int leaseDuration, boolean isReplication) { - // TODO: what to publish from info (whole object?) - this.ctxt.publishEvent(new EurekaInstanceRegisteredEvent(this, info, - leaseDuration, isReplication)); - } - - private void publishEurekaInstanceCanceledEvent(String appName, String serverId, + private void handleRegistration(InstanceInfo info, int leaseDuration, boolean isReplication) { - this.ctxt.publishEvent( - new EurekaInstanceCanceledEvent(this, appName, serverId, isReplication)); + log("register " + info.getAppName() + ", vip " + info.getVIPAddress() + + ", leaseDuration " + leaseDuration + ", isReplication " + + isReplication); + publishEvent(new EurekaInstanceRegisteredEvent(this, info, leaseDuration, + isReplication)); + } + + private void log(String message) { + if (log.isDebugEnabled()) { + log.debug(message); + } + } + + private void publishEvent(ApplicationEvent applicationEvent) { + this.ctxt.publishEvent(applicationEvent); } private int resolveInstanceLeaseDuration(final InstanceInfo info) { diff --git a/spring-cloud-netflix-eureka-server/src/test/java/org/springframework/cloud/netflix/eureka/server/InstanceRegistryTest.java b/spring-cloud-netflix-eureka-server/src/test/java/org/springframework/cloud/netflix/eureka/server/InstanceRegistryTest.java index fa740240e..9689e7795 100644 --- a/spring-cloud-netflix-eureka-server/src/test/java/org/springframework/cloud/netflix/eureka/server/InstanceRegistryTest.java +++ b/spring-cloud-netflix-eureka-server/src/test/java/org/springframework/cloud/netflix/eureka/server/InstanceRegistryTest.java @@ -3,10 +3,13 @@ package org.springframework.cloud.netflix.eureka.server; import static org.junit.Assert.*; import static org.mockito.Matchers.isA; import static org.mockito.Mockito.doAnswer; +import static org.mockito.Mockito.doReturn; +import java.util.ArrayList; import java.util.LinkedList; import java.util.List; +import com.netflix.discovery.shared.Application; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -17,9 +20,10 @@ import org.springframework.boot.builder.SpringApplicationBuilder; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.boot.test.mock.mockito.SpyBean; -import org.springframework.cloud.netflix.eureka.server.InstanceRegistryTest.Application; +import org.springframework.cloud.netflix.eureka.server.InstanceRegistryTest.TestApplication; import org.springframework.cloud.netflix.eureka.server.event.EurekaInstanceCanceledEvent; import org.springframework.cloud.netflix.eureka.server.event.EurekaInstanceRegisteredEvent; +import org.springframework.cloud.netflix.eureka.server.event.EurekaInstanceRenewedEvent; import org.springframework.context.ApplicationEvent; import org.springframework.context.ApplicationListener; import org.springframework.context.annotation.Configuration; @@ -33,13 +37,15 @@ import com.netflix.eureka.registry.PeerAwareInstanceRegistry; * @author Bartlomiej Slota */ @RunWith(SpringJUnit4ClassRunner.class) -@SpringBootTest(classes = Application.class, +@SpringBootTest(classes = TestApplication.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, value = {"spring.application.name=eureka", "logging.level.org.springframework." + "cloud.netflix.eureka.server.InstanceRegistry=DEBUG"}) public class InstanceRegistryTest { private final List applicationEvents = new LinkedList<>(); + private static final String APP_NAME = "MY-APP-NAME"; + private static final String HOST_NAME = "my-host-name"; @SpyBean(PeerAwareInstanceRegistry.class) private InstanceRegistry instanceRegistry; @@ -52,6 +58,9 @@ public class InstanceRegistryTest { private ApplicationListener instanceCanceledEventListenerMock; + @MockBean + private ApplicationListener instanceRenewedEventListener; + @Before public void setup() { applicationEvents.clear(); @@ -60,21 +69,23 @@ public class InstanceRegistryTest { .onApplicationEvent(isA(EurekaInstanceRegisteredEvent.class)); doAnswer(applicationListenerAnswer).when(instanceCanceledEventListenerMock) .onApplicationEvent(isA(EurekaInstanceCanceledEvent.class)); + doAnswer(applicationListenerAnswer).when(instanceRenewedEventListener) + .onApplicationEvent(isA(EurekaInstanceRenewedEvent.class)); } @Test public void testRegister() throws Exception { // creating instance info - LeaseInfo leaseInfo = getLeaseInfo(); - InstanceInfo instanceInfo = getInstanceInfo(leaseInfo); + final LeaseInfo leaseInfo = getLeaseInfo(); + final InstanceInfo instanceInfo = getInstanceInfo(leaseInfo); // calling tested method instanceRegistry.register(instanceInfo, false); // event of proper type is registered assertEquals(1, applicationEvents.size()); assertTrue(applicationEvents.get(0) instanceof EurekaInstanceRegisteredEvent); // event details are correct - EurekaInstanceRegisteredEvent registeredEvent = + final EurekaInstanceRegisteredEvent registeredEvent = (EurekaInstanceRegisteredEvent) (applicationEvents.get(0)); assertEquals(instanceInfo, registeredEvent.getInstanceInfo()); assertEquals(leaseInfo.getDurationInSecs(), registeredEvent.getLeaseDuration()); @@ -85,11 +96,11 @@ public class InstanceRegistryTest { @Test public void testDefaultLeaseDurationRegisterEvent() throws Exception { // creating instance info - InstanceInfo instanceInfo = getInstanceInfo(null); + final InstanceInfo instanceInfo = getInstanceInfo(null); // calling tested method instanceRegistry.register(instanceInfo, false); // instance info duration is set to default - EurekaInstanceRegisteredEvent registeredEvent = + final EurekaInstanceRegisteredEvent registeredEvent = (EurekaInstanceRegisteredEvent) (applicationEvents.get(0)); assertEquals(LeaseInfo.DEFAULT_LEASE_DURATION, registeredEvent.getLeaseDuration()); @@ -98,25 +109,52 @@ public class InstanceRegistryTest { @Test public void testInternalCancel() throws Exception { // calling tested method - instanceRegistry.internalCancel("my-app", "appId", false); + instanceRegistry.internalCancel(APP_NAME, HOST_NAME, false); // event of proper type is registered assertEquals(1, applicationEvents.size()); assertTrue(applicationEvents.get(0) instanceof EurekaInstanceCanceledEvent); // event details are correct - EurekaInstanceCanceledEvent registeredEvent = + final EurekaInstanceCanceledEvent registeredEvent = (EurekaInstanceCanceledEvent) (applicationEvents.get(0)); - assertEquals("my-app", registeredEvent.getAppName()); - assertEquals("appId", registeredEvent.getServerId()); + assertEquals(APP_NAME, registeredEvent.getAppName()); + assertEquals(HOST_NAME, registeredEvent.getServerId()); assertEquals(instanceRegistry, registeredEvent.getSource()); assertFalse(registeredEvent.isReplication()); } + @Test + public void testRenew() throws Exception { + // creating application list + final LeaseInfo leaseInfo = getLeaseInfo(); + final InstanceInfo instanceInfo = getInstanceInfo(leaseInfo); + final List instances = new ArrayList<>(); + instances.add(instanceInfo); + final Application application = new Application(APP_NAME, instances); + final List applications = new ArrayList<>(); + applications.add(application); + // stubbing applications list + doReturn(applications).when(instanceRegistry).getSortedApplications(); + // calling tested method + instanceRegistry.renew(APP_NAME, HOST_NAME, false); + // event of proper type is registered + assertEquals(1, applicationEvents.size()); + assertTrue(applicationEvents.get(0) instanceof EurekaInstanceRenewedEvent); + // event details are correct + final EurekaInstanceRenewedEvent registeredEvent = (EurekaInstanceRenewedEvent) + (applicationEvents.get(0)); + assertEquals(APP_NAME, registeredEvent.getAppName()); + assertEquals(HOST_NAME, registeredEvent.getServerId()); + assertEquals(instanceRegistry, registeredEvent.getSource()); + assertEquals(instanceInfo, registeredEvent.getInstanceInfo()); + assertFalse(registeredEvent.isReplication()); + } + @Configuration @EnableAutoConfiguration @EnableEurekaServer - protected static class Application { + protected static class TestApplication { public static void main(String[] args) { - new SpringApplicationBuilder(Application.class).run(args); + new SpringApplicationBuilder(TestApplication.class).run(args); } } @@ -129,8 +167,8 @@ public class InstanceRegistryTest { private InstanceInfo getInstanceInfo(LeaseInfo leaseInfo) { InstanceInfo.Builder builder = InstanceInfo.Builder.newBuilder(); - builder.setAppName("my-app-name"); - builder.setHostName("my-host-name"); + builder.setAppName(APP_NAME); + builder.setHostName(HOST_NAME); builder.setPort(8008); builder.setLeaseInfo(leaseInfo); return builder.build(); From e94c35d331cdbf6f71b4eae2fde9b62779d0553b Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Thu, 13 Oct 2016 10:02:15 +0100 Subject: [PATCH 17/48] Exclude aws jars from eureka client by default Saves about 5MB in the final executable jar, and it should be optional for Spring Cloud users. --- spring-cloud-netflix-dependencies/pom.xml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/spring-cloud-netflix-dependencies/pom.xml b/spring-cloud-netflix-dependencies/pom.xml index 8d0a85dae..c991136ac 100644 --- a/spring-cloud-netflix-dependencies/pom.xml +++ b/spring-cloud-netflix-dependencies/pom.xml @@ -270,6 +270,10 @@ jackson-dataformat-xml com.fasterxml.jackson.dataformat + + * + com.amazonaws + From acb12ea7d44ac0a2ebc8ac7c662d287b8b3038f5 Mon Sep 17 00:00:00 2001 From: Alena Date: Tue, 13 Sep 2016 18:40:08 +0300 Subject: [PATCH 18/48] Support DELETE method body for SimpleHostRoutingFilter fixes gh-1329 --- .../route/SimpleHostRoutingFilter.java | 63 ++++++++++++------- .../route/SimpleHostRoutingFilterTests.java | 18 ++++++ 2 files changed, 58 insertions(+), 23 deletions(-) diff --git a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/filters/route/SimpleHostRoutingFilter.java b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/filters/route/SimpleHostRoutingFilter.java index cdefd0223..a76a5dd50 100644 --- a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/filters/route/SimpleHostRoutingFilter.java +++ b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/filters/route/SimpleHostRoutingFilter.java @@ -63,6 +63,7 @@ import org.apache.http.impl.client.HttpClientBuilder; import org.apache.http.impl.client.HttpClients; import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; import org.apache.http.message.BasicHeader; +import org.apache.http.message.BasicHttpEntityEnclosingRequest; import org.apache.http.message.BasicHttpRequest; import org.apache.http.protocol.HttpContext; import org.springframework.cloud.netflix.zuul.filters.ProxyRequestHelper; @@ -271,34 +272,13 @@ public class SimpleHostRoutingFilter extends ZuulFilter { URL host = RequestContext.getCurrentContext().getRouteHost(); HttpHost httpHost = getHttpHost(host); uri = StringUtils.cleanPath((host.getPath() + uri).replaceAll("/{2,}", "/")); - HttpRequest httpRequest; int contentLength = request.getContentLength(); InputStreamEntity entity = new InputStreamEntity(requestEntity, contentLength, request.getContentType() != null ? ContentType.create(request.getContentType()) : null); - switch (verb.toUpperCase()) { - case "POST": - HttpPost httpPost = new HttpPost(uri + this.helper.getQueryString(params)); - httpRequest = httpPost; - httpPost.setEntity(entity); - break; - case "PUT": - HttpPut httpPut = new HttpPut(uri + this.helper.getQueryString(params)); - httpRequest = httpPut; - httpPut.setEntity(entity); - break; - case "PATCH": - HttpPatch httpPatch = new HttpPatch(uri + this.helper.getQueryString(params)); - httpRequest = httpPatch; - httpPatch.setEntity(entity); - break; - default: - httpRequest = new BasicHttpRequest(verb, - uri + this.helper.getQueryString(params)); - log.debug(uri + this.helper.getQueryString(params)); - } + + HttpRequest httpRequest = buildHttpRequest(verb, uri, entity, headers, params); try { - httpRequest.setHeaders(convertHeaders(headers)); log.debug(httpHost.getHostName() + " " + httpHost.getPort() + " " + httpHost.getSchemeName()); HttpResponse zuulResponse = forwardRequest(httpclient, httpHost, httpRequest); @@ -314,6 +294,43 @@ public class SimpleHostRoutingFilter extends ZuulFilter { } } + protected HttpRequest buildHttpRequest (String verb, String uri, InputStreamEntity entity, + MultiValueMap headers, MultiValueMap params) + { + HttpRequest httpRequest; + + switch (verb.toUpperCase()) { + case "POST": + HttpPost httpPost = new HttpPost(uri + this.helper.getQueryString(params)); + httpRequest = httpPost; + httpPost.setEntity(entity); + break; + case "PUT": + HttpPut httpPut = new HttpPut(uri + this.helper.getQueryString(params)); + httpRequest = httpPut; + httpPut.setEntity(entity); + break; + case "PATCH": + HttpPatch httpPatch = new HttpPatch(uri + this.helper.getQueryString(params)); + httpRequest = httpPatch; + httpPatch.setEntity(entity); + break; + case "DELETE": + BasicHttpEntityEnclosingRequest entityRequest = new BasicHttpEntityEnclosingRequest(verb, + uri + this.helper.getQueryString(params)); + httpRequest = entityRequest; + entityRequest.setEntity(entity); + break; + default: + httpRequest = new BasicHttpRequest(verb, + uri + this.helper.getQueryString(params)); + log.debug(uri + this.helper.getQueryString(params)); + } + + httpRequest.setHeaders(convertHeaders(headers)); + return httpRequest; + } + private MultiValueMap revertHeaders(Header[] headers) { MultiValueMap map = new LinkedMultiValueMap(); for (Header header : headers) { diff --git a/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/zuul/filters/route/SimpleHostRoutingFilterTests.java b/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/zuul/filters/route/SimpleHostRoutingFilterTests.java index 7275e36d7..faf5871e0 100644 --- a/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/zuul/filters/route/SimpleHostRoutingFilterTests.java +++ b/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/zuul/filters/route/SimpleHostRoutingFilterTests.java @@ -16,6 +16,11 @@ package org.springframework.cloud.netflix.zuul.filters.route; +import java.io.ByteArrayInputStream; + +import org.apache.http.HttpEntityEnclosingRequest; +import org.apache.http.HttpRequest; +import org.apache.http.entity.InputStreamEntity; import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; import org.junit.After; import org.junit.Test; @@ -26,6 +31,7 @@ import org.springframework.cloud.netflix.zuul.filters.ZuulProperties; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.util.LinkedMultiValueMap; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; @@ -80,6 +86,18 @@ public class SimpleHostRoutingFilterTests { assertEquals(20, connMgr.getDefaultMaxPerRoute()); } + @Test + public void deleteRequestBuiltWithBody() { + setupContext(); + InputStreamEntity inputStreamEntity = new InputStreamEntity(new ByteArrayInputStream(new byte[]{1})); + HttpRequest httpRequest = getFilter().buildHttpRequest("DELETE", "uri", inputStreamEntity, + new LinkedMultiValueMap(), new LinkedMultiValueMap()); + + assertTrue(httpRequest instanceof HttpEntityEnclosingRequest); + HttpEntityEnclosingRequest httpEntityEnclosingRequest = (HttpEntityEnclosingRequest) httpRequest; + assertTrue(httpEntityEnclosingRequest.getEntity() != null); + } + private void setupContext() { this.context.register(PropertyPlaceholderAutoConfiguration.class, TestConfiguration.class); From acb9e5ebdf1daec606c30504442eb18adafdece3 Mon Sep 17 00:00:00 2001 From: Gregor Zurowski Date: Thu, 13 Oct 2016 22:08:28 +0200 Subject: [PATCH 19/48] Fix formatting (#1397) Signed-off-by: Gregor Zurowski --- docs/src/main/asciidoc/spring-cloud-netflix.adoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/src/main/asciidoc/spring-cloud-netflix.adoc b/docs/src/main/asciidoc/spring-cloud-netflix.adoc index 13d3d4b0a..bd65af994 100644 --- a/docs/src/main/asciidoc/spring-cloud-netflix.adoc +++ b/docs/src/main/asciidoc/spring-cloud-netflix.adoc @@ -1387,7 +1387,7 @@ path rendering the `users` path unreachable. === Zuul Http Client The default HTTP client used by zuul is now backed by the Apache HTTP Client instead of the -deprecated Ribbon `RestClient. To use `RestClient` or to use the `okhttp3.OkHttpClient` set +deprecated Ribbon `RestClient`. To use `RestClient` or to use the `okhttp3.OkHttpClient` set `ribbon.restclient.enabled=true` or `ribbon.okhttp.enabled=true` respectively. === Cookies and Sensitive Headers From 90d6490feae93e54cf332400a0275f0d0b4bc76e Mon Sep 17 00:00:00 2001 From: Ryan Baxter Date: Tue, 18 Oct 2016 09:44:57 -0400 Subject: [PATCH 20/48] Version changes for the release --- docs/pom.xml | 2 +- pom.xml | 10 +++++----- spring-cloud-netflix-core/pom.xml | 2 +- spring-cloud-netflix-dependencies/pom.xml | 4 ++-- spring-cloud-netflix-eureka-client/pom.xml | 2 +- spring-cloud-netflix-eureka-server/pom.xml | 2 +- spring-cloud-netflix-hystrix-amqp/pom.xml | 2 +- spring-cloud-netflix-hystrix-dashboard/pom.xml | 2 +- spring-cloud-netflix-hystrix-stream/pom.xml | 2 +- spring-cloud-netflix-sidecar/pom.xml | 2 +- spring-cloud-netflix-spectator/pom.xml | 2 +- spring-cloud-netflix-turbine-stream/pom.xml | 2 +- spring-cloud-netflix-turbine/pom.xml | 2 +- spring-cloud-starter-archaius/pom.xml | 2 +- spring-cloud-starter-atlas/pom.xml | 2 +- spring-cloud-starter-eureka-server/pom.xml | 2 +- spring-cloud-starter-eureka/pom.xml | 2 +- spring-cloud-starter-feign/pom.xml | 2 +- spring-cloud-starter-hystrix-dashboard/pom.xml | 2 +- spring-cloud-starter-hystrix/pom.xml | 2 +- spring-cloud-starter-ribbon/pom.xml | 2 +- spring-cloud-starter-spectator/pom.xml | 2 +- spring-cloud-starter-turbine-amqp/pom.xml | 2 +- spring-cloud-starter-turbine-stream/pom.xml | 2 +- spring-cloud-starter-turbine/pom.xml | 2 +- spring-cloud-starter-zuul/pom.xml | 2 +- 26 files changed, 31 insertions(+), 31 deletions(-) diff --git a/docs/pom.xml b/docs/pom.xml index 750a06999..56528e767 100644 --- a/docs/pom.xml +++ b/docs/pom.xml @@ -5,7 +5,7 @@ org.springframework.cloud spring-cloud-netflix - 1.2.1.BUILD-SNAPSHOT + 1.2.1.RELEASE spring-cloud-netflix-docs pom diff --git a/pom.xml b/pom.xml index b0994d49a..04d13a77d 100644 --- a/pom.xml +++ b/pom.xml @@ -3,14 +3,14 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 spring-cloud-netflix - 1.2.1.BUILD-SNAPSHOT + 1.2.1.RELEASE pom Spring Cloud Netflix Spring Cloud Netflix org.springframework.cloud spring-cloud-build - 1.2.1.BUILD-SNAPSHOT + 1.2.1.RELEASE @@ -24,9 +24,9 @@ ${basedir} 4.0.27.Final 2.7.3 - 1.1.4.BUILD-SNAPSHOT - 1.2.1.BUILD-SNAPSHOT - Brooklyn.BUILD-SNAPSHOT + 1.1.4.RELEASE + 1.2.1.RELEASE + Brooklyn.RELEASE 2.19.1 diff --git a/spring-cloud-netflix-core/pom.xml b/spring-cloud-netflix-core/pom.xml index 8f6985cc3..614373d6c 100644 --- a/spring-cloud-netflix-core/pom.xml +++ b/spring-cloud-netflix-core/pom.xml @@ -5,7 +5,7 @@ org.springframework.cloud spring-cloud-netflix - 1.2.1.BUILD-SNAPSHOT + 1.2.1.RELEASE .. spring-cloud-netflix-core diff --git a/spring-cloud-netflix-dependencies/pom.xml b/spring-cloud-netflix-dependencies/pom.xml index c991136ac..d32b336ca 100644 --- a/spring-cloud-netflix-dependencies/pom.xml +++ b/spring-cloud-netflix-dependencies/pom.xml @@ -5,11 +5,11 @@ spring-cloud-dependencies-parent org.springframework.cloud - 1.2.1.BUILD-SNAPSHOT + 1.2.1.RELEASE spring-cloud-netflix-dependencies - 1.2.1.BUILD-SNAPSHOT + 1.2.1.RELEASE pom spring-cloud-netflix-dependencies Spring Cloud Netflix Dependencies diff --git a/spring-cloud-netflix-eureka-client/pom.xml b/spring-cloud-netflix-eureka-client/pom.xml index 6d6bdcd9c..4dbde6ca9 100644 --- a/spring-cloud-netflix-eureka-client/pom.xml +++ b/spring-cloud-netflix-eureka-client/pom.xml @@ -5,7 +5,7 @@ org.springframework.cloud spring-cloud-netflix - 1.2.1.BUILD-SNAPSHOT + 1.2.1.RELEASE .. spring-cloud-netflix-eureka-client diff --git a/spring-cloud-netflix-eureka-server/pom.xml b/spring-cloud-netflix-eureka-server/pom.xml index 74b41f126..2d21c4772 100644 --- a/spring-cloud-netflix-eureka-server/pom.xml +++ b/spring-cloud-netflix-eureka-server/pom.xml @@ -5,7 +5,7 @@ org.springframework.cloud spring-cloud-netflix - 1.2.1.BUILD-SNAPSHOT + 1.2.1.RELEASE .. spring-cloud-netflix-eureka-server diff --git a/spring-cloud-netflix-hystrix-amqp/pom.xml b/spring-cloud-netflix-hystrix-amqp/pom.xml index b3dcd0375..3801dd491 100644 --- a/spring-cloud-netflix-hystrix-amqp/pom.xml +++ b/spring-cloud-netflix-hystrix-amqp/pom.xml @@ -5,7 +5,7 @@ org.springframework.cloud spring-cloud-netflix - 1.2.1.BUILD-SNAPSHOT + 1.2.1.RELEASE .. spring-cloud-netflix-hystrix-amqp diff --git a/spring-cloud-netflix-hystrix-dashboard/pom.xml b/spring-cloud-netflix-hystrix-dashboard/pom.xml index 64d5f7198..9e89c9c2c 100644 --- a/spring-cloud-netflix-hystrix-dashboard/pom.xml +++ b/spring-cloud-netflix-hystrix-dashboard/pom.xml @@ -8,7 +8,7 @@ org.springframework.cloud spring-cloud-netflix - 1.2.1.BUILD-SNAPSHOT + 1.2.1.RELEASE .. diff --git a/spring-cloud-netflix-hystrix-stream/pom.xml b/spring-cloud-netflix-hystrix-stream/pom.xml index dd4c8f517..8cd94ea64 100644 --- a/spring-cloud-netflix-hystrix-stream/pom.xml +++ b/spring-cloud-netflix-hystrix-stream/pom.xml @@ -5,7 +5,7 @@ org.springframework.cloud spring-cloud-netflix - 1.2.1.BUILD-SNAPSHOT + 1.2.1.RELEASE .. spring-cloud-netflix-hystrix-stream diff --git a/spring-cloud-netflix-sidecar/pom.xml b/spring-cloud-netflix-sidecar/pom.xml index c39d4005f..4394947f4 100644 --- a/spring-cloud-netflix-sidecar/pom.xml +++ b/spring-cloud-netflix-sidecar/pom.xml @@ -5,7 +5,7 @@ org.springframework.cloud spring-cloud-netflix - 1.2.1.BUILD-SNAPSHOT + 1.2.1.RELEASE .. spring-cloud-netflix-sidecar diff --git a/spring-cloud-netflix-spectator/pom.xml b/spring-cloud-netflix-spectator/pom.xml index 55715ac68..c6d409e5c 100644 --- a/spring-cloud-netflix-spectator/pom.xml +++ b/spring-cloud-netflix-spectator/pom.xml @@ -6,7 +6,7 @@ org.springframework.cloud spring-cloud-netflix - 1.2.1.BUILD-SNAPSHOT + 1.2.1.RELEASE .. spring-cloud-netflix-spectator diff --git a/spring-cloud-netflix-turbine-stream/pom.xml b/spring-cloud-netflix-turbine-stream/pom.xml index 7fdeef11d..1af2a2e85 100644 --- a/spring-cloud-netflix-turbine-stream/pom.xml +++ b/spring-cloud-netflix-turbine-stream/pom.xml @@ -5,7 +5,7 @@ org.springframework.cloud spring-cloud-netflix - 1.2.1.BUILD-SNAPSHOT + 1.2.1.RELEASE .. spring-cloud-netflix-turbine-stream diff --git a/spring-cloud-netflix-turbine/pom.xml b/spring-cloud-netflix-turbine/pom.xml index f4ba02b16..fd49df2be 100644 --- a/spring-cloud-netflix-turbine/pom.xml +++ b/spring-cloud-netflix-turbine/pom.xml @@ -5,7 +5,7 @@ org.springframework.cloud spring-cloud-netflix - 1.2.1.BUILD-SNAPSHOT + 1.2.1.RELEASE .. spring-cloud-netflix-turbine diff --git a/spring-cloud-starter-archaius/pom.xml b/spring-cloud-starter-archaius/pom.xml index 29c05ed3a..f6c37d86c 100644 --- a/spring-cloud-starter-archaius/pom.xml +++ b/spring-cloud-starter-archaius/pom.xml @@ -5,7 +5,7 @@ org.springframework.cloud spring-cloud-netflix - 1.2.1.BUILD-SNAPSHOT + 1.2.1.RELEASE .. spring-cloud-starter-archaius diff --git a/spring-cloud-starter-atlas/pom.xml b/spring-cloud-starter-atlas/pom.xml index ef07240ef..6231e78f2 100644 --- a/spring-cloud-starter-atlas/pom.xml +++ b/spring-cloud-starter-atlas/pom.xml @@ -5,7 +5,7 @@ org.springframework.cloud spring-cloud-netflix - 1.2.1.BUILD-SNAPSHOT + 1.2.1.RELEASE .. spring-cloud-starter-atlas diff --git a/spring-cloud-starter-eureka-server/pom.xml b/spring-cloud-starter-eureka-server/pom.xml index 281d6840b..1588ca497 100644 --- a/spring-cloud-starter-eureka-server/pom.xml +++ b/spring-cloud-starter-eureka-server/pom.xml @@ -5,7 +5,7 @@ org.springframework.cloud spring-cloud-netflix - 1.2.1.BUILD-SNAPSHOT + 1.2.1.RELEASE .. spring-cloud-starter-eureka-server diff --git a/spring-cloud-starter-eureka/pom.xml b/spring-cloud-starter-eureka/pom.xml index 5db347ea8..2afb3f612 100644 --- a/spring-cloud-starter-eureka/pom.xml +++ b/spring-cloud-starter-eureka/pom.xml @@ -5,7 +5,7 @@ org.springframework.cloud spring-cloud-netflix - 1.2.1.BUILD-SNAPSHOT + 1.2.1.RELEASE .. spring-cloud-starter-eureka diff --git a/spring-cloud-starter-feign/pom.xml b/spring-cloud-starter-feign/pom.xml index cfced5bb3..b94d7929e 100644 --- a/spring-cloud-starter-feign/pom.xml +++ b/spring-cloud-starter-feign/pom.xml @@ -5,7 +5,7 @@ org.springframework.cloud spring-cloud-netflix - 1.2.1.BUILD-SNAPSHOT + 1.2.1.RELEASE .. spring-cloud-starter-feign diff --git a/spring-cloud-starter-hystrix-dashboard/pom.xml b/spring-cloud-starter-hystrix-dashboard/pom.xml index ef126ed61..7a4c92d87 100644 --- a/spring-cloud-starter-hystrix-dashboard/pom.xml +++ b/spring-cloud-starter-hystrix-dashboard/pom.xml @@ -5,7 +5,7 @@ org.springframework.cloud spring-cloud-netflix - 1.2.1.BUILD-SNAPSHOT + 1.2.1.RELEASE .. spring-cloud-starter-hystrix-dashboard diff --git a/spring-cloud-starter-hystrix/pom.xml b/spring-cloud-starter-hystrix/pom.xml index 220ad2e3b..42383f046 100644 --- a/spring-cloud-starter-hystrix/pom.xml +++ b/spring-cloud-starter-hystrix/pom.xml @@ -5,7 +5,7 @@ org.springframework.cloud spring-cloud-netflix - 1.2.1.BUILD-SNAPSHOT + 1.2.1.RELEASE .. spring-cloud-starter-hystrix diff --git a/spring-cloud-starter-ribbon/pom.xml b/spring-cloud-starter-ribbon/pom.xml index 533583c0e..8b1d971da 100644 --- a/spring-cloud-starter-ribbon/pom.xml +++ b/spring-cloud-starter-ribbon/pom.xml @@ -5,7 +5,7 @@ org.springframework.cloud spring-cloud-netflix - 1.2.1.BUILD-SNAPSHOT + 1.2.1.RELEASE .. spring-cloud-starter-ribbon diff --git a/spring-cloud-starter-spectator/pom.xml b/spring-cloud-starter-spectator/pom.xml index ee66b0eb2..1db00804c 100644 --- a/spring-cloud-starter-spectator/pom.xml +++ b/spring-cloud-starter-spectator/pom.xml @@ -5,7 +5,7 @@ org.springframework.cloud spring-cloud-netflix - 1.2.1.BUILD-SNAPSHOT + 1.2.1.RELEASE .. spring-cloud-starter-spectator diff --git a/spring-cloud-starter-turbine-amqp/pom.xml b/spring-cloud-starter-turbine-amqp/pom.xml index 15e5a043a..6f9633aa6 100644 --- a/spring-cloud-starter-turbine-amqp/pom.xml +++ b/spring-cloud-starter-turbine-amqp/pom.xml @@ -5,7 +5,7 @@ org.springframework.cloud spring-cloud-netflix - 1.2.1.BUILD-SNAPSHOT + 1.2.1.RELEASE .. spring-cloud-starter-turbine-amqp diff --git a/spring-cloud-starter-turbine-stream/pom.xml b/spring-cloud-starter-turbine-stream/pom.xml index ef45f8330..290adf428 100644 --- a/spring-cloud-starter-turbine-stream/pom.xml +++ b/spring-cloud-starter-turbine-stream/pom.xml @@ -5,7 +5,7 @@ org.springframework.cloud spring-cloud-netflix - 1.2.1.BUILD-SNAPSHOT + 1.2.1.RELEASE .. spring-cloud-starter-turbine-stream diff --git a/spring-cloud-starter-turbine/pom.xml b/spring-cloud-starter-turbine/pom.xml index 3639be91c..7867a073a 100644 --- a/spring-cloud-starter-turbine/pom.xml +++ b/spring-cloud-starter-turbine/pom.xml @@ -5,7 +5,7 @@ org.springframework.cloud spring-cloud-netflix - 1.2.1.BUILD-SNAPSHOT + 1.2.1.RELEASE .. spring-cloud-starter-turbine diff --git a/spring-cloud-starter-zuul/pom.xml b/spring-cloud-starter-zuul/pom.xml index 8b664ac84..1490174ed 100644 --- a/spring-cloud-starter-zuul/pom.xml +++ b/spring-cloud-starter-zuul/pom.xml @@ -5,7 +5,7 @@ org.springframework.cloud spring-cloud-netflix - 1.2.1.BUILD-SNAPSHOT + 1.2.1.RELEASE .. spring-cloud-starter-zuul From 34775eb8dbf3500f33f9e12083f831435d7cf87a Mon Sep 17 00:00:00 2001 From: Ryan Baxter Date: Tue, 18 Oct 2016 10:11:03 -0400 Subject: [PATCH 21/48] Revert "Version changes for the release" This reverts commit 90d6490feae93e54cf332400a0275f0d0b4bc76e. --- docs/pom.xml | 2 +- pom.xml | 10 +++++----- spring-cloud-netflix-core/pom.xml | 2 +- spring-cloud-netflix-dependencies/pom.xml | 4 ++-- spring-cloud-netflix-eureka-client/pom.xml | 2 +- spring-cloud-netflix-eureka-server/pom.xml | 2 +- spring-cloud-netflix-hystrix-amqp/pom.xml | 2 +- spring-cloud-netflix-hystrix-dashboard/pom.xml | 2 +- spring-cloud-netflix-hystrix-stream/pom.xml | 2 +- spring-cloud-netflix-sidecar/pom.xml | 2 +- spring-cloud-netflix-spectator/pom.xml | 2 +- spring-cloud-netflix-turbine-stream/pom.xml | 2 +- spring-cloud-netflix-turbine/pom.xml | 2 +- spring-cloud-starter-archaius/pom.xml | 2 +- spring-cloud-starter-atlas/pom.xml | 2 +- spring-cloud-starter-eureka-server/pom.xml | 2 +- spring-cloud-starter-eureka/pom.xml | 2 +- spring-cloud-starter-feign/pom.xml | 2 +- spring-cloud-starter-hystrix-dashboard/pom.xml | 2 +- spring-cloud-starter-hystrix/pom.xml | 2 +- spring-cloud-starter-ribbon/pom.xml | 2 +- spring-cloud-starter-spectator/pom.xml | 2 +- spring-cloud-starter-turbine-amqp/pom.xml | 2 +- spring-cloud-starter-turbine-stream/pom.xml | 2 +- spring-cloud-starter-turbine/pom.xml | 2 +- spring-cloud-starter-zuul/pom.xml | 2 +- 26 files changed, 31 insertions(+), 31 deletions(-) diff --git a/docs/pom.xml b/docs/pom.xml index 56528e767..750a06999 100644 --- a/docs/pom.xml +++ b/docs/pom.xml @@ -5,7 +5,7 @@ org.springframework.cloud spring-cloud-netflix - 1.2.1.RELEASE + 1.2.1.BUILD-SNAPSHOT spring-cloud-netflix-docs pom diff --git a/pom.xml b/pom.xml index 04d13a77d..b0994d49a 100644 --- a/pom.xml +++ b/pom.xml @@ -3,14 +3,14 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 spring-cloud-netflix - 1.2.1.RELEASE + 1.2.1.BUILD-SNAPSHOT pom Spring Cloud Netflix Spring Cloud Netflix org.springframework.cloud spring-cloud-build - 1.2.1.RELEASE + 1.2.1.BUILD-SNAPSHOT @@ -24,9 +24,9 @@ ${basedir} 4.0.27.Final 2.7.3 - 1.1.4.RELEASE - 1.2.1.RELEASE - Brooklyn.RELEASE + 1.1.4.BUILD-SNAPSHOT + 1.2.1.BUILD-SNAPSHOT + Brooklyn.BUILD-SNAPSHOT 2.19.1 diff --git a/spring-cloud-netflix-core/pom.xml b/spring-cloud-netflix-core/pom.xml index 614373d6c..8f6985cc3 100644 --- a/spring-cloud-netflix-core/pom.xml +++ b/spring-cloud-netflix-core/pom.xml @@ -5,7 +5,7 @@ org.springframework.cloud spring-cloud-netflix - 1.2.1.RELEASE + 1.2.1.BUILD-SNAPSHOT .. spring-cloud-netflix-core diff --git a/spring-cloud-netflix-dependencies/pom.xml b/spring-cloud-netflix-dependencies/pom.xml index d32b336ca..c991136ac 100644 --- a/spring-cloud-netflix-dependencies/pom.xml +++ b/spring-cloud-netflix-dependencies/pom.xml @@ -5,11 +5,11 @@ spring-cloud-dependencies-parent org.springframework.cloud - 1.2.1.RELEASE + 1.2.1.BUILD-SNAPSHOT spring-cloud-netflix-dependencies - 1.2.1.RELEASE + 1.2.1.BUILD-SNAPSHOT pom spring-cloud-netflix-dependencies Spring Cloud Netflix Dependencies diff --git a/spring-cloud-netflix-eureka-client/pom.xml b/spring-cloud-netflix-eureka-client/pom.xml index 4dbde6ca9..6d6bdcd9c 100644 --- a/spring-cloud-netflix-eureka-client/pom.xml +++ b/spring-cloud-netflix-eureka-client/pom.xml @@ -5,7 +5,7 @@ org.springframework.cloud spring-cloud-netflix - 1.2.1.RELEASE + 1.2.1.BUILD-SNAPSHOT .. spring-cloud-netflix-eureka-client diff --git a/spring-cloud-netflix-eureka-server/pom.xml b/spring-cloud-netflix-eureka-server/pom.xml index 2d21c4772..74b41f126 100644 --- a/spring-cloud-netflix-eureka-server/pom.xml +++ b/spring-cloud-netflix-eureka-server/pom.xml @@ -5,7 +5,7 @@ org.springframework.cloud spring-cloud-netflix - 1.2.1.RELEASE + 1.2.1.BUILD-SNAPSHOT .. spring-cloud-netflix-eureka-server diff --git a/spring-cloud-netflix-hystrix-amqp/pom.xml b/spring-cloud-netflix-hystrix-amqp/pom.xml index 3801dd491..b3dcd0375 100644 --- a/spring-cloud-netflix-hystrix-amqp/pom.xml +++ b/spring-cloud-netflix-hystrix-amqp/pom.xml @@ -5,7 +5,7 @@ org.springframework.cloud spring-cloud-netflix - 1.2.1.RELEASE + 1.2.1.BUILD-SNAPSHOT .. spring-cloud-netflix-hystrix-amqp diff --git a/spring-cloud-netflix-hystrix-dashboard/pom.xml b/spring-cloud-netflix-hystrix-dashboard/pom.xml index 9e89c9c2c..64d5f7198 100644 --- a/spring-cloud-netflix-hystrix-dashboard/pom.xml +++ b/spring-cloud-netflix-hystrix-dashboard/pom.xml @@ -8,7 +8,7 @@ org.springframework.cloud spring-cloud-netflix - 1.2.1.RELEASE + 1.2.1.BUILD-SNAPSHOT .. diff --git a/spring-cloud-netflix-hystrix-stream/pom.xml b/spring-cloud-netflix-hystrix-stream/pom.xml index 8cd94ea64..dd4c8f517 100644 --- a/spring-cloud-netflix-hystrix-stream/pom.xml +++ b/spring-cloud-netflix-hystrix-stream/pom.xml @@ -5,7 +5,7 @@ org.springframework.cloud spring-cloud-netflix - 1.2.1.RELEASE + 1.2.1.BUILD-SNAPSHOT .. spring-cloud-netflix-hystrix-stream diff --git a/spring-cloud-netflix-sidecar/pom.xml b/spring-cloud-netflix-sidecar/pom.xml index 4394947f4..c39d4005f 100644 --- a/spring-cloud-netflix-sidecar/pom.xml +++ b/spring-cloud-netflix-sidecar/pom.xml @@ -5,7 +5,7 @@ org.springframework.cloud spring-cloud-netflix - 1.2.1.RELEASE + 1.2.1.BUILD-SNAPSHOT .. spring-cloud-netflix-sidecar diff --git a/spring-cloud-netflix-spectator/pom.xml b/spring-cloud-netflix-spectator/pom.xml index c6d409e5c..55715ac68 100644 --- a/spring-cloud-netflix-spectator/pom.xml +++ b/spring-cloud-netflix-spectator/pom.xml @@ -6,7 +6,7 @@ org.springframework.cloud spring-cloud-netflix - 1.2.1.RELEASE + 1.2.1.BUILD-SNAPSHOT .. spring-cloud-netflix-spectator diff --git a/spring-cloud-netflix-turbine-stream/pom.xml b/spring-cloud-netflix-turbine-stream/pom.xml index 1af2a2e85..7fdeef11d 100644 --- a/spring-cloud-netflix-turbine-stream/pom.xml +++ b/spring-cloud-netflix-turbine-stream/pom.xml @@ -5,7 +5,7 @@ org.springframework.cloud spring-cloud-netflix - 1.2.1.RELEASE + 1.2.1.BUILD-SNAPSHOT .. spring-cloud-netflix-turbine-stream diff --git a/spring-cloud-netflix-turbine/pom.xml b/spring-cloud-netflix-turbine/pom.xml index fd49df2be..f4ba02b16 100644 --- a/spring-cloud-netflix-turbine/pom.xml +++ b/spring-cloud-netflix-turbine/pom.xml @@ -5,7 +5,7 @@ org.springframework.cloud spring-cloud-netflix - 1.2.1.RELEASE + 1.2.1.BUILD-SNAPSHOT .. spring-cloud-netflix-turbine diff --git a/spring-cloud-starter-archaius/pom.xml b/spring-cloud-starter-archaius/pom.xml index f6c37d86c..29c05ed3a 100644 --- a/spring-cloud-starter-archaius/pom.xml +++ b/spring-cloud-starter-archaius/pom.xml @@ -5,7 +5,7 @@ org.springframework.cloud spring-cloud-netflix - 1.2.1.RELEASE + 1.2.1.BUILD-SNAPSHOT .. spring-cloud-starter-archaius diff --git a/spring-cloud-starter-atlas/pom.xml b/spring-cloud-starter-atlas/pom.xml index 6231e78f2..ef07240ef 100644 --- a/spring-cloud-starter-atlas/pom.xml +++ b/spring-cloud-starter-atlas/pom.xml @@ -5,7 +5,7 @@ org.springframework.cloud spring-cloud-netflix - 1.2.1.RELEASE + 1.2.1.BUILD-SNAPSHOT .. spring-cloud-starter-atlas diff --git a/spring-cloud-starter-eureka-server/pom.xml b/spring-cloud-starter-eureka-server/pom.xml index 1588ca497..281d6840b 100644 --- a/spring-cloud-starter-eureka-server/pom.xml +++ b/spring-cloud-starter-eureka-server/pom.xml @@ -5,7 +5,7 @@ org.springframework.cloud spring-cloud-netflix - 1.2.1.RELEASE + 1.2.1.BUILD-SNAPSHOT .. spring-cloud-starter-eureka-server diff --git a/spring-cloud-starter-eureka/pom.xml b/spring-cloud-starter-eureka/pom.xml index 2afb3f612..5db347ea8 100644 --- a/spring-cloud-starter-eureka/pom.xml +++ b/spring-cloud-starter-eureka/pom.xml @@ -5,7 +5,7 @@ org.springframework.cloud spring-cloud-netflix - 1.2.1.RELEASE + 1.2.1.BUILD-SNAPSHOT .. spring-cloud-starter-eureka diff --git a/spring-cloud-starter-feign/pom.xml b/spring-cloud-starter-feign/pom.xml index b94d7929e..cfced5bb3 100644 --- a/spring-cloud-starter-feign/pom.xml +++ b/spring-cloud-starter-feign/pom.xml @@ -5,7 +5,7 @@ org.springframework.cloud spring-cloud-netflix - 1.2.1.RELEASE + 1.2.1.BUILD-SNAPSHOT .. spring-cloud-starter-feign diff --git a/spring-cloud-starter-hystrix-dashboard/pom.xml b/spring-cloud-starter-hystrix-dashboard/pom.xml index 7a4c92d87..ef126ed61 100644 --- a/spring-cloud-starter-hystrix-dashboard/pom.xml +++ b/spring-cloud-starter-hystrix-dashboard/pom.xml @@ -5,7 +5,7 @@ org.springframework.cloud spring-cloud-netflix - 1.2.1.RELEASE + 1.2.1.BUILD-SNAPSHOT .. spring-cloud-starter-hystrix-dashboard diff --git a/spring-cloud-starter-hystrix/pom.xml b/spring-cloud-starter-hystrix/pom.xml index 42383f046..220ad2e3b 100644 --- a/spring-cloud-starter-hystrix/pom.xml +++ b/spring-cloud-starter-hystrix/pom.xml @@ -5,7 +5,7 @@ org.springframework.cloud spring-cloud-netflix - 1.2.1.RELEASE + 1.2.1.BUILD-SNAPSHOT .. spring-cloud-starter-hystrix diff --git a/spring-cloud-starter-ribbon/pom.xml b/spring-cloud-starter-ribbon/pom.xml index 8b1d971da..533583c0e 100644 --- a/spring-cloud-starter-ribbon/pom.xml +++ b/spring-cloud-starter-ribbon/pom.xml @@ -5,7 +5,7 @@ org.springframework.cloud spring-cloud-netflix - 1.2.1.RELEASE + 1.2.1.BUILD-SNAPSHOT .. spring-cloud-starter-ribbon diff --git a/spring-cloud-starter-spectator/pom.xml b/spring-cloud-starter-spectator/pom.xml index 1db00804c..ee66b0eb2 100644 --- a/spring-cloud-starter-spectator/pom.xml +++ b/spring-cloud-starter-spectator/pom.xml @@ -5,7 +5,7 @@ org.springframework.cloud spring-cloud-netflix - 1.2.1.RELEASE + 1.2.1.BUILD-SNAPSHOT .. spring-cloud-starter-spectator diff --git a/spring-cloud-starter-turbine-amqp/pom.xml b/spring-cloud-starter-turbine-amqp/pom.xml index 6f9633aa6..15e5a043a 100644 --- a/spring-cloud-starter-turbine-amqp/pom.xml +++ b/spring-cloud-starter-turbine-amqp/pom.xml @@ -5,7 +5,7 @@ org.springframework.cloud spring-cloud-netflix - 1.2.1.RELEASE + 1.2.1.BUILD-SNAPSHOT .. spring-cloud-starter-turbine-amqp diff --git a/spring-cloud-starter-turbine-stream/pom.xml b/spring-cloud-starter-turbine-stream/pom.xml index 290adf428..ef45f8330 100644 --- a/spring-cloud-starter-turbine-stream/pom.xml +++ b/spring-cloud-starter-turbine-stream/pom.xml @@ -5,7 +5,7 @@ org.springframework.cloud spring-cloud-netflix - 1.2.1.RELEASE + 1.2.1.BUILD-SNAPSHOT .. spring-cloud-starter-turbine-stream diff --git a/spring-cloud-starter-turbine/pom.xml b/spring-cloud-starter-turbine/pom.xml index 7867a073a..3639be91c 100644 --- a/spring-cloud-starter-turbine/pom.xml +++ b/spring-cloud-starter-turbine/pom.xml @@ -5,7 +5,7 @@ org.springframework.cloud spring-cloud-netflix - 1.2.1.RELEASE + 1.2.1.BUILD-SNAPSHOT .. spring-cloud-starter-turbine diff --git a/spring-cloud-starter-zuul/pom.xml b/spring-cloud-starter-zuul/pom.xml index 1490174ed..8b664ac84 100644 --- a/spring-cloud-starter-zuul/pom.xml +++ b/spring-cloud-starter-zuul/pom.xml @@ -5,7 +5,7 @@ org.springframework.cloud spring-cloud-netflix - 1.2.1.RELEASE + 1.2.1.BUILD-SNAPSHOT .. spring-cloud-starter-zuul From c9704d3c97ddb35e52dc987b35343511523eed69 Mon Sep 17 00:00:00 2001 From: Ryan Baxter Date: Tue, 18 Oct 2016 10:16:01 -0400 Subject: [PATCH 22/48] Updating versions for next release --- docs/pom.xml | 2 +- pom.xml | 8 ++++---- spring-cloud-netflix-core/pom.xml | 2 +- spring-cloud-netflix-dependencies/pom.xml | 4 ++-- spring-cloud-netflix-eureka-client/pom.xml | 2 +- spring-cloud-netflix-eureka-server/pom.xml | 2 +- spring-cloud-netflix-hystrix-amqp/pom.xml | 2 +- spring-cloud-netflix-hystrix-dashboard/pom.xml | 2 +- spring-cloud-netflix-hystrix-stream/pom.xml | 2 +- spring-cloud-netflix-sidecar/pom.xml | 2 +- spring-cloud-netflix-spectator/pom.xml | 2 +- spring-cloud-netflix-turbine-stream/pom.xml | 2 +- spring-cloud-netflix-turbine/pom.xml | 2 +- spring-cloud-starter-archaius/pom.xml | 2 +- spring-cloud-starter-atlas/pom.xml | 2 +- spring-cloud-starter-eureka-server/pom.xml | 2 +- spring-cloud-starter-eureka/pom.xml | 2 +- spring-cloud-starter-feign/pom.xml | 2 +- spring-cloud-starter-hystrix-dashboard/pom.xml | 2 +- spring-cloud-starter-hystrix/pom.xml | 2 +- spring-cloud-starter-ribbon/pom.xml | 2 +- spring-cloud-starter-spectator/pom.xml | 2 +- spring-cloud-starter-turbine-amqp/pom.xml | 2 +- spring-cloud-starter-turbine-stream/pom.xml | 2 +- spring-cloud-starter-turbine/pom.xml | 2 +- spring-cloud-starter-zuul/pom.xml | 2 +- 26 files changed, 30 insertions(+), 30 deletions(-) diff --git a/docs/pom.xml b/docs/pom.xml index 750a06999..7225f151f 100644 --- a/docs/pom.xml +++ b/docs/pom.xml @@ -5,7 +5,7 @@ org.springframework.cloud spring-cloud-netflix - 1.2.1.BUILD-SNAPSHOT + 1.2.2.BUILD-SNAPSHOT spring-cloud-netflix-docs pom diff --git a/pom.xml b/pom.xml index b0994d49a..ef239e181 100644 --- a/pom.xml +++ b/pom.xml @@ -3,14 +3,14 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 spring-cloud-netflix - 1.2.1.BUILD-SNAPSHOT + 1.2.2.BUILD-SNAPSHOT pom Spring Cloud Netflix Spring Cloud Netflix org.springframework.cloud spring-cloud-build - 1.2.1.BUILD-SNAPSHOT + 1.2.2.BUILD-SNAPSHOT @@ -24,8 +24,8 @@ ${basedir} 4.0.27.Final 2.7.3 - 1.1.4.BUILD-SNAPSHOT - 1.2.1.BUILD-SNAPSHOT + 1.1.5.BUILD-SNAPSHOT + 1.2.2.BUILD-SNAPSHOT Brooklyn.BUILD-SNAPSHOT diff --git a/spring-cloud-netflix-core/pom.xml b/spring-cloud-netflix-core/pom.xml index 8f6985cc3..3343772a2 100644 --- a/spring-cloud-netflix-core/pom.xml +++ b/spring-cloud-netflix-core/pom.xml @@ -5,7 +5,7 @@ org.springframework.cloud spring-cloud-netflix - 1.2.1.BUILD-SNAPSHOT + 1.2.2.BUILD-SNAPSHOT .. spring-cloud-netflix-core diff --git a/spring-cloud-netflix-dependencies/pom.xml b/spring-cloud-netflix-dependencies/pom.xml index c991136ac..c40c98c60 100644 --- a/spring-cloud-netflix-dependencies/pom.xml +++ b/spring-cloud-netflix-dependencies/pom.xml @@ -5,11 +5,11 @@ spring-cloud-dependencies-parent org.springframework.cloud - 1.2.1.BUILD-SNAPSHOT + 1.2.2.BUILD-SNAPSHOT spring-cloud-netflix-dependencies - 1.2.1.BUILD-SNAPSHOT + 1.2.2.BUILD-SNAPSHOT pom spring-cloud-netflix-dependencies Spring Cloud Netflix Dependencies diff --git a/spring-cloud-netflix-eureka-client/pom.xml b/spring-cloud-netflix-eureka-client/pom.xml index 6d6bdcd9c..a30f0e751 100644 --- a/spring-cloud-netflix-eureka-client/pom.xml +++ b/spring-cloud-netflix-eureka-client/pom.xml @@ -5,7 +5,7 @@ org.springframework.cloud spring-cloud-netflix - 1.2.1.BUILD-SNAPSHOT + 1.2.2.BUILD-SNAPSHOT .. spring-cloud-netflix-eureka-client diff --git a/spring-cloud-netflix-eureka-server/pom.xml b/spring-cloud-netflix-eureka-server/pom.xml index 74b41f126..4c1d4190d 100644 --- a/spring-cloud-netflix-eureka-server/pom.xml +++ b/spring-cloud-netflix-eureka-server/pom.xml @@ -5,7 +5,7 @@ org.springframework.cloud spring-cloud-netflix - 1.2.1.BUILD-SNAPSHOT + 1.2.2.BUILD-SNAPSHOT .. spring-cloud-netflix-eureka-server diff --git a/spring-cloud-netflix-hystrix-amqp/pom.xml b/spring-cloud-netflix-hystrix-amqp/pom.xml index b3dcd0375..34442fc8c 100644 --- a/spring-cloud-netflix-hystrix-amqp/pom.xml +++ b/spring-cloud-netflix-hystrix-amqp/pom.xml @@ -5,7 +5,7 @@ org.springframework.cloud spring-cloud-netflix - 1.2.1.BUILD-SNAPSHOT + 1.2.2.BUILD-SNAPSHOT .. spring-cloud-netflix-hystrix-amqp diff --git a/spring-cloud-netflix-hystrix-dashboard/pom.xml b/spring-cloud-netflix-hystrix-dashboard/pom.xml index 64d5f7198..e0a0528b7 100644 --- a/spring-cloud-netflix-hystrix-dashboard/pom.xml +++ b/spring-cloud-netflix-hystrix-dashboard/pom.xml @@ -8,7 +8,7 @@ org.springframework.cloud spring-cloud-netflix - 1.2.1.BUILD-SNAPSHOT + 1.2.2.BUILD-SNAPSHOT .. diff --git a/spring-cloud-netflix-hystrix-stream/pom.xml b/spring-cloud-netflix-hystrix-stream/pom.xml index dd4c8f517..1e5715a25 100644 --- a/spring-cloud-netflix-hystrix-stream/pom.xml +++ b/spring-cloud-netflix-hystrix-stream/pom.xml @@ -5,7 +5,7 @@ org.springframework.cloud spring-cloud-netflix - 1.2.1.BUILD-SNAPSHOT + 1.2.2.BUILD-SNAPSHOT .. spring-cloud-netflix-hystrix-stream diff --git a/spring-cloud-netflix-sidecar/pom.xml b/spring-cloud-netflix-sidecar/pom.xml index c39d4005f..e919210c3 100644 --- a/spring-cloud-netflix-sidecar/pom.xml +++ b/spring-cloud-netflix-sidecar/pom.xml @@ -5,7 +5,7 @@ org.springframework.cloud spring-cloud-netflix - 1.2.1.BUILD-SNAPSHOT + 1.2.2.BUILD-SNAPSHOT .. spring-cloud-netflix-sidecar diff --git a/spring-cloud-netflix-spectator/pom.xml b/spring-cloud-netflix-spectator/pom.xml index 55715ac68..2d193b849 100644 --- a/spring-cloud-netflix-spectator/pom.xml +++ b/spring-cloud-netflix-spectator/pom.xml @@ -6,7 +6,7 @@ org.springframework.cloud spring-cloud-netflix - 1.2.1.BUILD-SNAPSHOT + 1.2.2.BUILD-SNAPSHOT .. spring-cloud-netflix-spectator diff --git a/spring-cloud-netflix-turbine-stream/pom.xml b/spring-cloud-netflix-turbine-stream/pom.xml index 7fdeef11d..9328f9054 100644 --- a/spring-cloud-netflix-turbine-stream/pom.xml +++ b/spring-cloud-netflix-turbine-stream/pom.xml @@ -5,7 +5,7 @@ org.springframework.cloud spring-cloud-netflix - 1.2.1.BUILD-SNAPSHOT + 1.2.2.BUILD-SNAPSHOT .. spring-cloud-netflix-turbine-stream diff --git a/spring-cloud-netflix-turbine/pom.xml b/spring-cloud-netflix-turbine/pom.xml index f4ba02b16..4af74b886 100644 --- a/spring-cloud-netflix-turbine/pom.xml +++ b/spring-cloud-netflix-turbine/pom.xml @@ -5,7 +5,7 @@ org.springframework.cloud spring-cloud-netflix - 1.2.1.BUILD-SNAPSHOT + 1.2.2.BUILD-SNAPSHOT .. spring-cloud-netflix-turbine diff --git a/spring-cloud-starter-archaius/pom.xml b/spring-cloud-starter-archaius/pom.xml index 29c05ed3a..fa0b7fa98 100644 --- a/spring-cloud-starter-archaius/pom.xml +++ b/spring-cloud-starter-archaius/pom.xml @@ -5,7 +5,7 @@ org.springframework.cloud spring-cloud-netflix - 1.2.1.BUILD-SNAPSHOT + 1.2.2.BUILD-SNAPSHOT .. spring-cloud-starter-archaius diff --git a/spring-cloud-starter-atlas/pom.xml b/spring-cloud-starter-atlas/pom.xml index ef07240ef..1add805c7 100644 --- a/spring-cloud-starter-atlas/pom.xml +++ b/spring-cloud-starter-atlas/pom.xml @@ -5,7 +5,7 @@ org.springframework.cloud spring-cloud-netflix - 1.2.1.BUILD-SNAPSHOT + 1.2.2.BUILD-SNAPSHOT .. spring-cloud-starter-atlas diff --git a/spring-cloud-starter-eureka-server/pom.xml b/spring-cloud-starter-eureka-server/pom.xml index 281d6840b..a7b346084 100644 --- a/spring-cloud-starter-eureka-server/pom.xml +++ b/spring-cloud-starter-eureka-server/pom.xml @@ -5,7 +5,7 @@ org.springframework.cloud spring-cloud-netflix - 1.2.1.BUILD-SNAPSHOT + 1.2.2.BUILD-SNAPSHOT .. spring-cloud-starter-eureka-server diff --git a/spring-cloud-starter-eureka/pom.xml b/spring-cloud-starter-eureka/pom.xml index 5db347ea8..feb3560ac 100644 --- a/spring-cloud-starter-eureka/pom.xml +++ b/spring-cloud-starter-eureka/pom.xml @@ -5,7 +5,7 @@ org.springframework.cloud spring-cloud-netflix - 1.2.1.BUILD-SNAPSHOT + 1.2.2.BUILD-SNAPSHOT .. spring-cloud-starter-eureka diff --git a/spring-cloud-starter-feign/pom.xml b/spring-cloud-starter-feign/pom.xml index cfced5bb3..ba5bb3109 100644 --- a/spring-cloud-starter-feign/pom.xml +++ b/spring-cloud-starter-feign/pom.xml @@ -5,7 +5,7 @@ org.springframework.cloud spring-cloud-netflix - 1.2.1.BUILD-SNAPSHOT + 1.2.2.BUILD-SNAPSHOT .. spring-cloud-starter-feign diff --git a/spring-cloud-starter-hystrix-dashboard/pom.xml b/spring-cloud-starter-hystrix-dashboard/pom.xml index ef126ed61..87069df1b 100644 --- a/spring-cloud-starter-hystrix-dashboard/pom.xml +++ b/spring-cloud-starter-hystrix-dashboard/pom.xml @@ -5,7 +5,7 @@ org.springframework.cloud spring-cloud-netflix - 1.2.1.BUILD-SNAPSHOT + 1.2.2.BUILD-SNAPSHOT .. spring-cloud-starter-hystrix-dashboard diff --git a/spring-cloud-starter-hystrix/pom.xml b/spring-cloud-starter-hystrix/pom.xml index 220ad2e3b..7c90a6f1c 100644 --- a/spring-cloud-starter-hystrix/pom.xml +++ b/spring-cloud-starter-hystrix/pom.xml @@ -5,7 +5,7 @@ org.springframework.cloud spring-cloud-netflix - 1.2.1.BUILD-SNAPSHOT + 1.2.2.BUILD-SNAPSHOT .. spring-cloud-starter-hystrix diff --git a/spring-cloud-starter-ribbon/pom.xml b/spring-cloud-starter-ribbon/pom.xml index 533583c0e..4a31be7c0 100644 --- a/spring-cloud-starter-ribbon/pom.xml +++ b/spring-cloud-starter-ribbon/pom.xml @@ -5,7 +5,7 @@ org.springframework.cloud spring-cloud-netflix - 1.2.1.BUILD-SNAPSHOT + 1.2.2.BUILD-SNAPSHOT .. spring-cloud-starter-ribbon diff --git a/spring-cloud-starter-spectator/pom.xml b/spring-cloud-starter-spectator/pom.xml index ee66b0eb2..5ed2f4ec9 100644 --- a/spring-cloud-starter-spectator/pom.xml +++ b/spring-cloud-starter-spectator/pom.xml @@ -5,7 +5,7 @@ org.springframework.cloud spring-cloud-netflix - 1.2.1.BUILD-SNAPSHOT + 1.2.2.BUILD-SNAPSHOT .. spring-cloud-starter-spectator diff --git a/spring-cloud-starter-turbine-amqp/pom.xml b/spring-cloud-starter-turbine-amqp/pom.xml index 15e5a043a..0820167f1 100644 --- a/spring-cloud-starter-turbine-amqp/pom.xml +++ b/spring-cloud-starter-turbine-amqp/pom.xml @@ -5,7 +5,7 @@ org.springframework.cloud spring-cloud-netflix - 1.2.1.BUILD-SNAPSHOT + 1.2.2.BUILD-SNAPSHOT .. spring-cloud-starter-turbine-amqp diff --git a/spring-cloud-starter-turbine-stream/pom.xml b/spring-cloud-starter-turbine-stream/pom.xml index ef45f8330..1a7edbcbb 100644 --- a/spring-cloud-starter-turbine-stream/pom.xml +++ b/spring-cloud-starter-turbine-stream/pom.xml @@ -5,7 +5,7 @@ org.springframework.cloud spring-cloud-netflix - 1.2.1.BUILD-SNAPSHOT + 1.2.2.BUILD-SNAPSHOT .. spring-cloud-starter-turbine-stream diff --git a/spring-cloud-starter-turbine/pom.xml b/spring-cloud-starter-turbine/pom.xml index 3639be91c..5f6ed33af 100644 --- a/spring-cloud-starter-turbine/pom.xml +++ b/spring-cloud-starter-turbine/pom.xml @@ -5,7 +5,7 @@ org.springframework.cloud spring-cloud-netflix - 1.2.1.BUILD-SNAPSHOT + 1.2.2.BUILD-SNAPSHOT .. spring-cloud-starter-turbine diff --git a/spring-cloud-starter-zuul/pom.xml b/spring-cloud-starter-zuul/pom.xml index 8b664ac84..fb397c1db 100644 --- a/spring-cloud-starter-zuul/pom.xml +++ b/spring-cloud-starter-zuul/pom.xml @@ -5,7 +5,7 @@ org.springframework.cloud spring-cloud-netflix - 1.2.1.BUILD-SNAPSHOT + 1.2.2.BUILD-SNAPSHOT .. spring-cloud-starter-zuul From ddc1069e86e57b3ff3e631780d59803e059bd3c1 Mon Sep 17 00:00:00 2001 From: Spencer Gibb Date: Wed, 19 Oct 2016 12:36:15 -0600 Subject: [PATCH 23/48] Move properties to new namespace. Moving eureka.server.{expectedNumberOfRenewsPerMin,defaultOpenForTrafficCount} to eureka.instance.registry so relaxed binding can be used. Default to old values for backwards compatibility. --- .../server/EurekaServerConfiguration.java | 19 ++---- .../eureka/server/InstanceRegistry.java | 4 +- .../server/InstanceRegistryProperties.java | 63 +++++++++++++++++++ 3 files changed, 71 insertions(+), 15 deletions(-) create mode 100644 spring-cloud-netflix-eureka-server/src/main/java/org/springframework/cloud/netflix/eureka/server/InstanceRegistryProperties.java diff --git a/spring-cloud-netflix-eureka-server/src/main/java/org/springframework/cloud/netflix/eureka/server/EurekaServerConfiguration.java b/spring-cloud-netflix-eureka-server/src/main/java/org/springframework/cloud/netflix/eureka/server/EurekaServerConfiguration.java index 0e2f81edf..e5fae1611 100644 --- a/spring-cloud-netflix-eureka-server/src/main/java/org/springframework/cloud/netflix/eureka/server/EurekaServerConfiguration.java +++ b/spring-cloud-netflix-eureka-server/src/main/java/org/springframework/cloud/netflix/eureka/server/EurekaServerConfiguration.java @@ -71,7 +71,7 @@ import com.sun.jersey.spi.container.servlet.ServletContainer; @Configuration @Import(EurekaServerInitializerConfiguration.class) @EnableDiscoveryClient -@EnableConfigurationProperties(EurekaDashboardProperties.class) +@EnableConfigurationProperties({ EurekaDashboardProperties.class, InstanceRegistryProperties.class }) @PropertySource("classpath:/eureka/server.properties") public class EurekaServerConfiguration extends WebMvcConfigurerAdapter { /** @@ -92,17 +92,9 @@ public class EurekaServerConfiguration extends WebMvcConfigurerAdapter { @Autowired private EurekaClient eurekaClient; - /* - * Setting expectedNumberOfRenewsPerMin to non-zero to ensure that even an isolated - * server can adjust its eviction policy to the number of registrations (when it's - * zero, even a successful registration won't reset the rate threshold in - * InstanceRegistry.register()). - */ - @Value("${eureka.server.expectedNumberOfRenewsPerMin:1}") - private int expectedNumberOfRenewsPerMin; + @Autowired + private InstanceRegistryProperties instanceRegistryProperties; - @Value("${eureka.server.defaultOpenForTrafficCount:1}") - private int defaultOpenForTrafficCount; public static final CloudJacksonJson JACKSON_JSON = new CloudJacksonJson(); @Bean @@ -166,8 +158,9 @@ public class EurekaServerConfiguration extends WebMvcConfigurerAdapter { ServerCodecs serverCodecs) { this.eurekaClient.getApplications(); // force initialization return new InstanceRegistry(this.eurekaServerConfig, this.eurekaClientConfig, - serverCodecs, this.eurekaClient, this.expectedNumberOfRenewsPerMin, - this.defaultOpenForTrafficCount); + serverCodecs, this.eurekaClient, + this.instanceRegistryProperties.getExpectedNumberOfRenewsPerMin(), + this.instanceRegistryProperties.getDefaultOpenForTrafficCount()); } @Bean diff --git a/spring-cloud-netflix-eureka-server/src/main/java/org/springframework/cloud/netflix/eureka/server/InstanceRegistry.java b/spring-cloud-netflix-eureka-server/src/main/java/org/springframework/cloud/netflix/eureka/server/InstanceRegistry.java index c1ba8b25d..3faaef7ee 100644 --- a/spring-cloud-netflix-eureka-server/src/main/java/org/springframework/cloud/netflix/eureka/server/InstanceRegistry.java +++ b/spring-cloud-netflix-eureka-server/src/main/java/org/springframework/cloud/netflix/eureka/server/InstanceRegistry.java @@ -66,8 +66,8 @@ public class InstanceRegistry extends PeerAwareInstanceRegistryImpl /** * If * {@link PeerAwareInstanceRegistryImpl#openForTraffic(ApplicationInfoManager, int)} - * is called with a zero * argument, it means that leases are not automatically * - * cancelled if the instance * hasn't sent any renewals recently. This happens for a + * is called with a zero argument, it means that leases are not automatically + * cancelled if the instance hasn't sent any renewals recently. This happens for a * standalone server. It seems like a bad default, so we set it to the smallest * non-zero value we can, so that any instances that subsequently register can bump up * the threshold. diff --git a/spring-cloud-netflix-eureka-server/src/main/java/org/springframework/cloud/netflix/eureka/server/InstanceRegistryProperties.java b/spring-cloud-netflix-eureka-server/src/main/java/org/springframework/cloud/netflix/eureka/server/InstanceRegistryProperties.java new file mode 100644 index 000000000..87a0ebaca --- /dev/null +++ b/spring-cloud-netflix-eureka-server/src/main/java/org/springframework/cloud/netflix/eureka/server/InstanceRegistryProperties.java @@ -0,0 +1,63 @@ +/* + * Copyright 2013-2016 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package org.springframework.cloud.netflix.eureka.server; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.context.properties.ConfigurationProperties; + +import static org.springframework.cloud.netflix.eureka.server.InstanceRegistryProperties.PREFIX; + +/** + * @author Spencer Gibb + */ +@ConfigurationProperties(PREFIX) +public class InstanceRegistryProperties { + + public static final String PREFIX = "eureka.instance.registry"; + + + /* Default number of expected renews per minute, defaults to 1. + * Setting expectedNumberOfRenewsPerMin to non-zero to ensure that even an isolated + * server can adjust its eviction policy to the number of registrations (when it's + * zero, even a successful registration won't reset the rate threshold in + * InstanceRegistry.register()). + */ + @Value("${eureka.server.expectedNumberOfRenewsPerMin:1}") // for backwards compatibility + private int expectedNumberOfRenewsPerMin = 1; + + /** Value used in determining when leases are cancelled, default to 1 for standalone. + * Should be set to 0 for peer replicated eurekas */ + @Value("${eureka.server.defaultOpenForTrafficCount:1}") // for backwards compatibility + private int defaultOpenForTrafficCount = 1; + + public int getExpectedNumberOfRenewsPerMin() { + return expectedNumberOfRenewsPerMin; + } + + public void setExpectedNumberOfRenewsPerMin(int expectedNumberOfRenewsPerMin) { + this.expectedNumberOfRenewsPerMin = expectedNumberOfRenewsPerMin; + } + + public int getDefaultOpenForTrafficCount() { + return defaultOpenForTrafficCount; + } + + public void setDefaultOpenForTrafficCount(int defaultOpenForTrafficCount) { + this.defaultOpenForTrafficCount = defaultOpenForTrafficCount; + } +} From cc24d00fdeadec2bcd3348a4b42576081cbccf82 Mon Sep 17 00:00:00 2001 From: Ryan Baxter Date: Wed, 19 Oct 2016 20:06:52 -0400 Subject: [PATCH 24/48] Fixes #1211 --- .../main/asciidoc/spring-cloud-netflix.adoc | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/docs/src/main/asciidoc/spring-cloud-netflix.adoc b/docs/src/main/asciidoc/spring-cloud-netflix.adoc index bd65af994..14663a1cb 100644 --- a/docs/src/main/asciidoc/spring-cloud-netflix.adoc +++ b/docs/src/main/asciidoc/spring-cloud-netflix.adoc @@ -970,6 +970,46 @@ This replaces the `SpringMvcContract` with `feign.Contract.Default` and adds a ` Default configurations can be specified in the `@EnableFeignClients` attribute `defaultConfiguration` in a similar manner as described above. The difference is that this configuration will apply to _all_ feign clients. +=== Creating Feign Clients Manually + +In some cases it might be necessary to customize your Feign Clients in a way that is not +possible using the methods above. In this case you can create Clients using the +https://github.com/OpenFeign/feign/#basics[Feign Builder API]. Below is an example +which creates two Feign Clients with the same interface but configures each one with +a separate request interceptor. + +[source,java,indent=0] +---- +@Import(FeignClientsConfiguration.class) +class FooController { + + private FooClient fooClient; + + private FooClient adminClient; + + @Autowired + public FooController( + ResponseEntityDecoder decoder, SpringEncoder encoder, EurekaClient discoveryClient) { + InstanceInfo prodSvcInfo = discoveryClient.getNextServerFromEureka("PROD-SVC", false); + this.fooClient = Feign.builder() + .encoder(encoder) + .decoder(decoder) + .requestInterceptor(new BasicAuthRequestInterceptor("user", "user")) + .target(FooClient.class, prodSvcInfo.getHomePageUrl()); + this.adminClient = Feign.builder() + .encoder(encoder) + .decoder(decoder) + .requestInterceptor(new BasicAuthRequestInterceptor("admin", "admin")) + .target(FooClient.class, prodSvcInfo.getHomePageUrl()); + } +} +---- + +NOTE: In the above example `FeignClientsConfiguration.class` is the default configuration +provided by Spring Cloud Netflix. + +NOTE: `prodSvcInfo` is the service the the Clients will be making requests to. + [[spring-cloud-feign-hystrix]] === Feign Hystrix Support From 8e6b64382995eab85d2275bc57eb279e23b746aa Mon Sep 17 00:00:00 2001 From: Spencer Gibb Date: Thu, 20 Oct 2016 11:19:54 -0600 Subject: [PATCH 25/48] Use new ServletRegistrationBean package. Breaks Spring Boot 1.3 compatibility, enables 1.5 --- .../springframework/cloud/netflix/zuul/ZuulConfiguration.java | 2 +- .../hystrix/dashboard/HystrixDashboardConfiguration.java | 4 ++-- .../cloud/netflix/turbine/TurbineHttpConfiguration.java | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/ZuulConfiguration.java b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/ZuulConfiguration.java index cc5a5d0ba..81f46576a 100644 --- a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/ZuulConfiguration.java +++ b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/ZuulConfiguration.java @@ -24,8 +24,8 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean import org.springframework.boot.autoconfigure.web.ErrorController; import org.springframework.boot.autoconfigure.web.ServerProperties; import org.springframework.boot.autoconfigure.web.ServerPropertiesAutoConfiguration; -import org.springframework.boot.context.embedded.ServletRegistrationBean; import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.boot.web.servlet.ServletRegistrationBean; import org.springframework.cloud.client.actuator.HasFeatures; import org.springframework.cloud.client.discovery.event.HeartbeatEvent; import org.springframework.cloud.client.discovery.event.HeartbeatMonitor; diff --git a/spring-cloud-netflix-hystrix-dashboard/src/main/java/org/springframework/cloud/netflix/hystrix/dashboard/HystrixDashboardConfiguration.java b/spring-cloud-netflix-hystrix-dashboard/src/main/java/org/springframework/cloud/netflix/hystrix/dashboard/HystrixDashboardConfiguration.java index 38569b633..4d05b5043 100644 --- a/spring-cloud-netflix-hystrix-dashboard/src/main/java/org/springframework/cloud/netflix/hystrix/dashboard/HystrixDashboardConfiguration.java +++ b/spring-cloud-netflix-hystrix-dashboard/src/main/java/org/springframework/cloud/netflix/hystrix/dashboard/HystrixDashboardConfiguration.java @@ -40,8 +40,8 @@ import org.apache.http.params.HttpParams; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.freemarker.FreeMarkerAutoConfiguration; -import org.springframework.boot.context.embedded.ServletRegistrationBean; import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.boot.web.servlet.ServletRegistrationBean; import org.springframework.cloud.client.actuator.HasFeatures; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -53,7 +53,6 @@ import org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer; * @author Dave Syer * @author Roy Clarkson */ -@SuppressWarnings("deprecation") @Configuration @EnableConfigurationProperties(HystrixDashboardProperties.class) public class HystrixDashboardConfiguration { @@ -263,6 +262,7 @@ public class HystrixDashboardConfiguration { } } + @SuppressWarnings("deprecation") private static class ProxyConnectionManager { private final static PoolingClientConnectionManager threadSafeConnectionManager = new PoolingClientConnectionManager(); diff --git a/spring-cloud-netflix-turbine/src/main/java/org/springframework/cloud/netflix/turbine/TurbineHttpConfiguration.java b/spring-cloud-netflix-turbine/src/main/java/org/springframework/cloud/netflix/turbine/TurbineHttpConfiguration.java index 0c58625c9..8c23c86f1 100644 --- a/spring-cloud-netflix-turbine/src/main/java/org/springframework/cloud/netflix/turbine/TurbineHttpConfiguration.java +++ b/spring-cloud-netflix-turbine/src/main/java/org/springframework/cloud/netflix/turbine/TurbineHttpConfiguration.java @@ -19,8 +19,8 @@ package org.springframework.cloud.netflix.turbine; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingClass; -import org.springframework.boot.context.embedded.ServletRegistrationBean; import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.boot.web.servlet.ServletRegistrationBean; import org.springframework.cloud.client.actuator.HasFeatures; import org.springframework.cloud.client.discovery.DiscoveryClient; import org.springframework.cloud.client.discovery.EnableDiscoveryClient; From 2c8bac56661f4d976519fb8f9032b4f2a5cbf5b4 Mon Sep 17 00:00:00 2001 From: Ryan Baxter Date: Thu, 20 Oct 2016 13:31:41 -0400 Subject: [PATCH 26/48] Use client interface instead of Eureka directly --- .../main/asciidoc/spring-cloud-netflix.adoc | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/docs/src/main/asciidoc/spring-cloud-netflix.adoc b/docs/src/main/asciidoc/spring-cloud-netflix.adoc index 14663a1cb..f99a3f932 100644 --- a/docs/src/main/asciidoc/spring-cloud-netflix.adoc +++ b/docs/src/main/asciidoc/spring-cloud-netflix.adoc @@ -989,18 +989,17 @@ class FooController { @Autowired public FooController( - ResponseEntityDecoder decoder, SpringEncoder encoder, EurekaClient discoveryClient) { - InstanceInfo prodSvcInfo = discoveryClient.getNextServerFromEureka("PROD-SVC", false); - this.fooClient = Feign.builder() + ResponseEntityDecoder decoder, SpringEncoder encoder, Client client) { + this.fooClient = Feign.builder().client(client) .encoder(encoder) - .decoder(decoder) - .requestInterceptor(new BasicAuthRequestInterceptor("user", "user")) - .target(FooClient.class, prodSvcInfo.getHomePageUrl()); - this.adminClient = Feign.builder() + .decoder(decoder) + .requestInterceptor(new BasicAuthRequestInterceptor("user", "user")) + .target(FooClient.class, "http://PROD-SVC"); + this.adminClient = Feign.builder().client(client) .encoder(encoder) - .decoder(decoder) - .requestInterceptor(new BasicAuthRequestInterceptor("admin", "admin")) - .target(FooClient.class, prodSvcInfo.getHomePageUrl()); + .decoder(decoder) + .requestInterceptor(new BasicAuthRequestInterceptor("admin", "admin")) + .target(FooClient.class, "http://PROD-SVC"); } } ---- From b16a95d0f2518bae5a608b0cbd05b56655f26aa9 Mon Sep 17 00:00:00 2001 From: Ryan Baxter Date: Thu, 20 Oct 2016 13:40:59 -0400 Subject: [PATCH 27/48] Fixed typo --- docs/src/main/asciidoc/spring-cloud-netflix.adoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/src/main/asciidoc/spring-cloud-netflix.adoc b/docs/src/main/asciidoc/spring-cloud-netflix.adoc index f99a3f932..65052fe6f 100644 --- a/docs/src/main/asciidoc/spring-cloud-netflix.adoc +++ b/docs/src/main/asciidoc/spring-cloud-netflix.adoc @@ -1007,7 +1007,7 @@ class FooController { NOTE: In the above example `FeignClientsConfiguration.class` is the default configuration provided by Spring Cloud Netflix. -NOTE: `prodSvcInfo` is the service the the Clients will be making requests to. +NOTE: `PROD-SVC` is the name of the service the Clients will be making requests to. [[spring-cloud-feign-hystrix]] === Feign Hystrix Support From 5a42cb1b2b3ab26b2acf0f1f277d0f2b4ff63975 Mon Sep 17 00:00:00 2001 From: Ryan Baxter Date: Thu, 20 Oct 2016 15:09:52 -0400 Subject: [PATCH 28/48] Updates based on latest version from commons --- spring-cloud-netflix-core/pom.xml | 8 ++++++++ .../RibbonLoadBalancedRetryPolicyFactory.java | 7 ++++--- .../netflix/ribbon/RibbonInterceptorTests.java | 15 +++++---------- 3 files changed, 17 insertions(+), 13 deletions(-) diff --git a/spring-cloud-netflix-core/pom.xml b/spring-cloud-netflix-core/pom.xml index 3343772a2..fcd3c6590 100644 --- a/spring-cloud-netflix-core/pom.xml +++ b/spring-cloud-netflix-core/pom.xml @@ -44,6 +44,14 @@ spring-boot-starter-web true + + org.springframework.boot + spring-boot-starter-aop + + + org.springframework.retry + spring-retry + org.springframework.cloud spring-cloud-commons diff --git a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/ribbon/RibbonLoadBalancedRetryPolicyFactory.java b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/ribbon/RibbonLoadBalancedRetryPolicyFactory.java index 35facbe2f..65f843540 100644 --- a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/ribbon/RibbonLoadBalancedRetryPolicyFactory.java +++ b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/ribbon/RibbonLoadBalancedRetryPolicyFactory.java @@ -16,10 +16,10 @@ package org.springframework.cloud.netflix.ribbon; import org.springframework.cloud.client.ServiceInstance; +import org.springframework.cloud.client.loadbalancer.LoadBalanceChooser; import org.springframework.cloud.client.loadbalancer.LoadBalancedRetryContext; import org.springframework.cloud.client.loadbalancer.LoadBalancedRetryPolicy; import org.springframework.cloud.client.loadbalancer.LoadBalancedRetryPolicyFactory; -import org.springframework.cloud.client.loadbalancer.LoadBalancerClient; import org.springframework.http.HttpMethod; /** @@ -32,8 +32,9 @@ public class RibbonLoadBalancedRetryPolicyFactory implements LoadBalancedRetryPo public RibbonLoadBalancedRetryPolicyFactory(SpringClientFactory clientFactory) { this.clientFactory = clientFactory; } + @Override - public LoadBalancedRetryPolicy create(final String serviceId, final LoadBalancerClient loadBalancerClient) { + public LoadBalancedRetryPolicy create(final String serviceId, final LoadBalanceChooser loadBalanceChooser) { final RibbonLoadBalancerContext lbContext = this.clientFactory .getLoadBalancerContext(serviceId); return new LoadBalancedRetryPolicy() { @@ -69,7 +70,7 @@ public class RibbonLoadBalancedRetryPolicyFactory implements LoadBalancedRetryPo //Do this before we increment the counters because the first call to this method //is not a retry it is just an initial failure. if(!canRetrySameServer(context) && canRetryNextServer(context)) { - context.setServiceInstance(loadBalancerClient.choose(serviceId)); + context.setServiceInstance(loadBalanceChooser.choose(serviceId)); } //This method is called regardless of whether we are retrying or making the first request. //Since we do not count the initial request in the retry count we don't reset the counter diff --git a/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/ribbon/RibbonInterceptorTests.java b/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/ribbon/RibbonInterceptorTests.java index 644a7c37a..aa9bb89ea 100644 --- a/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/ribbon/RibbonInterceptorTests.java +++ b/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/ribbon/RibbonInterceptorTests.java @@ -16,30 +16,26 @@ package org.springframework.cloud.netflix.ribbon; -import com.netflix.loadbalancer.Server; +import java.io.IOException; +import java.net.URI; +import java.net.URL; import org.junit.Before; import org.junit.Test; import org.mockito.ArgumentCaptor; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.springframework.cloud.client.ServiceInstance; -import org.springframework.cloud.client.loadbalancer.LoadBalancedRetryPolicyFactory; import org.springframework.cloud.client.loadbalancer.LoadBalancerClient; import org.springframework.cloud.client.loadbalancer.LoadBalancerInterceptor; import org.springframework.cloud.client.loadbalancer.LoadBalancerRequest; -import org.springframework.cloud.client.loadbalancer.LoadBalancerRetryProperties; import org.springframework.cloud.netflix.ribbon.RibbonLoadBalancerClient.RibbonServer; import org.springframework.http.HttpRequest; import org.springframework.http.client.ClientHttpRequestExecution; import org.springframework.http.client.ClientHttpResponse; import org.springframework.http.client.support.HttpRequestWrapper; -import org.springframework.retry.support.RetryTemplate; import org.springframework.util.ReflectionUtils; import org.springframework.web.util.UriComponentsBuilder; - -import java.io.IOException; -import java.net.URI; -import java.net.URL; +import com.netflix.loadbalancer.Server; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; @@ -69,8 +65,7 @@ public class RibbonInterceptorTests { @Test public void testIntercept() throws Exception { RibbonServer server = new RibbonServer("myservice", new Server("myhost", 8080)); - LoadBalancerInterceptor interceptor = new LoadBalancerInterceptor(new MyClient(server), new RetryTemplate(), - new LoadBalancerRetryProperties(), new LoadBalancedRetryPolicyFactory.NeverRetryFactory()); + LoadBalancerInterceptor interceptor = new LoadBalancerInterceptor(new MyClient(server)); given(this.request.getURI()).willReturn(new URL("http://myservice").toURI()); given(this.execution.execute(isA(HttpRequest.class), isA(byte[].class))) .willReturn(this.response); From 6e1ca54edcc181905e845ec79ddffc07ac692965 Mon Sep 17 00:00:00 2001 From: Ryan Baxter Date: Mon, 24 Oct 2016 13:42:21 -0400 Subject: [PATCH 29/48] increased max retried to help with failures --- .../cloud/netflix/resttemplate/RestTemplateRetryTests.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/resttemplate/RestTemplateRetryTests.java b/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/resttemplate/RestTemplateRetryTests.java index 90bf4d3a3..4a8856342 100644 --- a/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/resttemplate/RestTemplateRetryTests.java +++ b/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/resttemplate/RestTemplateRetryTests.java @@ -47,7 +47,7 @@ import static org.junit.Assert.assertTrue; @SpringBootTest(classes = RestTemplateRetryTests.Application.class, webEnvironment = WebEnvironment.RANDOM_PORT, value = { "spring.application.name=resttemplatetest", "logging.level.com.netflix=DEBUG", "logging.level.org.springframework.cloud.netflix.resttemplate=DEBUG", - "logging.level.com.netflix=DEBUG", "badClients.ribbon.MaxAutoRetries=0", + "logging.level.com.netflix=DEBUG", "badClients.ribbon.MaxAutoRetries=25", "badClients.ribbon.OkToRetryOnAllOperations=true", "ribbon.http.client.enabled" }) @DirtiesContext public class RestTemplateRetryTests { From 0235d779323cbb557ee1a576006f7a62192336ed Mon Sep 17 00:00:00 2001 From: Ryan Baxter Date: Mon, 24 Oct 2016 15:24:31 -0400 Subject: [PATCH 30/48] Zuul Route Hystrix Fallback Hystrix fallback support for Zuul routes. Fixes gh-250. --- .../netflix/zuul/ZuulProxyConfiguration.java | 19 ++++- .../route/RestClientRibbonCommand.java | 12 ++- .../route/RestClientRibbonCommandFactory.java | 21 +++-- .../filters/route/ZuulFallbackProvider.java | 40 +++++++++ .../route/apache/HttpClientRibbonCommand.java | 10 +++ .../HttpClientRibbonCommandFactory.java | 27 ++++-- .../route/okhttp/OkHttpRibbonCommand.java | 16 +++- .../okhttp/OkHttpRibbonCommandFactory.java | 31 +++++-- .../route/support/AbstractRibbonCommand.java | 18 +++- .../support/AbstractRibbonCommandFactory.java | 44 ++++++++++ .../HttpClientRibbonCommandFallbackTests.java | 46 ++++++++++ ...tpClientRibbonCommandIntegrationTests.java | 11 ++- .../OkHttpRibbonCommandFallbackTests.java | 44 ++++++++++ .../OkHttpRibbonCommandIntegrationTests.java | 11 ++- .../RestClientRibbonCommandFallbackTests.java | 44 ++++++++++ ...stClientRibbonCommandIntegrationTests.java | 17 ++-- .../support/RibbonCommandFallbackTests.java | 58 +++++++++++++ .../route/support/ZuulProxyTestBase.java | 84 +++++++++++++++++-- 18 files changed, 505 insertions(+), 48 deletions(-) create mode 100644 spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/filters/route/ZuulFallbackProvider.java create mode 100644 spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/filters/route/support/AbstractRibbonCommandFactory.java create mode 100644 spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/zuul/filters/route/apache/HttpClientRibbonCommandFallbackTests.java create mode 100644 spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/zuul/filters/route/okhttp/OkHttpRibbonCommandFallbackTests.java create mode 100644 spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/zuul/filters/route/restclient/RestClientRibbonCommandFallbackTests.java create mode 100644 spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/zuul/filters/route/support/RibbonCommandFallbackTests.java diff --git a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/ZuulProxyConfiguration.java b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/ZuulProxyConfiguration.java index 8777cd928..fa3e2838e 100644 --- a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/ZuulProxyConfiguration.java +++ b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/ZuulProxyConfiguration.java @@ -23,6 +23,7 @@ import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import java.util.Collections; import java.util.List; +import java.util.Set; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.actuate.endpoint.Endpoint; @@ -52,6 +53,7 @@ import org.springframework.cloud.netflix.zuul.filters.route.RestClientRibbonComm import org.springframework.cloud.netflix.zuul.filters.route.RibbonCommandFactory; import org.springframework.cloud.netflix.zuul.filters.route.RibbonRoutingFilter; import org.springframework.cloud.netflix.zuul.filters.route.SimpleHostRoutingFilter; +import org.springframework.cloud.netflix.zuul.filters.route.ZuulFallbackProvider; import org.springframework.cloud.netflix.zuul.filters.route.apache.HttpClientRibbonCommandFactory; import org.springframework.cloud.netflix.zuul.filters.route.okhttp.OkHttpRibbonCommandFactory; import org.springframework.cloud.netflix.zuul.web.ZuulHandlerMapping; @@ -94,11 +96,14 @@ public class ZuulProxyConfiguration extends ZuulConfiguration { @ConditionalOnRibbonHttpClient protected static class HttpClientRibbonConfiguration { + @Autowired(required = false) + private Set zuulFallbackProviders = Collections.emptySet(); + @Bean @ConditionalOnMissingBean public RibbonCommandFactory ribbonCommandFactory( SpringClientFactory clientFactory, ZuulProperties zuulProperties) { - return new HttpClientRibbonCommandFactory(clientFactory, zuulProperties); + return new HttpClientRibbonCommandFactory(clientFactory, zuulProperties, zuulFallbackProviders); } } @@ -106,11 +111,15 @@ public class ZuulProxyConfiguration extends ZuulConfiguration { @ConditionalOnRibbonRestClient protected static class RestClientRibbonConfiguration { + @Autowired(required = false) + private Set zuulFallbackProviders = Collections.emptySet(); + @Bean @ConditionalOnMissingBean public RibbonCommandFactory ribbonCommandFactory( SpringClientFactory clientFactory, ZuulProperties zuulProperties) { - return new RestClientRibbonCommandFactory(clientFactory, zuulProperties); + return new RestClientRibbonCommandFactory(clientFactory, zuulProperties, + zuulFallbackProviders); } } @@ -119,11 +128,15 @@ public class ZuulProxyConfiguration extends ZuulConfiguration { @ConditionalOnClass(name = "okhttp3.OkHttpClient") protected static class OkHttpRibbonConfiguration { + @Autowired(required = false) + private Set zuulFallbackProviders = Collections.emptySet(); + @Bean @ConditionalOnMissingBean public RibbonCommandFactory ribbonCommandFactory( SpringClientFactory clientFactory, ZuulProperties zuulProperties) { - return new OkHttpRibbonCommandFactory(clientFactory, zuulProperties); + return new OkHttpRibbonCommandFactory(clientFactory, zuulProperties, + zuulFallbackProviders); } } diff --git a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/filters/route/RestClientRibbonCommand.java b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/filters/route/RestClientRibbonCommand.java index d8fb01edf..bf913fe4c 100644 --- a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/filters/route/RestClientRibbonCommand.java +++ b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/filters/route/RestClientRibbonCommand.java @@ -17,20 +17,18 @@ package org.springframework.cloud.netflix.zuul.filters.route; -import static org.springframework.cloud.netflix.ribbon.support.RibbonRequestCustomizer.Runner.customize; - import java.io.InputStream; import java.net.URI; import java.util.List; - import org.springframework.cloud.netflix.zuul.filters.ZuulProperties; import org.springframework.cloud.netflix.zuul.filters.route.support.AbstractRibbonCommand; import org.springframework.util.MultiValueMap; - import com.netflix.client.http.HttpRequest; import com.netflix.client.http.HttpResponse; import com.netflix.niws.client.http.RestClient; +import static org.springframework.cloud.netflix.ribbon.support.RibbonRequestCustomizer.Runner.customize; + /** * Hystrix wrapper around Eureka Ribbon command * @@ -44,6 +42,12 @@ public class RestClientRibbonCommand extends AbstractRibbonCommand { +public class RestClientRibbonCommandFactory extends AbstractRibbonCommandFactory { - private final SpringClientFactory clientFactory; + private SpringClientFactory clientFactory; private ZuulProperties zuulProperties; public RestClientRibbonCommandFactory(SpringClientFactory clientFactory) { - this(clientFactory, new ZuulProperties()); + this(clientFactory, new ZuulProperties(), Collections.emptySet()); } public RestClientRibbonCommandFactory(SpringClientFactory clientFactory, - ZuulProperties zuulProperties) { + ZuulProperties zuulProperties, + Set zuulFallbackProviders) { + super(zuulFallbackProviders); this.clientFactory = clientFactory; this.zuulProperties = zuulProperties; } @@ -45,10 +52,12 @@ public class RestClientRibbonCommandFactory implements RibbonCommandFactory { @@ -36,6 +38,14 @@ public class HttpClientRibbonCommand extends AbstractRibbonCommand { +public class HttpClientRibbonCommandFactory extends AbstractRibbonCommandFactory { private final SpringClientFactory clientFactory; private final ZuulProperties zuulProperties; + public HttpClientRibbonCommandFactory(SpringClientFactory clientFactory, ZuulProperties zuulProperties) { + this(clientFactory, zuulProperties, Collections.emptySet()); + } + + public HttpClientRibbonCommandFactory(SpringClientFactory clientFactory, ZuulProperties zuulProperties, + Set fallbackProviders) { + super(fallbackProviders); + this.clientFactory = clientFactory; + this.zuulProperties = zuulProperties; + } + @Override public HttpClientRibbonCommand create(final RibbonCommandContext context) { + ZuulFallbackProvider zuulFallbackProvider = getFallbackProvider(context.getServiceId()); final String serviceId = context.getServiceId(); final RibbonLoadBalancingHttpClient client = this.clientFactory.getClient( serviceId, RibbonLoadBalancingHttpClient.class); client.setLoadBalancer(this.clientFactory.getLoadBalancer(serviceId)); - return new HttpClientRibbonCommand(serviceId, client, context, zuulProperties); + return new HttpClientRibbonCommand(serviceId, client, context, zuulProperties, zuulFallbackProvider); } } diff --git a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/filters/route/okhttp/OkHttpRibbonCommand.java b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/filters/route/okhttp/OkHttpRibbonCommand.java index f66f36b7a..e4cd1972d 100644 --- a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/filters/route/okhttp/OkHttpRibbonCommand.java +++ b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/filters/route/okhttp/OkHttpRibbonCommand.java @@ -22,20 +22,30 @@ import org.springframework.cloud.netflix.ribbon.okhttp.OkHttpRibbonRequest; import org.springframework.cloud.netflix.ribbon.okhttp.OkHttpRibbonResponse; import org.springframework.cloud.netflix.zuul.filters.ZuulProperties; import org.springframework.cloud.netflix.zuul.filters.route.RibbonCommandContext; +import org.springframework.cloud.netflix.zuul.filters.route.ZuulFallbackProvider; import org.springframework.cloud.netflix.zuul.filters.route.support.AbstractRibbonCommand; /** * @author Spencer Gibb + * @author Ryan Baxter */ public class OkHttpRibbonCommand extends AbstractRibbonCommand { public OkHttpRibbonCommand(final String commandKey, - final OkHttpLoadBalancingClient client, - final RibbonCommandContext context, - final ZuulProperties zuulProperties) { + final OkHttpLoadBalancingClient client, + final RibbonCommandContext context, + final ZuulProperties zuulProperties) { super(commandKey, client, context, zuulProperties); } + public OkHttpRibbonCommand(final String commandKey, + final OkHttpLoadBalancingClient client, + final RibbonCommandContext context, + final ZuulProperties zuulProperties, + final ZuulFallbackProvider zuulFallbackProvider) { + super(commandKey, client, context, zuulProperties, zuulFallbackProvider); + } + @Override protected OkHttpRibbonRequest createRequest() throws Exception { return new OkHttpRibbonRequest(this.context); diff --git a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/filters/route/okhttp/OkHttpRibbonCommandFactory.java b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/filters/route/okhttp/OkHttpRibbonCommandFactory.java index 610014438..67ca4fcc6 100644 --- a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/filters/route/okhttp/OkHttpRibbonCommandFactory.java +++ b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/filters/route/okhttp/OkHttpRibbonCommandFactory.java @@ -16,33 +16,46 @@ package org.springframework.cloud.netflix.zuul.filters.route.okhttp; +import java.util.Collections; +import java.util.Set; + import org.springframework.cloud.netflix.ribbon.SpringClientFactory; import org.springframework.cloud.netflix.ribbon.okhttp.OkHttpLoadBalancingClient; import org.springframework.cloud.netflix.zuul.filters.ZuulProperties; import org.springframework.cloud.netflix.zuul.filters.route.RibbonCommandContext; -import org.springframework.cloud.netflix.zuul.filters.route.RibbonCommandFactory; - -import lombok.RequiredArgsConstructor; +import org.springframework.cloud.netflix.zuul.filters.route.ZuulFallbackProvider; +import org.springframework.cloud.netflix.zuul.filters.route.support.AbstractRibbonCommandFactory; /** * @author Spencer Gibb + * @author Ryan Baxter */ -@RequiredArgsConstructor -public class OkHttpRibbonCommandFactory implements - RibbonCommandFactory { +public class OkHttpRibbonCommandFactory extends AbstractRibbonCommandFactory { - private final SpringClientFactory clientFactory; + private SpringClientFactory clientFactory; - private final ZuulProperties zuulProperties; + private ZuulProperties zuulProperties; + + public OkHttpRibbonCommandFactory(SpringClientFactory clientFactory, ZuulProperties zuulProperties) { + this(clientFactory, zuulProperties, Collections.emptySet()); + } + + public OkHttpRibbonCommandFactory(SpringClientFactory clientFactory, ZuulProperties zuulProperties, + Set zuulFallbackProviders) { + super(zuulFallbackProviders); + this.clientFactory = clientFactory; + this.zuulProperties = zuulProperties; + } @Override public OkHttpRibbonCommand create(final RibbonCommandContext context) { final String serviceId = context.getServiceId(); + ZuulFallbackProvider fallbackProvider = getFallbackProvider(serviceId); final OkHttpLoadBalancingClient client = this.clientFactory.getClient( serviceId, OkHttpLoadBalancingClient.class); client.setLoadBalancer(this.clientFactory.getLoadBalancer(serviceId)); - return new OkHttpRibbonCommand(serviceId, client, context, zuulProperties); + return new OkHttpRibbonCommand(serviceId, client, context, zuulProperties, fallbackProvider); } } diff --git a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/filters/route/support/AbstractRibbonCommand.java b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/filters/route/support/AbstractRibbonCommand.java index 64f74f870..f5cb685f4 100644 --- a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/filters/route/support/AbstractRibbonCommand.java +++ b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/filters/route/support/AbstractRibbonCommand.java @@ -21,8 +21,8 @@ import org.springframework.cloud.netflix.ribbon.RibbonHttpResponse; import org.springframework.cloud.netflix.zuul.filters.ZuulProperties; import org.springframework.cloud.netflix.zuul.filters.route.RibbonCommand; import org.springframework.cloud.netflix.zuul.filters.route.RibbonCommandContext; +import org.springframework.cloud.netflix.zuul.filters.route.ZuulFallbackProvider; import org.springframework.http.client.ClientHttpResponse; - import com.netflix.client.AbstractLoadBalancerAwareClient; import com.netflix.client.ClientRequest; import com.netflix.client.http.HttpResponse; @@ -44,6 +44,7 @@ public abstract class AbstractRibbonCommand fallbackProviderCache; + + public AbstractRibbonCommandFactory(Set fallbackProviders){ + this.fallbackProviderCache = new HashMap(); + for(ZuulFallbackProvider provider : fallbackProviders) { + fallbackProviderCache.put(provider.getRoute(), provider); + } + } + + protected ZuulFallbackProvider getFallbackProvider(String route) { + return fallbackProviderCache.get(route); + } +} diff --git a/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/zuul/filters/route/apache/HttpClientRibbonCommandFallbackTests.java b/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/zuul/filters/route/apache/HttpClientRibbonCommandFallbackTests.java new file mode 100644 index 000000000..ea30e4e1a --- /dev/null +++ b/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/zuul/filters/route/apache/HttpClientRibbonCommandFallbackTests.java @@ -0,0 +1,46 @@ +/* + * + * * Copyright 2013-2016 the original author or authors. + * * + * * Licensed under the Apache License, Version 2.0 (the "License"); + * * you may not use this file except in compliance with the License. + * * You may obtain a copy of the License at + * * + * * http://www.apache.org/licenses/LICENSE-2.0 + * * + * * Unless required by applicable law or agreed to in writing, software + * * distributed under the License is distributed on an "AS IS" BASIS, + * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * * See the License for the specific language governing permissions and + * * limitations under the License. + * + */ + +package org.springframework.cloud.netflix.zuul.filters.route.apache; + +import org.junit.Before; +import org.junit.runner.RunWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.cloud.netflix.zuul.filters.route.support.RibbonCommandFallbackTests; +import org.springframework.test.annotation.DirtiesContext; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +import com.netflix.zuul.context.RequestContext; + +/** + * @author Ryan Baxter + */ +@RunWith(SpringJUnit4ClassRunner.class) +@SpringBootTest(classes = HttpClientRibbonCommandIntegrationTests.TestConfig.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, value = { + "zuul.routes.simple: /simple/**", "zuul.routes.another: /another/twolevel/**", + "ribbon.ReadTimeout: 1"}) +@DirtiesContext +public class HttpClientRibbonCommandFallbackTests extends RibbonCommandFallbackTests { + + @Before + public void init() { + RequestContext.testSetCurrentContext(null); + RequestContext.getCurrentContext().unset(); + } + +} diff --git a/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/zuul/filters/route/apache/HttpClientRibbonCommandIntegrationTests.java b/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/zuul/filters/route/apache/HttpClientRibbonCommandIntegrationTests.java index b41940e74..6f4201506 100644 --- a/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/zuul/filters/route/apache/HttpClientRibbonCommandIntegrationTests.java +++ b/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/zuul/filters/route/apache/HttpClientRibbonCommandIntegrationTests.java @@ -22,6 +22,9 @@ import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.springframework.http.HttpHeaders.SET_COOKIE; +import java.util.Collections; +import java.util.Set; + import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @@ -29,6 +32,7 @@ import javax.servlet.http.HttpServletResponse; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.web.ErrorAttributes; @@ -44,6 +48,7 @@ import org.springframework.cloud.netflix.ribbon.apache.RibbonLoadBalancingHttpCl import org.springframework.cloud.netflix.zuul.EnableZuulProxy; import org.springframework.cloud.netflix.zuul.filters.ZuulProperties; import org.springframework.cloud.netflix.zuul.filters.route.RibbonCommandFactory; +import org.springframework.cloud.netflix.zuul.filters.route.ZuulFallbackProvider; import org.springframework.cloud.netflix.zuul.filters.route.support.ZuulProxyTestBase; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -155,6 +160,9 @@ public class HttpClientRibbonCommandIntegrationTests extends ZuulProxyTestBase { @RibbonClient(name = "singleton", configuration = SingletonRibbonClientConfiguration.class) }) static class TestConfig extends ZuulProxyTestBase.AbstractZuulProxyApplication { + @Autowired(required = false) + private Set zuulFallbackProviders = Collections.emptySet(); + @RequestMapping(value = "/local/{id}", method = RequestMethod.PATCH) public String patch(@PathVariable final String id, @RequestBody final String body) { @@ -176,7 +184,8 @@ public class HttpClientRibbonCommandIntegrationTests extends ZuulProxyTestBase { @Bean public RibbonCommandFactory ribbonCommandFactory( final SpringClientFactory clientFactory) { - return new HttpClientRibbonCommandFactory(clientFactory, new ZuulProperties()); + return new HttpClientRibbonCommandFactory(clientFactory, new ZuulProperties(), + zuulFallbackProviders); } @Bean diff --git a/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/zuul/filters/route/okhttp/OkHttpRibbonCommandFallbackTests.java b/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/zuul/filters/route/okhttp/OkHttpRibbonCommandFallbackTests.java new file mode 100644 index 000000000..864e5504c --- /dev/null +++ b/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/zuul/filters/route/okhttp/OkHttpRibbonCommandFallbackTests.java @@ -0,0 +1,44 @@ +/* + * + * * Copyright 2013-2016 the original author or authors. + * * + * * Licensed under the Apache License, Version 2.0 (the "License"); + * * you may not use this file except in compliance with the License. + * * You may obtain a copy of the License at + * * + * * http://www.apache.org/licenses/LICENSE-2.0 + * * + * * Unless required by applicable law or agreed to in writing, software + * * distributed under the License is distributed on an "AS IS" BASIS, + * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * * See the License for the specific language governing permissions and + * * limitations under the License. + * + */ + +package org.springframework.cloud.netflix.zuul.filters.route.okhttp; + +import org.junit.Before; +import org.junit.runner.RunWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.cloud.netflix.zuul.filters.route.support.RibbonCommandFallbackTests; +import org.springframework.test.annotation.DirtiesContext; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +import com.netflix.zuul.context.RequestContext; + +/** + * @author Ryan Baxter + */ +@RunWith(SpringJUnit4ClassRunner.class) +@SpringBootTest(classes = OkHttpRibbonCommandIntegrationTests.TestConfig.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, value = { + "zuul.routes.simple: /simple/**", "zuul.routes.another: /another/twolevel/**", + "ribbon.ReadTimeout: 1"}) +@DirtiesContext +public class OkHttpRibbonCommandFallbackTests extends RibbonCommandFallbackTests { + @Before + public void init() { + RequestContext.testSetCurrentContext(null); + RequestContext.getCurrentContext().unset(); + } +} diff --git a/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/zuul/filters/route/okhttp/OkHttpRibbonCommandIntegrationTests.java b/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/zuul/filters/route/okhttp/OkHttpRibbonCommandIntegrationTests.java index 80f068067..bfd5b7ea6 100644 --- a/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/zuul/filters/route/okhttp/OkHttpRibbonCommandIntegrationTests.java +++ b/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/zuul/filters/route/okhttp/OkHttpRibbonCommandIntegrationTests.java @@ -20,9 +20,13 @@ package org.springframework.cloud.netflix.zuul.filters.route.okhttp; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; +import java.util.Collections; +import java.util.Set; + import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.web.ErrorAttributes; import org.springframework.boot.test.context.SpringBootTest; @@ -34,6 +38,7 @@ import org.springframework.cloud.netflix.ribbon.SpringClientFactory; import org.springframework.cloud.netflix.zuul.EnableZuulProxy; import org.springframework.cloud.netflix.zuul.filters.ZuulProperties; import org.springframework.cloud.netflix.zuul.filters.route.RibbonCommandFactory; +import org.springframework.cloud.netflix.zuul.filters.route.ZuulFallbackProvider; import org.springframework.cloud.netflix.zuul.filters.route.support.ZuulProxyTestBase; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -100,10 +105,14 @@ public class OkHttpRibbonCommandIntegrationTests extends ZuulProxyTestBase { @RibbonClient(name = "another", configuration = AnotherRibbonClientConfiguration.class) }) static class TestConfig extends ZuulProxyTestBase.AbstractZuulProxyApplication { + @Autowired(required = false) + private Set zuulFallbackProviders = Collections.emptySet(); + @Bean public RibbonCommandFactory ribbonCommandFactory( final SpringClientFactory clientFactory) { - return new OkHttpRibbonCommandFactory(clientFactory, new ZuulProperties()); + return new OkHttpRibbonCommandFactory(clientFactory, new ZuulProperties(), + zuulFallbackProviders); } @Bean diff --git a/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/zuul/filters/route/restclient/RestClientRibbonCommandFallbackTests.java b/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/zuul/filters/route/restclient/RestClientRibbonCommandFallbackTests.java new file mode 100644 index 000000000..ca9784f3f --- /dev/null +++ b/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/zuul/filters/route/restclient/RestClientRibbonCommandFallbackTests.java @@ -0,0 +1,44 @@ +/* + * + * * Copyright 2013-2016 the original author or authors. + * * + * * Licensed under the Apache License, Version 2.0 (the "License"); + * * you may not use this file except in compliance with the License. + * * You may obtain a copy of the License at + * * + * * http://www.apache.org/licenses/LICENSE-2.0 + * * + * * Unless required by applicable law or agreed to in writing, software + * * distributed under the License is distributed on an "AS IS" BASIS, + * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * * See the License for the specific language governing permissions and + * * limitations under the License. + * + */ + +package org.springframework.cloud.netflix.zuul.filters.route.restclient; + +import org.junit.Before; +import org.junit.runner.RunWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.cloud.netflix.zuul.filters.route.support.RibbonCommandFallbackTests; +import org.springframework.test.annotation.DirtiesContext; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +import com.netflix.zuul.context.RequestContext; + +/** + * @author Ryan Baxter + */ +@RunWith(SpringJUnit4ClassRunner.class) +@SpringBootTest(classes = RestClientRibbonCommandIntegrationTests.TestConfig.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, value = { + "zuul.routes.simple: /simple/**", "zuul.routes.another: /another/twolevel/**", + "ribbon.ReadTimeout: 1"}) +@DirtiesContext +public class RestClientRibbonCommandFallbackTests extends RibbonCommandFallbackTests { + @Before + public void init() { + RequestContext.testSetCurrentContext(null); + RequestContext.getCurrentContext().unset(); + } +} diff --git a/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/zuul/filters/route/restclient/RestClientRibbonCommandIntegrationTests.java b/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/zuul/filters/route/restclient/RestClientRibbonCommandIntegrationTests.java index 7b1a4d8b4..790cab60a 100644 --- a/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/zuul/filters/route/restclient/RestClientRibbonCommandIntegrationTests.java +++ b/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/zuul/filters/route/restclient/RestClientRibbonCommandIntegrationTests.java @@ -26,10 +26,14 @@ import static org.junit.Assert.assertTrue; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; +import java.util.Set; import java.util.UUID; import javax.servlet.http.HttpServletRequest; +import lombok.SneakyThrows; + import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; @@ -52,6 +56,7 @@ import org.springframework.cloud.netflix.zuul.filters.route.RestClientRibbonComm import org.springframework.cloud.netflix.zuul.filters.route.RestClientRibbonCommandFactory; import org.springframework.cloud.netflix.zuul.filters.route.RibbonCommandContext; import org.springframework.cloud.netflix.zuul.filters.route.RibbonCommandFactory; +import org.springframework.cloud.netflix.zuul.filters.route.ZuulFallbackProvider; import org.springframework.cloud.netflix.zuul.filters.route.support.NoEncodingFormHttpMessageConverter; import org.springframework.cloud.netflix.zuul.filters.route.support.ZuulProxyTestBase; import org.springframework.context.annotation.Bean; @@ -80,8 +85,6 @@ import com.netflix.loadbalancer.Server; import com.netflix.loadbalancer.ServerList; import com.netflix.niws.client.http.RestClient; -import lombok.SneakyThrows; - @RunWith(SpringJUnit4ClassRunner.class) @SpringBootTest(classes = RestClientRibbonCommandIntegrationTests.TestConfig.class, webEnvironment = WebEnvironment.RANDOM_PORT, value = { "zuul.routes.other: /test/**=http://localhost:7777/local", @@ -285,6 +288,9 @@ public class RestClientRibbonCommandIntegrationTests extends ZuulProxyTestBase { @RibbonClient(name = "another", configuration = ZuulProxyTestBase.AnotherRibbonClientConfiguration.class) }) static class TestConfig extends ZuulProxyTestBase.AbstractZuulProxyApplication { + @Autowired(required = false) + private Set fallbackProviders = Collections.emptySet(); + @RequestMapping("/trailing-slash") public String trailingSlash(HttpServletRequest request) { return request.getRequestURI(); @@ -327,7 +333,7 @@ public class RestClientRibbonCommandIntegrationTests extends ZuulProxyTestBase { @Bean public RibbonCommandFactory ribbonCommandFactory( SpringClientFactory clientFactory) { - return new MyRibbonCommandFactory(clientFactory); + return new MyRibbonCommandFactory(clientFactory, fallbackProviders); } @Bean @@ -350,8 +356,9 @@ public class RestClientRibbonCommandIntegrationTests extends ZuulProxyTestBase { private SpringClientFactory clientFactory; - public MyRibbonCommandFactory(SpringClientFactory clientFactory) { - super(clientFactory, new ZuulProperties()); + public MyRibbonCommandFactory(SpringClientFactory clientFactory, + Set fallbackProviders) { + super(clientFactory, new ZuulProperties(), fallbackProviders); this.clientFactory = clientFactory; } diff --git a/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/zuul/filters/route/support/RibbonCommandFallbackTests.java b/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/zuul/filters/route/support/RibbonCommandFallbackTests.java new file mode 100644 index 000000000..303241e1c --- /dev/null +++ b/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/zuul/filters/route/support/RibbonCommandFallbackTests.java @@ -0,0 +1,58 @@ +/* + * + * * Copyright 2013-2016 the original author or authors. + * * + * * Licensed under the Apache License, Version 2.0 (the "License"); + * * you may not use this file except in compliance with the License. + * * You may obtain a copy of the License at + * * + * * http://www.apache.org/licenses/LICENSE-2.0 + * * + * * Unless required by applicable law or agreed to in writing, software + * * distributed under the License is distributed on an "AS IS" BASIS, + * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * * See the License for the specific language governing permissions and + * * limitations under the License. + * + */ + +package org.springframework.cloud.netflix.zuul.filters.route.support; + +import org.junit.Test; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.test.web.client.TestRestTemplate; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpMethod; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; + +import static org.junit.Assert.assertEquals; + +/** + * @author Ryan Baxter + */ +public abstract class RibbonCommandFallbackTests { + + @Value("${local.server.port}") + protected int port; + + @Test + public void fallback() { + String uri = "/simple/slow"; + ResponseEntity result = new TestRestTemplate().exchange( + "http://localhost:" + this.port + uri, HttpMethod.GET, + new HttpEntity<>((Void) null), String.class); + assertEquals(HttpStatus.OK, result.getStatusCode()); + assertEquals("fallback", result.getBody()); + } + + @Test + public void noFallback() { + String uri = "/another/twolevel/slow"; + ResponseEntity result = new TestRestTemplate().exchange( + "http://localhost:" + this.port + uri, HttpMethod.GET, + new HttpEntity<>((Void) null), String.class); + System.out.println("no fallback body: " + result.getBody()); + assertEquals(HttpStatus.INTERNAL_SERVER_ERROR, result.getStatusCode()); + } +} diff --git a/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/zuul/filters/route/support/ZuulProxyTestBase.java b/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/zuul/filters/route/support/ZuulProxyTestBase.java index 9119c4a38..58bd1806b 100644 --- a/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/zuul/filters/route/support/ZuulProxyTestBase.java +++ b/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/zuul/filters/route/support/ZuulProxyTestBase.java @@ -17,11 +17,9 @@ package org.springframework.cloud.netflix.zuul.filters.route.support; -import static org.hamcrest.Matchers.is; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assume.assumeThat; - +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; import java.nio.charset.Charset; import java.util.ArrayList; import java.util.Arrays; @@ -29,9 +27,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.concurrent.atomic.AtomicBoolean; - import javax.servlet.http.HttpServletRequest; - import org.junit.Before; import org.junit.Test; import org.springframework.beans.factory.annotation.Autowired; @@ -46,13 +42,16 @@ import org.springframework.cloud.netflix.zuul.filters.Route; import org.springframework.cloud.netflix.zuul.filters.ZuulProperties; import org.springframework.cloud.netflix.zuul.filters.discovery.DiscoveryClientRouteLocator; import org.springframework.cloud.netflix.zuul.filters.route.RibbonCommandFactory; +import org.springframework.cloud.netflix.zuul.filters.route.ZuulFallbackProvider; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; +import org.springframework.http.client.ClientHttpResponse; import org.springframework.http.converter.FormHttpMessageConverter; import org.springframework.http.converter.HttpMessageConverter; import org.springframework.http.converter.StringHttpMessageConverter; @@ -66,14 +65,19 @@ import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.servlet.config.annotation.DelegatingWebMvcConfiguration; import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping; - import com.netflix.loadbalancer.Server; import com.netflix.loadbalancer.ServerList; import com.netflix.zuul.ZuulFilter; import com.netflix.zuul.context.RequestContext; +import static org.hamcrest.Matchers.is; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assume.assumeThat; + /** * @author Spencer Gibb + * @author Ryan Baxter */ public abstract class ZuulProxyTestBase { @@ -363,6 +367,22 @@ public abstract class ZuulProxyTestBase { return "Hello space"; } + @RequestMapping("/slow") + public String slow() { + try { + Thread.sleep(80000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + return "slow"; + + } + + @Bean + public ZuulFallbackProvider fallbackProvider() { + return new FallbackProvider(); + } + @Bean public ZuulFilter sampleFilter() { return new ZuulFilter() { @@ -393,6 +413,7 @@ public abstract class ZuulProxyTestBase { return 0; } }; + } @Override @@ -401,6 +422,53 @@ public abstract class ZuulProxyTestBase { mapping.setRemoveSemicolonContent(false); return mapping; } + + + } + + public static class FallbackProvider implements ZuulFallbackProvider { + + @Override + public String getRoute() { + return "simple"; + } + + @Override + public ClientHttpResponse fallbackResponse() { + return new ClientHttpResponse() { + @Override + public HttpStatus getStatusCode() throws IOException { + return HttpStatus.OK; + } + + @Override + public int getRawStatusCode() throws IOException { + return 200; + } + + @Override + public String getStatusText() throws IOException { + return null; + } + + @Override + public void close() { + + } + + @Override + public InputStream getBody() throws IOException { + return new ByteArrayInputStream("fallback".getBytes()); + } + + @Override + public HttpHeaders getHeaders() { + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.TEXT_HTML); + return headers; + } + }; + } } @Configuration From 0e1b856fc5e6aedd8dc6ccb9ea4dc693d89794ac Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Tue, 25 Oct 2016 07:50:32 +0100 Subject: [PATCH 31/48] Extract proxy header manipulation into method --- .../zuul/filters/pre/PreDecorationFilter.java | 93 ++++++++++--------- 1 file changed, 48 insertions(+), 45 deletions(-) diff --git a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/filters/pre/PreDecorationFilter.java b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/filters/pre/PreDecorationFilter.java index 6db078a9a..1b5bd474d 100644 --- a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/filters/pre/PreDecorationFilter.java +++ b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/filters/pre/PreDecorationFilter.java @@ -50,12 +50,11 @@ public class PreDecorationFilter extends ZuulFilter { private ProxyRequestHelper proxyRequestHelper; - public PreDecorationFilter(RouteLocator routeLocator, String dispatcherServletPath, - ZuulProperties properties, ProxyRequestHelper proxyRequestHelper) { + public PreDecorationFilter(RouteLocator routeLocator, String dispatcherServletPath, ZuulProperties properties, + ProxyRequestHelper proxyRequestHelper) { this.routeLocator = routeLocator; this.properties = properties; - this.urlPathHelper - .setRemoveSemicolonContent(properties.isRemoveSemicolonContent()); + this.urlPathHelper.setRemoveSemicolonContent(properties.isRemoveSemicolonContent()); this.dispatcherServletPath = dispatcherServletPath; this.proxyRequestHelper = proxyRequestHelper; } @@ -81,8 +80,7 @@ public class PreDecorationFilter extends ZuulFilter { @Override public Object run() { RequestContext ctx = RequestContext.getCurrentContext(); - final String requestURI = this.urlPathHelper - .getPathWithinApplication(ctx.getRequest()); + final String requestURI = this.urlPathHelper.getPathWithinApplication(ctx.getRequest()); Route route = this.routeLocator.getMatchingRoute(requestURI); if (route != null) { String location = route.getLocation(); @@ -90,12 +88,11 @@ public class PreDecorationFilter extends ZuulFilter { ctx.put("requestURI", route.getPath()); ctx.put("proxy", route.getId()); if (!route.isCustomSensitiveHeaders()) { - this.proxyRequestHelper.addIgnoredHeaders( - this.properties.getSensitiveHeaders().toArray(new String[0])); + this.proxyRequestHelper + .addIgnoredHeaders(this.properties.getSensitiveHeaders().toArray(new String[0])); } else { - this.proxyRequestHelper.addIgnoredHeaders( - route.getSensitiveHeaders().toArray(new String[0])); + this.proxyRequestHelper.addIgnoredHeaders(route.getSensitiveHeaders().toArray(new String[0])); } if (route.getRetryable() != null) { @@ -107,8 +104,8 @@ public class PreDecorationFilter extends ZuulFilter { ctx.addOriginResponseHeader("X-Zuul-Service", location); } else if (location.startsWith("forward:")) { - ctx.set("forward.to", StringUtils.cleanPath( - location.substring("forward:".length()) + route.getPath())); + ctx.set("forward.to", + StringUtils.cleanPath(location.substring("forward:".length()) + route.getPath())); ctx.setRouteHost(null); return null; } @@ -119,35 +116,7 @@ public class PreDecorationFilter extends ZuulFilter { ctx.addOriginResponseHeader("X-Zuul-ServiceId", location); } if (this.properties.isAddProxyHeaders()) { - ctx.addZuulRequestHeader("X-Forwarded-Host", toHostHeader(ctx.getRequest())); - ctx.addZuulRequestHeader("X-Forwarded-Port", - String.valueOf(ctx.getRequest().getServerPort())); - ctx.addZuulRequestHeader(ZuulHeaders.X_FORWARDED_PROTO, - ctx.getRequest().getScheme()); - String forwardedPrefix = - ctx.getRequest().getHeader("X-Forwarded-Prefix"); - String contextPath = ctx.getRequest().getContextPath(); - String prefix = StringUtils.hasLength(forwardedPrefix) - ? forwardedPrefix - : (StringUtils.hasLength(contextPath) ? contextPath : null); - if (StringUtils.hasText(route.getPrefix())) { - StringBuilder newPrefixBuilder = new StringBuilder(); - if (prefix != null) { - if (prefix.endsWith("/") - && route.getPrefix().startsWith("/")) { - newPrefixBuilder.append(prefix, 0, - prefix.length() - 1); - } - else { - newPrefixBuilder.append(prefix); - } - } - newPrefixBuilder.append(route.getPrefix()); - prefix = newPrefixBuilder.toString(); - } - if (prefix != null) { - ctx.addZuulRequestHeader("X-Forwarded-Prefix", prefix); - } + addProxyHeaders(ctx, route); String xforwardedfor = ctx.getRequest().getHeader("X-Forwarded-For"); String remoteAddr = ctx.getRequest().getRemoteAddr(); if (xforwardedfor == null) { @@ -174,8 +143,7 @@ public class PreDecorationFilter extends ZuulFilter { if (RequestUtils.isZuulServletRequest()) { // remove the Zuul servletPath from the requestUri log.debug("zuulServletPath=" + this.properties.getServletPath()); - fallBackUri = fallBackUri.replaceFirst(this.properties.getServletPath(), - ""); + fallBackUri = fallBackUri.replaceFirst(this.properties.getServletPath(), ""); log.debug("Replaced Zuul servlet path:" + fallBackUri); } else { @@ -194,11 +162,46 @@ public class PreDecorationFilter extends ZuulFilter { return null; } + private void addProxyHeaders(RequestContext ctx, Route route) { + String host = toHostHeader(ctx.getRequest()); + String port = String.valueOf(ctx.getRequest().getServerPort()); + String proto = ctx.getRequest().getScheme(); + ctx.addZuulRequestHeader("X-Forwarded-Host", host); + ctx.addZuulRequestHeader("X-Forwarded-Port", port); + ctx.addZuulRequestHeader(ZuulHeaders.X_FORWARDED_PROTO, proto); + addProxyPrefix(ctx, route); + } + + private void addProxyPrefix(RequestContext ctx, Route route) { + String forwardedPrefix = ctx.getRequest().getHeader("X-Forwarded-Prefix"); + String contextPath = ctx.getRequest().getContextPath(); + String prefix = StringUtils.hasLength(forwardedPrefix) ? forwardedPrefix + : (StringUtils.hasLength(contextPath) ? contextPath : null); + if (StringUtils.hasText(route.getPrefix())) { + StringBuilder newPrefixBuilder = new StringBuilder(); + if (prefix != null) { + if (prefix.endsWith("/") && route.getPrefix().startsWith("/")) { + newPrefixBuilder.append(prefix, 0, prefix.length() - 1); + } + else { + newPrefixBuilder.append(prefix); + } + } + newPrefixBuilder.append(route.getPrefix()); + prefix = newPrefixBuilder.toString(); + } + if (prefix != null) { + ctx.addZuulRequestHeader("X-Forwarded-Prefix", prefix); + } + } + private String toHostHeader(HttpServletRequest request) { int port = request.getServerPort(); - if ((port == 80 && "http".equals(request.getScheme())) || (port == 443 && "https".equals(request.getScheme()))) { + if ((port == 80 && "http".equals(request.getScheme())) + || (port == 443 && "https".equals(request.getScheme()))) { return request.getServerName(); - } else { + } + else { return request.getServerName() + ":" + port; } } From 71ac67f9f17938277afe78482923695af5a60134 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Tue, 25 Oct 2016 08:50:26 +0100 Subject: [PATCH 32/48] Suppress some warnings --- .../cloud/netflix/zuul/ZuulProxyConfiguration.java | 1 + .../cloud/netflix/AdhocTestSuite.java | 12 +++++++----- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/ZuulProxyConfiguration.java b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/ZuulProxyConfiguration.java index fa3e2838e..11ee38b1b 100644 --- a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/ZuulProxyConfiguration.java +++ b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/ZuulProxyConfiguration.java @@ -70,6 +70,7 @@ import org.springframework.context.annotation.Configuration; @Configuration public class ZuulProxyConfiguration extends ZuulConfiguration { + @SuppressWarnings("rawtypes") @Autowired(required = false) private List requestCustomizers = Collections.emptyList(); diff --git a/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/AdhocTestSuite.java b/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/AdhocTestSuite.java index 2200743e9..47a365ede 100644 --- a/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/AdhocTestSuite.java +++ b/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/AdhocTestSuite.java @@ -20,7 +20,11 @@ import org.junit.Ignore; import org.junit.runner.RunWith; import org.junit.runners.Suite; import org.junit.runners.Suite.SuiteClasses; -import org.springframework.cloud.netflix.zuul.filters.route.restclient.RestClientRibbonCommandIntegrationTests; +import org.springframework.cloud.netflix.feign.encoding.FeignAcceptEncodingTests; +import org.springframework.cloud.netflix.metrics.servo.ServoMetricReaderTests; +import org.springframework.cloud.netflix.ribbon.RibbonInterceptorTests; +import org.springframework.cloud.netflix.ribbon.RibbonLoadBalancerClientTests; +import org.springframework.cloud.netflix.zuul.ZuulProxyConfigurationTests; /** * A test suite for probing weird ordering problems in the tests. @@ -28,10 +32,8 @@ import org.springframework.cloud.netflix.zuul.filters.route.restclient.RestClien * @author Dave Syer */ @RunWith(Suite.class) -@SuiteClasses({ - org.springframework.cloud.netflix.zuul.filters.ProxyRequestHelperTests.class, - RestClientRibbonCommandIntegrationTests.class, - org.springframework.cloud.netflix.zuul.FormZuulProxyApplicationTests.class }) +@SuiteClasses({ RibbonLoadBalancerClientTests.class, RibbonInterceptorTests.class, FeignAcceptEncodingTests.class, + ServoMetricReaderTests.class, ZuulProxyConfigurationTests.class }) @Ignore public class AdhocTestSuite { From 139ab95438d0eea0c90c8aea23f3098caeca2333 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Tue, 25 Oct 2016 09:35:35 +0100 Subject: [PATCH 33/48] Make configuration imports deterministic --- .../RibbonCommandFactoryConfiguration.java | 154 ++++++++++++++++++ .../netflix/zuul/ZuulProxyConfiguration.java | 143 ++-------------- 2 files changed, 166 insertions(+), 131 deletions(-) create mode 100644 spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/RibbonCommandFactoryConfiguration.java diff --git a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/RibbonCommandFactoryConfiguration.java b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/RibbonCommandFactoryConfiguration.java new file mode 100644 index 000000000..957416032 --- /dev/null +++ b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/RibbonCommandFactoryConfiguration.java @@ -0,0 +1,154 @@ +/* + * Copyright 2015-2016 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.netflix.zuul; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import java.util.Collections; +import java.util.Set; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.condition.AnyNestedCondition; +import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.cloud.netflix.ribbon.SpringClientFactory; +import org.springframework.cloud.netflix.zuul.filters.ZuulProperties; +import org.springframework.cloud.netflix.zuul.filters.route.RestClientRibbonCommandFactory; +import org.springframework.cloud.netflix.zuul.filters.route.RibbonCommandFactory; +import org.springframework.cloud.netflix.zuul.filters.route.ZuulFallbackProvider; +import org.springframework.cloud.netflix.zuul.filters.route.apache.HttpClientRibbonCommandFactory; +import org.springframework.cloud.netflix.zuul.filters.route.okhttp.OkHttpRibbonCommandFactory; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Conditional; +import org.springframework.context.annotation.Configuration; + +/** + * @author Dave Syer + * + */ +public class RibbonCommandFactoryConfiguration { + + @Configuration + @ConditionalOnRibbonRestClient + protected static class RestClientRibbonConfiguration { + + @Autowired(required = false) + private Set zuulFallbackProviders = Collections.emptySet(); + + @Bean + @ConditionalOnMissingBean + public RibbonCommandFactory ribbonCommandFactory( + SpringClientFactory clientFactory, ZuulProperties zuulProperties) { + return new RestClientRibbonCommandFactory(clientFactory, zuulProperties, + zuulFallbackProviders); + } + } + + @Configuration + @ConditionalOnRibbonOkHttpClient + @ConditionalOnClass(name = "okhttp3.OkHttpClient") + protected static class OkHttpRibbonConfiguration { + + @Autowired(required = false) + private Set zuulFallbackProviders = Collections.emptySet(); + + @Bean + @ConditionalOnMissingBean + public RibbonCommandFactory ribbonCommandFactory( + SpringClientFactory clientFactory, ZuulProperties zuulProperties) { + return new OkHttpRibbonCommandFactory(clientFactory, zuulProperties, + zuulFallbackProviders); + } + } + + @Configuration + @ConditionalOnRibbonHttpClient + protected static class HttpClientRibbonConfiguration { + + @Autowired(required = false) + private Set zuulFallbackProviders = Collections.emptySet(); + + @Bean + @ConditionalOnMissingBean + public RibbonCommandFactory ribbonCommandFactory( + SpringClientFactory clientFactory, ZuulProperties zuulProperties) { + return new HttpClientRibbonCommandFactory(clientFactory, zuulProperties, zuulFallbackProviders); + } + } + + @Target({ ElementType.TYPE, ElementType.METHOD }) + @Retention(RetentionPolicy.RUNTIME) + @Documented + @Conditional(OnRibbonHttpClientCondition.class) + @interface ConditionalOnRibbonHttpClient { } + + private static class OnRibbonHttpClientCondition extends AnyNestedCondition { + public OnRibbonHttpClientCondition() { + super(ConfigurationPhase.PARSE_CONFIGURATION); + } + + @Deprecated //remove in Edgware" + @ConditionalOnProperty(name = "zuul.ribbon.httpclient.enabled", matchIfMissing = true) + static class ZuulProperty {} + + @ConditionalOnProperty(name = "ribbon.httpclient.enabled", matchIfMissing = true) + static class RibbonProperty {} + } + + @Target({ ElementType.TYPE, ElementType.METHOD }) + @Retention(RetentionPolicy.RUNTIME) + @Documented + @Conditional(OnRibbonOkHttpClientCondition.class) + @interface ConditionalOnRibbonOkHttpClient { } + + private static class OnRibbonOkHttpClientCondition extends AnyNestedCondition { + public OnRibbonOkHttpClientCondition() { + super(ConfigurationPhase.PARSE_CONFIGURATION); + } + + @Deprecated //remove in Edgware" + @ConditionalOnProperty("zuul.ribbon.okhttp.enabled") + static class ZuulProperty {} + + @ConditionalOnProperty("ribbon.okhttp.enabled") + static class RibbonProperty {} + } + + @Target({ ElementType.TYPE, ElementType.METHOD }) + @Retention(RetentionPolicy.RUNTIME) + @Documented + @Conditional(OnRibbonRestClientCondition.class) + @interface ConditionalOnRibbonRestClient { } + + private static class OnRibbonRestClientCondition extends AnyNestedCondition { + public OnRibbonRestClientCondition() { + super(ConfigurationPhase.PARSE_CONFIGURATION); + } + + @Deprecated //remove in Edgware" + @ConditionalOnProperty("zuul.ribbon.restclient.enabled") + static class ZuulProperty {} + + @ConditionalOnProperty("ribbon.restclient.enabled") + static class RibbonProperty {} + } + +} diff --git a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/ZuulProxyConfiguration.java b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/ZuulProxyConfiguration.java index 11ee38b1b..40ea7a9cd 100644 --- a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/ZuulProxyConfiguration.java +++ b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/ZuulProxyConfiguration.java @@ -16,30 +16,21 @@ package org.springframework.cloud.netflix.zuul; -import java.lang.annotation.Documented; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; import java.util.Collections; import java.util.List; -import java.util.Set; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.actuate.endpoint.Endpoint; import org.springframework.boot.actuate.trace.TraceRepository; -import org.springframework.boot.autoconfigure.condition.AnyNestedCondition; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingClass; -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.cloud.client.actuator.HasFeatures; import org.springframework.cloud.client.discovery.DiscoveryClient; import org.springframework.cloud.client.discovery.event.HeartbeatEvent; import org.springframework.cloud.client.discovery.event.HeartbeatMonitor; import org.springframework.cloud.client.discovery.event.InstanceRegisteredEvent; import org.springframework.cloud.client.discovery.event.ParentHeartbeatEvent; -import org.springframework.cloud.netflix.ribbon.SpringClientFactory; import org.springframework.cloud.netflix.ribbon.support.RibbonRequestCustomizer; import org.springframework.cloud.netflix.zuul.filters.ProxyRequestHelper; import org.springframework.cloud.netflix.zuul.filters.RouteLocator; @@ -49,25 +40,24 @@ import org.springframework.cloud.netflix.zuul.filters.discovery.DiscoveryClientR import org.springframework.cloud.netflix.zuul.filters.discovery.ServiceRouteMapper; import org.springframework.cloud.netflix.zuul.filters.discovery.SimpleServiceRouteMapper; import org.springframework.cloud.netflix.zuul.filters.pre.PreDecorationFilter; -import org.springframework.cloud.netflix.zuul.filters.route.RestClientRibbonCommandFactory; import org.springframework.cloud.netflix.zuul.filters.route.RibbonCommandFactory; import org.springframework.cloud.netflix.zuul.filters.route.RibbonRoutingFilter; import org.springframework.cloud.netflix.zuul.filters.route.SimpleHostRoutingFilter; -import org.springframework.cloud.netflix.zuul.filters.route.ZuulFallbackProvider; -import org.springframework.cloud.netflix.zuul.filters.route.apache.HttpClientRibbonCommandFactory; -import org.springframework.cloud.netflix.zuul.filters.route.okhttp.OkHttpRibbonCommandFactory; import org.springframework.cloud.netflix.zuul.web.ZuulHandlerMapping; import org.springframework.context.ApplicationEvent; import org.springframework.context.ApplicationListener; import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Conditional; import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Import; /** * @author Spencer Gibb * @author Dave Syer */ @Configuration +@Import({ RibbonCommandFactoryConfiguration.RestClientRibbonConfiguration.class, + RibbonCommandFactoryConfiguration.OkHttpRibbonConfiguration.class, + RibbonCommandFactoryConfiguration.HttpClientRibbonConfiguration.class }) public class ZuulProxyConfiguration extends ZuulConfiguration { @SuppressWarnings("rawtypes") @@ -89,135 +79,27 @@ public class ZuulProxyConfiguration extends ZuulConfiguration { @Override @ConditionalOnMissingBean(RouteLocator.class) public DiscoveryClientRouteLocator routeLocator() { - return new DiscoveryClientRouteLocator(this.server.getServletPrefix(), - this.discovery, this.zuulProperties, this.serviceRouteMapper); - } - - @Configuration - @ConditionalOnRibbonHttpClient - protected static class HttpClientRibbonConfiguration { - - @Autowired(required = false) - private Set zuulFallbackProviders = Collections.emptySet(); - - @Bean - @ConditionalOnMissingBean - public RibbonCommandFactory ribbonCommandFactory( - SpringClientFactory clientFactory, ZuulProperties zuulProperties) { - return new HttpClientRibbonCommandFactory(clientFactory, zuulProperties, zuulFallbackProviders); - } - } - - @Configuration - @ConditionalOnRibbonRestClient - protected static class RestClientRibbonConfiguration { - - @Autowired(required = false) - private Set zuulFallbackProviders = Collections.emptySet(); - - @Bean - @ConditionalOnMissingBean - public RibbonCommandFactory ribbonCommandFactory( - SpringClientFactory clientFactory, ZuulProperties zuulProperties) { - return new RestClientRibbonCommandFactory(clientFactory, zuulProperties, - zuulFallbackProviders); - } - } - - @Configuration - @ConditionalOnRibbonOkHttpClient - @ConditionalOnClass(name = "okhttp3.OkHttpClient") - protected static class OkHttpRibbonConfiguration { - - @Autowired(required = false) - private Set zuulFallbackProviders = Collections.emptySet(); - - @Bean - @ConditionalOnMissingBean - public RibbonCommandFactory ribbonCommandFactory( - SpringClientFactory clientFactory, ZuulProperties zuulProperties) { - return new OkHttpRibbonCommandFactory(clientFactory, zuulProperties, - zuulFallbackProviders); - } - } - - @Target({ ElementType.TYPE, ElementType.METHOD }) - @Retention(RetentionPolicy.RUNTIME) - @Documented - @Conditional(OnRibbonHttpClientCondition.class) - @interface ConditionalOnRibbonHttpClient { } - - private static class OnRibbonHttpClientCondition extends AnyNestedCondition { - public OnRibbonHttpClientCondition() { - super(ConfigurationPhase.REGISTER_BEAN); - } - - @Deprecated //remove in Edgware" - @ConditionalOnProperty(name = "zuul.ribbon.httpclient.enabled", matchIfMissing = true) - static class ZuulProperty {} - - @ConditionalOnProperty(name = "ribbon.httpclient.enabled", matchIfMissing = true) - static class RibbonProperty {} - } - - @Target({ ElementType.TYPE, ElementType.METHOD }) - @Retention(RetentionPolicy.RUNTIME) - @Documented - @Conditional(OnRibbonOkHttpClientCondition.class) - @interface ConditionalOnRibbonOkHttpClient { } - - private static class OnRibbonOkHttpClientCondition extends AnyNestedCondition { - public OnRibbonOkHttpClientCondition() { - super(ConfigurationPhase.REGISTER_BEAN); - } - - @Deprecated //remove in Edgware" - @ConditionalOnProperty("zuul.ribbon.okhttp.enabled") - static class ZuulProperty {} - - @ConditionalOnProperty("ribbon.okhttp.enabled") - static class RibbonProperty {} - } - - @Target({ ElementType.TYPE, ElementType.METHOD }) - @Retention(RetentionPolicy.RUNTIME) - @Documented - @Conditional(OnRibbonRestClientCondition.class) - @interface ConditionalOnRibbonRestClient { } - - private static class OnRibbonRestClientCondition extends AnyNestedCondition { - public OnRibbonRestClientCondition() { - super(ConfigurationPhase.REGISTER_BEAN); - } - - @Deprecated //remove in Edgware" - @ConditionalOnProperty("zuul.ribbon.restclient.enabled") - static class ZuulProperty {} - - @ConditionalOnProperty("ribbon.restclient.enabled") - static class RibbonProperty {} + return new DiscoveryClientRouteLocator(this.server.getServletPrefix(), this.discovery, this.zuulProperties, + this.serviceRouteMapper); } // pre filters @Bean - public PreDecorationFilter preDecorationFilter(RouteLocator routeLocator, - ProxyRequestHelper proxyRequestHelper) { - return new PreDecorationFilter(routeLocator, this.server.getServletPrefix(), - this.zuulProperties, proxyRequestHelper); + public PreDecorationFilter preDecorationFilter(RouteLocator routeLocator, ProxyRequestHelper proxyRequestHelper) { + return new PreDecorationFilter(routeLocator, this.server.getServletPrefix(), this.zuulProperties, + proxyRequestHelper); } // route filters @Bean public RibbonRoutingFilter ribbonRoutingFilter(ProxyRequestHelper helper, RibbonCommandFactory ribbonCommandFactory) { - RibbonRoutingFilter filter = new RibbonRoutingFilter(helper, ribbonCommandFactory, - this.requestCustomizers); + RibbonRoutingFilter filter = new RibbonRoutingFilter(helper, ribbonCommandFactory, this.requestCustomizers); return filter; } @Bean - public SimpleHostRoutingFilter simpleHostRoutingFilter(ProxyRequestHelper helper, - ZuulProperties zuulProperties) { + public SimpleHostRoutingFilter simpleHostRoutingFilter(ProxyRequestHelper helper, ZuulProperties zuulProperties) { return new SimpleHostRoutingFilter(helper, zuulProperties); } @@ -270,8 +152,7 @@ public class ZuulProxyConfiguration extends ZuulConfiguration { } } - private static class ZuulDiscoveryRefreshListener - implements ApplicationListener { + private static class ZuulDiscoveryRefreshListener implements ApplicationListener { private HeartbeatMonitor monitor = new HeartbeatMonitor(); From a38b7b71ac8be9608ac2530dac41cd6298d696cf Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Tue, 25 Oct 2016 12:56:49 +0100 Subject: [PATCH 34/48] Append to X-Forwarded-* headers instead of replacing them This fixes most of the issues people encounter when there are multiple proxies in the request. The tricky thing is that there is another header "Forwarded" that we don't recognize, but which backends probably do, at least some of the time (since it is from an actual RFC). The problem is that "Forwarded" does not contain the ports, so Spring UriComponentsBuilder cannot use it to rewrite links to a specific port. Since we do not support it already, this change doesn't make things any worse, but the corner case is there still. --- .../zuul/filters/pre/PreDecorationFilter.java | 30 +++++++++++++++++-- .../filters/pre/PreDecorationFilterTests.java | 17 +++++++++++ 2 files changed, 44 insertions(+), 3 deletions(-) diff --git a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/filters/pre/PreDecorationFilter.java b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/filters/pre/PreDecorationFilter.java index 1b5bd474d..1f65218fa 100644 --- a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/filters/pre/PreDecorationFilter.java +++ b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/filters/pre/PreDecorationFilter.java @@ -163,15 +163,39 @@ public class PreDecorationFilter extends ZuulFilter { } private void addProxyHeaders(RequestContext ctx, Route route) { - String host = toHostHeader(ctx.getRequest()); - String port = String.valueOf(ctx.getRequest().getServerPort()); - String proto = ctx.getRequest().getScheme(); + HttpServletRequest request = ctx.getRequest(); + String host = toHostHeader(request); + String port = String.valueOf(request.getServerPort()); + String proto = request.getScheme(); + if (hasHeader(request, "X-Forwarded-Host")) { + host = request.getHeader("X-Forwarded-Host") + "," + host; + if (!hasHeader(request, "X-Forwarded-Port")) { + if (hasHeader(request, "X-Forwarded-Proto")) { + StringBuilder builder = new StringBuilder(); + for (String previous : StringUtils.commaDelimitedListToStringArray(request.getHeader("X-Forwarded-Proto"))) { + if (builder.length()>0) { + builder.append(","); + } + builder.append("https".equals(previous) ? "443" : "80"); + } + builder.append(",").append(port); + port = builder.toString(); + } + } else { + port = request.getHeader("X-Forwarded-Port") + "," + port; + } + proto = request.getHeader("X-Forwarded-Proto") + "," + proto; + } ctx.addZuulRequestHeader("X-Forwarded-Host", host); ctx.addZuulRequestHeader("X-Forwarded-Port", port); ctx.addZuulRequestHeader(ZuulHeaders.X_FORWARDED_PROTO, proto); addProxyPrefix(ctx, route); } + private boolean hasHeader(HttpServletRequest request, String name) { + return StringUtils.hasLength(request.getHeader(name)); + } + private void addProxyPrefix(RequestContext ctx, Route route) { String forwardedPrefix = ctx.getRequest().getHeader("X-Forwarded-Prefix"); String contextPath = ctx.getRequest().getContextPath(); diff --git a/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/zuul/filters/pre/PreDecorationFilterTests.java b/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/zuul/filters/pre/PreDecorationFilterTests.java index 940634ff1..b07b43a28 100644 --- a/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/zuul/filters/pre/PreDecorationFilterTests.java +++ b/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/zuul/filters/pre/PreDecorationFilterTests.java @@ -103,6 +103,23 @@ public class PreDecorationFilterTests { assertEquals("localhost:8080", ctx.getZuulRequestHeaders().get("x-forwarded-host")); } + @Test + public void xForwardedHostAppends() throws Exception { + this.properties.setPrefix("/api"); + this.request.setRequestURI("/api/foo/1"); + this.request.setRemoteAddr("5.6.7.8"); + this.request.setServerPort(8080); + this.request.addHeader("X-Forwarded-Host", "example.com"); + this.request.addHeader("X-Forwarded-Proto", "https"); + this.routeLocator.addRoute( + new ZuulRoute("foo", "/foo/**", "foo", null, false, null, null)); + this.filter.run(); + RequestContext ctx = RequestContext.getCurrentContext(); + assertEquals("example.com,localhost:8080", ctx.getZuulRequestHeaders().get("x-forwarded-host")); + assertEquals("443,8080", ctx.getZuulRequestHeaders().get("x-forwarded-port")); + assertEquals("https,http", ctx.getZuulRequestHeaders().get("x-forwarded-proto")); + } + @Test public void hostHeaderSet() throws Exception { this.properties.setPrefix("/api"); From 7f075d11ee56d57fa1a38a7d02555f9b8c3ed95e Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Tue, 25 Oct 2016 14:06:16 +0100 Subject: [PATCH 35/48] Allow Cors requests through to backend by default Instead of blocking them (which is the default behaviour of a Spring MVC controller) Cors requests will flow through the Zuul filters by default. Users can control it by grabbing the ZuulHandlerMapping in a @PostConstruct and injecting some CorsConfiguration via its setCorsConfigurations() method. --- .../netflix/zuul/web/ZuulController.java | 5 ++- .../netflix/zuul/web/ZuulHandlerMapping.java | 18 ++++++-- .../ServletPathZuulProxyApplicationTests.java | 45 ++++++++++++++++--- 3 files changed, 57 insertions(+), 11 deletions(-) diff --git a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/web/ZuulController.java b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/web/ZuulController.java index 8f5d4b1d5..d8fe936d1 100644 --- a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/web/ZuulController.java +++ b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/web/ZuulController.java @@ -37,9 +37,10 @@ public class ZuulController extends ServletWrappingController { } @Override - protected ModelAndView handleRequestInternal(HttpServletRequest request, - HttpServletResponse response) throws Exception { + public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception { try { + // We don't care about the other features of the base class, just want to + // handle the request return super.handleRequestInternal(request, response); } finally { diff --git a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/web/ZuulHandlerMapping.java b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/web/ZuulHandlerMapping.java index af81c9ae1..c1e6dd540 100644 --- a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/web/ZuulHandlerMapping.java +++ b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/web/ZuulHandlerMapping.java @@ -25,6 +25,8 @@ import org.springframework.cloud.netflix.zuul.filters.RefreshableRouteLocator; import org.springframework.cloud.netflix.zuul.filters.Route; import org.springframework.cloud.netflix.zuul.filters.RouteLocator; import org.springframework.util.PatternMatchUtils; +import org.springframework.web.cors.CorsConfiguration; +import org.springframework.web.servlet.HandlerExecutionChain; import org.springframework.web.servlet.handler.AbstractUrlHandlerMapping; import com.netflix.zuul.context.RequestContext; @@ -51,6 +53,16 @@ public class ZuulHandlerMapping extends AbstractUrlHandlerMapping { setOrder(-200); } + @Override + protected HandlerExecutionChain getCorsHandlerExecutionChain(HttpServletRequest request, + HandlerExecutionChain chain, CorsConfiguration config) { + if (config == null) { + // Allow CORS requests to go to the backend + return chain; + } + return super.getCorsHandlerExecutionChain(request, chain, config); + } + public void setErrorController(ErrorController errorController) { this.errorController = errorController; } @@ -63,10 +75,8 @@ public class ZuulHandlerMapping extends AbstractUrlHandlerMapping { } @Override - protected Object lookupHandler(String urlPath, HttpServletRequest request) - throws Exception { - if (this.errorController != null - && urlPath.equals(this.errorController.getErrorPath())) { + protected Object lookupHandler(String urlPath, HttpServletRequest request) throws Exception { + if (this.errorController != null && urlPath.equals(this.errorController.getErrorPath())) { return null; } String[] ignored = this.routeLocator.getIgnoredPaths().toArray(new String[0]); diff --git a/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/zuul/ServletPathZuulProxyApplicationTests.java b/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/zuul/ServletPathZuulProxyApplicationTests.java index 9b103cce7..eb14d9110 100644 --- a/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/zuul/ServletPathZuulProxyApplicationTests.java +++ b/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/zuul/ServletPathZuulProxyApplicationTests.java @@ -18,6 +18,9 @@ package org.springframework.cloud.netflix.zuul; import static org.junit.Assert.assertEquals; +import java.net.URI; +import java.net.URISyntaxException; + import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -33,13 +36,16 @@ import org.springframework.context.annotation.Configuration; import org.springframework.http.HttpEntity; import org.springframework.http.HttpMethod; import org.springframework.http.HttpStatus; +import org.springframework.http.RequestEntity; import org.springframework.http.ResponseEntity; import org.springframework.test.annotation.DirtiesContext; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.web.bind.annotation.CrossOrigin; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.client.RestClientException; import com.netflix.zuul.context.RequestContext; @@ -68,9 +74,38 @@ public class ServletPathZuulProxyApplicationTests { public void getOnSelfViaSimpleHostRoutingFilter() { this.routes.addRoute("/self/**", "http://localhost:" + this.port + "/app/local"); this.endpoint.reset(); + ResponseEntity result = new TestRestTemplate().exchange("http://localhost:" + this.port + "/app/self/1", + HttpMethod.GET, new HttpEntity<>((Void) null), String.class); + assertEquals(HttpStatus.OK, result.getStatusCode()); + assertEquals("Gotten 1!", result.getBody()); + } + + @Test + public void optionsOnRawEndpoint() throws Exception { + ResponseEntity result = new TestRestTemplate().exchange(RequestEntity + .options(new URI("http://localhost:" + this.port + "/app/local/1")) + .header("Origin", "http://localhost:9000").header("Access-Control-Request-Method", "GET").build(), + String.class); + assertEquals(HttpStatus.OK, result.getStatusCode()); + assertEquals("http://localhost:9000", result.getHeaders().getFirst("Access-Control-Allow-Origin")); + } + + @Test + public void optionsOnSelf() throws Exception { + this.routes.addRoute("/self/**", "http://localhost:" + this.port + "/app/local"); + this.endpoint.reset(); + ResponseEntity result = new TestRestTemplate().exchange(RequestEntity + .options(new URI("http://localhost:" + this.port + "/app/self/1")) + .header("Origin", "http://localhost:9000").header("Access-Control-Request-Method", "GET").build(), + String.class); + assertEquals(HttpStatus.OK, result.getStatusCode()); + assertEquals("http://localhost:9000", result.getHeaders().getFirst("Access-Control-Allow-Origin")); + } + + @Test + public void contentOnRawEndpoint() throws Exception { ResponseEntity result = new TestRestTemplate().exchange( - "http://localhost:" + this.port + "/app/self/1", HttpMethod.GET, - new HttpEntity<>((Void) null), String.class); + RequestEntity.get(new URI("http://localhost:" + this.port + "/app/local/1")).build(), String.class); assertEquals(HttpStatus.OK, result.getStatusCode()); assertEquals("Gotten 1!", result.getBody()); } @@ -80,9 +115,8 @@ public class ServletPathZuulProxyApplicationTests { this.routes.addRoute(new ZuulRoute("strip", "/strip/**", "strip", "http://localhost:" + this.port + "/app/local", false, false, null)); this.endpoint.reset(); - ResponseEntity result = new TestRestTemplate().exchange( - "http://localhost:" + this.port + "/app/strip", HttpMethod.GET, - new HttpEntity<>((Void) null), String.class); + ResponseEntity result = new TestRestTemplate().exchange("http://localhost:" + this.port + "/app/strip", + HttpMethod.GET, new HttpEntity<>((Void) null), String.class); assertEquals(HttpStatus.OK, result.getStatusCode()); // Prefix not stripped to it goes to /local/strip assertEquals("Gotten strip!", result.getBody()); @@ -96,6 +130,7 @@ public class ServletPathZuulProxyApplicationTests { static class ServletPathZuulProxyApplication { @RequestMapping(value = "/local/{id}", method = RequestMethod.GET) + @CrossOrigin(origins = "*") public String get(@PathVariable String id) { return "Gotten " + id + "!"; } From 2dfee97563b4a0658507add6984c152f5e2a7098 Mon Sep 17 00:00:00 2001 From: Ryan Baxter Date: Tue, 25 Oct 2016 12:56:08 -0400 Subject: [PATCH 36/48] Resolve spring.application.name value via a property resolver instead of @Value. Fixes #1398 --- .../eureka/EurekaClientAutoConfiguration.java | 8 +++++ .../eureka/EurekaInstanceConfigBean.java | 33 +++++++++---------- .../eureka/EurekaInstanceConfigBeanTests.java | 25 ++++++++++++-- .../netflix/sidecar/SidecarConfiguration.java | 13 ++++++-- 4 files changed, 57 insertions(+), 22 deletions(-) diff --git a/spring-cloud-netflix-eureka-client/src/main/java/org/springframework/cloud/netflix/eureka/EurekaClientAutoConfiguration.java b/spring-cloud-netflix-eureka-client/src/main/java/org/springframework/cloud/netflix/eureka/EurekaClientAutoConfiguration.java index 9f6e5c26c..0d6784453 100644 --- a/spring-cloud-netflix-eureka-client/src/main/java/org/springframework/cloud/netflix/eureka/EurekaClientAutoConfiguration.java +++ b/spring-cloud-netflix-eureka-client/src/main/java/org/springframework/cloud/netflix/eureka/EurekaClientAutoConfiguration.java @@ -64,6 +64,7 @@ import static org.springframework.cloud.commons.util.IdUtils.getDefaultInstanceI * @author Spencer Gibb * @author Jon Schneider * @author Matt Jenkins + * @author Ryan Baxter */ @Configuration @EnableConfigurationProperties @@ -107,9 +108,16 @@ public class EurekaClientAutoConfiguration { @ConditionalOnMissingBean(value = EurekaInstanceConfig.class, search = SearchStrategy.CURRENT) public EurekaInstanceConfigBean eurekaInstanceConfigBean(InetUtils inetUtils) { RelaxedPropertyResolver relaxedPropertyResolver = new RelaxedPropertyResolver(env, "eureka.instance."); + RelaxedPropertyResolver springPropertyResolver = new RelaxedPropertyResolver(env, "spring.application."); + String springAppName = springPropertyResolver.getProperty("name"); EurekaInstanceConfigBean instance = new EurekaInstanceConfigBean(inetUtils); instance.setNonSecurePort(this.nonSecurePort); instance.setInstanceId(getDefaultInstanceId(this.env)); + if(springAppName != null) { + instance.setAppname(springAppName); + instance.setVirtualHostName(springAppName); + instance.setSecureVirtualHostName(springAppName); + } if (this.managementPort != this.nonSecurePort && this.managementPort != 0) { if (StringUtils.hasText(this.hostname)) { instance.setHostname(this.hostname); diff --git a/spring-cloud-netflix-eureka-client/src/main/java/org/springframework/cloud/netflix/eureka/EurekaInstanceConfigBean.java b/spring-cloud-netflix-eureka-client/src/main/java/org/springframework/cloud/netflix/eureka/EurekaInstanceConfigBean.java index cf4cc1854..dbbb07269 100644 --- a/spring-cloud-netflix-eureka-client/src/main/java/org/springframework/cloud/netflix/eureka/EurekaInstanceConfigBean.java +++ b/spring-cloud-netflix-eureka-client/src/main/java/org/springframework/cloud/netflix/eureka/EurekaInstanceConfigBean.java @@ -16,31 +16,31 @@ package org.springframework.cloud.netflix.eureka; -import java.util.HashMap; -import java.util.Map; - -import org.springframework.beans.factory.annotation.Value; -import org.springframework.boot.context.properties.ConfigurationProperties; -import org.springframework.cloud.commons.util.InetUtils; -import org.springframework.cloud.commons.util.InetUtils.HostInfo; - -import com.netflix.appinfo.DataCenterInfo; -import com.netflix.appinfo.InstanceInfo.InstanceStatus; -import com.netflix.appinfo.MyDataCenterInfo; - import lombok.AccessLevel; import lombok.Data; import lombok.Getter; import lombok.Setter; +import java.util.HashMap; +import java.util.Map; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.cloud.commons.util.InetUtils; +import org.springframework.cloud.commons.util.InetUtils.HostInfo; +import com.netflix.appinfo.DataCenterInfo; +import com.netflix.appinfo.InstanceInfo.InstanceStatus; +import com.netflix.appinfo.MyDataCenterInfo; + /** * @author Dave Syer * @author Spencer Gibb + * @author Ryan Baxter */ @Data @ConfigurationProperties("eureka.instance") public class EurekaInstanceConfigBean implements CloudEurekaInstanceConfig { + private static final String UNKNOWN = "unknown"; + @Getter(AccessLevel.PRIVATE) @Setter(AccessLevel.PRIVATE) private HostInfo hostInfo; @@ -52,8 +52,7 @@ public class EurekaInstanceConfigBean implements CloudEurekaInstanceConfig { /** * Get the name of the application to be registered with eureka. */ - @Value("${spring.application.name:unknown}") - private String appname = "unknown"; + private String appname = UNKNOWN; /** * Get the name of the application group to be registered with eureka. @@ -119,8 +118,7 @@ public class EurekaInstanceConfigBean implements CloudEurekaInstanceConfig { * virtual host name.Think of this as similar to the fully qualified domain name, that * the users of your services will need to find this instance. */ - @Value("${spring.application.name:unknown}") - private String virtualHostName; + private String virtualHostName = UNKNOWN; /** * Get the unique Id (within the scope of the appName) of this instance to be @@ -135,8 +133,7 @@ public class EurekaInstanceConfigBean implements CloudEurekaInstanceConfig { * secure virtual host name.Think of this as similar to the fully qualified domain * name, that the users of your services will need to find this instance. */ - @Value("${spring.application.name:unknown}") - private String secureVirtualHostName; + private String secureVirtualHostName = UNKNOWN; /** * Gets the AWS autoscaling group name associated with this instance. This information diff --git a/spring-cloud-netflix-eureka-client/src/test/java/org/springframework/cloud/netflix/eureka/EurekaInstanceConfigBeanTests.java b/spring-cloud-netflix-eureka-client/src/test/java/org/springframework/cloud/netflix/eureka/EurekaInstanceConfigBeanTests.java index 0f3f99b62..bb745e2b1 100644 --- a/spring-cloud-netflix-eureka-client/src/test/java/org/springframework/cloud/netflix/eureka/EurekaInstanceConfigBeanTests.java +++ b/spring-cloud-netflix-eureka-client/src/test/java/org/springframework/cloud/netflix/eureka/EurekaInstanceConfigBeanTests.java @@ -20,15 +20,17 @@ import org.junit.After; import org.junit.Before; import org.junit.Test; import org.springframework.beans.factory.BeanCreationException; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.PropertyPlaceholderAutoConfiguration; +import org.springframework.boot.bind.RelaxedPropertyResolver; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.cloud.commons.util.InetUtils; import org.springframework.cloud.commons.util.InetUtilsProperties; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.core.env.ConfigurableEnvironment; import org.springframework.test.util.ReflectionTestUtils; - import com.netflix.appinfo.InstanceInfo.InstanceStatus; import static org.junit.Assert.assertEquals; @@ -38,6 +40,7 @@ import static org.springframework.boot.test.util.EnvironmentTestUtils.addEnviron /** * @author Dave Syer * @author Spencer Gibb + * @author Ryan Baxter */ public class EurekaInstanceConfigBeanTests { @@ -185,6 +188,14 @@ public class EurekaInstanceConfigBeanTests { } + @Test + public void testDefaultAppName() throws Exception { + setupContext(); + assertEquals("default app name is wrong", "unknown", getInstanceConfig().getAppname()); + assertEquals("default virtual hostname is wrong", "unknown", getInstanceConfig().getVirtualHostName()); + assertEquals("default secure virtual hostname is wrong", "unknown", getInstanceConfig().getSecureVirtualHostName()); + } + private void setupContext() { this.context.register(PropertyPlaceholderAutoConfiguration.class, TestConfiguration.class); @@ -198,9 +209,19 @@ public class EurekaInstanceConfigBeanTests { @Configuration @EnableConfigurationProperties protected static class TestConfiguration { + @Autowired + ConfigurableEnvironment env; @Bean public EurekaInstanceConfigBean eurekaInstanceConfigBean() { - return new EurekaInstanceConfigBean(new InetUtils(new InetUtilsProperties())); + EurekaInstanceConfigBean configBean = new EurekaInstanceConfigBean(new InetUtils(new InetUtilsProperties())); + RelaxedPropertyResolver springPropertyResolver = new RelaxedPropertyResolver(env, "spring.application."); + String springAppName = springPropertyResolver.getProperty("name"); + if(springAppName != null) { + configBean.setSecureVirtualHostName(springAppName); + configBean.setVirtualHostName(springAppName); + configBean.setAppname(springAppName); + } + return configBean; } } diff --git a/spring-cloud-netflix-sidecar/src/main/java/org/springframework/cloud/netflix/sidecar/SidecarConfiguration.java b/spring-cloud-netflix-sidecar/src/main/java/org/springframework/cloud/netflix/sidecar/SidecarConfiguration.java index 52357293b..17db83f53 100644 --- a/spring-cloud-netflix-sidecar/src/main/java/org/springframework/cloud/netflix/sidecar/SidecarConfiguration.java +++ b/spring-cloud-netflix-sidecar/src/main/java/org/springframework/cloud/netflix/sidecar/SidecarConfiguration.java @@ -16,10 +16,13 @@ package org.springframework.cloud.netflix.sidecar; +import static org.springframework.cloud.commons.util.IdUtils.getDefaultInstanceId; + import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.boot.bind.RelaxedPropertyResolver; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.cloud.client.actuator.HasFeatures; import org.springframework.cloud.commons.util.InetUtils; @@ -32,10 +35,9 @@ import org.springframework.util.StringUtils; import com.netflix.appinfo.HealthCheckHandler; import com.netflix.discovery.EurekaClientConfig; -import static org.springframework.cloud.commons.util.IdUtils.getDefaultInstanceId; - /** * @author Spencer Gibb + * @author Ryan Baxter */ @Configuration @EnableConfigurationProperties @@ -73,9 +75,16 @@ public class SidecarConfiguration { @Bean public EurekaInstanceConfigBean eurekaInstanceConfigBean() { EurekaInstanceConfigBean config = new EurekaInstanceConfigBean(inetUtils); + RelaxedPropertyResolver springPropertyResolver = new RelaxedPropertyResolver(env, "spring.application."); + String springAppName = springPropertyResolver.getProperty("name"); int port = this.sidecarProperties.getPort(); config.setNonSecurePort(port); config.setInstanceId(getDefaultInstanceId(this.env)); + if(StringUtils.hasText(springAppName)) { + config.setAppname(springAppName); + config.setVirtualHostName(springAppName); + config.setSecureVirtualHostName(springAppName); + } if (StringUtils.hasText(this.hostname)) { config.setHostname(this.hostname); } From 81959b5ef3e0ec7738a79fdef923caa8e31a51cc Mon Sep 17 00:00:00 2001 From: Spencer Gibb Date: Tue, 25 Oct 2016 11:24:42 -0600 Subject: [PATCH 37/48] Use new FilterRegistrationBean package. Breaks Spring Boot 1.3 compatibility, enables 1.5 --- .../cloud/netflix/eureka/server/EurekaServerConfiguration.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/spring-cloud-netflix-eureka-server/src/main/java/org/springframework/cloud/netflix/eureka/server/EurekaServerConfiguration.java b/spring-cloud-netflix-eureka-server/src/main/java/org/springframework/cloud/netflix/eureka/server/EurekaServerConfiguration.java index e5fae1611..73d4571fa 100644 --- a/spring-cloud-netflix-eureka-server/src/main/java/org/springframework/cloud/netflix/eureka/server/EurekaServerConfiguration.java +++ b/spring-cloud-netflix-eureka-server/src/main/java/org/springframework/cloud/netflix/eureka/server/EurekaServerConfiguration.java @@ -28,12 +28,11 @@ import javax.ws.rs.ext.Provider; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; -import org.springframework.boot.context.embedded.FilterRegistrationBean; import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.cloud.client.actuator.HasFeatures; import org.springframework.cloud.client.discovery.EnableDiscoveryClient; import org.springframework.cloud.netflix.eureka.EurekaConstants; From 85b2fe37e235013df7d5fa052aacf37f9374ced3 Mon Sep 17 00:00:00 2001 From: Ryan Baxter Date: Tue, 25 Oct 2016 13:54:29 -0400 Subject: [PATCH 38/48] Added some additional tests --- .../eureka/EurekaClientAutoConfiguration.java | 2 +- .../EurekaClientAutoConfigurationTests.java | 17 +++++++++++++++++ .../eureka/EurekaInstanceConfigBeanTests.java | 3 ++- 3 files changed, 20 insertions(+), 2 deletions(-) diff --git a/spring-cloud-netflix-eureka-client/src/main/java/org/springframework/cloud/netflix/eureka/EurekaClientAutoConfiguration.java b/spring-cloud-netflix-eureka-client/src/main/java/org/springframework/cloud/netflix/eureka/EurekaClientAutoConfiguration.java index 0d6784453..46b0f1fde 100644 --- a/spring-cloud-netflix-eureka-client/src/main/java/org/springframework/cloud/netflix/eureka/EurekaClientAutoConfiguration.java +++ b/spring-cloud-netflix-eureka-client/src/main/java/org/springframework/cloud/netflix/eureka/EurekaClientAutoConfiguration.java @@ -113,7 +113,7 @@ public class EurekaClientAutoConfiguration { EurekaInstanceConfigBean instance = new EurekaInstanceConfigBean(inetUtils); instance.setNonSecurePort(this.nonSecurePort); instance.setInstanceId(getDefaultInstanceId(this.env)); - if(springAppName != null) { + if(StringUtils.hasText(springAppName)) { instance.setAppname(springAppName); instance.setVirtualHostName(springAppName); instance.setSecureVirtualHostName(springAppName); diff --git a/spring-cloud-netflix-eureka-client/src/test/java/org/springframework/cloud/netflix/eureka/EurekaClientAutoConfigurationTests.java b/spring-cloud-netflix-eureka-client/src/test/java/org/springframework/cloud/netflix/eureka/EurekaClientAutoConfigurationTests.java index c1a159150..5d97b5989 100644 --- a/spring-cloud-netflix-eureka-client/src/test/java/org/springframework/cloud/netflix/eureka/EurekaClientAutoConfigurationTests.java +++ b/spring-cloud-netflix-eureka-client/src/test/java/org/springframework/cloud/netflix/eureka/EurekaClientAutoConfigurationTests.java @@ -189,6 +189,23 @@ public class EurekaClientAutoConfigurationTests { // Mockito.verify(http).addFilter(Matchers.any(HTTPBasicAuthFilter.class)); } + @Test + public void testDefaultAppName() throws Exception { + setupContext(); + assertEquals("unknown", getInstanceConfig().getAppname()); + assertEquals("unknown", getInstanceConfig().getVirtualHostName()); + assertEquals("unknown", getInstanceConfig().getSecureVirtualHostName()); + } + + @Test + public void testAppName() throws Exception { + EnvironmentTestUtils.addEnvironment(this.context, "spring.application.name=mytest"); + setupContext(); + assertEquals("mytest", getInstanceConfig().getAppname()); + assertEquals("mytest", getInstanceConfig().getVirtualHostName()); + assertEquals("mytest", getInstanceConfig().getSecureVirtualHostName()); + } + private void testNonSecurePort(String propName) { addEnvironment(this.context, propName + ":8888"); setupContext(); diff --git a/spring-cloud-netflix-eureka-client/src/test/java/org/springframework/cloud/netflix/eureka/EurekaInstanceConfigBeanTests.java b/spring-cloud-netflix-eureka-client/src/test/java/org/springframework/cloud/netflix/eureka/EurekaInstanceConfigBeanTests.java index bb745e2b1..284388dd5 100644 --- a/spring-cloud-netflix-eureka-client/src/test/java/org/springframework/cloud/netflix/eureka/EurekaInstanceConfigBeanTests.java +++ b/spring-cloud-netflix-eureka-client/src/test/java/org/springframework/cloud/netflix/eureka/EurekaInstanceConfigBeanTests.java @@ -31,6 +31,7 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.env.ConfigurableEnvironment; import org.springframework.test.util.ReflectionTestUtils; +import org.springframework.util.StringUtils; import com.netflix.appinfo.InstanceInfo.InstanceStatus; import static org.junit.Assert.assertEquals; @@ -216,7 +217,7 @@ public class EurekaInstanceConfigBeanTests { EurekaInstanceConfigBean configBean = new EurekaInstanceConfigBean(new InetUtils(new InetUtilsProperties())); RelaxedPropertyResolver springPropertyResolver = new RelaxedPropertyResolver(env, "spring.application."); String springAppName = springPropertyResolver.getProperty("name"); - if(springAppName != null) { + if(StringUtils.hasText(springAppName)) { configBean.setSecureVirtualHostName(springAppName); configBean.setVirtualHostName(springAppName); configBean.setAppname(springAppName); From aef753a3a09d48086dc1391eb4c51a2a74b2b15a Mon Sep 17 00:00:00 2001 From: Venil Noronha Date: Tue, 25 Oct 2016 14:39:22 -0700 Subject: [PATCH 39/48] Adds Feign Logger factory interface (#1411) Fixes gh-1363 --- .../feign/DefaultFeignLoggerFactory.java | 38 ++++++ .../netflix/feign/FeignClientFactoryBean.java | 8 +- .../feign/FeignClientsConfiguration.java | 14 +- .../netflix/feign/FeignLoggerFactory.java | 36 +++++ .../feign/FeignLoggerFactoryTests.java | 126 ++++++++++++++++++ 5 files changed, 213 insertions(+), 9 deletions(-) create mode 100644 spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/feign/DefaultFeignLoggerFactory.java create mode 100644 spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/feign/FeignLoggerFactory.java create mode 100644 spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/feign/FeignLoggerFactoryTests.java diff --git a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/feign/DefaultFeignLoggerFactory.java b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/feign/DefaultFeignLoggerFactory.java new file mode 100644 index 000000000..d7ca25d18 --- /dev/null +++ b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/feign/DefaultFeignLoggerFactory.java @@ -0,0 +1,38 @@ +/* + * Copyright 2016 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.netflix.feign; + +import feign.Logger; +import feign.slf4j.Slf4jLogger; + +/** + * @author Venil Noronha + */ +public class DefaultFeignLoggerFactory implements FeignLoggerFactory { + + private Logger logger; + + public DefaultFeignLoggerFactory(Logger logger) { + this.logger = logger; + } + + @Override + public Logger create(Class type) { + return this.logger != null ? this.logger : new Slf4jLogger(type); + } + +} 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 e5fcffc7b..bf21845f3 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 @@ -39,7 +39,6 @@ import feign.Target.HardCodedTarget; import feign.codec.Decoder; import feign.codec.Encoder; import feign.codec.ErrorDecoder; -import feign.slf4j.Slf4jLogger; import lombok.Data; import lombok.EqualsAndHashCode; @@ -83,11 +82,8 @@ class FeignClientFactoryBean implements FactoryBean, InitializingBean, } protected Feign.Builder feign(FeignContext context) { - Logger logger = getOptional(context, Logger.class); - - if (logger == null) { - logger = new Slf4jLogger(this.type); - } + FeignLoggerFactory loggerFactory = get(context, FeignLoggerFactory.class); + Logger logger = loggerFactory.create(this.type); // @formatter:off Feign.Builder builder = get(context, Feign.Builder.class) diff --git a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/feign/FeignClientsConfiguration.java b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/feign/FeignClientsConfiguration.java index ee4cf5687..606cbbb52 100644 --- a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/feign/FeignClientsConfiguration.java +++ b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/feign/FeignClientsConfiguration.java @@ -19,7 +19,6 @@ package org.springframework.cloud.netflix.feign; import java.util.ArrayList; import java.util.List; -import org.apache.http.client.HttpClient; import org.springframework.beans.factory.ObjectFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; @@ -39,16 +38,16 @@ import org.springframework.format.support.FormattingConversionService; import com.netflix.hystrix.HystrixCommand; -import feign.Client; import feign.Contract; import feign.Feign; +import feign.Logger; import feign.codec.Decoder; import feign.codec.Encoder; -import feign.httpclient.ApacheHttpClient; import feign.hystrix.HystrixFeign; /** * @author Dave Syer + * @author Venil Noronha */ @Configuration public class FeignClientsConfiguration { @@ -62,6 +61,9 @@ public class FeignClientsConfiguration { @Autowired(required = false) private List feignFormatterRegistrars = new ArrayList<>(); + @Autowired(required = false) + private Logger logger; + @Bean @ConditionalOnMissingBean public Decoder feignDecoder() { @@ -108,4 +110,10 @@ public class FeignClientsConfiguration { return Feign.builder(); } + @Bean + @ConditionalOnMissingBean(FeignLoggerFactory.class) + public FeignLoggerFactory feignLoggerFactory() { + return new DefaultFeignLoggerFactory(logger); + } + } diff --git a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/feign/FeignLoggerFactory.java b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/feign/FeignLoggerFactory.java new file mode 100644 index 000000000..9440fdf0d --- /dev/null +++ b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/feign/FeignLoggerFactory.java @@ -0,0 +1,36 @@ +/* + * Copyright 2016 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.netflix.feign; + +import feign.Logger; + +/** + * Allows an application to use a custom Feign {@link Logger}. + * + * @author Venil Noronha + */ +public interface FeignLoggerFactory { + + /** + * Factory method to provide a {@link Logger} for a given {@link Class}. + * + * @param type the {@link Class} for which a {@link Logger} instance is to be created + * @return a {@link Logger} instance + */ + public Logger create(Class type); + +} diff --git a/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/feign/FeignLoggerFactoryTests.java b/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/feign/FeignLoggerFactoryTests.java new file mode 100644 index 000000000..c773ab4d8 --- /dev/null +++ b/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/feign/FeignLoggerFactoryTests.java @@ -0,0 +1,126 @@ +/* + * Copyright 2016 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.netflix.feign; + +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import org.junit.Test; + +import org.springframework.context.annotation.AnnotationConfigApplicationContext; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Import; + +import feign.Logger; +import feign.slf4j.Slf4jLogger; + +/** + * @author Venil Noronha + */ +public class FeignLoggerFactoryTests { + + @Test + public void testDefaultLogger() { + AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(SampleConfiguration1.class); + FeignLoggerFactory loggerFactory = context.getBean(FeignLoggerFactory.class); + assertNotNull(loggerFactory); + Logger logger = loggerFactory.create(Object.class); + assertNotNull(logger); + assertTrue(logger instanceof Slf4jLogger); + context.close(); + } + + @Configuration + @Import(FeignClientsConfiguration.class) + protected static class SampleConfiguration1 { + + } + + @Test + public void testCustomLogger() { + AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(SampleConfiguration2.class); + FeignLoggerFactory loggerFactory = context.getBean(FeignLoggerFactory.class); + assertNotNull(loggerFactory); + Logger logger = loggerFactory.create(Object.class); + assertNotNull(logger); + assertTrue(logger instanceof LoggerImpl1); + context.close(); + } + + @Configuration + @Import(FeignClientsConfiguration.class) + protected static class SampleConfiguration2 { + + @Bean + public Logger logger() { + return new LoggerImpl1(); + } + + } + + static class LoggerImpl1 extends Logger { + + @Override + protected void log(String arg0, String arg1, Object... arg2) { + // noop + } + + } + + @Test + public void testCustomLoggerFactory() { + AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(SampleConfiguration3.class); + FeignLoggerFactory loggerFactory = context.getBean(FeignLoggerFactory.class); + assertNotNull(loggerFactory); + assertTrue(loggerFactory instanceof LoggerFactoryImpl); + Logger logger = loggerFactory.create(Object.class); + assertNotNull(logger); + assertTrue(logger instanceof LoggerImpl2); + context.close(); + } + + @Configuration + @Import(FeignClientsConfiguration.class) + protected static class SampleConfiguration3 { + + @Bean + public FeignLoggerFactory feignLoggerFactory() { + return new LoggerFactoryImpl(); + } + + } + + static class LoggerFactoryImpl implements FeignLoggerFactory { + + @Override + public Logger create(Class type) { + return new LoggerImpl2(); + } + + } + + static class LoggerImpl2 extends Logger { + + @Override + protected void log(String arg0, String arg1, Object... arg2) { + // noop + } + + } + +} From 5a5a1aaa7f71e6d8093d7bf5d19adaca152892a7 Mon Sep 17 00:00:00 2001 From: Ryan Baxter Date: Wed, 26 Oct 2016 15:04:51 -0400 Subject: [PATCH 40/48] -Made spring-retry optional -additional refactoring from changes in s-c-commons --- pom.xml | 7 +++ spring-cloud-netflix-core/pom.xml | 8 +++ .../ribbon/RibbonAutoConfiguration.java | 4 ++ .../RibbonLoadBalancedRetryPolicyFactory.java | 4 +- .../ribbon/RibbonLoadBalancerClient.java | 18 +++--- .../ribbon/SpringRetryDisabledTests.java | 63 +++++++++++++++++++ .../ribbon/SpringRetryEnabledTests.java | 56 +++++++++++++++++ spring-cloud-starter-ribbon/pom.xml | 8 +++ 8 files changed, 156 insertions(+), 12 deletions(-) create mode 100644 spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/ribbon/SpringRetryDisabledTests.java create mode 100644 spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/ribbon/SpringRetryEnabledTests.java diff --git a/pom.xml b/pom.xml index ef239e181..89ac5e98f 100644 --- a/pom.xml +++ b/pom.xml @@ -79,6 +79,13 @@ pom import + + org.springframework.cloud + spring-cloud-commons + test-jar + test + ${spring-cloud-commons.version} + org.springframework.cloud spring-cloud-config-dependencies diff --git a/spring-cloud-netflix-core/pom.xml b/spring-cloud-netflix-core/pom.xml index fcd3c6590..4260ddb0b 100644 --- a/spring-cloud-netflix-core/pom.xml +++ b/spring-cloud-netflix-core/pom.xml @@ -47,10 +47,12 @@ org.springframework.boot spring-boot-starter-aop + true org.springframework.retry spring-retry + true org.springframework.cloud @@ -191,6 +193,12 @@ spring-boot-starter-test test + + org.springframework.cloud + spring-cloud-commons + test-jar + test + org.aspectj aspectjweaver diff --git a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/ribbon/RibbonAutoConfiguration.java b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/ribbon/RibbonAutoConfiguration.java index cc12ecd81..55f48ecbd 100644 --- a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/ribbon/RibbonAutoConfiguration.java +++ b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/ribbon/RibbonAutoConfiguration.java @@ -28,6 +28,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.AutoConfigureAfter; import org.springframework.boot.autoconfigure.AutoConfigureBefore; import org.springframework.boot.autoconfigure.condition.AnyNestedCondition; +import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; @@ -36,9 +37,11 @@ import org.springframework.cloud.client.loadbalancer.LoadBalancedRetryPolicyFact import org.springframework.cloud.client.loadbalancer.LoadBalancerAutoConfiguration; import org.springframework.cloud.client.loadbalancer.LoadBalancerClient; import org.springframework.cloud.client.loadbalancer.RestTemplateCustomizer; +import org.springframework.cloud.client.loadbalancer.RetryLoadBalancerInterceptor; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Conditional; import org.springframework.context.annotation.Configuration; +import org.springframework.retry.support.RetryTemplate; import org.springframework.web.client.RestTemplate; import com.netflix.client.IClient; @@ -80,6 +83,7 @@ public class RibbonAutoConfiguration { } @Bean + @ConditionalOnClass(name = "org.springframework.retry.support.RetryTemplate") public LoadBalancedRetryPolicyFactory loadBalancedRetryPolicyFactory(SpringClientFactory clientFactory) { return new RibbonLoadBalancedRetryPolicyFactory(clientFactory); } diff --git a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/ribbon/RibbonLoadBalancedRetryPolicyFactory.java b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/ribbon/RibbonLoadBalancedRetryPolicyFactory.java index 65f843540..563071c35 100644 --- a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/ribbon/RibbonLoadBalancedRetryPolicyFactory.java +++ b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/ribbon/RibbonLoadBalancedRetryPolicyFactory.java @@ -16,10 +16,10 @@ package org.springframework.cloud.netflix.ribbon; import org.springframework.cloud.client.ServiceInstance; -import org.springframework.cloud.client.loadbalancer.LoadBalanceChooser; import org.springframework.cloud.client.loadbalancer.LoadBalancedRetryContext; import org.springframework.cloud.client.loadbalancer.LoadBalancedRetryPolicy; import org.springframework.cloud.client.loadbalancer.LoadBalancedRetryPolicyFactory; +import org.springframework.cloud.client.loadbalancer.ServiceInstanceChooser; import org.springframework.http.HttpMethod; /** @@ -34,7 +34,7 @@ public class RibbonLoadBalancedRetryPolicyFactory implements LoadBalancedRetryPo } @Override - public LoadBalancedRetryPolicy create(final String serviceId, final LoadBalanceChooser loadBalanceChooser) { + public LoadBalancedRetryPolicy create(final String serviceId, final ServiceInstanceChooser loadBalanceChooser) { final RibbonLoadBalancerContext lbContext = this.clientFactory .getLoadBalancerContext(serviceId); return new LoadBalancedRetryPolicy() { diff --git a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/ribbon/RibbonLoadBalancerClient.java b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/ribbon/RibbonLoadBalancerClient.java index ca6ddfd8d..414e86745 100644 --- a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/ribbon/RibbonLoadBalancerClient.java +++ b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/ribbon/RibbonLoadBalancerClient.java @@ -16,28 +16,26 @@ package org.springframework.cloud.netflix.ribbon; -import com.netflix.client.config.IClientConfig; -import com.netflix.loadbalancer.ILoadBalancer; -import com.netflix.loadbalancer.Server; +import java.io.IOException; +import java.net.URI; +import java.util.Collections; +import java.util.Map; import org.springframework.cloud.client.DefaultServiceInstance; import org.springframework.cloud.client.ServiceInstance; import org.springframework.cloud.client.loadbalancer.LoadBalancerClient; import org.springframework.cloud.client.loadbalancer.LoadBalancerRequest; import org.springframework.util.Assert; import org.springframework.util.ReflectionUtils; -import org.springframework.web.util.UriComponentsBuilder; - -import java.io.IOException; -import java.net.URI; -import java.util.Collections; -import java.util.Map; +import com.netflix.client.config.IClientConfig; +import com.netflix.loadbalancer.ILoadBalancer; +import com.netflix.loadbalancer.Server; /** * @author Spencer Gibb * @author Dave Syer * @author Ryan Baxter */ -public class RibbonLoadBalancerClient implements LoadBalancerClient{ +public class RibbonLoadBalancerClient implements LoadBalancerClient { private SpringClientFactory clientFactory; diff --git a/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/ribbon/SpringRetryDisabledTests.java b/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/ribbon/SpringRetryDisabledTests.java new file mode 100644 index 000000000..3317c567d --- /dev/null +++ b/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/ribbon/SpringRetryDisabledTests.java @@ -0,0 +1,63 @@ +/* + * + * * Copyright 2013-2016 the original author or authors. + * * + * * Licensed under the Apache License, Version 2.0 (the "License"); + * * you may not use this file except in compliance with the License. + * * You may obtain a copy of the License at + * * + * * http://www.apache.org/licenses/LICENSE-2.0 + * * + * * Unless required by applicable law or agreed to in writing, software + * * distributed under the License is distributed on an "AS IS" BASIS, + * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * * See the License for the specific language governing permissions and + * * limitations under the License. + * + */ + +package org.springframework.cloud.netflix.ribbon; + +import java.util.Map; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.builder.SpringApplicationBuilder; +import org.springframework.cloud.ClassPathExclusions; +import org.springframework.cloud.FilteredClassPathRunner; +import org.springframework.cloud.client.loadbalancer.LoadBalancedRetryPolicyFactory; +import org.springframework.cloud.client.loadbalancer.LoadBalancerAutoConfiguration; +import org.springframework.context.ConfigurableApplicationContext; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.hasSize; + +/** + * @author Ryan Baxter + */ +@RunWith(FilteredClassPathRunner.class) +@ClassPathExclusions({"spring-retry-*.jar", "spring-boot-starter-aop-*.jar"}) +public class SpringRetryDisabledTests { + + private ConfigurableApplicationContext context; + + @Before + public void setUp() { + context = new SpringApplicationBuilder().web(false) + .sources(RibbonAutoConfiguration.class,LoadBalancerAutoConfiguration.class).run(); + } + + @After + public void tearDown() { + if(context != null) { + context.close(); + } + } + + @Test + public void testLoadBalancedRetryFactoryBean() throws Exception { + Map factories = context.getBeansOfType(LoadBalancedRetryPolicyFactory.class); + assertThat(factories.values(), hasSize(0)); + } +} diff --git a/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/ribbon/SpringRetryEnabledTests.java b/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/ribbon/SpringRetryEnabledTests.java new file mode 100644 index 000000000..539b94bc4 --- /dev/null +++ b/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/ribbon/SpringRetryEnabledTests.java @@ -0,0 +1,56 @@ +/* + * + * * Copyright 2013-2016 the original author or authors. + * * + * * Licensed under the Apache License, Version 2.0 (the "License"); + * * you may not use this file except in compliance with the License. + * * You may obtain a copy of the License at + * * + * * http://www.apache.org/licenses/LICENSE-2.0 + * * + * * Unless required by applicable law or agreed to in writing, software + * * distributed under the License is distributed on an "AS IS" BASIS, + * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * * See the License for the specific language governing permissions and + * * limitations under the License. + * + */ + +package org.springframework.cloud.netflix.ribbon; + +import java.util.Map; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.BeansException; +import org.springframework.cloud.client.loadbalancer.LoadBalancedRetryPolicyFactory; +import org.springframework.cloud.client.loadbalancer.LoadBalancerAutoConfiguration; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.instanceOf; +import static org.hamcrest.collection.IsCollectionWithSize.hasSize; + +/** + * @author Ryan Baxter + */ +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(classes = {RibbonAutoConfiguration.class, LoadBalancerAutoConfiguration.class}) +public class SpringRetryEnabledTests implements ApplicationContextAware { + + private ApplicationContext context; + + @Test + public void testLoadBalancedRetryFactoryBean() throws Exception { + Map factories = context.getBeansOfType(LoadBalancedRetryPolicyFactory.class); + assertThat(factories.values(), hasSize(1)); + assertThat(factories.values().toArray()[0], instanceOf(RibbonLoadBalancedRetryPolicyFactory.class)); + } + + @Override + public void setApplicationContext(ApplicationContext context) throws BeansException { + this.context = context; + } +} diff --git a/spring-cloud-starter-ribbon/pom.xml b/spring-cloud-starter-ribbon/pom.xml index 4a31be7c0..549ad625c 100644 --- a/spring-cloud-starter-ribbon/pom.xml +++ b/spring-cloud-starter-ribbon/pom.xml @@ -20,6 +20,14 @@ ${basedir}/../.. + + org.springframework.boot + spring-boot-starter-aop + + + org.springframework.retry + spring-retry + org.springframework.cloud spring-cloud-starter From 0f0c6b62049e3138f3d718b305fdb9371dc83f23 Mon Sep 17 00:00:00 2001 From: Spencer Gibb Date: Thu, 27 Oct 2016 08:29:30 -0600 Subject: [PATCH 41/48] Revert to deprecated boot APIs to support boot 1.3 --- .../springframework/cloud/netflix/zuul/ZuulConfiguration.java | 2 +- .../cloud/netflix/eureka/server/EurekaServerConfiguration.java | 2 +- .../hystrix/dashboard/HystrixDashboardConfiguration.java | 2 +- .../cloud/netflix/turbine/TurbineHttpConfiguration.java | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/ZuulConfiguration.java b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/ZuulConfiguration.java index 81f46576a..cc5a5d0ba 100644 --- a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/ZuulConfiguration.java +++ b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/ZuulConfiguration.java @@ -24,8 +24,8 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean import org.springframework.boot.autoconfigure.web.ErrorController; import org.springframework.boot.autoconfigure.web.ServerProperties; import org.springframework.boot.autoconfigure.web.ServerPropertiesAutoConfiguration; +import org.springframework.boot.context.embedded.ServletRegistrationBean; import org.springframework.boot.context.properties.EnableConfigurationProperties; -import org.springframework.boot.web.servlet.ServletRegistrationBean; import org.springframework.cloud.client.actuator.HasFeatures; import org.springframework.cloud.client.discovery.event.HeartbeatEvent; import org.springframework.cloud.client.discovery.event.HeartbeatMonitor; diff --git a/spring-cloud-netflix-eureka-server/src/main/java/org/springframework/cloud/netflix/eureka/server/EurekaServerConfiguration.java b/spring-cloud-netflix-eureka-server/src/main/java/org/springframework/cloud/netflix/eureka/server/EurekaServerConfiguration.java index 73d4571fa..8a19354a0 100644 --- a/spring-cloud-netflix-eureka-server/src/main/java/org/springframework/cloud/netflix/eureka/server/EurekaServerConfiguration.java +++ b/spring-cloud-netflix-eureka-server/src/main/java/org/springframework/cloud/netflix/eureka/server/EurekaServerConfiguration.java @@ -31,8 +31,8 @@ import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.boot.context.embedded.FilterRegistrationBean; import org.springframework.boot.context.properties.EnableConfigurationProperties; -import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.cloud.client.actuator.HasFeatures; import org.springframework.cloud.client.discovery.EnableDiscoveryClient; import org.springframework.cloud.netflix.eureka.EurekaConstants; diff --git a/spring-cloud-netflix-hystrix-dashboard/src/main/java/org/springframework/cloud/netflix/hystrix/dashboard/HystrixDashboardConfiguration.java b/spring-cloud-netflix-hystrix-dashboard/src/main/java/org/springframework/cloud/netflix/hystrix/dashboard/HystrixDashboardConfiguration.java index 4d05b5043..4431463f1 100644 --- a/spring-cloud-netflix-hystrix-dashboard/src/main/java/org/springframework/cloud/netflix/hystrix/dashboard/HystrixDashboardConfiguration.java +++ b/spring-cloud-netflix-hystrix-dashboard/src/main/java/org/springframework/cloud/netflix/hystrix/dashboard/HystrixDashboardConfiguration.java @@ -40,8 +40,8 @@ import org.apache.http.params.HttpParams; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.freemarker.FreeMarkerAutoConfiguration; +import org.springframework.boot.context.embedded.ServletRegistrationBean; import org.springframework.boot.context.properties.EnableConfigurationProperties; -import org.springframework.boot.web.servlet.ServletRegistrationBean; import org.springframework.cloud.client.actuator.HasFeatures; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; diff --git a/spring-cloud-netflix-turbine/src/main/java/org/springframework/cloud/netflix/turbine/TurbineHttpConfiguration.java b/spring-cloud-netflix-turbine/src/main/java/org/springframework/cloud/netflix/turbine/TurbineHttpConfiguration.java index 8c23c86f1..0c58625c9 100644 --- a/spring-cloud-netflix-turbine/src/main/java/org/springframework/cloud/netflix/turbine/TurbineHttpConfiguration.java +++ b/spring-cloud-netflix-turbine/src/main/java/org/springframework/cloud/netflix/turbine/TurbineHttpConfiguration.java @@ -19,8 +19,8 @@ package org.springframework.cloud.netflix.turbine; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingClass; +import org.springframework.boot.context.embedded.ServletRegistrationBean; import org.springframework.boot.context.properties.EnableConfigurationProperties; -import org.springframework.boot.web.servlet.ServletRegistrationBean; import org.springframework.cloud.client.actuator.HasFeatures; import org.springframework.cloud.client.discovery.DiscoveryClient; import org.springframework.cloud.client.discovery.EnableDiscoveryClient; From 45e7a088bbca79cea0e6292f508458d394e9e404 Mon Sep 17 00:00:00 2001 From: Spencer Gibb Date: Thu, 27 Oct 2016 15:17:18 -0600 Subject: [PATCH 42/48] Move initalizing appname, etc.. to afterPropertiesSet --- .../eureka/EurekaClientAutoConfiguration.java | 10 +---- .../eureka/EurekaInstanceConfigBean.java | 44 ++++++++++++++----- .../EurekaClientAutoConfigurationTests.java | 9 ++++ 3 files changed, 45 insertions(+), 18 deletions(-) diff --git a/spring-cloud-netflix-eureka-client/src/main/java/org/springframework/cloud/netflix/eureka/EurekaClientAutoConfiguration.java b/spring-cloud-netflix-eureka-client/src/main/java/org/springframework/cloud/netflix/eureka/EurekaClientAutoConfiguration.java index 46b0f1fde..d8b6205bb 100644 --- a/spring-cloud-netflix-eureka-client/src/main/java/org/springframework/cloud/netflix/eureka/EurekaClientAutoConfiguration.java +++ b/spring-cloud-netflix-eureka-client/src/main/java/org/springframework/cloud/netflix/eureka/EurekaClientAutoConfiguration.java @@ -107,21 +107,15 @@ public class EurekaClientAutoConfiguration { @Bean @ConditionalOnMissingBean(value = EurekaInstanceConfig.class, search = SearchStrategy.CURRENT) public EurekaInstanceConfigBean eurekaInstanceConfigBean(InetUtils inetUtils) { - RelaxedPropertyResolver relaxedPropertyResolver = new RelaxedPropertyResolver(env, "eureka.instance."); - RelaxedPropertyResolver springPropertyResolver = new RelaxedPropertyResolver(env, "spring.application."); - String springAppName = springPropertyResolver.getProperty("name"); EurekaInstanceConfigBean instance = new EurekaInstanceConfigBean(inetUtils); instance.setNonSecurePort(this.nonSecurePort); instance.setInstanceId(getDefaultInstanceId(this.env)); - if(StringUtils.hasText(springAppName)) { - instance.setAppname(springAppName); - instance.setVirtualHostName(springAppName); - instance.setSecureVirtualHostName(springAppName); - } + if (this.managementPort != this.nonSecurePort && this.managementPort != 0) { if (StringUtils.hasText(this.hostname)) { instance.setHostname(this.hostname); } + RelaxedPropertyResolver relaxedPropertyResolver = new RelaxedPropertyResolver(env, "eureka.instance."); String statusPageUrlPath = relaxedPropertyResolver.getProperty("statusPageUrlPath"); String healthCheckUrlPath = relaxedPropertyResolver.getProperty("healthCheckUrlPath"); if (StringUtils.hasText(statusPageUrlPath)) { diff --git a/spring-cloud-netflix-eureka-client/src/main/java/org/springframework/cloud/netflix/eureka/EurekaInstanceConfigBean.java b/spring-cloud-netflix-eureka-client/src/main/java/org/springframework/cloud/netflix/eureka/EurekaInstanceConfigBean.java index dbbb07269..4bf14cd41 100644 --- a/spring-cloud-netflix-eureka-client/src/main/java/org/springframework/cloud/netflix/eureka/EurekaInstanceConfigBean.java +++ b/spring-cloud-netflix-eureka-client/src/main/java/org/springframework/cloud/netflix/eureka/EurekaInstanceConfigBean.java @@ -16,20 +16,27 @@ package org.springframework.cloud.netflix.eureka; +import java.util.HashMap; +import java.util.Map; + +import org.springframework.beans.factory.InitializingBean; +import org.springframework.boot.bind.RelaxedPropertyResolver; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.cloud.commons.util.InetUtils; +import org.springframework.cloud.commons.util.InetUtils.HostInfo; +import org.springframework.context.EnvironmentAware; +import org.springframework.core.env.Environment; +import org.springframework.util.StringUtils; + +import com.netflix.appinfo.DataCenterInfo; +import com.netflix.appinfo.InstanceInfo.InstanceStatus; +import com.netflix.appinfo.MyDataCenterInfo; + import lombok.AccessLevel; import lombok.Data; import lombok.Getter; import lombok.Setter; -import java.util.HashMap; -import java.util.Map; -import org.springframework.boot.context.properties.ConfigurationProperties; -import org.springframework.cloud.commons.util.InetUtils; -import org.springframework.cloud.commons.util.InetUtils.HostInfo; -import com.netflix.appinfo.DataCenterInfo; -import com.netflix.appinfo.InstanceInfo.InstanceStatus; -import com.netflix.appinfo.MyDataCenterInfo; - /** * @author Dave Syer * @author Spencer Gibb @@ -37,7 +44,7 @@ import com.netflix.appinfo.MyDataCenterInfo; */ @Data @ConfigurationProperties("eureka.instance") -public class EurekaInstanceConfigBean implements CloudEurekaInstanceConfig { +public class EurekaInstanceConfigBean implements CloudEurekaInstanceConfig, EnvironmentAware, InitializingBean { private static final String UNKNOWN = "unknown"; @@ -272,6 +279,7 @@ public class EurekaInstanceConfigBean implements CloudEurekaInstanceConfig { private InstanceStatus initialStatus = InstanceStatus.UP; private String[] defaultAddressResolutionOrder = new String[0]; + private Environment environment; public String getHostname() { return getHostName(false); @@ -319,4 +327,20 @@ public class EurekaInstanceConfigBean implements CloudEurekaInstanceConfig { } return this.preferIpAddress ? this.ipAddress : this.hostname; } + + @Override + public void setEnvironment(Environment environment) { + this.environment = environment; + } + + @Override + public void afterPropertiesSet() throws Exception { + RelaxedPropertyResolver springPropertyResolver = new RelaxedPropertyResolver(this.environment, "spring.application."); + String springAppName = springPropertyResolver.getProperty("name"); + if(StringUtils.hasText(springAppName)) { + setAppname(springAppName); + setVirtualHostName(springAppName); + setSecureVirtualHostName(springAppName); + } + } } diff --git a/spring-cloud-netflix-eureka-client/src/test/java/org/springframework/cloud/netflix/eureka/EurekaClientAutoConfigurationTests.java b/spring-cloud-netflix-eureka-client/src/test/java/org/springframework/cloud/netflix/eureka/EurekaClientAutoConfigurationTests.java index 5d97b5989..be8145d69 100644 --- a/spring-cloud-netflix-eureka-client/src/test/java/org/springframework/cloud/netflix/eureka/EurekaClientAutoConfigurationTests.java +++ b/spring-cloud-netflix-eureka-client/src/test/java/org/springframework/cloud/netflix/eureka/EurekaClientAutoConfigurationTests.java @@ -206,6 +206,15 @@ public class EurekaClientAutoConfigurationTests { assertEquals("mytest", getInstanceConfig().getSecureVirtualHostName()); } + @Test + public void testAppNameUpper() throws Exception { + EnvironmentTestUtils.addEnvironment(this.context, "SPRING_APPLICATION_NAME=mytestupper"); + setupContext(); + assertEquals("mytestupper", getInstanceConfig().getAppname()); + assertEquals("mytestupper", getInstanceConfig().getVirtualHostName()); + assertEquals("mytestupper", getInstanceConfig().getSecureVirtualHostName()); + } + private void testNonSecurePort(String propName) { addEnvironment(this.context, propName + ":8888"); setupContext(); From 3df42159fb457cc5b23f4b5d2517e21d7e6d2b13 Mon Sep 17 00:00:00 2001 From: Ryan Baxter Date: Thu, 27 Oct 2016 14:25:18 -0400 Subject: [PATCH 43/48] Fixes #1429 --- .../main/asciidoc/spring-cloud-netflix.adoc | 58 ++++++++++++++++++- 1 file changed, 57 insertions(+), 1 deletion(-) diff --git a/docs/src/main/asciidoc/spring-cloud-netflix.adoc b/docs/src/main/asciidoc/spring-cloud-netflix.adoc index 65052fe6f..91d97543c 100644 --- a/docs/src/main/asciidoc/spring-cloud-netflix.adoc +++ b/docs/src/main/asciidoc/spring-cloud-netflix.adoc @@ -1236,7 +1236,8 @@ To enable it, annotate a Spring Boot main class with service. By convention, a service with the ID "users", will receive requests from the proxy located at `/users` (with the prefix stripped). The proxy uses Ribbon to locate an instance to forward to -via discovery, and all requests are executed in a hystrix command, so +via discovery, and all requests are executed in a +<>, so failures will show up in Hystrix metrics, and once the circuit is open the proxy will not try to contact the service. @@ -1604,6 +1605,61 @@ possible filters that are enabled. If you want to disable one, simply set `org.springframework.cloud.netflix.zuul.filters.post.SendResponseFilter` set `zuul.SendResponseFilter.post.disable=true`. +[[hystrix-fallbacks-for-routes]] +=== Providing Hystrix Fallbacks For Routes + +When a circuit for a given route in Zuul is tripped you can provide a fallback response +by creating a bean of type `ZuulFallbackProvider`. Within this bean you need to specify +the route ID the fallback is for and provide a `ClientHttpResponse` to return +as a fallback. Here is a very simple `ZuulFallbackProvider` implementation. + +[source,java] +---- +class MyFallbackProvider implements ZuulFallbackProvider { + @Override + public String getRoute() { + return "zuulserver"; + } + + @Override + public ClientHttpResponse fallbackResponse() { + return new ClientHttpResponse() { + @Override + public HttpStatus getStatusCode() throws IOException { + return HttpStatus.OK; + } + + @Override + public int getRawStatusCode() throws IOException { + return 200; + } + + @Override + public String getStatusText() throws IOException { + return "OK"; + } + + @Override + public void close() { + + } + + @Override + public InputStream getBody() throws IOException { + return new ByteArrayInputStream("fallback".getBytes()); + } + + @Override + public HttpHeaders getHeaders() { + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.TEXT_HTML); + return headers; + } + }; + } +} +---- + === Polyglot support with Sidecar Do you have non-jvm languages you want to take advantage of Eureka, Ribbon and From 72ccf2e649a004d6a54d2760c3a251256cba94f7 Mon Sep 17 00:00:00 2001 From: Ryan Baxter Date: Thu, 27 Oct 2016 15:02:17 -0400 Subject: [PATCH 44/48] Added route config --- docs/src/main/asciidoc/spring-cloud-netflix.adoc | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/docs/src/main/asciidoc/spring-cloud-netflix.adoc b/docs/src/main/asciidoc/spring-cloud-netflix.adoc index 91d97543c..ad1d9458b 100644 --- a/docs/src/main/asciidoc/spring-cloud-netflix.adoc +++ b/docs/src/main/asciidoc/spring-cloud-netflix.adoc @@ -1618,7 +1618,7 @@ as a fallback. Here is a very simple `ZuulFallbackProvider` implementation. class MyFallbackProvider implements ZuulFallbackProvider { @Override public String getRoute() { - return "zuulserver"; + return "customers"; } @Override @@ -1660,6 +1660,15 @@ class MyFallbackProvider implements ZuulFallbackProvider { } ---- +And here is what the route configuration would look like. + +[source,yaml] +---- +zuul: + routes: + customers: /customers/** +---- + === Polyglot support with Sidecar Do you have non-jvm languages you want to take advantage of Eureka, Ribbon and From 7c48814234362e9b4b9be1de0999ed8693741c16 Mon Sep 17 00:00:00 2001 From: Ryan Baxter Date: Thu, 27 Oct 2016 15:09:21 -0400 Subject: [PATCH 45/48] Switched media type to application/json --- docs/src/main/asciidoc/spring-cloud-netflix.adoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/src/main/asciidoc/spring-cloud-netflix.adoc b/docs/src/main/asciidoc/spring-cloud-netflix.adoc index ad1d9458b..129b47dd3 100644 --- a/docs/src/main/asciidoc/spring-cloud-netflix.adoc +++ b/docs/src/main/asciidoc/spring-cloud-netflix.adoc @@ -1652,7 +1652,7 @@ class MyFallbackProvider implements ZuulFallbackProvider { @Override public HttpHeaders getHeaders() { HttpHeaders headers = new HttpHeaders(); - headers.setContentType(MediaType.TEXT_HTML); + headers.setContentType(MediaType.APPLICATION_JSON); return headers; } }; From be8eece91e53d3b5d9856fc9e2603afce5be54d7 Mon Sep 17 00:00:00 2001 From: Ryan Baxter Date: Tue, 1 Nov 2016 15:36:32 -0400 Subject: [PATCH 46/48] Version changes for 1.2.2 release --- docs/pom.xml | 2 +- pom.xml | 10 +++++----- spring-cloud-netflix-core/pom.xml | 2 +- spring-cloud-netflix-dependencies/pom.xml | 4 ++-- spring-cloud-netflix-eureka-client/pom.xml | 2 +- spring-cloud-netflix-eureka-server/pom.xml | 2 +- spring-cloud-netflix-hystrix-amqp/pom.xml | 2 +- spring-cloud-netflix-hystrix-dashboard/pom.xml | 2 +- spring-cloud-netflix-hystrix-stream/pom.xml | 2 +- spring-cloud-netflix-sidecar/pom.xml | 2 +- spring-cloud-netflix-spectator/pom.xml | 2 +- spring-cloud-netflix-turbine-stream/pom.xml | 2 +- spring-cloud-netflix-turbine/pom.xml | 2 +- spring-cloud-starter-archaius/pom.xml | 2 +- spring-cloud-starter-atlas/pom.xml | 2 +- spring-cloud-starter-eureka-server/pom.xml | 2 +- spring-cloud-starter-eureka/pom.xml | 2 +- spring-cloud-starter-feign/pom.xml | 2 +- spring-cloud-starter-hystrix-dashboard/pom.xml | 2 +- spring-cloud-starter-hystrix/pom.xml | 2 +- spring-cloud-starter-ribbon/pom.xml | 2 +- spring-cloud-starter-spectator/pom.xml | 2 +- spring-cloud-starter-turbine-amqp/pom.xml | 2 +- spring-cloud-starter-turbine-stream/pom.xml | 2 +- spring-cloud-starter-turbine/pom.xml | 2 +- spring-cloud-starter-zuul/pom.xml | 2 +- 26 files changed, 31 insertions(+), 31 deletions(-) diff --git a/docs/pom.xml b/docs/pom.xml index 7225f151f..bd84becc5 100644 --- a/docs/pom.xml +++ b/docs/pom.xml @@ -5,7 +5,7 @@ org.springframework.cloud spring-cloud-netflix - 1.2.2.BUILD-SNAPSHOT + 1.2.2.RELEASE spring-cloud-netflix-docs pom diff --git a/pom.xml b/pom.xml index 89ac5e98f..b846d634a 100644 --- a/pom.xml +++ b/pom.xml @@ -3,14 +3,14 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 spring-cloud-netflix - 1.2.2.BUILD-SNAPSHOT + 1.2.2.RELEASE pom Spring Cloud Netflix Spring Cloud Netflix org.springframework.cloud spring-cloud-build - 1.2.2.BUILD-SNAPSHOT + 1.2.1.RELEASE @@ -24,9 +24,9 @@ ${basedir} 4.0.27.Final 2.7.3 - 1.1.5.BUILD-SNAPSHOT - 1.2.2.BUILD-SNAPSHOT - Brooklyn.BUILD-SNAPSHOT + 1.1.5.RELEASE + 1.2.1.RELEASE + Brooklyn.SR1 2.19.1 diff --git a/spring-cloud-netflix-core/pom.xml b/spring-cloud-netflix-core/pom.xml index 4260ddb0b..aec0647d4 100644 --- a/spring-cloud-netflix-core/pom.xml +++ b/spring-cloud-netflix-core/pom.xml @@ -5,7 +5,7 @@ org.springframework.cloud spring-cloud-netflix - 1.2.2.BUILD-SNAPSHOT + 1.2.2.RELEASE .. spring-cloud-netflix-core diff --git a/spring-cloud-netflix-dependencies/pom.xml b/spring-cloud-netflix-dependencies/pom.xml index c40c98c60..b29a71a3d 100644 --- a/spring-cloud-netflix-dependencies/pom.xml +++ b/spring-cloud-netflix-dependencies/pom.xml @@ -5,11 +5,11 @@ spring-cloud-dependencies-parent org.springframework.cloud - 1.2.2.BUILD-SNAPSHOT + 1.2.1.RELEASE spring-cloud-netflix-dependencies - 1.2.2.BUILD-SNAPSHOT + 1.2.2.RELEASE pom spring-cloud-netflix-dependencies Spring Cloud Netflix Dependencies diff --git a/spring-cloud-netflix-eureka-client/pom.xml b/spring-cloud-netflix-eureka-client/pom.xml index a30f0e751..6d645fa18 100644 --- a/spring-cloud-netflix-eureka-client/pom.xml +++ b/spring-cloud-netflix-eureka-client/pom.xml @@ -5,7 +5,7 @@ org.springframework.cloud spring-cloud-netflix - 1.2.2.BUILD-SNAPSHOT + 1.2.2.RELEASE .. spring-cloud-netflix-eureka-client diff --git a/spring-cloud-netflix-eureka-server/pom.xml b/spring-cloud-netflix-eureka-server/pom.xml index 4c1d4190d..3ddc5fbf9 100644 --- a/spring-cloud-netflix-eureka-server/pom.xml +++ b/spring-cloud-netflix-eureka-server/pom.xml @@ -5,7 +5,7 @@ org.springframework.cloud spring-cloud-netflix - 1.2.2.BUILD-SNAPSHOT + 1.2.2.RELEASE .. spring-cloud-netflix-eureka-server diff --git a/spring-cloud-netflix-hystrix-amqp/pom.xml b/spring-cloud-netflix-hystrix-amqp/pom.xml index 34442fc8c..b0779598e 100644 --- a/spring-cloud-netflix-hystrix-amqp/pom.xml +++ b/spring-cloud-netflix-hystrix-amqp/pom.xml @@ -5,7 +5,7 @@ org.springframework.cloud spring-cloud-netflix - 1.2.2.BUILD-SNAPSHOT + 1.2.2.RELEASE .. spring-cloud-netflix-hystrix-amqp diff --git a/spring-cloud-netflix-hystrix-dashboard/pom.xml b/spring-cloud-netflix-hystrix-dashboard/pom.xml index e0a0528b7..c5324fade 100644 --- a/spring-cloud-netflix-hystrix-dashboard/pom.xml +++ b/spring-cloud-netflix-hystrix-dashboard/pom.xml @@ -8,7 +8,7 @@ org.springframework.cloud spring-cloud-netflix - 1.2.2.BUILD-SNAPSHOT + 1.2.2.RELEASE .. diff --git a/spring-cloud-netflix-hystrix-stream/pom.xml b/spring-cloud-netflix-hystrix-stream/pom.xml index 1e5715a25..5f334c610 100644 --- a/spring-cloud-netflix-hystrix-stream/pom.xml +++ b/spring-cloud-netflix-hystrix-stream/pom.xml @@ -5,7 +5,7 @@ org.springframework.cloud spring-cloud-netflix - 1.2.2.BUILD-SNAPSHOT + 1.2.2.RELEASE .. spring-cloud-netflix-hystrix-stream diff --git a/spring-cloud-netflix-sidecar/pom.xml b/spring-cloud-netflix-sidecar/pom.xml index e919210c3..863636064 100644 --- a/spring-cloud-netflix-sidecar/pom.xml +++ b/spring-cloud-netflix-sidecar/pom.xml @@ -5,7 +5,7 @@ org.springframework.cloud spring-cloud-netflix - 1.2.2.BUILD-SNAPSHOT + 1.2.2.RELEASE .. spring-cloud-netflix-sidecar diff --git a/spring-cloud-netflix-spectator/pom.xml b/spring-cloud-netflix-spectator/pom.xml index 2d193b849..62c75dbb2 100644 --- a/spring-cloud-netflix-spectator/pom.xml +++ b/spring-cloud-netflix-spectator/pom.xml @@ -6,7 +6,7 @@ org.springframework.cloud spring-cloud-netflix - 1.2.2.BUILD-SNAPSHOT + 1.2.2.RELEASE .. spring-cloud-netflix-spectator diff --git a/spring-cloud-netflix-turbine-stream/pom.xml b/spring-cloud-netflix-turbine-stream/pom.xml index 9328f9054..5bfb17da4 100644 --- a/spring-cloud-netflix-turbine-stream/pom.xml +++ b/spring-cloud-netflix-turbine-stream/pom.xml @@ -5,7 +5,7 @@ org.springframework.cloud spring-cloud-netflix - 1.2.2.BUILD-SNAPSHOT + 1.2.2.RELEASE .. spring-cloud-netflix-turbine-stream diff --git a/spring-cloud-netflix-turbine/pom.xml b/spring-cloud-netflix-turbine/pom.xml index 4af74b886..e2747112e 100644 --- a/spring-cloud-netflix-turbine/pom.xml +++ b/spring-cloud-netflix-turbine/pom.xml @@ -5,7 +5,7 @@ org.springframework.cloud spring-cloud-netflix - 1.2.2.BUILD-SNAPSHOT + 1.2.2.RELEASE .. spring-cloud-netflix-turbine diff --git a/spring-cloud-starter-archaius/pom.xml b/spring-cloud-starter-archaius/pom.xml index fa0b7fa98..6ee42cdb6 100644 --- a/spring-cloud-starter-archaius/pom.xml +++ b/spring-cloud-starter-archaius/pom.xml @@ -5,7 +5,7 @@ org.springframework.cloud spring-cloud-netflix - 1.2.2.BUILD-SNAPSHOT + 1.2.2.RELEASE .. spring-cloud-starter-archaius diff --git a/spring-cloud-starter-atlas/pom.xml b/spring-cloud-starter-atlas/pom.xml index 1add805c7..4688a1e03 100644 --- a/spring-cloud-starter-atlas/pom.xml +++ b/spring-cloud-starter-atlas/pom.xml @@ -5,7 +5,7 @@ org.springframework.cloud spring-cloud-netflix - 1.2.2.BUILD-SNAPSHOT + 1.2.2.RELEASE .. spring-cloud-starter-atlas diff --git a/spring-cloud-starter-eureka-server/pom.xml b/spring-cloud-starter-eureka-server/pom.xml index a7b346084..56eb3ae14 100644 --- a/spring-cloud-starter-eureka-server/pom.xml +++ b/spring-cloud-starter-eureka-server/pom.xml @@ -5,7 +5,7 @@ org.springframework.cloud spring-cloud-netflix - 1.2.2.BUILD-SNAPSHOT + 1.2.2.RELEASE .. spring-cloud-starter-eureka-server diff --git a/spring-cloud-starter-eureka/pom.xml b/spring-cloud-starter-eureka/pom.xml index feb3560ac..d673cfa19 100644 --- a/spring-cloud-starter-eureka/pom.xml +++ b/spring-cloud-starter-eureka/pom.xml @@ -5,7 +5,7 @@ org.springframework.cloud spring-cloud-netflix - 1.2.2.BUILD-SNAPSHOT + 1.2.2.RELEASE .. spring-cloud-starter-eureka diff --git a/spring-cloud-starter-feign/pom.xml b/spring-cloud-starter-feign/pom.xml index ba5bb3109..488ad45b3 100644 --- a/spring-cloud-starter-feign/pom.xml +++ b/spring-cloud-starter-feign/pom.xml @@ -5,7 +5,7 @@ org.springframework.cloud spring-cloud-netflix - 1.2.2.BUILD-SNAPSHOT + 1.2.2.RELEASE .. spring-cloud-starter-feign diff --git a/spring-cloud-starter-hystrix-dashboard/pom.xml b/spring-cloud-starter-hystrix-dashboard/pom.xml index 87069df1b..3f9b5041a 100644 --- a/spring-cloud-starter-hystrix-dashboard/pom.xml +++ b/spring-cloud-starter-hystrix-dashboard/pom.xml @@ -5,7 +5,7 @@ org.springframework.cloud spring-cloud-netflix - 1.2.2.BUILD-SNAPSHOT + 1.2.2.RELEASE .. spring-cloud-starter-hystrix-dashboard diff --git a/spring-cloud-starter-hystrix/pom.xml b/spring-cloud-starter-hystrix/pom.xml index 7c90a6f1c..183ec6376 100644 --- a/spring-cloud-starter-hystrix/pom.xml +++ b/spring-cloud-starter-hystrix/pom.xml @@ -5,7 +5,7 @@ org.springframework.cloud spring-cloud-netflix - 1.2.2.BUILD-SNAPSHOT + 1.2.2.RELEASE .. spring-cloud-starter-hystrix diff --git a/spring-cloud-starter-ribbon/pom.xml b/spring-cloud-starter-ribbon/pom.xml index 549ad625c..25430df6f 100644 --- a/spring-cloud-starter-ribbon/pom.xml +++ b/spring-cloud-starter-ribbon/pom.xml @@ -5,7 +5,7 @@ org.springframework.cloud spring-cloud-netflix - 1.2.2.BUILD-SNAPSHOT + 1.2.2.RELEASE .. spring-cloud-starter-ribbon diff --git a/spring-cloud-starter-spectator/pom.xml b/spring-cloud-starter-spectator/pom.xml index 5ed2f4ec9..8fdac7b52 100644 --- a/spring-cloud-starter-spectator/pom.xml +++ b/spring-cloud-starter-spectator/pom.xml @@ -5,7 +5,7 @@ org.springframework.cloud spring-cloud-netflix - 1.2.2.BUILD-SNAPSHOT + 1.2.2.RELEASE .. spring-cloud-starter-spectator diff --git a/spring-cloud-starter-turbine-amqp/pom.xml b/spring-cloud-starter-turbine-amqp/pom.xml index 0820167f1..6b5781ff3 100644 --- a/spring-cloud-starter-turbine-amqp/pom.xml +++ b/spring-cloud-starter-turbine-amqp/pom.xml @@ -5,7 +5,7 @@ org.springframework.cloud spring-cloud-netflix - 1.2.2.BUILD-SNAPSHOT + 1.2.2.RELEASE .. spring-cloud-starter-turbine-amqp diff --git a/spring-cloud-starter-turbine-stream/pom.xml b/spring-cloud-starter-turbine-stream/pom.xml index 1a7edbcbb..66655e9e1 100644 --- a/spring-cloud-starter-turbine-stream/pom.xml +++ b/spring-cloud-starter-turbine-stream/pom.xml @@ -5,7 +5,7 @@ org.springframework.cloud spring-cloud-netflix - 1.2.2.BUILD-SNAPSHOT + 1.2.2.RELEASE .. spring-cloud-starter-turbine-stream diff --git a/spring-cloud-starter-turbine/pom.xml b/spring-cloud-starter-turbine/pom.xml index 5f6ed33af..daeb19774 100644 --- a/spring-cloud-starter-turbine/pom.xml +++ b/spring-cloud-starter-turbine/pom.xml @@ -5,7 +5,7 @@ org.springframework.cloud spring-cloud-netflix - 1.2.2.BUILD-SNAPSHOT + 1.2.2.RELEASE .. spring-cloud-starter-turbine diff --git a/spring-cloud-starter-zuul/pom.xml b/spring-cloud-starter-zuul/pom.xml index fb397c1db..708d0192b 100644 --- a/spring-cloud-starter-zuul/pom.xml +++ b/spring-cloud-starter-zuul/pom.xml @@ -5,7 +5,7 @@ org.springframework.cloud spring-cloud-netflix - 1.2.2.BUILD-SNAPSHOT + 1.2.2.RELEASE .. spring-cloud-starter-zuul From 9b64d0da8f15a9f1d2b6012830ad129bc4436b71 Mon Sep 17 00:00:00 2001 From: Ryan Baxter Date: Tue, 1 Nov 2016 20:05:07 -0400 Subject: [PATCH 47/48] Revert "Version changes for 1.2.2 release" This reverts commit be8eece91e53d3b5d9856fc9e2603afce5be54d7. --- docs/pom.xml | 2 +- pom.xml | 10 +++++----- spring-cloud-netflix-core/pom.xml | 2 +- spring-cloud-netflix-dependencies/pom.xml | 4 ++-- spring-cloud-netflix-eureka-client/pom.xml | 2 +- spring-cloud-netflix-eureka-server/pom.xml | 2 +- spring-cloud-netflix-hystrix-amqp/pom.xml | 2 +- spring-cloud-netflix-hystrix-dashboard/pom.xml | 2 +- spring-cloud-netflix-hystrix-stream/pom.xml | 2 +- spring-cloud-netflix-sidecar/pom.xml | 2 +- spring-cloud-netflix-spectator/pom.xml | 2 +- spring-cloud-netflix-turbine-stream/pom.xml | 2 +- spring-cloud-netflix-turbine/pom.xml | 2 +- spring-cloud-starter-archaius/pom.xml | 2 +- spring-cloud-starter-atlas/pom.xml | 2 +- spring-cloud-starter-eureka-server/pom.xml | 2 +- spring-cloud-starter-eureka/pom.xml | 2 +- spring-cloud-starter-feign/pom.xml | 2 +- spring-cloud-starter-hystrix-dashboard/pom.xml | 2 +- spring-cloud-starter-hystrix/pom.xml | 2 +- spring-cloud-starter-ribbon/pom.xml | 2 +- spring-cloud-starter-spectator/pom.xml | 2 +- spring-cloud-starter-turbine-amqp/pom.xml | 2 +- spring-cloud-starter-turbine-stream/pom.xml | 2 +- spring-cloud-starter-turbine/pom.xml | 2 +- spring-cloud-starter-zuul/pom.xml | 2 +- 26 files changed, 31 insertions(+), 31 deletions(-) diff --git a/docs/pom.xml b/docs/pom.xml index bd84becc5..7225f151f 100644 --- a/docs/pom.xml +++ b/docs/pom.xml @@ -5,7 +5,7 @@ org.springframework.cloud spring-cloud-netflix - 1.2.2.RELEASE + 1.2.2.BUILD-SNAPSHOT spring-cloud-netflix-docs pom diff --git a/pom.xml b/pom.xml index b846d634a..89ac5e98f 100644 --- a/pom.xml +++ b/pom.xml @@ -3,14 +3,14 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 spring-cloud-netflix - 1.2.2.RELEASE + 1.2.2.BUILD-SNAPSHOT pom Spring Cloud Netflix Spring Cloud Netflix org.springframework.cloud spring-cloud-build - 1.2.1.RELEASE + 1.2.2.BUILD-SNAPSHOT @@ -24,9 +24,9 @@ ${basedir} 4.0.27.Final 2.7.3 - 1.1.5.RELEASE - 1.2.1.RELEASE - Brooklyn.SR1 + 1.1.5.BUILD-SNAPSHOT + 1.2.2.BUILD-SNAPSHOT + Brooklyn.BUILD-SNAPSHOT 2.19.1 diff --git a/spring-cloud-netflix-core/pom.xml b/spring-cloud-netflix-core/pom.xml index aec0647d4..4260ddb0b 100644 --- a/spring-cloud-netflix-core/pom.xml +++ b/spring-cloud-netflix-core/pom.xml @@ -5,7 +5,7 @@ org.springframework.cloud spring-cloud-netflix - 1.2.2.RELEASE + 1.2.2.BUILD-SNAPSHOT .. spring-cloud-netflix-core diff --git a/spring-cloud-netflix-dependencies/pom.xml b/spring-cloud-netflix-dependencies/pom.xml index b29a71a3d..c40c98c60 100644 --- a/spring-cloud-netflix-dependencies/pom.xml +++ b/spring-cloud-netflix-dependencies/pom.xml @@ -5,11 +5,11 @@ spring-cloud-dependencies-parent org.springframework.cloud - 1.2.1.RELEASE + 1.2.2.BUILD-SNAPSHOT spring-cloud-netflix-dependencies - 1.2.2.RELEASE + 1.2.2.BUILD-SNAPSHOT pom spring-cloud-netflix-dependencies Spring Cloud Netflix Dependencies diff --git a/spring-cloud-netflix-eureka-client/pom.xml b/spring-cloud-netflix-eureka-client/pom.xml index 6d645fa18..a30f0e751 100644 --- a/spring-cloud-netflix-eureka-client/pom.xml +++ b/spring-cloud-netflix-eureka-client/pom.xml @@ -5,7 +5,7 @@ org.springframework.cloud spring-cloud-netflix - 1.2.2.RELEASE + 1.2.2.BUILD-SNAPSHOT .. spring-cloud-netflix-eureka-client diff --git a/spring-cloud-netflix-eureka-server/pom.xml b/spring-cloud-netflix-eureka-server/pom.xml index 3ddc5fbf9..4c1d4190d 100644 --- a/spring-cloud-netflix-eureka-server/pom.xml +++ b/spring-cloud-netflix-eureka-server/pom.xml @@ -5,7 +5,7 @@ org.springframework.cloud spring-cloud-netflix - 1.2.2.RELEASE + 1.2.2.BUILD-SNAPSHOT .. spring-cloud-netflix-eureka-server diff --git a/spring-cloud-netflix-hystrix-amqp/pom.xml b/spring-cloud-netflix-hystrix-amqp/pom.xml index b0779598e..34442fc8c 100644 --- a/spring-cloud-netflix-hystrix-amqp/pom.xml +++ b/spring-cloud-netflix-hystrix-amqp/pom.xml @@ -5,7 +5,7 @@ org.springframework.cloud spring-cloud-netflix - 1.2.2.RELEASE + 1.2.2.BUILD-SNAPSHOT .. spring-cloud-netflix-hystrix-amqp diff --git a/spring-cloud-netflix-hystrix-dashboard/pom.xml b/spring-cloud-netflix-hystrix-dashboard/pom.xml index c5324fade..e0a0528b7 100644 --- a/spring-cloud-netflix-hystrix-dashboard/pom.xml +++ b/spring-cloud-netflix-hystrix-dashboard/pom.xml @@ -8,7 +8,7 @@ org.springframework.cloud spring-cloud-netflix - 1.2.2.RELEASE + 1.2.2.BUILD-SNAPSHOT .. diff --git a/spring-cloud-netflix-hystrix-stream/pom.xml b/spring-cloud-netflix-hystrix-stream/pom.xml index 5f334c610..1e5715a25 100644 --- a/spring-cloud-netflix-hystrix-stream/pom.xml +++ b/spring-cloud-netflix-hystrix-stream/pom.xml @@ -5,7 +5,7 @@ org.springframework.cloud spring-cloud-netflix - 1.2.2.RELEASE + 1.2.2.BUILD-SNAPSHOT .. spring-cloud-netflix-hystrix-stream diff --git a/spring-cloud-netflix-sidecar/pom.xml b/spring-cloud-netflix-sidecar/pom.xml index 863636064..e919210c3 100644 --- a/spring-cloud-netflix-sidecar/pom.xml +++ b/spring-cloud-netflix-sidecar/pom.xml @@ -5,7 +5,7 @@ org.springframework.cloud spring-cloud-netflix - 1.2.2.RELEASE + 1.2.2.BUILD-SNAPSHOT .. spring-cloud-netflix-sidecar diff --git a/spring-cloud-netflix-spectator/pom.xml b/spring-cloud-netflix-spectator/pom.xml index 62c75dbb2..2d193b849 100644 --- a/spring-cloud-netflix-spectator/pom.xml +++ b/spring-cloud-netflix-spectator/pom.xml @@ -6,7 +6,7 @@ org.springframework.cloud spring-cloud-netflix - 1.2.2.RELEASE + 1.2.2.BUILD-SNAPSHOT .. spring-cloud-netflix-spectator diff --git a/spring-cloud-netflix-turbine-stream/pom.xml b/spring-cloud-netflix-turbine-stream/pom.xml index 5bfb17da4..9328f9054 100644 --- a/spring-cloud-netflix-turbine-stream/pom.xml +++ b/spring-cloud-netflix-turbine-stream/pom.xml @@ -5,7 +5,7 @@ org.springframework.cloud spring-cloud-netflix - 1.2.2.RELEASE + 1.2.2.BUILD-SNAPSHOT .. spring-cloud-netflix-turbine-stream diff --git a/spring-cloud-netflix-turbine/pom.xml b/spring-cloud-netflix-turbine/pom.xml index e2747112e..4af74b886 100644 --- a/spring-cloud-netflix-turbine/pom.xml +++ b/spring-cloud-netflix-turbine/pom.xml @@ -5,7 +5,7 @@ org.springframework.cloud spring-cloud-netflix - 1.2.2.RELEASE + 1.2.2.BUILD-SNAPSHOT .. spring-cloud-netflix-turbine diff --git a/spring-cloud-starter-archaius/pom.xml b/spring-cloud-starter-archaius/pom.xml index 6ee42cdb6..fa0b7fa98 100644 --- a/spring-cloud-starter-archaius/pom.xml +++ b/spring-cloud-starter-archaius/pom.xml @@ -5,7 +5,7 @@ org.springframework.cloud spring-cloud-netflix - 1.2.2.RELEASE + 1.2.2.BUILD-SNAPSHOT .. spring-cloud-starter-archaius diff --git a/spring-cloud-starter-atlas/pom.xml b/spring-cloud-starter-atlas/pom.xml index 4688a1e03..1add805c7 100644 --- a/spring-cloud-starter-atlas/pom.xml +++ b/spring-cloud-starter-atlas/pom.xml @@ -5,7 +5,7 @@ org.springframework.cloud spring-cloud-netflix - 1.2.2.RELEASE + 1.2.2.BUILD-SNAPSHOT .. spring-cloud-starter-atlas diff --git a/spring-cloud-starter-eureka-server/pom.xml b/spring-cloud-starter-eureka-server/pom.xml index 56eb3ae14..a7b346084 100644 --- a/spring-cloud-starter-eureka-server/pom.xml +++ b/spring-cloud-starter-eureka-server/pom.xml @@ -5,7 +5,7 @@ org.springframework.cloud spring-cloud-netflix - 1.2.2.RELEASE + 1.2.2.BUILD-SNAPSHOT .. spring-cloud-starter-eureka-server diff --git a/spring-cloud-starter-eureka/pom.xml b/spring-cloud-starter-eureka/pom.xml index d673cfa19..feb3560ac 100644 --- a/spring-cloud-starter-eureka/pom.xml +++ b/spring-cloud-starter-eureka/pom.xml @@ -5,7 +5,7 @@ org.springframework.cloud spring-cloud-netflix - 1.2.2.RELEASE + 1.2.2.BUILD-SNAPSHOT .. spring-cloud-starter-eureka diff --git a/spring-cloud-starter-feign/pom.xml b/spring-cloud-starter-feign/pom.xml index 488ad45b3..ba5bb3109 100644 --- a/spring-cloud-starter-feign/pom.xml +++ b/spring-cloud-starter-feign/pom.xml @@ -5,7 +5,7 @@ org.springframework.cloud spring-cloud-netflix - 1.2.2.RELEASE + 1.2.2.BUILD-SNAPSHOT .. spring-cloud-starter-feign diff --git a/spring-cloud-starter-hystrix-dashboard/pom.xml b/spring-cloud-starter-hystrix-dashboard/pom.xml index 3f9b5041a..87069df1b 100644 --- a/spring-cloud-starter-hystrix-dashboard/pom.xml +++ b/spring-cloud-starter-hystrix-dashboard/pom.xml @@ -5,7 +5,7 @@ org.springframework.cloud spring-cloud-netflix - 1.2.2.RELEASE + 1.2.2.BUILD-SNAPSHOT .. spring-cloud-starter-hystrix-dashboard diff --git a/spring-cloud-starter-hystrix/pom.xml b/spring-cloud-starter-hystrix/pom.xml index 183ec6376..7c90a6f1c 100644 --- a/spring-cloud-starter-hystrix/pom.xml +++ b/spring-cloud-starter-hystrix/pom.xml @@ -5,7 +5,7 @@ org.springframework.cloud spring-cloud-netflix - 1.2.2.RELEASE + 1.2.2.BUILD-SNAPSHOT .. spring-cloud-starter-hystrix diff --git a/spring-cloud-starter-ribbon/pom.xml b/spring-cloud-starter-ribbon/pom.xml index 25430df6f..549ad625c 100644 --- a/spring-cloud-starter-ribbon/pom.xml +++ b/spring-cloud-starter-ribbon/pom.xml @@ -5,7 +5,7 @@ org.springframework.cloud spring-cloud-netflix - 1.2.2.RELEASE + 1.2.2.BUILD-SNAPSHOT .. spring-cloud-starter-ribbon diff --git a/spring-cloud-starter-spectator/pom.xml b/spring-cloud-starter-spectator/pom.xml index 8fdac7b52..5ed2f4ec9 100644 --- a/spring-cloud-starter-spectator/pom.xml +++ b/spring-cloud-starter-spectator/pom.xml @@ -5,7 +5,7 @@ org.springframework.cloud spring-cloud-netflix - 1.2.2.RELEASE + 1.2.2.BUILD-SNAPSHOT .. spring-cloud-starter-spectator diff --git a/spring-cloud-starter-turbine-amqp/pom.xml b/spring-cloud-starter-turbine-amqp/pom.xml index 6b5781ff3..0820167f1 100644 --- a/spring-cloud-starter-turbine-amqp/pom.xml +++ b/spring-cloud-starter-turbine-amqp/pom.xml @@ -5,7 +5,7 @@ org.springframework.cloud spring-cloud-netflix - 1.2.2.RELEASE + 1.2.2.BUILD-SNAPSHOT .. spring-cloud-starter-turbine-amqp diff --git a/spring-cloud-starter-turbine-stream/pom.xml b/spring-cloud-starter-turbine-stream/pom.xml index 66655e9e1..1a7edbcbb 100644 --- a/spring-cloud-starter-turbine-stream/pom.xml +++ b/spring-cloud-starter-turbine-stream/pom.xml @@ -5,7 +5,7 @@ org.springframework.cloud spring-cloud-netflix - 1.2.2.RELEASE + 1.2.2.BUILD-SNAPSHOT .. spring-cloud-starter-turbine-stream diff --git a/spring-cloud-starter-turbine/pom.xml b/spring-cloud-starter-turbine/pom.xml index daeb19774..5f6ed33af 100644 --- a/spring-cloud-starter-turbine/pom.xml +++ b/spring-cloud-starter-turbine/pom.xml @@ -5,7 +5,7 @@ org.springframework.cloud spring-cloud-netflix - 1.2.2.RELEASE + 1.2.2.BUILD-SNAPSHOT .. spring-cloud-starter-turbine diff --git a/spring-cloud-starter-zuul/pom.xml b/spring-cloud-starter-zuul/pom.xml index 708d0192b..fb397c1db 100644 --- a/spring-cloud-starter-zuul/pom.xml +++ b/spring-cloud-starter-zuul/pom.xml @@ -5,7 +5,7 @@ org.springframework.cloud spring-cloud-netflix - 1.2.2.RELEASE + 1.2.2.BUILD-SNAPSHOT .. spring-cloud-starter-zuul From 3201234ee1c81d8e06f40ba9b34c3a5304e36311 Mon Sep 17 00:00:00 2001 From: Ryan Baxter Date: Tue, 1 Nov 2016 20:15:26 -0400 Subject: [PATCH 48/48] Version changes for next release --- docs/pom.xml | 2 +- pom.xml | 4 ++-- spring-cloud-netflix-core/pom.xml | 2 +- spring-cloud-netflix-dependencies/pom.xml | 2 +- spring-cloud-netflix-eureka-client/pom.xml | 2 +- spring-cloud-netflix-eureka-server/pom.xml | 2 +- spring-cloud-netflix-hystrix-amqp/pom.xml | 2 +- spring-cloud-netflix-hystrix-dashboard/pom.xml | 2 +- spring-cloud-netflix-hystrix-stream/pom.xml | 2 +- spring-cloud-netflix-sidecar/pom.xml | 2 +- spring-cloud-netflix-spectator/pom.xml | 2 +- spring-cloud-netflix-turbine-stream/pom.xml | 2 +- spring-cloud-netflix-turbine/pom.xml | 2 +- spring-cloud-starter-archaius/pom.xml | 2 +- spring-cloud-starter-atlas/pom.xml | 2 +- spring-cloud-starter-eureka-server/pom.xml | 2 +- spring-cloud-starter-eureka/pom.xml | 2 +- spring-cloud-starter-feign/pom.xml | 2 +- spring-cloud-starter-hystrix-dashboard/pom.xml | 2 +- spring-cloud-starter-hystrix/pom.xml | 2 +- spring-cloud-starter-ribbon/pom.xml | 2 +- spring-cloud-starter-spectator/pom.xml | 2 +- spring-cloud-starter-turbine-amqp/pom.xml | 2 +- spring-cloud-starter-turbine-stream/pom.xml | 2 +- spring-cloud-starter-turbine/pom.xml | 2 +- spring-cloud-starter-zuul/pom.xml | 2 +- 26 files changed, 27 insertions(+), 27 deletions(-) diff --git a/docs/pom.xml b/docs/pom.xml index 7225f151f..baa750767 100644 --- a/docs/pom.xml +++ b/docs/pom.xml @@ -5,7 +5,7 @@ org.springframework.cloud spring-cloud-netflix - 1.2.2.BUILD-SNAPSHOT + 1.2.3.BUILD-SNAPSHOT spring-cloud-netflix-docs pom diff --git a/pom.xml b/pom.xml index 89ac5e98f..ca7de3596 100644 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 spring-cloud-netflix - 1.2.2.BUILD-SNAPSHOT + 1.2.3.BUILD-SNAPSHOT pom Spring Cloud Netflix Spring Cloud Netflix @@ -24,7 +24,7 @@ ${basedir} 4.0.27.Final 2.7.3 - 1.1.5.BUILD-SNAPSHOT + 1.1.6.BUILD-SNAPSHOT 1.2.2.BUILD-SNAPSHOT Brooklyn.BUILD-SNAPSHOT diff --git a/spring-cloud-netflix-core/pom.xml b/spring-cloud-netflix-core/pom.xml index 4260ddb0b..681bde90d 100644 --- a/spring-cloud-netflix-core/pom.xml +++ b/spring-cloud-netflix-core/pom.xml @@ -5,7 +5,7 @@ org.springframework.cloud spring-cloud-netflix - 1.2.2.BUILD-SNAPSHOT + 1.2.3.BUILD-SNAPSHOT .. spring-cloud-netflix-core diff --git a/spring-cloud-netflix-dependencies/pom.xml b/spring-cloud-netflix-dependencies/pom.xml index c40c98c60..c2123fa6b 100644 --- a/spring-cloud-netflix-dependencies/pom.xml +++ b/spring-cloud-netflix-dependencies/pom.xml @@ -9,7 +9,7 @@ spring-cloud-netflix-dependencies - 1.2.2.BUILD-SNAPSHOT + 1.2.3.BUILD-SNAPSHOT pom spring-cloud-netflix-dependencies Spring Cloud Netflix Dependencies diff --git a/spring-cloud-netflix-eureka-client/pom.xml b/spring-cloud-netflix-eureka-client/pom.xml index a30f0e751..e43ee8ec8 100644 --- a/spring-cloud-netflix-eureka-client/pom.xml +++ b/spring-cloud-netflix-eureka-client/pom.xml @@ -5,7 +5,7 @@ org.springframework.cloud spring-cloud-netflix - 1.2.2.BUILD-SNAPSHOT + 1.2.3.BUILD-SNAPSHOT .. spring-cloud-netflix-eureka-client diff --git a/spring-cloud-netflix-eureka-server/pom.xml b/spring-cloud-netflix-eureka-server/pom.xml index 4c1d4190d..9ee12b8a4 100644 --- a/spring-cloud-netflix-eureka-server/pom.xml +++ b/spring-cloud-netflix-eureka-server/pom.xml @@ -5,7 +5,7 @@ org.springframework.cloud spring-cloud-netflix - 1.2.2.BUILD-SNAPSHOT + 1.2.3.BUILD-SNAPSHOT .. spring-cloud-netflix-eureka-server diff --git a/spring-cloud-netflix-hystrix-amqp/pom.xml b/spring-cloud-netflix-hystrix-amqp/pom.xml index 34442fc8c..1155ec05d 100644 --- a/spring-cloud-netflix-hystrix-amqp/pom.xml +++ b/spring-cloud-netflix-hystrix-amqp/pom.xml @@ -5,7 +5,7 @@ org.springframework.cloud spring-cloud-netflix - 1.2.2.BUILD-SNAPSHOT + 1.2.3.BUILD-SNAPSHOT .. spring-cloud-netflix-hystrix-amqp diff --git a/spring-cloud-netflix-hystrix-dashboard/pom.xml b/spring-cloud-netflix-hystrix-dashboard/pom.xml index e0a0528b7..e300272cb 100644 --- a/spring-cloud-netflix-hystrix-dashboard/pom.xml +++ b/spring-cloud-netflix-hystrix-dashboard/pom.xml @@ -8,7 +8,7 @@ org.springframework.cloud spring-cloud-netflix - 1.2.2.BUILD-SNAPSHOT + 1.2.3.BUILD-SNAPSHOT .. diff --git a/spring-cloud-netflix-hystrix-stream/pom.xml b/spring-cloud-netflix-hystrix-stream/pom.xml index 1e5715a25..852cc61ad 100644 --- a/spring-cloud-netflix-hystrix-stream/pom.xml +++ b/spring-cloud-netflix-hystrix-stream/pom.xml @@ -5,7 +5,7 @@ org.springframework.cloud spring-cloud-netflix - 1.2.2.BUILD-SNAPSHOT + 1.2.3.BUILD-SNAPSHOT .. spring-cloud-netflix-hystrix-stream diff --git a/spring-cloud-netflix-sidecar/pom.xml b/spring-cloud-netflix-sidecar/pom.xml index e919210c3..01f838d71 100644 --- a/spring-cloud-netflix-sidecar/pom.xml +++ b/spring-cloud-netflix-sidecar/pom.xml @@ -5,7 +5,7 @@ org.springframework.cloud spring-cloud-netflix - 1.2.2.BUILD-SNAPSHOT + 1.2.3.BUILD-SNAPSHOT .. spring-cloud-netflix-sidecar diff --git a/spring-cloud-netflix-spectator/pom.xml b/spring-cloud-netflix-spectator/pom.xml index 2d193b849..5c9f16c84 100644 --- a/spring-cloud-netflix-spectator/pom.xml +++ b/spring-cloud-netflix-spectator/pom.xml @@ -6,7 +6,7 @@ org.springframework.cloud spring-cloud-netflix - 1.2.2.BUILD-SNAPSHOT + 1.2.3.BUILD-SNAPSHOT .. spring-cloud-netflix-spectator diff --git a/spring-cloud-netflix-turbine-stream/pom.xml b/spring-cloud-netflix-turbine-stream/pom.xml index 9328f9054..73d7fcba0 100644 --- a/spring-cloud-netflix-turbine-stream/pom.xml +++ b/spring-cloud-netflix-turbine-stream/pom.xml @@ -5,7 +5,7 @@ org.springframework.cloud spring-cloud-netflix - 1.2.2.BUILD-SNAPSHOT + 1.2.3.BUILD-SNAPSHOT .. spring-cloud-netflix-turbine-stream diff --git a/spring-cloud-netflix-turbine/pom.xml b/spring-cloud-netflix-turbine/pom.xml index 4af74b886..9d1a39e0b 100644 --- a/spring-cloud-netflix-turbine/pom.xml +++ b/spring-cloud-netflix-turbine/pom.xml @@ -5,7 +5,7 @@ org.springframework.cloud spring-cloud-netflix - 1.2.2.BUILD-SNAPSHOT + 1.2.3.BUILD-SNAPSHOT .. spring-cloud-netflix-turbine diff --git a/spring-cloud-starter-archaius/pom.xml b/spring-cloud-starter-archaius/pom.xml index fa0b7fa98..1a9d18879 100644 --- a/spring-cloud-starter-archaius/pom.xml +++ b/spring-cloud-starter-archaius/pom.xml @@ -5,7 +5,7 @@ org.springframework.cloud spring-cloud-netflix - 1.2.2.BUILD-SNAPSHOT + 1.2.3.BUILD-SNAPSHOT .. spring-cloud-starter-archaius diff --git a/spring-cloud-starter-atlas/pom.xml b/spring-cloud-starter-atlas/pom.xml index 1add805c7..f35598d00 100644 --- a/spring-cloud-starter-atlas/pom.xml +++ b/spring-cloud-starter-atlas/pom.xml @@ -5,7 +5,7 @@ org.springframework.cloud spring-cloud-netflix - 1.2.2.BUILD-SNAPSHOT + 1.2.3.BUILD-SNAPSHOT .. spring-cloud-starter-atlas diff --git a/spring-cloud-starter-eureka-server/pom.xml b/spring-cloud-starter-eureka-server/pom.xml index a7b346084..239c6d1f5 100644 --- a/spring-cloud-starter-eureka-server/pom.xml +++ b/spring-cloud-starter-eureka-server/pom.xml @@ -5,7 +5,7 @@ org.springframework.cloud spring-cloud-netflix - 1.2.2.BUILD-SNAPSHOT + 1.2.3.BUILD-SNAPSHOT .. spring-cloud-starter-eureka-server diff --git a/spring-cloud-starter-eureka/pom.xml b/spring-cloud-starter-eureka/pom.xml index feb3560ac..dfe0cba5b 100644 --- a/spring-cloud-starter-eureka/pom.xml +++ b/spring-cloud-starter-eureka/pom.xml @@ -5,7 +5,7 @@ org.springframework.cloud spring-cloud-netflix - 1.2.2.BUILD-SNAPSHOT + 1.2.3.BUILD-SNAPSHOT .. spring-cloud-starter-eureka diff --git a/spring-cloud-starter-feign/pom.xml b/spring-cloud-starter-feign/pom.xml index ba5bb3109..d24c79f4c 100644 --- a/spring-cloud-starter-feign/pom.xml +++ b/spring-cloud-starter-feign/pom.xml @@ -5,7 +5,7 @@ org.springframework.cloud spring-cloud-netflix - 1.2.2.BUILD-SNAPSHOT + 1.2.3.BUILD-SNAPSHOT .. spring-cloud-starter-feign diff --git a/spring-cloud-starter-hystrix-dashboard/pom.xml b/spring-cloud-starter-hystrix-dashboard/pom.xml index 87069df1b..b78098b66 100644 --- a/spring-cloud-starter-hystrix-dashboard/pom.xml +++ b/spring-cloud-starter-hystrix-dashboard/pom.xml @@ -5,7 +5,7 @@ org.springframework.cloud spring-cloud-netflix - 1.2.2.BUILD-SNAPSHOT + 1.2.3.BUILD-SNAPSHOT .. spring-cloud-starter-hystrix-dashboard diff --git a/spring-cloud-starter-hystrix/pom.xml b/spring-cloud-starter-hystrix/pom.xml index 7c90a6f1c..4034e8b46 100644 --- a/spring-cloud-starter-hystrix/pom.xml +++ b/spring-cloud-starter-hystrix/pom.xml @@ -5,7 +5,7 @@ org.springframework.cloud spring-cloud-netflix - 1.2.2.BUILD-SNAPSHOT + 1.2.3.BUILD-SNAPSHOT .. spring-cloud-starter-hystrix diff --git a/spring-cloud-starter-ribbon/pom.xml b/spring-cloud-starter-ribbon/pom.xml index 549ad625c..e2937c5f4 100644 --- a/spring-cloud-starter-ribbon/pom.xml +++ b/spring-cloud-starter-ribbon/pom.xml @@ -5,7 +5,7 @@ org.springframework.cloud spring-cloud-netflix - 1.2.2.BUILD-SNAPSHOT + 1.2.3.BUILD-SNAPSHOT .. spring-cloud-starter-ribbon diff --git a/spring-cloud-starter-spectator/pom.xml b/spring-cloud-starter-spectator/pom.xml index 5ed2f4ec9..56927535c 100644 --- a/spring-cloud-starter-spectator/pom.xml +++ b/spring-cloud-starter-spectator/pom.xml @@ -5,7 +5,7 @@ org.springframework.cloud spring-cloud-netflix - 1.2.2.BUILD-SNAPSHOT + 1.2.3.BUILD-SNAPSHOT .. spring-cloud-starter-spectator diff --git a/spring-cloud-starter-turbine-amqp/pom.xml b/spring-cloud-starter-turbine-amqp/pom.xml index 0820167f1..f7da82435 100644 --- a/spring-cloud-starter-turbine-amqp/pom.xml +++ b/spring-cloud-starter-turbine-amqp/pom.xml @@ -5,7 +5,7 @@ org.springframework.cloud spring-cloud-netflix - 1.2.2.BUILD-SNAPSHOT + 1.2.3.BUILD-SNAPSHOT .. spring-cloud-starter-turbine-amqp diff --git a/spring-cloud-starter-turbine-stream/pom.xml b/spring-cloud-starter-turbine-stream/pom.xml index 1a7edbcbb..fa71b1d2b 100644 --- a/spring-cloud-starter-turbine-stream/pom.xml +++ b/spring-cloud-starter-turbine-stream/pom.xml @@ -5,7 +5,7 @@ org.springframework.cloud spring-cloud-netflix - 1.2.2.BUILD-SNAPSHOT + 1.2.3.BUILD-SNAPSHOT .. spring-cloud-starter-turbine-stream diff --git a/spring-cloud-starter-turbine/pom.xml b/spring-cloud-starter-turbine/pom.xml index 5f6ed33af..03ec13466 100644 --- a/spring-cloud-starter-turbine/pom.xml +++ b/spring-cloud-starter-turbine/pom.xml @@ -5,7 +5,7 @@ org.springframework.cloud spring-cloud-netflix - 1.2.2.BUILD-SNAPSHOT + 1.2.3.BUILD-SNAPSHOT .. spring-cloud-starter-turbine diff --git a/spring-cloud-starter-zuul/pom.xml b/spring-cloud-starter-zuul/pom.xml index fb397c1db..55436f6b2 100644 --- a/spring-cloud-starter-zuul/pom.xml +++ b/spring-cloud-starter-zuul/pom.xml @@ -5,7 +5,7 @@ org.springframework.cloud spring-cloud-netflix - 1.2.2.BUILD-SNAPSHOT + 1.2.3.BUILD-SNAPSHOT .. spring-cloud-starter-zuul