Compare commits

...
Author SHA1 Message Date
Ryan Baxter 931f058068 Updated dependencies and versions for 1.1.4 release 2016-07-07 16:48:59 -04:00
Ryan Baxter c1dd0a6b6d Merge pull request #1170 from ryanjbaxter/upgrade-eureka-to-1.4.9-1167
Upgrade Eureka to 1.4.9
2016-07-07 13:19:31 -04:00
Ryan Baxter c57a0e323c Upgrade Eureka to 1.4.9. Fixes #1167 2016-07-07 12:15:06 -04:00
Dave Syer e1dca45c10 Revert to snapshots 2016-06-30 08:09:22 -07:00
Dave Syer a8282dd0bd Update to 1.1.3.RELEASE 2016-06-30 08:07:45 -07:00
Spencer Gibb 9e3e749438 fix typo 2016-06-29 11:38:33 -06:00
Patrick Cornelißen 434305de19 Adds ability to disable hostname validation.
Adds property zuul.sslHostnameValidationEnabled to be able to disable the hostname validation in the simpleHostRoutingFilter

fixes gh-1057
2016-06-28 10:34:57 -06:00
Spencer Gibb a9c0fc1502 Split ProxyRequestHelper to function without Actuator.
Previously ProxyRequestHelper contained a TraceRepository field. This caused zuul apps to fail with a class not found exception if they excluded actuator. This splits TraceRepository functionality into a new TraceProxyRequestHelper that extends ProxyRequestHelper. Auto configuration creates the appropriate ProxyRequestHelper based on the existence or not of actuator classes.

fixes gh-1135
2016-06-24 16:03:59 -06:00
Spencer Gibb 9dafae6c01 add .shelf to .gitignore 2016-06-24 09:53:10 -06:00
Spencer Gibb f538444dee Add hystrix.stream.queue.size to customize queue size.
Also added descriptions to properties.

fixes gh-1131
2016-06-24 09:52:36 -06:00
Spencer Gibb 99beb9d045 Merge pull request #1127 from william-tran/schemeless-uri
* schemeless-uri:
  Without explicit client config of IsSecure, lookup from registration
2016-06-23 15:09:36 -06:00
Will Tran 4cada7c8cc Without explicit client config of IsSecure, lookup from registration
instead of defaulting to false.

Fixes gh-1126
2016-06-23 15:09:16 -06:00
Spencer Gibb 34dff916cf Change parent poms to snapshot. 2016-06-22 12:36:22 -06:00
Spencer Gibb 7e9faef2e7 Set entity contentLength to 0 for GET requests.
Zuul sets an empty entity for GET requests. The apache http client either sets transfer encoding to chunked or a content length header. This change sets the apache entity contentLength to 0 (not the header), to that in RequestContent the "content-length" header is set to 0 rathern than transfer encoding.

See gh-1042
2016-06-22 12:32:57 -06:00
Jérôme Mirc 476a5cb84c Fix hystrix dashboard TPS.
fixes gh-1113

See https://github.com/Netflix/Hystrix/issues/1251
2016-06-21 15:24:31 -06:00
Spencer Gibb cfa4302965 Set entity contentLength for HttpClientRibbonCommand.
If the content length isn't set on the entity, when http client determines which header to set, it sets transfer-encoding to chunked rather than content-length.

This fixes a missing content-length issue when using `HttpClientRibbonCommandFactory`.

See gh-1042
2016-06-20 12:42:33 -06:00
Spencer Gibb 5d6590da44 Angel eureka clients can use brixton eureka servers.
Updates so CloudJacksonJson extension is properly recognized by Eureka
Server as LegacyJacksonJson.

see gh-978
fixes gh-1111
2016-06-17 16:46:31 -06:00
46 changed files with 476 additions and 161 deletions
+1
View File
@@ -14,3 +14,4 @@ _site/
*.ipr
*.iws
.factorypath
.shelf
+1 -1
View File
@@ -5,7 +5,7 @@
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-netflix</artifactId>
<version>1.1.3.BUILD-SNAPSHOT</version>
<version>1.1.4.RELEASE</version>
</parent>
<artifactId>spring-cloud-netflix-docs</artifactId>
<packaging>pom</packaging>
+1 -1
View File
@@ -9,7 +9,7 @@
<relativePath />
</parent>
<artifactId>spring-cloud-netflix</artifactId>
<version>1.1.3.BUILD-SNAPSHOT</version>
<version>1.1.4.RELEASE</version>
<packaging>pom</packaging>
<name>Spring Cloud Netflix</name>
<description>Spring Cloud Netflix</description>
+1 -1
View File
@@ -5,7 +5,7 @@
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-netflix</artifactId>
<version>1.1.3.BUILD-SNAPSHOT</version>
<version>1.1.4.RELEASE</version>
<relativePath>..</relativePath> <!-- lookup parent from repository -->
</parent>
<artifactId>spring-cloud-netflix-core</artifactId>
@@ -114,7 +114,10 @@ public class RibbonLoadBalancerClient implements LoadBalancerClient {
private boolean isSecure(Server server, String serviceId) {
IClientConfig config = this.clientFactory.getClientConfig(serviceId);
if (config != null) {
return config.get(CommonClientConfigKey.IsSecure, false);
Boolean isSecure = config.get(CommonClientConfigKey.IsSecure);
if (isSecure != null) {
return isSecure;
}
}
return serverIntrospector(serviceId).isSecure(server);
@@ -37,6 +37,7 @@ import lombok.Getter;
public class RibbonApacheHttpRequest extends ClientRequest implements Cloneable {
private final String method;
private Long contentLength;
private final MultiValueMap<String, String> headers;
@@ -44,11 +45,18 @@ public class RibbonApacheHttpRequest extends ClientRequest implements Cloneable
private final InputStream requestEntity;
public RibbonApacheHttpRequest(final String method, final URI uri,
final Boolean retryable, final MultiValueMap<String, String> headers,
final MultiValueMap<String, String> params, final InputStream requestEntity) {
this(method, uri, retryable, headers, params, requestEntity, null);
}
public RibbonApacheHttpRequest(final String method, final URI uri,
final Boolean retryable, final MultiValueMap<String, String> headers,
final MultiValueMap<String, String> params, final InputStream requestEntity) {
final MultiValueMap<String, String> params, final InputStream requestEntity, Long contentLength) {
this.method = method;
this.contentLength = contentLength;
this.uri = uri;
this.isRetriable = retryable;
this.headers = headers;
@@ -77,6 +85,13 @@ public class RibbonApacheHttpRequest extends ClientRequest implements Cloneable
final BasicHttpEntity entity;
entity = new BasicHttpEntity();
entity.setContent(this.requestEntity);
// if the entity contentLength isn't set, transfer-encoding will be set
// to chunked in org.apache.http.protocol.RequestContent. See gh-1042
if (contentLength != null) {
entity.setContentLength(this.contentLength);
} else if ("GET".equals(this.method)) {
entity.setContentLength(0);
}
builder.setEntity(entity);
}
@@ -21,6 +21,7 @@ import org.springframework.boot.actuate.endpoint.Endpoint;
import org.springframework.boot.actuate.trace.TraceRepository;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingClass;
import org.springframework.cloud.client.actuator.HasFeatures;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.cloud.client.discovery.event.HeartbeatEvent;
@@ -30,6 +31,7 @@ import org.springframework.cloud.client.discovery.event.ParentHeartbeatEvent;
import org.springframework.cloud.netflix.ribbon.SpringClientFactory;
import org.springframework.cloud.netflix.zuul.filters.ProxyRequestHelper;
import org.springframework.cloud.netflix.zuul.filters.RouteLocator;
import org.springframework.cloud.netflix.zuul.filters.TraceProxyRequestHelper;
import org.springframework.cloud.netflix.zuul.filters.ZuulProperties;
import org.springframework.cloud.netflix.zuul.filters.discovery.DiscoveryClientRouteLocator;
import org.springframework.cloud.netflix.zuul.filters.discovery.ServiceRouteMapper;
@@ -52,9 +54,6 @@ import org.springframework.context.annotation.Configuration;
@Configuration
public class ZuulProxyConfiguration extends ZuulConfiguration {
@Autowired(required = false)
private TraceRepository traces;
@Autowired
private SpringClientFactory clientFactory;
@@ -108,17 +107,6 @@ public class ZuulProxyConfiguration extends ZuulConfiguration {
return new SimpleHostRoutingFilter(helper, zuulProperties);
}
@Bean
public ProxyRequestHelper proxyRequestHelper() {
ProxyRequestHelper helper = new ProxyRequestHelper();
if (this.traces != null) {
helper.setTraces(this.traces);
}
helper.setIgnoredHeaders(this.zuulProperties.getIgnoredHeaders());
helper.setTraceRequestBody(this.zuulProperties.isTraceRequestBody());
return helper;
}
@Bean
public ApplicationListener<ApplicationEvent> zuulDiscoveryRefreshRoutesListener() {
return new ZuulDiscoveryRefreshListener();
@@ -130,15 +118,42 @@ public class ZuulProxyConfiguration extends ZuulConfiguration {
return new SimpleServiceRouteMapper();
}
@Configuration
@ConditionalOnMissingClass("org.springframework.boot.actuate.endpoint.Endpoint")
protected static class NoActuatorConfiguration {
@Bean
public ProxyRequestHelper proxyRequestHelper(ZuulProperties zuulProperties) {
ProxyRequestHelper helper = new ProxyRequestHelper();
helper.setIgnoredHeaders(zuulProperties.getIgnoredHeaders());
helper.setTraceRequestBody(zuulProperties.isTraceRequestBody());
return helper;
}
}
@Configuration
@ConditionalOnClass(Endpoint.class)
protected static class RoutesEndpointConfiguration {
@Autowired(required = false)
private TraceRepository traces;
@Bean
public RoutesEndpoint zuulEndpoint(RouteLocator routeLocator) {
return new RoutesEndpoint(routeLocator);
}
@Bean
public ProxyRequestHelper proxyRequestHelper(ZuulProperties zuulProperties) {
TraceProxyRequestHelper helper = new TraceProxyRequestHelper();
if (this.traces != null) {
helper.setTraces(this.traces);
}
helper.setIgnoredHeaders(zuulProperties.getIgnoredHeaders());
helper.setTraceRequestBody(zuulProperties.isTraceRequestBody());
return helper;
}
}
private static class ZuulDiscoveryRefreshListener
@@ -16,10 +16,11 @@
package org.springframework.cloud.netflix.zuul.filters;
import static org.springframework.http.HttpHeaders.CONTENT_ENCODING;
import static org.springframework.http.HttpHeaders.CONTENT_LENGTH;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.Charset;
import java.util.Collection;
import java.util.Enumeration;
import java.util.HashMap;
@@ -33,7 +34,6 @@ import java.util.Set;
import javax.servlet.http.HttpServletRequest;
import org.springframework.boot.actuate.trace.TraceRepository;
import org.springframework.cloud.netflix.zuul.util.RequestUtils;
import org.springframework.http.HttpHeaders;
import org.springframework.util.LinkedMultiValueMap;
@@ -45,14 +45,12 @@ import org.springframework.web.util.WebUtils;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.util.HTTPRequestUtils;
import static org.springframework.http.HttpHeaders.CONTENT_ENCODING;
import static org.springframework.http.HttpHeaders.CONTENT_LENGTH;
import lombok.extern.apachecommons.CommonsLog;
/**
* @author Dave Syer
* @author Marcos Barbero
* @author Spencer Gibb
*/
@CommonsLog
public class ProxyRequestHelper {
@@ -63,8 +61,6 @@ public class ProxyRequestHelper {
*/
public static final String IGNORED_HEADERS = "ignoredHeaders";
private TraceRepository traces;
private Set<String> ignoredHeaders = new LinkedHashSet<>();
private Set<String> sensitiveHeaders = new LinkedHashSet<>();
@@ -85,10 +81,6 @@ public class ProxyRequestHelper {
this.ignoredHeaders.addAll(ignoredHeaders);
}
public void setTraces(TraceRepository traces) {
this.traces = traces;
}
public void setTraceRequestBody(boolean traceRequestBody) {
this.traceRequestBody = traceRequestBody;
}
@@ -238,39 +230,10 @@ public class ProxyRequestHelper {
MultiValueMap<String, String> headers, MultiValueMap<String, String> params,
InputStream requestEntity) throws IOException {
Map<String, Object> info = new LinkedHashMap<>();
if (this.traces != null) {
RequestContext context = RequestContext.getCurrentContext();
info.put("method", verb);
info.put("path", uri);
info.put("query", getQueryString(params));
info.put("remote", true);
info.put("proxy", context.get("proxy"));
Map<String, Object> trace = new LinkedHashMap<>();
Map<String, Object> input = new LinkedHashMap<>();
trace.put("request", input);
info.put("headers", trace);
for (Entry<String, List<String>> entry : headers.entrySet()) {
Collection<String> collection = entry.getValue();
Object value = collection;
if (collection.size() < 2) {
value = collection.isEmpty() ? "" : collection.iterator().next();
}
input.put(entry.getKey(), value);
}
RequestContext ctx = RequestContext.getCurrentContext();
if (shouldDebugBody(ctx)) {
// Prevent input stream from being read if it needs to go downstream
if (requestEntity != null) {
debugRequestEntity(info, ctx.getRequest().getInputStream());
}
}
this.traces.add(info);
return info;
}
return info;
}
/* for tests */ boolean shouldDebugBody(RequestContext ctx) {
protected boolean shouldDebugBody(RequestContext ctx) {
HttpServletRequest request = ctx.getRequest();
if (!this.traceRequestBody || ctx.isChunkedRequestBody()
|| RequestUtils.isZuulServletRequest()) {
@@ -284,36 +247,6 @@ public class ProxyRequestHelper {
public void appendDebug(Map<String, Object> info, int status,
MultiValueMap<String, String> headers) {
if (this.traces != null) {
@SuppressWarnings("unchecked")
Map<String, Object> trace = (Map<String, Object>) info.get("headers");
Map<String, Object> output = new LinkedHashMap<String, Object>();
trace.put("response", output);
for (Entry<String, List<String>> key : headers.entrySet()) {
Collection<String> collection = key.getValue();
Object value = collection;
if (collection.size() < 2) {
value = collection.isEmpty() ? "" : collection.iterator().next();
}
output.put(key.getKey(), value);
}
output.put("status", "" + status);
}
}
private void debugRequestEntity(Map<String, Object> info, InputStream inputStream)
throws IOException {
if (RequestContext.getCurrentContext().isChunkedRequestBody()) {
info.put("body", "<chunked>");
return;
}
char[] buffer = new char[4096];
int count = new InputStreamReader(inputStream, Charset.forName("UTF-8"))
.read(buffer, 0, buffer.length);
if (count > 0) {
String entity = new String(buffer).substring(0, count);
info.put("body", entity.length() < 4096 ? entity : entity + "<truncated>");
}
}
public String getQueryString(MultiValueMap<String, String> params) {
@@ -0,0 +1,117 @@
/*
* 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;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.Charset;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import org.springframework.boot.actuate.trace.TraceRepository;
import org.springframework.util.MultiValueMap;
import com.netflix.zuul.context.RequestContext;
import lombok.extern.apachecommons.CommonsLog;
/**
* @author Spencer Gibb
*/
@CommonsLog
public class TraceProxyRequestHelper extends ProxyRequestHelper {
private TraceRepository traces;
public void setTraces(TraceRepository traces) {
this.traces = traces;
}
@Override
public Map<String, Object> debug(String verb, String uri,
MultiValueMap<String, String> headers, MultiValueMap<String, String> params,
InputStream requestEntity) throws IOException {
Map<String, Object> info = new LinkedHashMap<>();
if (this.traces != null) {
RequestContext context = RequestContext.getCurrentContext();
info.put("method", verb);
info.put("path", uri);
info.put("query", getQueryString(params));
info.put("remote", true);
info.put("proxy", context.get("proxy"));
Map<String, Object> trace = new LinkedHashMap<>();
Map<String, Object> input = new LinkedHashMap<>();
trace.put("request", input);
info.put("headers", trace);
debugHeaders(headers, input);
RequestContext ctx = RequestContext.getCurrentContext();
if (shouldDebugBody(ctx)) {
// Prevent input stream from being read if it needs to go downstream
if (requestEntity != null) {
debugRequestEntity(info, ctx.getRequest().getInputStream());
}
}
this.traces.add(info);
return info;
}
return info;
}
void debugHeaders(MultiValueMap<String, String> headers, Map<String, Object> map) {
for (Entry<String, List<String>> entry : headers.entrySet()) {
Collection<String> collection = entry.getValue();
Object value = collection;
if (collection.size() < 2) {
value = collection.isEmpty() ? "" : collection.iterator().next();
}
map.put(entry.getKey(), value);
}
}
public void appendDebug(Map<String, Object> info, int status,
MultiValueMap<String, String> headers) {
if (this.traces != null) {
@SuppressWarnings("unchecked")
Map<String, Object> trace = (Map<String, Object>) info.get("headers");
Map<String, Object> output = new LinkedHashMap<String, Object>();
trace.put("response", output);
debugHeaders(headers, output);
output.put("status", "" + status);
}
}
private void debugRequestEntity(Map<String, Object> info, InputStream inputStream)
throws IOException {
if (RequestContext.getCurrentContext().isChunkedRequestBody()) {
info.put("body", "<chunked>");
return;
}
char[] buffer = new char[4096];
int count = new InputStreamReader(inputStream, Charset.forName("UTF-8"))
.read(buffer, 0, buffer.length);
if (count > 0) {
String entity = new String(buffer).substring(0, count);
info.put("body", entity.length() < 4096 ? entity : entity + "<truncated>");
}
}
}
@@ -111,7 +111,7 @@ public class ZuulProperties {
private boolean traceRequestBody = true;
/**
* Flag to say that path elelents past the first semicolon can be dropped.
* Flag to say that path elements past the first semicolon can be dropped.
*/
private boolean removeSemicolonContent = true;
@@ -125,6 +125,12 @@ public class ZuulProperties {
private Set<String> sensitiveHeaders = new LinkedHashSet<>(
Arrays.asList("Cookie", "Set-Cookie", "Authorization"));
/**
* Flag to say whether the hostname for ssl connections should be verified or not. Default is true.
* This should only be used in test setups!
*/
private boolean sslHostnameValidationEnabled =true;
public Set<String> getIgnoredHeaders() {
Set<String> ignoredHeaders = new LinkedHashSet<>(this.ignoredHeaders);
if (ClassUtils.isPresent(
@@ -53,11 +53,13 @@ import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.InputStreamEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.DefaultHttpRequestRetryHandler;
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;
@@ -66,7 +68,6 @@ import org.apache.http.protocol.HttpContext;
import org.springframework.cloud.netflix.zuul.filters.ProxyRequestHelper;
import org.springframework.cloud.netflix.zuul.filters.ZuulProperties;
import org.springframework.cloud.netflix.zuul.filters.ZuulProperties.Host;
import org.springframework.http.HttpStatus;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.util.StringUtils;
@@ -94,6 +95,8 @@ public class SimpleHostRoutingFilter extends ZuulFilter {
private final Timer connectionManagerTimer = new Timer(
"SimpleHostRoutingFilter.connectionManagerTimer", true);
private boolean sslHostnameValidationEnabled;
private ProxyRequestHelper helper;
private Host hostProperties;
private PoolingHttpClientConnectionManager connectionManager;
@@ -115,6 +118,7 @@ public class SimpleHostRoutingFilter extends ZuulFilter {
public SimpleHostRoutingFilter(ProxyRequestHelper helper, ZuulProperties properties) {
this.helper = helper;
this.hostProperties = properties.getHost();
this.sslHostnameValidationEnabled = properties.isSslHostnameValidationEnabled();
}
@PostConstruct
@@ -204,11 +208,18 @@ public class SimpleHostRoutingFilter extends ZuulFilter {
}
} }, new SecureRandom());
final Registry<ConnectionSocketFactory> registry = RegistryBuilder
RegistryBuilder<ConnectionSocketFactory> registryBuilder = RegistryBuilder
.<ConnectionSocketFactory> create()
.register("http", PlainConnectionSocketFactory.INSTANCE)
.register("https", new SSLConnectionSocketFactory(sslContext))
.build();
.register("http", PlainConnectionSocketFactory.INSTANCE);
if (sslHostnameValidationEnabled) {
registryBuilder.register("https",
new SSLConnectionSocketFactory(sslContext));
}
else {
registryBuilder.register("https", new SSLConnectionSocketFactory(
sslContext, NoopHostnameVerifier.INSTANCE));
}
final Registry<ConnectionSocketFactory> registry = registryBuilder.build();
this.connectionManager = new PoolingHttpClientConnectionManager(registry);
this.connectionManager
@@ -228,7 +239,11 @@ public class SimpleHostRoutingFilter extends ZuulFilter {
.setConnectTimeout(CONNECTION_TIMEOUT.get())
.setCookieSpec(CookieSpecs.IGNORE_COOKIES).build();
return HttpClients.custom().setConnectionManager(newConnectionManager())
HttpClientBuilder httpClientBuilder = HttpClients.custom();
if (!sslHostnameValidationEnabled) {
httpClientBuilder.setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE);
}
return httpClientBuilder.setConnectionManager(newConnectionManager())
.setDefaultRequestConfig(requestConfig)
.setRetryHandler(new DefaultHttpRequestRetryHandler(0, false))
.setRedirectStrategy(new RedirectStrategy() {
@@ -363,4 +378,11 @@ public class SimpleHostRoutingFilter extends ZuulFilter {
this.helper.addIgnoredHeaders(names);
}
/**
* Determines whether the filter enables the validation for ssl hostnames.
* @return
*/
boolean isSslHostnameValidationEnabled() {
return sslHostnameValidationEnabled;
}
}
@@ -35,6 +35,7 @@ import com.netflix.hystrix.HystrixCommandKey;
import com.netflix.hystrix.HystrixCommandProperties;
import com.netflix.zuul.constants.ZuulConstants;
import com.netflix.zuul.context.RequestContext;
import org.springframework.util.StringUtils;
/**
* @author Christian Lohmann
@@ -100,10 +101,15 @@ public class HttpClientRibbonCommand extends HystrixCommand<ClientHttpResponse>
protected ClientHttpResponse forward() throws Exception {
final RequestContext context = RequestContext.getCurrentContext();
Long contentLength = null;
String contentLengthHeader = context.getRequest().getHeader("Content-Length");
if (StringUtils.hasText(contentLengthHeader)) {
contentLength = new Long(contentLengthHeader);
}
URI uriInstance = new URI(this.uri);
RibbonApacheHttpRequest request = new RibbonApacheHttpRequest(this.method,
uriInstance, this.retryable, this.headers, this.params,
this.requestEntity);
this.requestEntity, contentLength);
final RibbonApacheHttpResponse response = this.client
.executeWithLoadBalancer(request);
context.set("ribbonResponse", response);
@@ -112,7 +112,7 @@ public class RibbonLoadBalancerClientTests {
public void testReconstructUriWithSecureClientConfig() {
RibbonServer server = getRibbonServer();
IClientConfig config = mock(IClientConfig.class);
when(config.get(CommonClientConfigKey.IsSecure, false)).thenReturn(true);
when(config.get(CommonClientConfigKey.IsSecure)).thenReturn(true);
when(clientFactory.getClientConfig(server.getServiceId())).thenReturn(config);
RibbonLoadBalancerClient client = getRibbonLoadBalancerClient(server);
@@ -124,6 +124,33 @@ public class RibbonLoadBalancerClientTests {
assertEquals("https", uri.getScheme());
}
@Test
@SneakyThrows
public void testReconstructSecureUriWithoutScheme() {
testReconstructSchemelessUriWithoutClientConfig(getSecureRibbonServer(), "https");
}
@Test
@SneakyThrows
public void testReconstructUnsecureSchemelessUri() {
testReconstructSchemelessUriWithoutClientConfig(getRibbonServer(), "http");
}
@SneakyThrows
public void testReconstructSchemelessUriWithoutClientConfig(RibbonServer server, String expectedScheme) {
IClientConfig config = mock(IClientConfig.class);
when(config.get(CommonClientConfigKey.IsSecure)).thenReturn(null);
when(clientFactory.getClientConfig(server.getServiceId())).thenReturn(config);
RibbonLoadBalancerClient client = getRibbonLoadBalancerClient(server);
ServiceInstance serviceInstance = client.choose(server.getServiceId());
URI uri = client.reconstructURI(serviceInstance,
new URI("//" + server.getServiceId()));
assertEquals(server.getHost(), uri.getHost());
assertEquals(server.getPort(), uri.getPort());
assertEquals(expectedScheme, uri.getScheme());
}
@Test
public void testChoose() {
RibbonServer server = getRibbonServer();
@@ -206,6 +233,11 @@ public class RibbonLoadBalancerClientTests {
Collections.singletonMap("mykey", "myvalue"));
}
protected RibbonServer getSecureRibbonServer() {
return new RibbonServer("testService", new Server("myhost", 8443), false,
Collections.singletonMap("mykey", "myvalue"));
}
protected void verifyServerStats() {
verify(this.serverStats).incrementActiveRequestsCount();
verify(this.serverStats).decrementActiveRequestsCount();
@@ -0,0 +1,109 @@
/*
* 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.apache;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.instanceOf;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.not;
import static org.hamcrest.Matchers.notNullValue;
import static org.hamcrest.Matchers.startsWith;
import static org.junit.Assert.assertThat;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.net.URI;
import java.nio.charset.Charset;
import org.apache.http.HttpEntity;
import org.apache.http.HttpEntityEnclosingRequest;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.HttpUriRequest;
import org.junit.Test;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.StreamUtils;
/**
* @author Spencer Gibb
*/
public class RibbonApacheHttpRequestTests {
@Test
public void testNullEntity() throws Exception {
URI uri = URI.create("http://example.com");
LinkedMultiValueMap<String, String> headers = new LinkedMultiValueMap<>();
headers.add("my-header", "my-value");
LinkedMultiValueMap<String, String> params = new LinkedMultiValueMap<>();
params.add("myparam", "myparamval");
RibbonApacheHttpRequest httpRequest = new RibbonApacheHttpRequest("GET", uri, false,
headers, params, null);
HttpUriRequest request = httpRequest.toRequest(RequestConfig.custom().build());
assertThat("request is wrong type", request, is(not(instanceOf(HttpEntityEnclosingRequest.class))));
assertThat("uri is wrong", request.getURI().toString(), startsWith(uri.toString()));
assertThat("my-header is missing", request.getFirstHeader("my-header"), is(notNullValue()));
assertThat("my-header is wrong", request.getFirstHeader("my-header").getValue(), is(equalTo("my-value")));
assertThat("myparam is missing", request.getURI().getQuery(), is(equalTo("myparam=myparamval")));
}
@Test
// this situation happens, see https://github.com/spring-cloud/spring-cloud-netflix/issues/1042#issuecomment-227723877
public void testEmptyEntityGet() throws Exception {
String entityValue = "";
testEntity(entityValue, new ByteArrayInputStream(entityValue.getBytes()), false, "GET");
}
@Test
public void testNonEmptyEntityPost() throws Exception {
String entityValue = "abcd";
testEntity(entityValue, new ByteArrayInputStream(entityValue.getBytes()), true, "POST");
}
void testEntity(String entityValue, ByteArrayInputStream requestEntity, boolean addContentLengthHeader, String method) throws IOException {
String lengthString = String.valueOf(entityValue.length());
Long length = null;
URI uri = URI.create("http://example.com");
LinkedMultiValueMap<String, String> headers = new LinkedMultiValueMap<>();
if (addContentLengthHeader) {
headers.add("Content-Length", lengthString);
length = (long) entityValue.length();
}
RibbonApacheHttpRequest httpRequest = new RibbonApacheHttpRequest(method, uri, false,
headers, new LinkedMultiValueMap<String, String>(), requestEntity,
length);
HttpUriRequest request = httpRequest.toRequest(RequestConfig.custom().build());
assertThat("request is wrong type", request, is(instanceOf(HttpEntityEnclosingRequest.class)));
assertThat("uri is wrong", request.getURI().toString(), startsWith(uri.toString()));
if (addContentLengthHeader) {
assertThat("Content-Length is missing", request.getFirstHeader("Content-Length"), is(notNullValue()));
assertThat("Content-Length is wrong", request.getFirstHeader("Content-Length").getValue(),
is(equalTo(lengthString)));
}
HttpEntityEnclosingRequest entityRequest = (HttpEntityEnclosingRequest) request;
assertThat("entity is missing", entityRequest.getEntity(), is(notNullValue()));
HttpEntity entity = entityRequest.getEntity();
assertThat("contentLength is wrong", entity.getContentLength(), is(equalTo((long)entityValue.length())));
assertThat("content is missing", entity.getContent(), is(notNullValue()));
String string = StreamUtils.copyToString(entity.getContent(), Charset.forName("UTF-8"));
assertThat("content is wrong", string, is(equalTo(entityValue)));
}
}
@@ -72,7 +72,7 @@ public class ProxyRequestHelperTests {
request.addHeader("multiName", "multiValue2");
RequestContext.getCurrentContext().setRequest(request);
ProxyRequestHelper helper = new ProxyRequestHelper();
TraceProxyRequestHelper helper = new TraceProxyRequestHelper();
this.traceRepository = new InMemoryTraceRepository();
helper.setTraces(this.traceRepository);
@@ -172,7 +172,7 @@ public class ProxyRequestHelperTests {
request.addHeader("multiName", "multiValue1");
request.addHeader("multiName", "multiValue2");
ProxyRequestHelper helper = new ProxyRequestHelper();
TraceProxyRequestHelper helper = new TraceProxyRequestHelper();
helper.setTraces(this.traceRepository);
MultiValueMap<String, String> headers = helper.buildZuulRequestHeaders(request);
@@ -28,6 +28,8 @@ import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.springframework.boot.test.EnvironmentTestUtils.addEnvironment;
/**
@@ -54,6 +56,21 @@ public class SimpleHostRoutingFilterTests {
assertEquals(10, connMgr.getDefaultMaxPerRoute());
}
@Test
public void validateSslHostnamesByDefault() {
setupContext();
assertTrue("Hostname verification should be enabled by default",
getFilter().isSslHostnameValidationEnabled());
}
@Test
public void validationOfSslHostnamesCanBeDisabledViaProperty() {
addEnvironment(this.context, "zuul.sslHostnameValidationEnabled=false");
setupContext();
assertFalse("Hostname verification should be disabled via property",
getFilter().isSslHostnameValidationEnabled());
}
@Test
public void defaultPropertiesAreApplied() {
setupContext();
+5 -5
View File
@@ -9,16 +9,16 @@
<relativePath/>
</parent>
<artifactId>spring-cloud-netflix-dependencies</artifactId>
<version>1.1.3.BUILD-SNAPSHOT</version>
<version>1.1.4.RELEASE</version>
<packaging>pom</packaging>
<name>spring-cloud-netflix-dependencies</name>
<description>Spring Cloud Netflix Dependencies</description>
<properties>
<spring-cloud-commons.version>1.1.2.BUILD-SNAPSHOT</spring-cloud-commons.version>
<spring-cloud-config.version>1.1.2.BUILD-SNAPSHOT</spring-cloud-config.version>
<spring-cloud-stream.version>1.0.3.BUILD-SNAPSHOT</spring-cloud-stream.version>
<spring-cloud-commons.version>1.1.1.RELEASE</spring-cloud-commons.version>
<spring-cloud-config.version>1.1.2.RELEASE</spring-cloud-config.version>
<spring-cloud-stream.version>1.0.2.RELEASE</spring-cloud-stream.version>
<archaius.version>0.7.4</archaius.version>
<eureka.version>1.4.8</eureka.version>
<eureka.version>1.4.9</eureka.version>
<feign.version>8.16.2</feign.version>
<hystrix.version>1.5.3</hystrix.version>
<ribbon.version>2.2.0</ribbon.version>
+1 -1
View File
@@ -5,7 +5,7 @@
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-netflix</artifactId>
<version>1.1.3.BUILD-SNAPSHOT</version>
<version>1.1.4.RELEASE</version>
<relativePath>..</relativePath> <!-- lookup parent from repository -->
</parent>
<artifactId>spring-cloud-netflix-eureka-client</artifactId>
+1 -1
View File
@@ -5,7 +5,7 @@
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-netflix</artifactId>
<version>1.1.3.BUILD-SNAPSHOT</version>
<version>1.1.4.RELEASE</version>
<relativePath>..</relativePath> <!-- lookup parent from repository -->
</parent>
<artifactId>spring-cloud-netflix-eureka-server</artifactId>
@@ -11,7 +11,9 @@ import org.springframework.util.StringUtils;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.Version;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ObjectReader;
import com.fasterxml.jackson.databind.ObjectWriter;
@@ -36,9 +38,13 @@ public class CloudJacksonJson extends LegacyJacksonJson {
protected final CloudJacksonCodec codec = new CloudJacksonCodec();
public CloudJacksonCodec getCodec() {
return codec;
}
@Override
public String codecName() {
return getCodecName(this.getClass());
return getCodecName(LegacyJacksonJson.class);
}
@Override
@@ -120,25 +126,26 @@ public class CloudJacksonJson extends LegacyJacksonJson {
static class CloudInstanceInfoSerializer extends InstanceInfoSerializer {
@Override
public void serialize(InstanceInfo info, JsonGenerator jgen,
public void serialize(final InstanceInfo info, JsonGenerator jgen,
SerializerProvider provider) throws IOException {
if (info.getInstanceId() == null && info.getMetadata() != null) {
String instanceId = calculateInstanceId(info);
info = new InstanceInfo.Builder(info).setInstanceId(instanceId).build();
}
super.serialize(info, jgen, provider);
InstanceInfo updated = updateIfNeeded(info);
super.serialize(updated, jgen, provider);
}
}
private String calculateInstanceId(InstanceInfo info) {
static InstanceInfo updateIfNeeded(final InstanceInfo info) {
if (info.getInstanceId() == null && info.getMetadata() != null) {
String instanceId = info.getMetadata().get("instanceId");
String hostName = info.getHostName();
if (instanceId != null && StringUtils.hasText(hostName) && !instanceId.startsWith(hostName)) {
instanceId = hostName + ":" + instanceId;
if (StringUtils.hasText(instanceId)) {
// backwards compatibility for Angel
if (StringUtils.hasText(info.getHostName()) && !instanceId.startsWith(info.getHostName())) {
instanceId = info.getHostName()+":"+instanceId;
}
return new InstanceInfo.Builder(info).setInstanceId(instanceId).build();
}
return instanceId == null ? hostName : instanceId;
}
return info;
}
static class CloudInstanceInfoDeserializer extends InstanceInfoDeserializer {
@@ -146,5 +153,12 @@ public class CloudJacksonJson extends LegacyJacksonJson {
protected CloudInstanceInfoDeserializer(ObjectMapper mapper) {
super(mapper);
}
@Override
public InstanceInfo deserialize(JsonParser jp, DeserializationContext context) throws IOException {
InstanceInfo info = super.deserialize(jp, context);
InstanceInfo updated = updateIfNeeded(info);
return updated;
}
}
}
@@ -52,6 +52,7 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter
import com.netflix.appinfo.ApplicationInfoManager;
import com.netflix.discovery.EurekaClient;
import com.netflix.discovery.EurekaClientConfig;
import com.netflix.discovery.converters.EurekaJacksonCodec;
import com.netflix.discovery.converters.wrappers.CodecWrapper;
import com.netflix.discovery.converters.wrappers.CodecWrappers;
import com.netflix.eureka.DefaultEurekaServerContext;
@@ -102,6 +103,7 @@ public class EurekaServerConfiguration extends WebMvcConfigurerAdapter {
@Value("${eureka.server.defaultOpenForTrafficCount:1}")
private int defaultOpenForTrafficCount;
public static final CloudJacksonJson JACKSON_JSON = new CloudJacksonJson();
@Bean
public HasFeatures eurekaServerFeature() {
@@ -128,15 +130,19 @@ public class EurekaServerConfiguration extends WebMvcConfigurerAdapter {
return new EurekaController(this.applicationInfoManager);
}
static {
CodecWrappers.registerWrapper(JACKSON_JSON);
EurekaJacksonCodec.setInstance(JACKSON_JSON.getCodec());
}
@Bean
public ServerCodecs serverCodecs() {
CodecWrappers.registerWrapper(new CloudJacksonJson());
return new CloudServerCodecs(this.eurekaServerConfig);
}
private static CodecWrapper getFullJson(EurekaServerConfig serverConfig) {
CodecWrapper codec = CodecWrappers.getCodec(serverConfig.getJsonCodecName());
return codec == null ? CodecWrappers.getCodec(CloudJacksonJson.class) : codec;
return codec == null ? CodecWrappers.getCodec(JACKSON_JSON.codecName()) : codec;
}
private static CodecWrapper getFullXml(EurekaServerConfig serverConfig) {
+1 -1
View File
@@ -5,7 +5,7 @@
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-netflix</artifactId>
<version>1.1.3.BUILD-SNAPSHOT</version>
<version>1.1.4.RELEASE</version>
<relativePath>..</relativePath> <!-- lookup parent from repository -->
</parent>
<artifactId>spring-cloud-netflix-hystrix-amqp</artifactId>
@@ -8,7 +8,7 @@
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-netflix</artifactId>
<version>1.1.3.BUILD-SNAPSHOT</version>
<version>1.1.4.RELEASE</version>
<relativePath>..</relativePath> <!-- lookup parent from repository -->
</parent>
<properties>
@@ -114,9 +114,6 @@
convertAvg(data, "errorPercentage", true);
convertAvg(data, "latencyExecute_mean", false);
convertAvg(data, "latencyTotal_mean", false);
// the following will break when it becomes a compound string if the property is dynamically changed
convertAvg(data, "propertyValue_metricsRollingStatisticalWindowInMilliseconds", false);
}
function convertAvg(data, key, decimal) {
+1 -1
View File
@@ -5,7 +5,7 @@
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-netflix</artifactId>
<version>1.1.3.BUILD-SNAPSHOT</version>
<version>1.1.4.RELEASE</version>
<relativePath>..</relativePath> <!-- lookup parent from repository -->
</parent>
<artifactId>spring-cloud-netflix-hystrix-stream</artifactId>
@@ -23,11 +23,14 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cloud.client.actuator.HasFeatures;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.cloud.stream.annotation.EnableBinding;
import org.springframework.cloud.stream.annotation.Output;
import org.springframework.cloud.stream.config.BindingProperties;
import org.springframework.cloud.stream.config.ChannelBindingServiceProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.messaging.MessageChannel;
import org.springframework.scheduling.annotation.EnableScheduling;
import com.netflix.hystrix.HystrixCircuitBreaker;
@@ -57,6 +60,10 @@ public class HystrixStreamAutoConfiguration {
@Autowired
private HystrixStreamProperties properties;
@Autowired
@Output(HystrixStreamClient.OUTPUT)
private MessageChannel outboundChannel;
@Bean
public HasFeatures hystrixStreamQueueFeature() {
return HasFeatures.namedFeature("Hystrix Stream (Queue)",
@@ -87,8 +94,8 @@ public class HystrixStreamAutoConfiguration {
}
@Bean
public HystrixStreamTask hystrixStreamTask() {
return new HystrixStreamTask();
public HystrixStreamTask hystrixStreamTask(DiscoveryClient discoveryClient) {
return new HystrixStreamTask(this.outboundChannel, discoveryClient, this.properties);
}
}
@@ -28,14 +28,28 @@ import lombok.Data;
@Data
public class HystrixStreamProperties {
/** Flag to indicate that Hystrix Stream is enabled. Default is true. */
private boolean enabled = true;
/** Flag to indicate to prefix metric names with serviceId. Default is true. */
private boolean prefixMetricName = true;
/** Flag to indicate to send the id field in the metrics. Default is true */
private boolean sendId = true;
/** The destination of the stream. Destination as defined by Spring Cloud Stream. Defaults to springCloudHystrixStream */
private String destination = HystrixConstants.HYSTRIX_STREAM_DESTINATION;
/** The content type of the messages. Defaults to application/json */
private String contentType = "application/json";
/** How often (in ms) to send messages to the stream. Defaults to 500. */
private long sendRate = 500;
/** How often to put messages in the queue. This queue drains to the stream. Defaults to 500. */
private long gatherRate = 500;
/** The size of the metrics queue. This queue drains to the stream. Defaults to 1000. */
private int size = 1000;
}
@@ -23,10 +23,8 @@ import java.util.Collection;
import java.util.concurrent.LinkedBlockingQueue;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.cloud.stream.annotation.Output;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.messaging.MessageChannel;
@@ -55,24 +53,26 @@ import lombok.extern.apachecommons.CommonsLog;
@CommonsLog
public class HystrixStreamTask implements ApplicationContextAware {
@Autowired
@Output(HystrixStreamClient.OUTPUT)
private MessageChannel outboundChannel;
@Autowired
private DiscoveryClient discoveryClient;
private HystrixStreamProperties properties;
private ApplicationContext context;
@Autowired
private HystrixStreamProperties properties;
// Visible for testing
final LinkedBlockingQueue<String> jsonMetrics = new LinkedBlockingQueue<>(
1000);
final LinkedBlockingQueue<String> jsonMetrics;
private final JsonFactory jsonFactory = new JsonFactory();
public HystrixStreamTask(MessageChannel outboundChannel, DiscoveryClient discoveryClient, HystrixStreamProperties properties) {
this.outboundChannel = outboundChannel;
this.discoveryClient = discoveryClient;
this.properties = properties;
this.jsonMetrics = new LinkedBlockingQueue<>(properties.getSize());
}
@Override
public void setApplicationContext(ApplicationContext applicationContext)
throws BeansException {
@@ -95,7 +95,7 @@ public class HystrixStreamTask implements ApplicationContextAware {
// TODO: remove the explicit content type when s-c-stream can handle that for us
this.outboundChannel.send(MessageBuilder.withPayload(json)
.setHeader(MessageHeaders.CONTENT_TYPE,
"application/json")
this.properties.getContentType())
.build());
}
catch (Exception ex) {
@@ -61,8 +61,9 @@ public class HystrixStreamTaskTests {
new HystrixPropertiesCommandDefault(hystrixCommandKey, HystrixCommandProperties.defaultSetter()));
given(this.discoveryClient.getLocalServiceInstance()).willReturn(this.serviceInstance);
this.hystrixStreamTask.setApplicationContext(this.context);
this.hystrixStreamTask.gatherMetrics();
assertThat(this.hystrixStreamTask.jsonMetrics.isEmpty(), is(false));
}
}
}
+1 -1
View File
@@ -5,7 +5,7 @@
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-netflix</artifactId>
<version>1.1.3.BUILD-SNAPSHOT</version>
<version>1.1.4.RELEASE</version>
<relativePath>..</relativePath> <!-- lookup parent from repository -->
</parent>
<artifactId>spring-cloud-netflix-sidecar</artifactId>
+1 -1
View File
@@ -6,7 +6,7 @@
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-netflix</artifactId>
<version>1.1.3.BUILD-SNAPSHOT</version>
<version>1.1.4.RELEASE</version>
<relativePath>..</relativePath> <!-- lookup parent from repository -->
</parent>
<artifactId>spring-cloud-netflix-spectator</artifactId>
+1 -1
View File
@@ -5,7 +5,7 @@
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-netflix</artifactId>
<version>1.1.3.BUILD-SNAPSHOT</version>
<version>1.1.4.RELEASE</version>
<relativePath>..</relativePath> <!-- lookup parent from repository -->
</parent>
<artifactId>spring-cloud-netflix-turbine-stream</artifactId>
+1 -1
View File
@@ -5,7 +5,7 @@
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-netflix</artifactId>
<version>1.1.3.BUILD-SNAPSHOT</version>
<version>1.1.4.RELEASE</version>
<relativePath>..</relativePath> <!-- lookup parent from repository -->
</parent>
<artifactId>spring-cloud-netflix-turbine</artifactId>
+1 -1
View File
@@ -5,7 +5,7 @@
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-netflix</artifactId>
<version>1.1.3.BUILD-SNAPSHOT</version>
<version>1.1.4.RELEASE</version>
<relativePath>..</relativePath> <!-- lookup parent from repository -->
</parent>
<artifactId>spring-cloud-starter-archaius</artifactId>
+1 -1
View File
@@ -5,7 +5,7 @@
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-netflix</artifactId>
<version>1.1.3.BUILD-SNAPSHOT</version>
<version>1.1.4.RELEASE</version>
<relativePath>..</relativePath> <!-- lookup parent from repository -->
</parent>
<artifactId>spring-cloud-starter-atlas</artifactId>
+1 -1
View File
@@ -5,7 +5,7 @@
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-netflix</artifactId>
<version>1.1.3.BUILD-SNAPSHOT</version>
<version>1.1.4.RELEASE</version>
<relativePath>..</relativePath> <!-- lookup parent from repository -->
</parent>
<artifactId>spring-cloud-starter-eureka-server</artifactId>
+1 -1
View File
@@ -5,7 +5,7 @@
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-netflix</artifactId>
<version>1.1.3.BUILD-SNAPSHOT</version>
<version>1.1.4.RELEASE</version>
<relativePath>..</relativePath> <!-- lookup parent from repository -->
</parent>
<artifactId>spring-cloud-starter-eureka</artifactId>
+1 -1
View File
@@ -5,7 +5,7 @@
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-netflix</artifactId>
<version>1.1.3.BUILD-SNAPSHOT</version>
<version>1.1.4.RELEASE</version>
<relativePath>..</relativePath> <!-- lookup parent from repository -->
</parent>
<artifactId>spring-cloud-starter-feign</artifactId>
@@ -5,7 +5,7 @@
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-netflix</artifactId>
<version>1.1.3.BUILD-SNAPSHOT</version>
<version>1.1.4.RELEASE</version>
<relativePath>..</relativePath> <!-- lookup parent from repository -->
</parent>
<artifactId>spring-cloud-starter-hystrix-dashboard</artifactId>
+1 -1
View File
@@ -5,7 +5,7 @@
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-netflix</artifactId>
<version>1.1.3.BUILD-SNAPSHOT</version>
<version>1.1.4.RELEASE</version>
<relativePath>..</relativePath> <!-- lookup parent from repository -->
</parent>
<artifactId>spring-cloud-starter-hystrix</artifactId>
+1 -1
View File
@@ -5,7 +5,7 @@
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-netflix</artifactId>
<version>1.1.3.BUILD-SNAPSHOT</version>
<version>1.1.4.RELEASE</version>
<relativePath>..</relativePath> <!-- lookup parent from repository -->
</parent>
<artifactId>spring-cloud-starter-ribbon</artifactId>
+1 -1
View File
@@ -5,7 +5,7 @@
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-netflix</artifactId>
<version>1.1.3.BUILD-SNAPSHOT</version>
<version>1.1.4.RELEASE</version>
<relativePath>..</relativePath> <!-- lookup parent from repository -->
</parent>
<artifactId>spring-cloud-starter-spectator</artifactId>
+1 -1
View File
@@ -5,7 +5,7 @@
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-netflix</artifactId>
<version>1.1.3.BUILD-SNAPSHOT</version>
<version>1.1.4.RELEASE</version>
<relativePath>..</relativePath> <!-- lookup parent from repository -->
</parent>
<artifactId>spring-cloud-starter-turbine-amqp</artifactId>
+1 -1
View File
@@ -5,7 +5,7 @@
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-netflix</artifactId>
<version>1.1.3.BUILD-SNAPSHOT</version>
<version>1.1.4.RELEASE</version>
<relativePath>..</relativePath> <!-- lookup parent from repository -->
</parent>
<artifactId>spring-cloud-starter-turbine-stream</artifactId>
+1 -1
View File
@@ -5,7 +5,7 @@
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-netflix</artifactId>
<version>1.1.3.BUILD-SNAPSHOT</version>
<version>1.1.4.RELEASE</version>
<relativePath>..</relativePath> <!-- lookup parent from repository -->
</parent>
<artifactId>spring-cloud-starter-turbine</artifactId>
+1 -1
View File
@@ -5,7 +5,7 @@
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-netflix</artifactId>
<version>1.1.3.BUILD-SNAPSHOT</version>
<version>1.1.4.RELEASE</version>
<relativePath>..</relativePath> <!-- lookup parent from repository -->
</parent>
<artifactId>spring-cloud-starter-zuul</artifactId>