Merge branch 'master' into 2.0.x
This commit is contained in:
@@ -1107,7 +1107,7 @@ favor for an opt-in approach.
|
||||
[[spring-cloud-feign-hystrix-fallback]]
|
||||
=== Feign Hystrix Fallbacks
|
||||
|
||||
Hystrix supports the notion of a fallback: a default code path that is executed when they circuit is open or there is an error. To enable fallbacks for a given `@FeignClient` set the `fallback` attribute to the class name that implements the fallback.
|
||||
Hystrix supports the notion of a fallback: a default code path that is executed when they circuit is open or there is an error. To enable fallbacks for a given `@FeignClient` set the `fallback` attribute to the class name that implements the fallback. You also need to declare your implementation as a Spring bean.
|
||||
|
||||
[source,java,indent=0]
|
||||
----
|
||||
|
||||
286
mvnw.cmd
vendored
286
mvnw.cmd
vendored
@@ -1,145 +1,145 @@
|
||||
@REM ----------------------------------------------------------------------------
|
||||
@REM Licensed to the Apache Software Foundation (ASF) under one
|
||||
@REM or more contributor license agreements. See the NOTICE file
|
||||
@REM distributed with this work for additional information
|
||||
@REM regarding copyright ownership. The ASF licenses this file
|
||||
@REM to you under the Apache License, Version 2.0 (the
|
||||
@REM "License"); you may not use this file except in compliance
|
||||
@REM with the License. You may obtain a copy of the License at
|
||||
@REM
|
||||
@REM http://www.apache.org/licenses/LICENSE-2.0
|
||||
@REM
|
||||
@REM Unless required by applicable law or agreed to in writing,
|
||||
@REM software distributed under the License is distributed on an
|
||||
@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
@REM KIND, either express or implied. See the License for the
|
||||
@REM specific language governing permissions and limitations
|
||||
@REM under the License.
|
||||
@REM ----------------------------------------------------------------------------
|
||||
|
||||
@REM ----------------------------------------------------------------------------
|
||||
@REM Maven2 Start Up Batch script
|
||||
@REM
|
||||
@REM Required ENV vars:
|
||||
@REM JAVA_HOME - location of a JDK home dir
|
||||
@REM
|
||||
@REM Optional ENV vars
|
||||
@REM M2_HOME - location of maven2's installed home dir
|
||||
@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
|
||||
@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending
|
||||
@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
|
||||
@REM e.g. to debug Maven itself, use
|
||||
@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
|
||||
@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
|
||||
@REM ----------------------------------------------------------------------------
|
||||
|
||||
@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
|
||||
@echo off
|
||||
@REM enable echoing my setting MAVEN_BATCH_ECHO to 'on'
|
||||
@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
|
||||
|
||||
@REM set %HOME% to equivalent of $HOME
|
||||
if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
|
||||
|
||||
@REM Execute a user defined script before this one
|
||||
if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
|
||||
@REM check for pre script, once with legacy .bat ending and once with .cmd ending
|
||||
if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat"
|
||||
if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd"
|
||||
:skipRcPre
|
||||
|
||||
@setlocal
|
||||
|
||||
set ERROR_CODE=0
|
||||
|
||||
@REM To isolate internal variables from possible post scripts, we use another setlocal
|
||||
@setlocal
|
||||
|
||||
@REM ==== START VALIDATION ====
|
||||
if not "%JAVA_HOME%" == "" goto OkJHome
|
||||
|
||||
echo.
|
||||
echo Error: JAVA_HOME not found in your environment. >&2
|
||||
echo Please set the JAVA_HOME variable in your environment to match the >&2
|
||||
echo location of your Java installation. >&2
|
||||
echo.
|
||||
goto error
|
||||
|
||||
:OkJHome
|
||||
if exist "%JAVA_HOME%\bin\java.exe" goto init
|
||||
|
||||
echo.
|
||||
echo Error: JAVA_HOME is set to an invalid directory. >&2
|
||||
echo JAVA_HOME = "%JAVA_HOME%" >&2
|
||||
echo Please set the JAVA_HOME variable in your environment to match the >&2
|
||||
echo location of your Java installation. >&2
|
||||
echo.
|
||||
goto error
|
||||
|
||||
@REM ==== END VALIDATION ====
|
||||
|
||||
:init
|
||||
|
||||
set MAVEN_CMD_LINE_ARGS=%*
|
||||
|
||||
@REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
|
||||
@REM Fallback to current working directory if not found.
|
||||
|
||||
set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
|
||||
IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
|
||||
|
||||
set EXEC_DIR=%CD%
|
||||
set WDIR=%EXEC_DIR%
|
||||
:findBaseDir
|
||||
IF EXIST "%WDIR%"\.mvn goto baseDirFound
|
||||
cd ..
|
||||
IF "%WDIR%"=="%CD%" goto baseDirNotFound
|
||||
set WDIR=%CD%
|
||||
goto findBaseDir
|
||||
|
||||
:baseDirFound
|
||||
set MAVEN_PROJECTBASEDIR=%WDIR%
|
||||
cd "%EXEC_DIR%"
|
||||
goto endDetectBaseDir
|
||||
|
||||
:baseDirNotFound
|
||||
set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
|
||||
cd "%EXEC_DIR%"
|
||||
|
||||
:endDetectBaseDir
|
||||
|
||||
IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
|
||||
|
||||
@setlocal EnableExtensions EnableDelayedExpansion
|
||||
for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
|
||||
@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
|
||||
|
||||
:endReadAdditionalConfig
|
||||
|
||||
SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
|
||||
@REM ----------------------------------------------------------------------------
|
||||
@REM Licensed to the Apache Software Foundation (ASF) under one
|
||||
@REM or more contributor license agreements. See the NOTICE file
|
||||
@REM distributed with this work for additional information
|
||||
@REM regarding copyright ownership. The ASF licenses this file
|
||||
@REM to you under the Apache License, Version 2.0 (the
|
||||
@REM "License"); you may not use this file except in compliance
|
||||
@REM with the License. You may obtain a copy of the License at
|
||||
@REM
|
||||
@REM http://www.apache.org/licenses/LICENSE-2.0
|
||||
@REM
|
||||
@REM Unless required by applicable law or agreed to in writing,
|
||||
@REM software distributed under the License is distributed on an
|
||||
@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
@REM KIND, either express or implied. See the License for the
|
||||
@REM specific language governing permissions and limitations
|
||||
@REM under the License.
|
||||
@REM ----------------------------------------------------------------------------
|
||||
|
||||
@REM ----------------------------------------------------------------------------
|
||||
@REM Maven2 Start Up Batch script
|
||||
@REM
|
||||
@REM Required ENV vars:
|
||||
@REM JAVA_HOME - location of a JDK home dir
|
||||
@REM
|
||||
@REM Optional ENV vars
|
||||
@REM M2_HOME - location of maven2's installed home dir
|
||||
@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
|
||||
@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending
|
||||
@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
|
||||
@REM e.g. to debug Maven itself, use
|
||||
@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
|
||||
@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
|
||||
@REM ----------------------------------------------------------------------------
|
||||
|
||||
@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
|
||||
@echo off
|
||||
@REM enable echoing my setting MAVEN_BATCH_ECHO to 'on'
|
||||
@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
|
||||
|
||||
@REM set %HOME% to equivalent of $HOME
|
||||
if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
|
||||
|
||||
@REM Execute a user defined script before this one
|
||||
if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
|
||||
@REM check for pre script, once with legacy .bat ending and once with .cmd ending
|
||||
if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat"
|
||||
if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd"
|
||||
:skipRcPre
|
||||
|
||||
@setlocal
|
||||
|
||||
set ERROR_CODE=0
|
||||
|
||||
@REM To isolate internal variables from possible post scripts, we use another setlocal
|
||||
@setlocal
|
||||
|
||||
@REM ==== START VALIDATION ====
|
||||
if not "%JAVA_HOME%" == "" goto OkJHome
|
||||
|
||||
echo.
|
||||
echo Error: JAVA_HOME not found in your environment. >&2
|
||||
echo Please set the JAVA_HOME variable in your environment to match the >&2
|
||||
echo location of your Java installation. >&2
|
||||
echo.
|
||||
goto error
|
||||
|
||||
:OkJHome
|
||||
if exist "%JAVA_HOME%\bin\java.exe" goto init
|
||||
|
||||
echo.
|
||||
echo Error: JAVA_HOME is set to an invalid directory. >&2
|
||||
echo JAVA_HOME = "%JAVA_HOME%" >&2
|
||||
echo Please set the JAVA_HOME variable in your environment to match the >&2
|
||||
echo location of your Java installation. >&2
|
||||
echo.
|
||||
goto error
|
||||
|
||||
@REM ==== END VALIDATION ====
|
||||
|
||||
:init
|
||||
|
||||
set MAVEN_CMD_LINE_ARGS=%*
|
||||
|
||||
@REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
|
||||
@REM Fallback to current working directory if not found.
|
||||
|
||||
set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
|
||||
IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
|
||||
|
||||
set EXEC_DIR=%CD%
|
||||
set WDIR=%EXEC_DIR%
|
||||
:findBaseDir
|
||||
IF EXIST "%WDIR%"\.mvn goto baseDirFound
|
||||
cd ..
|
||||
IF "%WDIR%"=="%CD%" goto baseDirNotFound
|
||||
set WDIR=%CD%
|
||||
goto findBaseDir
|
||||
|
||||
:baseDirFound
|
||||
set MAVEN_PROJECTBASEDIR=%WDIR%
|
||||
cd "%EXEC_DIR%"
|
||||
goto endDetectBaseDir
|
||||
|
||||
:baseDirNotFound
|
||||
set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
|
||||
cd "%EXEC_DIR%"
|
||||
|
||||
:endDetectBaseDir
|
||||
|
||||
IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
|
||||
|
||||
@setlocal EnableExtensions EnableDelayedExpansion
|
||||
for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
|
||||
@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
|
||||
|
||||
:endReadAdditionalConfig
|
||||
|
||||
SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
|
||||
|
||||
set WRAPPER_JAR="".\.mvn\wrapper\maven-wrapper.jar""
|
||||
set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
|
||||
|
||||
%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CMD_LINE_ARGS%
|
||||
if ERRORLEVEL 1 goto error
|
||||
goto end
|
||||
|
||||
:error
|
||||
set ERROR_CODE=1
|
||||
|
||||
:end
|
||||
@endlocal & set ERROR_CODE=%ERROR_CODE%
|
||||
|
||||
if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost
|
||||
@REM check for post script, once with legacy .bat ending and once with .cmd ending
|
||||
if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat"
|
||||
if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd"
|
||||
:skipRcPost
|
||||
|
||||
@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
|
||||
if "%MAVEN_BATCH_PAUSE%" == "on" pause
|
||||
|
||||
if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE%
|
||||
|
||||
exit /B %ERROR_CODE%
|
||||
set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
|
||||
|
||||
%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CMD_LINE_ARGS%
|
||||
if ERRORLEVEL 1 goto error
|
||||
goto end
|
||||
|
||||
:error
|
||||
set ERROR_CODE=1
|
||||
|
||||
:end
|
||||
@endlocal & set ERROR_CODE=%ERROR_CODE%
|
||||
|
||||
if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost
|
||||
@REM check for post script, once with legacy .bat ending and once with .cmd ending
|
||||
if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat"
|
||||
if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd"
|
||||
:skipRcPost
|
||||
|
||||
@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
|
||||
if "%MAVEN_BATCH_PAUSE%" == "on" pause
|
||||
|
||||
if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE%
|
||||
|
||||
exit /B %ERROR_CODE%
|
||||
|
||||
@@ -107,7 +107,7 @@ public @interface FeignClient {
|
||||
String path() default "";
|
||||
|
||||
/**
|
||||
* Whether to mark the feign proxy as a primary bean. Defaults to false.
|
||||
* Whether to mark the feign proxy as a primary bean. Defaults to true.
|
||||
*/
|
||||
boolean primary() default true;
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@ import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
import java.lang.reflect.Type;
|
||||
import java.lang.reflect.WildcardType;
|
||||
|
||||
import org.springframework.beans.factory.ObjectFactory;
|
||||
import org.springframework.boot.autoconfigure.http.HttpMessageConverters;
|
||||
@@ -48,9 +49,10 @@ public class SpringDecoder implements Decoder {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object decode(final Response response, Type type) throws IOException,
|
||||
FeignException {
|
||||
if (type instanceof Class || type instanceof ParameterizedType) {
|
||||
public Object decode(final Response response, Type type)
|
||||
throws IOException, FeignException {
|
||||
if (type instanceof Class || type instanceof ParameterizedType
|
||||
|| type instanceof WildcardType) {
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
HttpMessageConverterExtractor<?> extractor = new HttpMessageConverterExtractor(
|
||||
type, this.messageConverters.getObject().getConverters());
|
||||
|
||||
@@ -74,11 +74,6 @@ public class HystrixSecurityAutoConfiguration {
|
||||
super(ConfigurationPhase.REGISTER_BEAN);
|
||||
}
|
||||
|
||||
@ConditionalOnProperty(name = "feign.hystrix.enabled", matchIfMissing = false)
|
||||
static class HystrixEnabled {
|
||||
|
||||
}
|
||||
|
||||
@ConditionalOnProperty(name = "hystrix.shareSecurityContext")
|
||||
static class ShareSecurityContext {
|
||||
|
||||
|
||||
@@ -83,6 +83,11 @@ public class SimpleRouteLocator implements RouteLocator, Ordered {
|
||||
@Override
|
||||
public Route getMatchingRoute(final String path) {
|
||||
|
||||
return getSimpleMatchingRoute(path);
|
||||
|
||||
}
|
||||
|
||||
protected Route getSimpleMatchingRoute(final String path) {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Finding route for path: " + path);
|
||||
}
|
||||
@@ -102,29 +107,31 @@ public class SimpleRouteLocator implements RouteLocator, Ordered {
|
||||
|
||||
String adjustedPath = adjustPath(path);
|
||||
|
||||
ZuulRoute route = null;
|
||||
ZuulRoute route = getZuulRoute(adjustedPath);
|
||||
|
||||
return getRoute(route, adjustedPath);
|
||||
}
|
||||
|
||||
protected ZuulRoute getZuulRoute(String adjustedPath) {
|
||||
if (!matchesIgnoredPatterns(adjustedPath)) {
|
||||
for (Entry<String, ZuulRoute> entry : this.routes.get().entrySet()) {
|
||||
String pattern = entry.getKey();
|
||||
log.debug("Matching pattern:" + pattern);
|
||||
if (this.pathMatcher.match(pattern, adjustedPath)) {
|
||||
route = entry.getValue();
|
||||
break;
|
||||
return entry.getValue();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("route matched=" + route);
|
||||
}
|
||||
|
||||
return getRoute(route, adjustedPath);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private Route getRoute(ZuulRoute route, String path) {
|
||||
protected Route getRoute(ZuulRoute route, String path) {
|
||||
if (route == null) {
|
||||
return null;
|
||||
}
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("route matched=" + route);
|
||||
}
|
||||
String targetPath = path;
|
||||
String prefix = this.properties.getPrefix();
|
||||
if (path.startsWith(prefix) && this.properties.isStripPrefix()) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2015 the original author or authors.
|
||||
* Copyright 2013-2017 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.
|
||||
@@ -33,6 +33,7 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import static com.netflix.hystrix.HystrixCommandProperties.ExecutionIsolationStrategy.SEMAPHORE;
|
||||
|
||||
@@ -40,6 +41,7 @@ import static com.netflix.hystrix.HystrixCommandProperties.ExecutionIsolationStr
|
||||
* @author Spencer Gibb
|
||||
* @author Dave Syer
|
||||
* @author Mathias Düsterhöft
|
||||
* @author Bilal Alp
|
||||
*/
|
||||
@Data
|
||||
@ConfigurationProperties("zuul")
|
||||
@@ -326,6 +328,14 @@ public class ZuulProperties {
|
||||
* The maximum number of connections that can be used by a single route.
|
||||
*/
|
||||
private int maxPerRouteConnections = 20;
|
||||
/**
|
||||
* The lifetime for the connection pool.
|
||||
*/
|
||||
private long timeToLive = -1;
|
||||
/**
|
||||
* The time unit for timeToLive.
|
||||
*/
|
||||
private TimeUnit timeUnit = TimeUnit.MILLISECONDS;
|
||||
}
|
||||
|
||||
@Data
|
||||
|
||||
@@ -71,7 +71,7 @@ public class SendResponseFilter extends ZuulFilter {
|
||||
|
||||
public SendResponseFilter() {
|
||||
super();
|
||||
// To support Servlet API 3.0.1 we need to check if setcontentLengthLong exists
|
||||
// To support Servlet API 3.1 we need to check if setContentLengthLong exists
|
||||
try {
|
||||
HttpServletResponse.class.getMethod("setContentLengthLong");
|
||||
} catch(NoSuchMethodException e) {
|
||||
|
||||
@@ -68,7 +68,7 @@ public class RibbonRoutingFilter extends ZuulFilter {
|
||||
this.helper = helper;
|
||||
this.ribbonCommandFactory = ribbonCommandFactory;
|
||||
this.requestCustomizers = requestCustomizers;
|
||||
// To support Servlet API 3.0.1 we need to check if getcontentLengthLong exists
|
||||
// To support Servlet API 3.1 we need to check if getContentLengthLong exists
|
||||
try {
|
||||
HttpServletRequest.class.getMethod("getContentLengthLong");
|
||||
} catch(NoSuchMethodException e) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2015 the original author or authors.
|
||||
* Copyright 2013-2017 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.
|
||||
@@ -92,6 +92,7 @@ import static org.springframework.cloud.netflix.zuul.filters.support.FilterConst
|
||||
*
|
||||
* @author Spencer Gibb
|
||||
* @author Dave Syer
|
||||
* @author Bilal Alp
|
||||
*/
|
||||
public class SimpleHostRoutingFilter extends ZuulFilter {
|
||||
|
||||
@@ -235,7 +236,8 @@ public class SimpleHostRoutingFilter extends ZuulFilter {
|
||||
}
|
||||
final Registry<ConnectionSocketFactory> registry = registryBuilder.build();
|
||||
|
||||
this.connectionManager = new PoolingHttpClientConnectionManager(registry);
|
||||
this.connectionManager = new PoolingHttpClientConnectionManager(registry, null, null, null,
|
||||
hostProperties.getTimeToLive(), hostProperties.getTimeUnit());
|
||||
this.connectionManager
|
||||
.setMaxTotal(this.hostProperties.getMaxTotalConnections());
|
||||
this.connectionManager.setDefaultMaxPerRoute(
|
||||
|
||||
@@ -19,9 +19,11 @@ package org.springframework.cloud.netflix.feign;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
@@ -36,6 +38,7 @@ import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.test.annotation.DirtiesContext;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
@@ -108,6 +111,19 @@ public class SpringDecoderTests extends FeignClientFactoryBean {
|
||||
assertEquals("first hello didn't match", "hello world 1", hellos.get(0));
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void testWildcardTypeDecode() {
|
||||
ResponseEntity<?> wildcard = testClient().getWildcard();
|
||||
assertNotNull("wildcard was null", wildcard);
|
||||
assertEquals("wrong status code", HttpStatus.OK, wildcard.getStatusCode());
|
||||
Object wildcardBody = wildcard.getBody();
|
||||
assertNotNull("wildcardBody was null", wildcardBody);
|
||||
assertTrue("wildcard not an instance of Map", wildcardBody instanceof Map);
|
||||
Map<String, String> hello = (Map<String, String>) wildcardBody;
|
||||
assertEquals("first hello didn't match", "wildcard", hello.get("message"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testResponseEntityVoid() {
|
||||
ResponseEntity<Void> response = testClient().getHelloVoid();
|
||||
@@ -156,6 +172,9 @@ public class SpringDecoderTests extends FeignClientFactoryBean {
|
||||
|
||||
@RequestMapping(method = RequestMethod.GET, value = "/hellonotfound")
|
||||
ResponseEntity<String> getNotFound();
|
||||
|
||||
@GetMapping("/helloWildcard")
|
||||
ResponseEntity<?> getWildcard();
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@@ -199,6 +218,11 @@ public class SpringDecoderTests extends FeignClientFactoryBean {
|
||||
return ResponseEntity.status(HttpStatus.NOT_FOUND).body((String) null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResponseEntity<?> getWildcard() {
|
||||
return ResponseEntity.ok(new Hello("wildcard"));
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
new SpringApplicationBuilder(Application.class)
|
||||
.properties("spring.application.name=springdecodertest",
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright 2013-2017 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.hystrix.security;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.test.annotation.DirtiesContext;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
import com.netflix.hystrix.strategy.HystrixPlugins;
|
||||
import com.netflix.hystrix.strategy.concurrency.HystrixConcurrencyStrategy;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
@RunWith(SpringRunner.class)
|
||||
@DirtiesContext
|
||||
@SpringBootTest(classes = HystrixSecurityApplication.class)
|
||||
public class HystrixSecurityNoFeignTests {
|
||||
|
||||
@Test
|
||||
public void testSecurityConcurrencyStrategyInstalled() {
|
||||
HystrixConcurrencyStrategy concurrencyStrategy = HystrixPlugins.getInstance().getConcurrencyStrategy();
|
||||
assertThat(concurrencyStrategy).isInstanceOf(SecurityContextConcurrencyStrategy.class);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -18,6 +18,8 @@ package org.springframework.cloud.netflix.hystrix.security;
|
||||
|
||||
import java.util.Base64;
|
||||
|
||||
import com.netflix.hystrix.strategy.HystrixPlugins;
|
||||
import com.netflix.hystrix.strategy.concurrency.HystrixConcurrencyStrategy;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
@@ -33,6 +35,8 @@ import org.springframework.test.annotation.DirtiesContext;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Tests that a secured web service returning values using a feign client properly access
|
||||
* the security context from a hystrix command.
|
||||
@@ -40,7 +44,9 @@ import org.springframework.web.client.RestTemplate;
|
||||
*/
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@DirtiesContext
|
||||
@SpringBootTest(classes = HystrixSecurityApplication.class, webEnvironment = WebEnvironment.RANDOM_PORT, properties = {"username.ribbon.listOfServers=localhost:${local.server.port}","feign.hystrix.enabled=true"})
|
||||
@SpringBootTest(classes = HystrixSecurityApplication.class, webEnvironment = WebEnvironment.RANDOM_PORT,
|
||||
properties = { "username.ribbon.listOfServers=localhost:${local.server.port}",
|
||||
"feign.hystrix.enabled=true"})
|
||||
public class HystrixSecurityTests {
|
||||
@Autowired
|
||||
private CustomConcurrenyStrategy customConcurrenyStrategy;
|
||||
@@ -54,6 +60,12 @@ public class HystrixSecurityTests {
|
||||
@Value("${security.user.password}")
|
||||
private String password;
|
||||
|
||||
@Test
|
||||
public void testSecurityConcurrencyStrategyInstalled() {
|
||||
HystrixConcurrencyStrategy concurrencyStrategy = HystrixPlugins.getInstance().getConcurrencyStrategy();
|
||||
assertThat(concurrencyStrategy).isInstanceOf(SecurityContextConcurrencyStrategy.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFeignHystrixSecurity() {
|
||||
HttpHeaders headers = HystrixSecurityTests.createBasicAuthHeader(username,
|
||||
|
||||
@@ -1,121 +1,121 @@
|
||||
/*
|
||||
* Copyright 2013-2017 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.net.ConnectException;
|
||||
import java.net.SocketException;
|
||||
import java.net.SocketTimeoutException;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.cloud.netflix.archaius.ArchaiusAutoConfiguration;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.test.annotation.DirtiesContext;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import com.netflix.client.DefaultLoadBalancerRetryHandler;
|
||||
import com.netflix.client.RetryHandler;
|
||||
import com.netflix.client.config.IClientConfig;
|
||||
|
||||
/**
|
||||
* @author Tyler Van Gorder
|
||||
*/
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@SpringBootTest(classes = RibbonClientPreprocessorOverridesRetryTests.TestConfiguration.class, value = {
|
||||
"customRetry.ribbon.MaxAutoRetries=0",
|
||||
"customRetry.ribbon.MaxAutoRetriesNextServer=1",
|
||||
"customRetry.ribbon.OkToRetryOnAllOperations=true" })
|
||||
@DirtiesContext
|
||||
public class RibbonClientPreprocessorOverridesRetryTests {
|
||||
|
||||
@Autowired
|
||||
private SpringClientFactory factory;
|
||||
|
||||
@Test
|
||||
public void customRetryIsConfigured() throws Exception {
|
||||
RibbonLoadBalancerContext context = (RibbonLoadBalancerContext) this.factory
|
||||
.getLoadBalancerContext("customRetry");
|
||||
Assert.isInstanceOf(RetryRibbonConfiguration.CustomRetryHandler.class,
|
||||
context.getRetryHandler());
|
||||
Assert.isTrue(context.getRetryHandler().getMaxRetriesOnSameServer() == 0);
|
||||
Assert.isTrue(context.getRetryHandler().getMaxRetriesOnNextServer() == 1);
|
||||
Assert.isTrue(context.getRetryHandler()
|
||||
.isCircuitTrippingException(new UnknownHostException("Unknown Host")));
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@RibbonClient(name = "customRetry", configuration = RetryRibbonConfiguration.class)
|
||||
@Import({ PropertyPlaceholderAutoConfiguration.class, ArchaiusAutoConfiguration.class,
|
||||
RibbonAutoConfiguration.class })
|
||||
protected static class TestConfiguration {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
class RetryRibbonConfiguration {
|
||||
@Bean
|
||||
public RetryHandler retryHandler(IClientConfig config) {
|
||||
return new CustomRetryHandler(config);
|
||||
}
|
||||
|
||||
class CustomRetryHandler extends DefaultLoadBalancerRetryHandler {
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private List<Class<? extends Throwable>> retriable = new ArrayList() {
|
||||
{
|
||||
add(UnknownHostException.class);
|
||||
add(ConnectException.class);
|
||||
add(SocketTimeoutException.class);
|
||||
}
|
||||
};
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private List<Class<? extends Throwable>> circuitRelated = new ArrayList() {
|
||||
{
|
||||
add(UnknownHostException.class);
|
||||
add(SocketException.class);
|
||||
add(SocketTimeoutException.class);
|
||||
}
|
||||
};
|
||||
|
||||
CustomRetryHandler(IClientConfig config) {
|
||||
super(config);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<Class<? extends Throwable>> getRetriableExceptions() {
|
||||
return retriable;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<Class<? extends Throwable>> getCircuitRelatedExceptions() {
|
||||
return circuitRelated;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Copyright 2013-2017 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.net.ConnectException;
|
||||
import java.net.SocketException;
|
||||
import java.net.SocketTimeoutException;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.cloud.netflix.archaius.ArchaiusAutoConfiguration;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.test.annotation.DirtiesContext;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import com.netflix.client.DefaultLoadBalancerRetryHandler;
|
||||
import com.netflix.client.RetryHandler;
|
||||
import com.netflix.client.config.IClientConfig;
|
||||
|
||||
/**
|
||||
* @author Tyler Van Gorder
|
||||
*/
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@SpringBootTest(classes = RibbonClientPreprocessorOverridesRetryTests.TestConfiguration.class, value = {
|
||||
"customRetry.ribbon.MaxAutoRetries=0",
|
||||
"customRetry.ribbon.MaxAutoRetriesNextServer=1",
|
||||
"customRetry.ribbon.OkToRetryOnAllOperations=true" })
|
||||
@DirtiesContext
|
||||
public class RibbonClientPreprocessorOverridesRetryTests {
|
||||
|
||||
@Autowired
|
||||
private SpringClientFactory factory;
|
||||
|
||||
@Test
|
||||
public void customRetryIsConfigured() throws Exception {
|
||||
RibbonLoadBalancerContext context = (RibbonLoadBalancerContext) this.factory
|
||||
.getLoadBalancerContext("customRetry");
|
||||
Assert.isInstanceOf(RetryRibbonConfiguration.CustomRetryHandler.class,
|
||||
context.getRetryHandler());
|
||||
Assert.isTrue(context.getRetryHandler().getMaxRetriesOnSameServer() == 0);
|
||||
Assert.isTrue(context.getRetryHandler().getMaxRetriesOnNextServer() == 1);
|
||||
Assert.isTrue(context.getRetryHandler()
|
||||
.isCircuitTrippingException(new UnknownHostException("Unknown Host")));
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@RibbonClient(name = "customRetry", configuration = RetryRibbonConfiguration.class)
|
||||
@Import({ PropertyPlaceholderAutoConfiguration.class, ArchaiusAutoConfiguration.class,
|
||||
RibbonAutoConfiguration.class })
|
||||
protected static class TestConfiguration {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
class RetryRibbonConfiguration {
|
||||
@Bean
|
||||
public RetryHandler retryHandler(IClientConfig config) {
|
||||
return new CustomRetryHandler(config);
|
||||
}
|
||||
|
||||
class CustomRetryHandler extends DefaultLoadBalancerRetryHandler {
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private List<Class<? extends Throwable>> retriable = new ArrayList() {
|
||||
{
|
||||
add(UnknownHostException.class);
|
||||
add(ConnectException.class);
|
||||
add(SocketTimeoutException.class);
|
||||
}
|
||||
};
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private List<Class<? extends Throwable>> circuitRelated = new ArrayList() {
|
||||
{
|
||||
add(UnknownHostException.class);
|
||||
add(SocketException.class);
|
||||
add(SocketTimeoutException.class);
|
||||
}
|
||||
};
|
||||
|
||||
CustomRetryHandler(IClientConfig config) {
|
||||
super(config);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<Class<? extends Throwable>> getRetriableExceptions() {
|
||||
return retriable;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<Class<? extends Throwable>> getCircuitRelatedExceptions() {
|
||||
return circuitRelated;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,8 +20,10 @@ package org.springframework.cloud.netflix.zuul.filters.route;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Field;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.Arrays;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.zip.GZIPOutputStream;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
@@ -29,9 +31,13 @@ import javax.servlet.http.HttpServletResponse;
|
||||
import org.apache.http.HttpEntityEnclosingRequest;
|
||||
import org.apache.http.HttpHost;
|
||||
import org.apache.http.HttpRequest;
|
||||
import org.apache.http.client.config.RequestConfig;
|
||||
import org.apache.http.client.methods.CloseableHttpResponse;
|
||||
import org.apache.http.client.methods.Configurable;
|
||||
import org.apache.http.entity.InputStreamEntity;
|
||||
import org.apache.http.impl.client.CloseableHttpClient;
|
||||
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
|
||||
import org.assertj.core.api.Assertions;
|
||||
import org.junit.After;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
@@ -50,6 +56,7 @@ import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.test.annotation.DirtiesContext;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
import org.springframework.util.LinkedMultiValueMap;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
@@ -70,7 +77,8 @@ import static org.springframework.util.StreamUtils.copyToString;
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest(classes = SampleApplication.class,
|
||||
webEnvironment = RANDOM_PORT,
|
||||
properties = "server.servlet.contextPath: /app")
|
||||
properties = {"server.servlet.contextPath: /app", "zuul.host.socket-timeout-millis=11000",
|
||||
"zuul.host.connect-timeout-millis=2100"})
|
||||
@DirtiesContext
|
||||
public class SimpleHostRoutingFilterTests {
|
||||
|
||||
@@ -86,13 +94,37 @@ public class SimpleHostRoutingFilterTests {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void timeoutPropertiesAreApplied() {
|
||||
setupContext();
|
||||
CloseableHttpClient httpClient = getFilter().newClient();
|
||||
Assertions.assertThat(httpClient).isInstanceOf(Configurable.class);
|
||||
RequestConfig config = ((Configurable) httpClient).getConfig();
|
||||
assertEquals(11000, config.getSocketTimeout());
|
||||
assertEquals(2100, config.getConnectTimeout());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void connectionPropertiesAreApplied() {
|
||||
addEnvironment(this.context, "zuul.host.maxTotalConnections=100", "zuul.host.maxPerRouteConnections=10");
|
||||
addEnvironment(this.context, "zuul.host.maxTotalConnections=100",
|
||||
"zuul.host.maxPerRouteConnections=10", "zuul.host.timeToLive=5",
|
||||
"zuul.host.timeUnit=SECONDS");
|
||||
setupContext();
|
||||
PoolingHttpClientConnectionManager connMgr = getFilter().newConnectionManager();
|
||||
assertEquals(100, connMgr.getMaxTotal());
|
||||
assertEquals(10, connMgr.getDefaultMaxPerRoute());
|
||||
Object pool = getField(connMgr, "pool");
|
||||
Long timeToLive = getField(pool, "timeToLive");
|
||||
TimeUnit timeUnit = getField(pool, "tunit");
|
||||
assertEquals(new Long(5), timeToLive);
|
||||
assertEquals(TimeUnit.SECONDS, timeUnit);
|
||||
}
|
||||
|
||||
protected <T> T getField(Object target, String name) {
|
||||
Field field = ReflectionUtils.findField(target.getClass(), name);
|
||||
ReflectionUtils.makeAccessible(field);
|
||||
Object value = ReflectionUtils.getField(field, target);
|
||||
return (T)value;
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -16,8 +16,8 @@
|
||||
<properties>
|
||||
<archaius.version>0.7.4</archaius.version>
|
||||
<eureka.version>1.6.2</eureka.version>
|
||||
<feign.version>9.4.0</feign.version>
|
||||
<hystrix.version>1.5.11</hystrix.version>
|
||||
<feign.version>9.5.0</feign.version>
|
||||
<hystrix.version>1.5.12</hystrix.version>
|
||||
<ribbon.version>2.2.2</ribbon.version>
|
||||
<servo.version>0.10.1</servo.version>
|
||||
<zuul.version>1.3.0</zuul.version>
|
||||
@@ -238,11 +238,6 @@
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax-inject</groupId>
|
||||
<artifactId>javax-inject</artifactId>
|
||||
<version>1</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.netflix.eureka</groupId>
|
||||
<artifactId>eureka-core</artifactId>
|
||||
|
||||
@@ -22,9 +22,11 @@ import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.boot.actuate.endpoint.Endpoint;
|
||||
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
|
||||
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
|
||||
import org.springframework.boot.autoconfigure.condition.AnyNestedCondition;
|
||||
@@ -53,6 +55,7 @@ import org.springframework.context.annotation.Conditional;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.core.env.ConfigurableEnvironment;
|
||||
import org.springframework.core.env.PropertyResolver;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import com.netflix.appinfo.ApplicationInfoManager;
|
||||
@@ -62,7 +65,6 @@ import com.netflix.appinfo.InstanceInfo;
|
||||
import com.netflix.discovery.DiscoveryClient.DiscoveryClientOptionalArgs;
|
||||
import com.netflix.discovery.EurekaClient;
|
||||
import com.netflix.discovery.EurekaClientConfig;
|
||||
|
||||
import static org.springframework.cloud.commons.util.IdUtils.getDefaultInstanceId;
|
||||
|
||||
/**
|
||||
@@ -82,18 +84,14 @@ import static org.springframework.cloud.commons.util.IdUtils.getDefaultInstanceI
|
||||
@AutoConfigureAfter(name = "org.springframework.cloud.autoconfigure.RefreshAutoConfiguration")
|
||||
public class EurekaClientAutoConfiguration {
|
||||
|
||||
@Value("${server.port:${SERVER_PORT:${PORT:8080}}}")
|
||||
private int nonSecurePort;
|
||||
|
||||
@Value("${management.port:${MANAGEMENT_PORT:${server.port:${SERVER_PORT:${PORT:8080}}}}}")
|
||||
private int managementPort;
|
||||
|
||||
@Autowired
|
||||
private ConfigurableEnvironment env;
|
||||
|
||||
@Autowired(required = false)
|
||||
private HealthCheckHandler healthCheckHandler;
|
||||
|
||||
public EurekaClientAutoConfiguration(ConfigurableEnvironment env) {
|
||||
this.env = env;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public HasFeatures eurekaFeature() {
|
||||
return HasFeatures.namedFeature("Eureka Client", EurekaClient.class);
|
||||
@@ -120,17 +118,22 @@ public class EurekaClientAutoConfiguration {
|
||||
public EurekaInstanceConfigBean eurekaInstanceConfigBean(InetUtils inetUtils) {
|
||||
String hostname = getProperty("eureka.instance.hostname");
|
||||
boolean preferIpAddress = Boolean.parseBoolean(getProperty("eureka.instance.prefer-ip-address"));
|
||||
int nonSecurePort = Integer.valueOf(env.getProperty("server.port", env.getProperty("port", "8080")));
|
||||
int managementPort = Integer.valueOf(env.getProperty("management.port", String.valueOf(nonSecurePort)));
|
||||
String managementContextPath = env.getProperty("management.context-path", env.getProperty("server.servlet.context-path", "/"));
|
||||
EurekaInstanceConfigBean instance = new EurekaInstanceConfigBean(inetUtils);
|
||||
instance.setNonSecurePort(this.nonSecurePort);
|
||||
instance.setInstanceId(getDefaultInstanceId(this.env));
|
||||
instance.setNonSecurePort(nonSecurePort);
|
||||
instance.setInstanceId(getDefaultInstanceId(propertyResolver));
|
||||
instance.setPreferIpAddress(preferIpAddress);
|
||||
|
||||
if (this.managementPort != this.nonSecurePort && this.managementPort != 0) {
|
||||
if (managementPort != nonSecurePort && managementPort != 0) {
|
||||
if (StringUtils.hasText(hostname)) {
|
||||
instance.setHostname(hostname);
|
||||
}
|
||||
String statusPageUrlPath = getProperty("eureka.instance.status-page-url-path");
|
||||
String healthCheckUrlPath = getProperty("eureka.instance.health-check-url-path");
|
||||
if (!managementContextPath.endsWith("/")) {
|
||||
managementContextPath = managementContextPath + "/";
|
||||
}
|
||||
if (StringUtils.hasText(statusPageUrlPath)) {
|
||||
instance.setStatusPageUrlPath(statusPageUrlPath);
|
||||
}
|
||||
@@ -138,17 +141,15 @@ public class EurekaClientAutoConfiguration {
|
||||
instance.setHealthCheckUrlPath(healthCheckUrlPath);
|
||||
}
|
||||
String scheme = instance.getSecurePortEnabled() ? "https" : "http";
|
||||
instance.setStatusPageUrl(scheme + "://" + instance.getHostname() + ":"
|
||||
+ this.managementPort + instance.getStatusPageUrlPath());
|
||||
instance.setHealthCheckUrl(scheme + "://" + instance.getHostname() + ":"
|
||||
+ this.managementPort + instance.getHealthCheckUrlPath());
|
||||
URL base = new URL(scheme, instance.getHostname(), managementPort, managementContextPath);
|
||||
instance.setStatusPageUrl(new URL(base, StringUtils.trimLeadingCharacter(instance.getStatusPageUrlPath(), '/')).toString());
|
||||
instance.setHealthCheckUrl(new URL(base, StringUtils.trimLeadingCharacter(instance.getHealthCheckUrlPath(), '/')).toString());
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public DiscoveryClient discoveryClient(EurekaInstanceConfig config,
|
||||
EurekaClient client) {
|
||||
public DiscoveryClient discoveryClient(EurekaInstanceConfig config, EurekaClient client) {
|
||||
return new EurekaDiscoveryClient(config, client);
|
||||
}
|
||||
|
||||
@@ -193,8 +194,7 @@ public class EurekaClientAutoConfiguration {
|
||||
|
||||
@Bean(destroyMethod = "shutdown")
|
||||
@ConditionalOnMissingBean(value = EurekaClient.class, search = SearchStrategy.CURRENT)
|
||||
public EurekaClient eurekaClient(ApplicationInfoManager manager,
|
||||
EurekaClientConfig config) {
|
||||
public EurekaClient eurekaClient(ApplicationInfoManager manager, EurekaClientConfig config) {
|
||||
return new CloudEurekaClient(manager, config, this.optionalArgs,
|
||||
this.context);
|
||||
}
|
||||
@@ -222,8 +222,7 @@ public class EurekaClientAutoConfiguration {
|
||||
@ConditionalOnMissingBean(value = EurekaClient.class, search = SearchStrategy.CURRENT)
|
||||
@org.springframework.cloud.context.config.annotation.RefreshScope
|
||||
@Lazy
|
||||
public EurekaClient eurekaClient(ApplicationInfoManager manager,
|
||||
EurekaClientConfig config, EurekaInstanceConfig instance) {
|
||||
public EurekaClient eurekaClient(ApplicationInfoManager manager, EurekaClientConfig config, EurekaInstanceConfig instance) {
|
||||
manager.getInfo(); // force initialization
|
||||
return new CloudEurekaClient(manager, config, this.optionalArgs,
|
||||
this.context);
|
||||
@@ -233,8 +232,7 @@ public class EurekaClientAutoConfiguration {
|
||||
@ConditionalOnMissingBean(value = ApplicationInfoManager.class, search = SearchStrategy.CURRENT)
|
||||
@org.springframework.cloud.context.config.annotation.RefreshScope
|
||||
@Lazy
|
||||
public ApplicationInfoManager eurekaApplicationInfoManager(
|
||||
EurekaInstanceConfig config) {
|
||||
public ApplicationInfoManager eurekaApplicationInfoManager(EurekaInstanceConfig config) {
|
||||
InstanceInfo instanceInfo = new InstanceInfoFactory().create(config);
|
||||
return new ApplicationInfoManager(config, instanceInfo);
|
||||
}
|
||||
@@ -274,4 +272,14 @@ public class EurekaClientAutoConfiguration {
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@ConditionalOnClass(Endpoint.class)
|
||||
protected static class EurekaHealthIndicatorConfiguration {
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public EurekaHealthIndicator eurekaHealthIndicator(EurekaClient eurekaClient,
|
||||
EurekaInstanceConfig instanceConfig, EurekaClientConfig clientConfig) {
|
||||
return new EurekaHealthIndicator(eurekaClient, instanceConfig, clientConfig);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2014 the original author or authors.
|
||||
* Copyright 2013-2017 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.
|
||||
@@ -12,12 +12,12 @@
|
||||
* 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;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.actuate.endpoint.Endpoint;
|
||||
import org.springframework.boot.actuate.health.HealthAggregator;
|
||||
import org.springframework.boot.actuate.health.OrderedHealthAggregator;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
@@ -30,7 +30,6 @@ import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.event.EventListener;
|
||||
|
||||
import com.netflix.appinfo.EurekaInstanceConfig;
|
||||
import com.netflix.appinfo.HealthCheckHandler;
|
||||
import com.netflix.discovery.EurekaClient;
|
||||
import com.netflix.discovery.EurekaClientConfig;
|
||||
@@ -82,16 +81,6 @@ public class EurekaDiscoveryClientConfiguration {
|
||||
}
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@ConditionalOnClass(Endpoint.class)
|
||||
protected static class EurekaHealthIndicatorConfiguration {
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public EurekaHealthIndicator eurekaHealthIndicator(EurekaClient eurekaClient,
|
||||
EurekaInstanceConfig instanceConfig, EurekaClientConfig clientConfig) {
|
||||
return new EurekaHealthIndicator(eurekaClient, instanceConfig, clientConfig);
|
||||
}
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@ConditionalOnProperty(value = "eureka.client.healthcheck.enabled", matchIfMissing = false)
|
||||
|
||||
@@ -121,6 +121,54 @@ public class EurekaClientAutoConfigurationTests {
|
||||
instance.getHealthCheckUrl().contains("/myHealthCheck"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void statusPageUrlPathAndManagementPortAndContextPath() {
|
||||
EnvironmentTestUtils.addEnvironment(this.context, "server.port=8989",
|
||||
"management.port=9999", "management.contextPath=/manage",
|
||||
"eureka.instance.statusPageUrlPath=/myStatusPage");
|
||||
setupContext(RefreshAutoConfiguration.class);
|
||||
EurekaInstanceConfigBean instance = this.context
|
||||
.getBean(EurekaInstanceConfigBean.class);
|
||||
assertTrue("Wrong status page: " + instance.getStatusPageUrl(),
|
||||
instance.getStatusPageUrl().endsWith(":9999/manage/myStatusPage"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void healthCheckUrlPathAndManagementPortAndContextPath() {
|
||||
EnvironmentTestUtils.addEnvironment(this.context, "server.port=8989",
|
||||
"management.port=9999", "management.contextPath=/manage",
|
||||
"eureka.instance.healthCheckUrlPath=/myHealthCheck");
|
||||
setupContext(RefreshAutoConfiguration.class);
|
||||
EurekaInstanceConfigBean instance = this.context
|
||||
.getBean(EurekaInstanceConfigBean.class);
|
||||
assertTrue("Wrong health check: " + instance.getHealthCheckUrl(),
|
||||
instance.getHealthCheckUrl().endsWith(":9999/manage/myHealthCheck"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void statusPageUrlPathAndManagementPortAndContextPathKebobCase() {
|
||||
EnvironmentTestUtils.addEnvironment(this.context, "server.port=8989",
|
||||
"management.port=9999", "management.context-path=/manage",
|
||||
"eureka.instance.statusPageUrlPath=/myStatusPage");
|
||||
setupContext(RefreshAutoConfiguration.class);
|
||||
EurekaInstanceConfigBean instance = this.context
|
||||
.getBean(EurekaInstanceConfigBean.class);
|
||||
assertTrue("Wrong status page: " + instance.getStatusPageUrl(),
|
||||
instance.getStatusPageUrl().endsWith(":9999/manage/myStatusPage"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void healthCheckUrlPathAndManagementPortAndContextPathKebobCase() {
|
||||
EnvironmentTestUtils.addEnvironment(this.context, "server.port=8989",
|
||||
"management.port=9999", "management.context-path=/manage",
|
||||
"eureka.instance.healthCheckUrlPath=/myHealthCheck");
|
||||
setupContext(RefreshAutoConfiguration.class);
|
||||
EurekaInstanceConfigBean instance = this.context
|
||||
.getBean(EurekaInstanceConfigBean.class);
|
||||
assertTrue("Wrong health check: " + instance.getHealthCheckUrl(),
|
||||
instance.getHealthCheckUrl().endsWith(":9999/manage/myHealthCheck"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void statusPageUrlPathAndManagementPortKabobCase() {
|
||||
EnvironmentTestUtils.addEnvironment(this.context, "server.port=8989",
|
||||
@@ -280,6 +328,12 @@ public class EurekaClientAutoConfigurationTests {
|
||||
assertEquals("mytesteurekaappname", getInstanceConfig().getAppname());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void eurekaHealthIndicatorCreated() {
|
||||
setupContext();
|
||||
this.context.getBean(EurekaHealthIndicator.class);
|
||||
}
|
||||
|
||||
private void testNonSecurePort(String propName) {
|
||||
addEnvironment(this.context, propName + ":8888");
|
||||
setupContext();
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2015 the original author or authors.
|
||||
* Copyright 2013-2017 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.
|
||||
@@ -19,11 +19,13 @@ package org.springframework.cloud.netflix.hystrix.stream;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
|
||||
import org.springframework.cloud.client.ServiceInstance;
|
||||
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
|
||||
import org.springframework.cloud.client.discovery.DiscoveryClient;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.test.annotation.DirtiesContext;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
@@ -31,12 +33,14 @@ import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* @author Spencer Gibb
|
||||
*/
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@SpringBootTest(classes = HystrixStreamTests.Application.class, webEnvironment = WebEnvironment.RANDOM_PORT,
|
||||
properties = { "spring.jmx.enabled=true" })
|
||||
properties = { "spring.jmx.enabled=true", "spring.application.name=mytestapp" })
|
||||
@DirtiesContext
|
||||
public class HystrixStreamTests {
|
||||
|
||||
@@ -46,9 +50,13 @@ public class HystrixStreamTests {
|
||||
@Autowired
|
||||
private Application application;
|
||||
|
||||
@Autowired
|
||||
private DiscoveryClient discoveryClient;
|
||||
|
||||
@EnableAutoConfiguration
|
||||
@EnableCircuitBreaker
|
||||
@RestController
|
||||
@Configuration
|
||||
public static class Application {
|
||||
|
||||
@HystrixCommand
|
||||
@@ -56,16 +64,16 @@ public class HystrixStreamTests {
|
||||
public String hello() {
|
||||
return "Hello World";
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(Application.class, args);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void contextLoads() {
|
||||
this.application.hello();
|
||||
//It is important that local service instance resolves for metrics
|
||||
//origin details to be populated
|
||||
ServiceInstance localServiceInstance = discoveryClient.getLocalServiceInstance();
|
||||
assertThat(localServiceInstance).isNotNull();
|
||||
assertThat(localServiceInstance.getServiceId()).isEqualTo("mytestapp");
|
||||
this.task.gatherMetrics();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user