diff --git a/pom.xml b/pom.xml
index e620e125..580f2d03 100644
--- a/pom.xml
+++ b/pom.xml
@@ -82,21 +82,6 @@
pom
import
-
- org.springframework.cloud
- spring-cloud-starter-netflix-ribbon
- ${spring-cloud-netflix.version}
-
-
- com.netflix.ribbon
- ribbon-transport
-
-
- io.reactivex
- rxnetty
-
-
-
org.springframework.cloud
spring-cloud-test-support
@@ -108,11 +93,6 @@
spring-cloud-starter-netflix-eureka-client
${spring-cloud-netflix.version}
-
- org.springframework.cloud
- spring-cloud-starter-netflix-hystrix
- ${spring-cloud-netflix.version}
-
org.springframework.cloud
spring-cloud-circuitbreaker-dependencies
diff --git a/spring-cloud-gateway-core/pom.xml b/spring-cloud-gateway-core/pom.xml
index e8046a5b..83b60d3e 100644
--- a/spring-cloud-gateway-core/pom.xml
+++ b/spring-cloud-gateway-core/pom.xml
@@ -38,16 +38,6 @@
spring-boot-configuration-processor
true
-
- org.springframework.cloud
- spring-cloud-starter-netflix-ribbon
- true
-
-
- org.springframework.cloud
- spring-cloud-starter-netflix-hystrix
- true
-
org.springframework.cloud
spring-cloud-loadbalancer
diff --git a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/config/GatewayAutoConfiguration.java b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/config/GatewayAutoConfiguration.java
index 00ce39cf..583ef7f4 100644
--- a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/config/GatewayAutoConfiguration.java
+++ b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/config/GatewayAutoConfiguration.java
@@ -19,7 +19,6 @@ package org.springframework.cloud.gateway.config;
import java.security.cert.X509Certificate;
import java.util.List;
-import com.netflix.hystrix.HystrixObservableCommand;
import io.netty.channel.ChannelOption;
import io.netty.handler.ssl.SslContextBuilder;
import io.netty.handler.ssl.util.InsecureTrustManagerFactory;
@@ -29,7 +28,6 @@ import reactor.core.publisher.Flux;
import reactor.netty.http.client.HttpClient;
import reactor.netty.resources.ConnectionProvider;
import reactor.netty.tcp.ProxyProvider;
-import rx.RxReactiveStreams;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.ObjectProvider;
@@ -66,9 +64,7 @@ import org.springframework.cloud.gateway.filter.factory.AddRequestHeaderGatewayF
import org.springframework.cloud.gateway.filter.factory.AddRequestParameterGatewayFilterFactory;
import org.springframework.cloud.gateway.filter.factory.AddResponseHeaderGatewayFilterFactory;
import org.springframework.cloud.gateway.filter.factory.DedupeResponseHeaderGatewayFilterFactory;
-import org.springframework.cloud.gateway.filter.factory.FallbackHeadersGatewayFilterFactory;
import org.springframework.cloud.gateway.filter.factory.GatewayFilterFactory;
-import org.springframework.cloud.gateway.filter.factory.HystrixGatewayFilterFactory;
import org.springframework.cloud.gateway.filter.factory.MapRequestHeaderGatewayFilterFactory;
import org.springframework.cloud.gateway.filter.factory.PrefixPathGatewayFilterFactory;
import org.springframework.cloud.gateway.filter.factory.PreserveHostHeaderGatewayFilterFactory;
@@ -160,7 +156,7 @@ import static org.springframework.cloud.gateway.config.HttpClientProperties.Pool
@EnableConfigurationProperties
@AutoConfigureBefore({ HttpHandlerAutoConfiguration.class,
WebFluxAutoConfiguration.class })
-@AutoConfigureAfter({ GatewayLoadBalancerClientAutoConfiguration.class,
+@AutoConfigureAfter({ GatewayReactiveLoadBalancerClientAutoConfiguration.class,
GatewayClassPathWarningAutoConfiguration.class })
@ConditionalOnClass(DispatcherHandler.class)
public class GatewayAutoConfiguration {
@@ -712,24 +708,6 @@ public class GatewayAutoConfiguration {
}
- @Configuration(proxyBeanMethods = false)
- @ConditionalOnClass({ HystrixObservableCommand.class, RxReactiveStreams.class })
- protected static class HystrixConfiguration {
-
- @Bean
- public HystrixGatewayFilterFactory hystrixGatewayFilterFactory(
- ObjectProvider dispatcherHandler) {
- return new HystrixGatewayFilterFactory(dispatcherHandler);
- }
-
- @Bean
- @ConditionalOnMissingBean(FallbackHeadersGatewayFilterFactory.class)
- public FallbackHeadersGatewayFilterFactory fallbackHeadersGatewayFilterFactory() {
- return new FallbackHeadersGatewayFilterFactory();
- }
-
- }
-
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass(Health.class)
protected static class GatewayActuatorConfiguration {
diff --git a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/config/GatewayHystrixCircuitBreakerAutoConfiguration.java b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/config/GatewayHystrixCircuitBreakerAutoConfiguration.java
deleted file mode 100644
index d4780c9e..00000000
--- a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/config/GatewayHystrixCircuitBreakerAutoConfiguration.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright 2013-2019 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
- *
- * https://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.gateway.config;
-
-import org.springframework.beans.factory.ObjectProvider;
-import org.springframework.boot.autoconfigure.AutoConfigureAfter;
-import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
-import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
-import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
-import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
-import org.springframework.cloud.client.circuitbreaker.ReactiveCircuitBreakerFactory;
-import org.springframework.cloud.gateway.filter.factory.FallbackHeadersGatewayFilterFactory;
-import org.springframework.cloud.gateway.filter.factory.SpringCloudCircuitBreakerHystrixFilterFactory;
-import org.springframework.cloud.netflix.hystrix.HystrixCircuitBreakerAutoConfiguration;
-import org.springframework.cloud.netflix.hystrix.ReactiveHystrixCircuitBreakerAutoConfiguration;
-import org.springframework.cloud.netflix.hystrix.ReactiveHystrixCircuitBreakerFactory;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-import org.springframework.web.reactive.DispatcherHandler;
-
-/**
- * @author Ryan Baxter
- */
-@Configuration(proxyBeanMethods = false)
-@ConditionalOnProperty(name = "spring.cloud.gateway.enabled", matchIfMissing = true)
-@AutoConfigureAfter({ ReactiveHystrixCircuitBreakerAutoConfiguration.class })
-@ConditionalOnClass({ DispatcherHandler.class,
- HystrixCircuitBreakerAutoConfiguration.class, ReactiveCircuitBreakerFactory.class,
- ReactiveHystrixCircuitBreakerFactory.class })
-public class GatewayHystrixCircuitBreakerAutoConfiguration {
-
- @Bean
- @ConditionalOnBean(ReactiveHystrixCircuitBreakerFactory.class)
- public SpringCloudCircuitBreakerHystrixFilterFactory springCloudCircuitBreakerHystrixFilterFactory(
- ReactiveHystrixCircuitBreakerFactory reactiveCircuitBreakerFactory,
- ObjectProvider dispatcherHandler) {
- return new SpringCloudCircuitBreakerHystrixFilterFactory(
- reactiveCircuitBreakerFactory, dispatcherHandler);
- }
-
- @Bean
- @ConditionalOnMissingBean(FallbackHeadersGatewayFilterFactory.class)
- public FallbackHeadersGatewayFilterFactory fallbackHeadersGatewayFilterFactory() {
- return new FallbackHeadersGatewayFilterFactory();
- }
-
-}
diff --git a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/config/GatewayLoadBalancerClientAutoConfiguration.java b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/config/GatewayLoadBalancerClientAutoConfiguration.java
deleted file mode 100644
index 7567e812..00000000
--- a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/config/GatewayLoadBalancerClientAutoConfiguration.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright 2013-2019 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
- *
- * https://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.gateway.config;
-
-import org.springframework.boot.autoconfigure.AutoConfigureAfter;
-import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
-import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
-import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
-import org.springframework.boot.context.properties.EnableConfigurationProperties;
-import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
-import org.springframework.cloud.gateway.filter.LoadBalancerClientFilter;
-import org.springframework.cloud.gateway.filter.ReactiveLoadBalancerClientFilter;
-import org.springframework.cloud.netflix.ribbon.RibbonAutoConfiguration;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-import org.springframework.web.reactive.DispatcherHandler;
-
-/**
- * AutoConfiguration for {@link LoadBalancerClientFilter}.
- *
- * @author Spencer Gibb
- * @author Olga Maciaszek-Sharma
- */
-@Configuration(proxyBeanMethods = false)
-@ConditionalOnClass({ LoadBalancerClient.class, RibbonAutoConfiguration.class,
- DispatcherHandler.class })
-@AutoConfigureAfter(RibbonAutoConfiguration.class)
-@EnableConfigurationProperties(LoadBalancerProperties.class)
-public class GatewayLoadBalancerClientAutoConfiguration {
-
- @Bean
- @ConditionalOnBean(LoadBalancerClient.class)
- @ConditionalOnMissingBean({ LoadBalancerClientFilter.class,
- ReactiveLoadBalancerClientFilter.class })
- public LoadBalancerClientFilter loadBalancerClientFilter(LoadBalancerClient client,
- LoadBalancerProperties properties) {
- return new LoadBalancerClientFilter(client, properties);
- }
-
-}
diff --git a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/config/GatewayNoLoadBalancerClientAutoConfiguration.java b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/config/GatewayNoLoadBalancerClientAutoConfiguration.java
index b51db395..9efcf12e 100644
--- a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/config/GatewayNoLoadBalancerClientAutoConfiguration.java
+++ b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/config/GatewayNoLoadBalancerClientAutoConfiguration.java
@@ -24,17 +24,17 @@ import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingClass;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
-import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
+import org.springframework.cloud.client.loadbalancer.reactive.ReactiveLoadBalancer;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
-import org.springframework.cloud.gateway.filter.LoadBalancerClientFilter;
+import org.springframework.cloud.gateway.filter.ReactiveLoadBalancerClientFilter;
import org.springframework.cloud.gateway.support.NotFoundException;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.web.server.ServerWebExchange;
-import static org.springframework.cloud.gateway.filter.LoadBalancerClientFilter.LOAD_BALANCER_CLIENT_FILTER_ORDER;
+import static org.springframework.cloud.gateway.filter.ReactiveLoadBalancerClientFilter.LOAD_BALANCER_CLIENT_FILTER_ORDER;
import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR;
import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.GATEWAY_SCHEME_PREFIX_ATTR;
@@ -42,14 +42,14 @@ import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.G
* @author Spencer Gibb
*/
@Configuration(proxyBeanMethods = false)
-@ConditionalOnMissingClass("org.springframework.cloud.netflix.ribbon.RibbonAutoConfiguration")
-@ConditionalOnMissingBean(LoadBalancerClient.class)
+@ConditionalOnMissingClass("org.springframework.cloud.loadbalancer.core.ReactorLoadBalancer")
+@ConditionalOnMissingBean(ReactiveLoadBalancer.class)
@EnableConfigurationProperties(LoadBalancerProperties.class)
-@AutoConfigureAfter(GatewayLoadBalancerClientAutoConfiguration.class)
+@AutoConfigureAfter(GatewayReactiveLoadBalancerClientAutoConfiguration.class)
public class GatewayNoLoadBalancerClientAutoConfiguration {
@Bean
- @ConditionalOnMissingBean(LoadBalancerClientFilter.class)
+ @ConditionalOnMissingBean(ReactiveLoadBalancerClientFilter.class)
public NoLoadBalancerClientFilter noLoadBalancerClientFilter(
LoadBalancerProperties properties) {
return new NoLoadBalancerClientFilter(properties.isUse404());
diff --git a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/config/GatewayReactiveLoadBalancerClientAutoConfiguration.java b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/config/GatewayReactiveLoadBalancerClientAutoConfiguration.java
index 20d0bdfd..6b06bd24 100644
--- a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/config/GatewayReactiveLoadBalancerClientAutoConfiguration.java
+++ b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/config/GatewayReactiveLoadBalancerClientAutoConfiguration.java
@@ -17,20 +17,15 @@
package org.springframework.cloud.gateway.config;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
-import org.springframework.boot.autoconfigure.AutoConfigureBefore;
-import org.springframework.boot.autoconfigure.condition.AnyNestedCondition;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
-import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingClass;
-import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cloud.client.loadbalancer.reactive.ReactiveLoadBalancer;
import org.springframework.cloud.gateway.filter.ReactiveLoadBalancerClientFilter;
import org.springframework.cloud.loadbalancer.config.LoadBalancerAutoConfiguration;
import org.springframework.cloud.loadbalancer.support.LoadBalancerClientFactory;
import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.reactive.DispatcherHandler;
@@ -43,7 +38,6 @@ import org.springframework.web.reactive.DispatcherHandler;
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass({ ReactiveLoadBalancer.class, LoadBalancerAutoConfiguration.class,
DispatcherHandler.class })
-@AutoConfigureBefore(GatewayLoadBalancerClientAutoConfiguration.class)
@AutoConfigureAfter(LoadBalancerAutoConfiguration.class)
@EnableConfigurationProperties(LoadBalancerProperties.class)
public class GatewayReactiveLoadBalancerClientAutoConfiguration {
@@ -51,29 +45,9 @@ public class GatewayReactiveLoadBalancerClientAutoConfiguration {
@Bean
@ConditionalOnBean(LoadBalancerClientFactory.class)
@ConditionalOnMissingBean(ReactiveLoadBalancerClientFilter.class)
- @Conditional(OnNoRibbonDefaultCondition.class)
public ReactiveLoadBalancerClientFilter gatewayLoadBalancerClientFilter(
LoadBalancerClientFactory clientFactory, LoadBalancerProperties properties) {
return new ReactiveLoadBalancerClientFilter(clientFactory, properties);
}
- private static final class OnNoRibbonDefaultCondition extends AnyNestedCondition {
-
- private OnNoRibbonDefaultCondition() {
- super(ConfigurationPhase.REGISTER_BEAN);
- }
-
- @ConditionalOnProperty(value = "spring.cloud.loadbalancer.ribbon.enabled",
- havingValue = "false")
- static class RibbonNotEnabled {
-
- }
-
- @ConditionalOnMissingClass("org.springframework.cloud.netflix.ribbon.RibbonLoadBalancerClient")
- static class RibbonLoadBalancerNotPresent {
-
- }
-
- }
-
}
diff --git a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/LoadBalancerClientFilter.java b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/LoadBalancerClientFilter.java
deleted file mode 100644
index 6391f27f..00000000
--- a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/LoadBalancerClientFilter.java
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- * Copyright 2013-2019 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
- *
- * https://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.gateway.filter;
-
-import java.net.URI;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import reactor.core.publisher.Mono;
-
-import org.springframework.cloud.client.ServiceInstance;
-import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
-import org.springframework.cloud.gateway.config.LoadBalancerProperties;
-import org.springframework.cloud.gateway.support.DelegatingServiceInstance;
-import org.springframework.cloud.gateway.support.NotFoundException;
-import org.springframework.core.Ordered;
-import org.springframework.web.server.ServerWebExchange;
-
-import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR;
-import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.GATEWAY_SCHEME_PREFIX_ATTR;
-import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.addOriginalRequestUrl;
-
-/**
- * @deprecated in favour of {@link ReactiveLoadBalancerClientFilter}
- * @author Spencer Gibb
- * @author Tim Ysewyn
- */
-@Deprecated
-public class LoadBalancerClientFilter implements GlobalFilter, Ordered {
-
- /**
- * Filter order for {@link LoadBalancerClientFilter}.
- */
- public static final int LOAD_BALANCER_CLIENT_FILTER_ORDER = 10100;
-
- private static final Log log = LogFactory.getLog(LoadBalancerClientFilter.class);
-
- protected final LoadBalancerClient loadBalancer;
-
- private LoadBalancerProperties properties;
-
- public LoadBalancerClientFilter(LoadBalancerClient loadBalancer,
- LoadBalancerProperties properties) {
- this.loadBalancer = loadBalancer;
- this.properties = properties;
- }
-
- @Override
- public int getOrder() {
- return LOAD_BALANCER_CLIENT_FILTER_ORDER;
- }
-
- @Override
- @SuppressWarnings("Duplicates")
- public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) {
- URI url = exchange.getAttribute(GATEWAY_REQUEST_URL_ATTR);
- String schemePrefix = exchange.getAttribute(GATEWAY_SCHEME_PREFIX_ATTR);
- if (url == null
- || (!"lb".equals(url.getScheme()) && !"lb".equals(schemePrefix))) {
- return chain.filter(exchange);
- }
- // preserve the original url
- addOriginalRequestUrl(exchange, url);
-
- if (log.isTraceEnabled()) {
- log.trace("LoadBalancerClientFilter url before: " + url);
- }
-
- final ServiceInstance instance = choose(exchange);
-
- if (instance == null) {
- throw NotFoundException.create(properties.isUse404(),
- "Unable to find instance for " + url.getHost());
- }
-
- URI uri = exchange.getRequest().getURI();
-
- // if the `lb:` mechanism was used, use `` as the default,
- // if the loadbalancer doesn't provide one.
- String overrideScheme = instance.isSecure() ? "https" : "http";
- if (schemePrefix != null) {
- overrideScheme = url.getScheme();
- }
-
- URI requestUrl = loadBalancer.reconstructURI(
- new DelegatingServiceInstance(instance, overrideScheme), uri);
-
- if (log.isTraceEnabled()) {
- log.trace("LoadBalancerClientFilter url chosen: " + requestUrl);
- }
-
- exchange.getAttributes().put(GATEWAY_REQUEST_URL_ATTR, requestUrl);
- return chain.filter(exchange);
- }
-
- protected ServiceInstance choose(ServerWebExchange exchange) {
- return loadBalancer.choose(
- ((URI) exchange.getAttribute(GATEWAY_REQUEST_URL_ATTR)).getHost());
- }
-
-}
diff --git a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/ReactiveLoadBalancerClientFilter.java b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/ReactiveLoadBalancerClientFilter.java
index 7b462653..850969f1 100644
--- a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/ReactiveLoadBalancerClientFilter.java
+++ b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/ReactiveLoadBalancerClientFilter.java
@@ -52,7 +52,10 @@ public class ReactiveLoadBalancerClientFilter implements GlobalFilter, Ordered {
private static final Log log = LogFactory
.getLog(ReactiveLoadBalancerClientFilter.class);
- private static final int LOAD_BALANCER_CLIENT_FILTER_ORDER = 10150;
+ /**
+ * Order of filter.
+ */
+ public static final int LOAD_BALANCER_CLIENT_FILTER_ORDER = 10150;
private final LoadBalancerClientFactory clientFactory;
diff --git a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/FallbackHeadersGatewayFilterFactory.java b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/FallbackHeadersGatewayFilterFactory.java
index 9a18076a..371ab6df 100644
--- a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/FallbackHeadersGatewayFilterFactory.java
+++ b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/FallbackHeadersGatewayFilterFactory.java
@@ -16,6 +16,7 @@
package org.springframework.cloud.gateway.filter.factory;
+import java.util.ArrayList;
import java.util.List;
import org.springframework.cloud.gateway.filter.GatewayFilter;
@@ -23,10 +24,7 @@ import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.web.server.ServerWebExchange;
import static java.util.Collections.singletonList;
-import static java.util.Optional.ofNullable;
-import static org.apache.commons.lang.exception.ExceptionUtils.getRootCause;
import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.CIRCUITBREAKER_EXECUTION_EXCEPTION_ATTR;
-import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.HYSTRIX_EXECUTION_EXCEPTION_ATTR;
/**
* @author Olga Maciaszek-Sharma
@@ -47,41 +45,50 @@ public class FallbackHeadersGatewayFilterFactory
@Override
public GatewayFilter apply(Config config) {
return (exchange, chain) -> {
- ServerWebExchange filteredExchange = ofNullable(ofNullable(
- (Throwable) exchange.getAttribute(HYSTRIX_EXECUTION_EXCEPTION_ATTR))
- .orElseGet(() -> exchange.getAttribute(
- CIRCUITBREAKER_EXECUTION_EXCEPTION_ATTR)))
- .map(executionException -> {
- ServerHttpRequest.Builder requestBuilder = exchange
- .getRequest().mutate();
- requestBuilder.header(
- config.executionExceptionTypeHeaderName,
- executionException.getClass()
- .getName());
- requestBuilder.header(
- config.executionExceptionMessageHeaderName,
- executionException.getMessage());
- ofNullable(
- getRootCause(executionException))
- .ifPresent(rootCause -> {
- requestBuilder.header(
- config.rootCauseExceptionTypeHeaderName,
- rootCause
- .getClass()
- .getName());
- requestBuilder.header(
- config.rootCauseExceptionMessageHeaderName,
- rootCause
- .getMessage());
- });
- return exchange.mutate()
- .request(requestBuilder.build())
- .build();
- }).orElse(exchange);
+ Throwable exception = exchange
+ .getAttribute(CIRCUITBREAKER_EXECUTION_EXCEPTION_ATTR);
+ ServerWebExchange filteredExchange;
+ if (exception == null) {
+ filteredExchange = exchange;
+ }
+ else {
+ filteredExchange = addFallbackHeaders(config, exchange, exception);
+ }
return chain.filter(filteredExchange);
};
}
+ private ServerWebExchange addFallbackHeaders(Config config,
+ ServerWebExchange exchange, Throwable executionException) {
+ ServerHttpRequest.Builder requestBuilder = exchange.getRequest().mutate();
+ requestBuilder.header(config.executionExceptionTypeHeaderName,
+ executionException.getClass().getName());
+ requestBuilder.header(config.executionExceptionMessageHeaderName,
+ executionException.getMessage());
+ Throwable rootCause = getRootCause(executionException);
+ if (rootCause != null) {
+ requestBuilder.header(config.rootCauseExceptionTypeHeaderName,
+ rootCause.getClass().getName());
+ requestBuilder.header(config.rootCauseExceptionMessageHeaderName,
+ rootCause.getMessage());
+ }
+ return exchange.mutate().request(requestBuilder.build()).build();
+ }
+
+ private static Throwable getRootCause(final Throwable throwable) {
+ final List list = getThrowableList(throwable);
+ return list.isEmpty() ? null : list.get(list.size() - 1);
+ }
+
+ private static List getThrowableList(Throwable throwable) {
+ final List list = new ArrayList<>();
+ while (throwable != null && !list.contains(throwable)) {
+ list.add(throwable);
+ throwable = throwable.getCause();
+ }
+ return list;
+ }
+
public static class Config {
private static final String EXECUTION_EXCEPTION_TYPE = "Execution-Exception-Type";
diff --git a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/HystrixGatewayFilterFactory.java b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/HystrixGatewayFilterFactory.java
deleted file mode 100644
index f91f8073..00000000
--- a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/HystrixGatewayFilterFactory.java
+++ /dev/null
@@ -1,291 +0,0 @@
-/*
- * Copyright 2013-2019 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
- *
- * https://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.gateway.filter.factory;
-
-import java.net.URI;
-import java.util.List;
-import java.util.function.Consumer;
-import java.util.function.Function;
-
-import com.netflix.hystrix.HystrixCommandGroupKey;
-import com.netflix.hystrix.HystrixCommandKey;
-import com.netflix.hystrix.HystrixObservableCommand;
-import com.netflix.hystrix.HystrixObservableCommand.Setter;
-import com.netflix.hystrix.exception.HystrixRuntimeException;
-import reactor.core.publisher.Mono;
-import reactor.util.context.Context;
-import rx.Observable;
-import rx.RxReactiveStreams;
-import rx.Subscription;
-
-import org.springframework.beans.factory.ObjectProvider;
-import org.springframework.cloud.gateway.filter.GatewayFilter;
-import org.springframework.cloud.gateway.filter.GatewayFilterChain;
-import org.springframework.cloud.gateway.support.ServiceUnavailableException;
-import org.springframework.cloud.gateway.support.TimeoutException;
-import org.springframework.core.annotation.AnnotatedElementUtils;
-import org.springframework.http.server.reactive.ServerHttpRequest;
-import org.springframework.util.Assert;
-import org.springframework.util.StringUtils;
-import org.springframework.web.bind.annotation.ResponseStatus;
-import org.springframework.web.reactive.DispatcherHandler;
-import org.springframework.web.server.ResponseStatusException;
-import org.springframework.web.server.ServerWebExchange;
-import org.springframework.web.util.UriComponentsBuilder;
-
-import static java.util.Collections.singletonList;
-import static java.util.Optional.ofNullable;
-import static org.springframework.cloud.gateway.support.GatewayToStringStyler.filterToStringCreator;
-import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR;
-import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.HYSTRIX_EXECUTION_EXCEPTION_ATTR;
-import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.containsEncodedParts;
-import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.removeAlreadyRouted;
-
-/**
- * Depends on `spring-cloud-starter-netflix-hystrix`,
- * {@see https://cloud.spring.io/spring-cloud-netflix/}.
- *
- * @author Spencer Gibb
- * @author Michele Mancioppi
- * @author Olga Maciaszek-Sharma
- */
-public class HystrixGatewayFilterFactory
- extends AbstractGatewayFilterFactory {
-
- private final ObjectProvider dispatcherHandlerProvider;
-
- // do not use this dispatcherHandler directly, use getDispatcherHandler() instead.
- private volatile DispatcherHandler dispatcherHandler;
-
- public HystrixGatewayFilterFactory(
- ObjectProvider dispatcherHandlerProvider) {
- super(Config.class);
- this.dispatcherHandlerProvider = dispatcherHandlerProvider;
- }
-
- private DispatcherHandler getDispatcherHandler() {
- if (dispatcherHandler == null) {
- dispatcherHandler = dispatcherHandlerProvider.getIfAvailable();
- }
-
- return dispatcherHandler;
- }
-
- @Override
- public List shortcutFieldOrder() {
- return singletonList(NAME_KEY);
- }
-
- @Override
- // TODO: make Config implement HasRouteId and remove this method.
- public GatewayFilter apply(String routeId, Consumer consumer) {
- Config config = newConfig();
- consumer.accept(config);
-
- if (StringUtils.isEmpty(config.getName()) && !StringUtils.isEmpty(routeId)) {
- config.setName(routeId);
- }
-
- return apply(config);
- }
-
- /**
- * Create a {@link Setter} based on incoming request attribute.
- * This could be useful for example to create a Setter with {@link HystrixCommandKey}
- * being set as the target service's host:port, as obtained from
- * {@link ServerWebExchange#getRequest()} to do per service instance level circuit
- * breaking.
- */
- protected Setter createCommandSetter(Config config, ServerWebExchange exchange) {
- return config.setter;
- }
-
- @Override
- public GatewayFilter apply(Config config) {
- // TODO: if no name is supplied, generate one from command id (useful for default
- // filter)
- if (config.setter == null) {
- Assert.notNull(config.name,
- "A name must be supplied for the Hystrix Command Key");
- HystrixCommandGroupKey groupKey = HystrixCommandGroupKey.Factory
- .asKey(getClass().getSimpleName());
- HystrixCommandKey commandKey = HystrixCommandKey.Factory.asKey(config.name);
-
- config.setter = Setter.withGroupKey(groupKey).andCommandKey(commandKey);
- }
-
- return new GatewayFilter() {
- @Override
- public Mono filter(ServerWebExchange exchange,
- GatewayFilterChain chain) {
- return Mono.deferWithContext(context -> {
- RouteHystrixCommand command = new RouteHystrixCommand(
- createCommandSetter(config, exchange), config.fallbackUri,
- exchange, chain, context);
-
- return Mono.create(s -> {
- Subscription sub = command.toObservable().subscribe(s::success,
- s::error, s::success);
- s.onCancel(sub::unsubscribe);
- }).onErrorResume((Function>) throwable -> {
- if (throwable instanceof HystrixRuntimeException) {
- HystrixRuntimeException e = (HystrixRuntimeException) throwable;
- HystrixRuntimeException.FailureType failureType = e
- .getFailureType();
-
- switch (failureType) {
- case TIMEOUT:
- return Mono.error(new TimeoutException());
- case SHORTCIRCUIT:
- return Mono.error(new ServiceUnavailableException());
- case COMMAND_EXCEPTION: {
- Throwable cause = e.getCause();
-
- /*
- * We forsake here the null check for cause as
- * HystrixRuntimeException will always have a cause if the
- * failure type is COMMAND_EXCEPTION.
- */
- if (cause instanceof ResponseStatusException
- || AnnotatedElementUtils.findMergedAnnotation(
- cause.getClass(),
- ResponseStatus.class) != null) {
- return Mono.error(cause);
- }
- }
- default:
- break;
- }
- }
- return Mono.error(throwable);
- }).then();
- });
- }
-
- @Override
- public String toString() {
- return filterToStringCreator(HystrixGatewayFilterFactory.this)
- .append("name", config.getName())
- .append("fallback", config.fallbackUri).toString();
- }
- };
- }
-
- public static class Config {
-
- private String name;
-
- private Setter setter;
-
- private URI fallbackUri;
-
- public String getName() {
- return name;
- }
-
- public Config setName(String name) {
- this.name = name;
- return this;
- }
-
- public Config setFallbackUri(String fallbackUri) {
- if (fallbackUri != null) {
- setFallbackUri(URI.create(fallbackUri));
- }
- return this;
- }
-
- public URI getFallbackUri() {
- return fallbackUri;
- }
-
- public void setFallbackUri(URI fallbackUri) {
- if (fallbackUri != null && !"forward".equals(fallbackUri.getScheme())) {
- throw new IllegalArgumentException(
- "Hystrix Filter currently only supports 'forward' URIs, found "
- + fallbackUri);
- }
- this.fallbackUri = fallbackUri;
- }
-
- public Config setSetter(Setter setter) {
- this.setter = setter;
- return this;
- }
-
- }
-
- // TODO: replace with HystrixMonoCommand that we write
- private class RouteHystrixCommand extends HystrixObservableCommand {
-
- private final URI fallbackUri;
-
- private final ServerWebExchange exchange;
-
- private final GatewayFilterChain chain;
-
- private final Context context;
-
- RouteHystrixCommand(Setter setter, URI fallbackUri, ServerWebExchange exchange,
- GatewayFilterChain chain, Context context) {
- super(setter);
- this.fallbackUri = fallbackUri;
- this.exchange = exchange;
- this.chain = chain;
- this.context = context;
- }
-
- @Override
- protected Observable construct() {
- return RxReactiveStreams
- .toObservable(this.chain.filter(exchange).subscriberContext(context));
- }
-
- @Override
- protected Observable resumeWithFallback() {
- if (this.fallbackUri == null) {
- return super.resumeWithFallback();
- }
-
- // TODO: copied from RouteToRequestUrlFilter
- URI uri = exchange.getRequest().getURI();
- // TODO: assume always?
- boolean encoded = containsEncodedParts(uri);
- URI requestUrl = UriComponentsBuilder.fromUri(uri).host(null).port(null)
- .uri(this.fallbackUri).scheme(null).build(encoded).toUri();
- exchange.getAttributes().put(GATEWAY_REQUEST_URL_ATTR, requestUrl);
- addExceptionDetails();
-
- ServerHttpRequest request = this.exchange.getRequest().mutate()
- .uri(requestUrl).build();
- ServerWebExchange mutated = exchange.mutate().request(request).build();
- // Before we continue on remove the already routed attribute since the
- // fallback may go back through the route handler if the fallback
- // is to another route in the Gateway
- removeAlreadyRouted(mutated);
- return RxReactiveStreams.toObservable(getDispatcherHandler().handle(mutated));
- }
-
- private void addExceptionDetails() {
- Throwable executionException = getExecutionException();
- ofNullable(executionException).ifPresent(exception -> exchange.getAttributes()
- .put(HYSTRIX_EXECUTION_EXCEPTION_ATTR, exception));
- }
-
- }
-
-}
diff --git a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/SpringCloudCircuitBreakerHystrixFilterFactory.java b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/SpringCloudCircuitBreakerHystrixFilterFactory.java
deleted file mode 100644
index fd026ed8..00000000
--- a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/SpringCloudCircuitBreakerHystrixFilterFactory.java
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright 2013-2019 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
- *
- * https://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.gateway.filter.factory;
-
-import com.netflix.hystrix.exception.HystrixRuntimeException;
-import reactor.core.publisher.Mono;
-
-import org.springframework.beans.factory.ObjectProvider;
-import org.springframework.cloud.client.circuitbreaker.ReactiveCircuitBreakerFactory;
-import org.springframework.cloud.gateway.support.ServiceUnavailableException;
-import org.springframework.cloud.gateway.support.TimeoutException;
-import org.springframework.core.annotation.AnnotatedElementUtils;
-import org.springframework.web.bind.annotation.ResponseStatus;
-import org.springframework.web.reactive.DispatcherHandler;
-import org.springframework.web.server.ResponseStatusException;
-
-/**
- * @author Ryan Baxter
- */
-public class SpringCloudCircuitBreakerHystrixFilterFactory
- extends SpringCloudCircuitBreakerFilterFactory {
-
- public SpringCloudCircuitBreakerHystrixFilterFactory(
- ReactiveCircuitBreakerFactory reactiveCircuitBreakerFactory,
- ObjectProvider dispatcherHandlerProvider) {
- super(reactiveCircuitBreakerFactory, dispatcherHandlerProvider);
- }
-
- @Override
- protected Mono handleErrorWithoutFallback(Throwable throwable) {
- if (throwable instanceof HystrixRuntimeException) {
- HystrixRuntimeException e = (HystrixRuntimeException) throwable;
- HystrixRuntimeException.FailureType failureType = e.getFailureType();
-
- switch (failureType) {
- case TIMEOUT:
- return Mono.error(new TimeoutException());
- case SHORTCIRCUIT:
- return Mono.error(new ServiceUnavailableException());
- case COMMAND_EXCEPTION: {
- Throwable cause = e.getCause();
-
- /*
- * We forsake here the null check for cause as HystrixRuntimeException
- * will always have a cause if the failure type is COMMAND_EXCEPTION.
- */
- if (cause instanceof ResponseStatusException
- || AnnotatedElementUtils.findMergedAnnotation(cause.getClass(),
- ResponseStatus.class) != null) {
- return Mono.error(cause);
- }
- }
- default:
- break;
- }
- }
- return Mono.error(throwable);
- }
-
-}
diff --git a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/route/builder/GatewayFilterSpec.java b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/route/builder/GatewayFilterSpec.java
index df8aca99..a6bdfbbb 100644
--- a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/route/builder/GatewayFilterSpec.java
+++ b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/route/builder/GatewayFilterSpec.java
@@ -42,7 +42,6 @@ import org.springframework.cloud.gateway.filter.factory.AddResponseHeaderGateway
import org.springframework.cloud.gateway.filter.factory.DedupeResponseHeaderGatewayFilterFactory;
import org.springframework.cloud.gateway.filter.factory.DedupeResponseHeaderGatewayFilterFactory.Strategy;
import org.springframework.cloud.gateway.filter.factory.FallbackHeadersGatewayFilterFactory;
-import org.springframework.cloud.gateway.filter.factory.HystrixGatewayFilterFactory;
import org.springframework.cloud.gateway.filter.factory.MapRequestHeaderGatewayFilterFactory;
import org.springframework.cloud.gateway.filter.factory.PrefixPathGatewayFilterFactory;
import org.springframework.cloud.gateway.filter.factory.PreserveHostHeaderGatewayFilterFactory;
@@ -74,7 +73,6 @@ import org.springframework.cloud.gateway.filter.ratelimit.RateLimiter;
import org.springframework.cloud.gateway.route.Route;
import org.springframework.core.Ordered;
import org.springframework.http.HttpStatus;
-import org.springframework.util.StringUtils;
import org.springframework.util.unit.DataSize;
import org.springframework.web.server.ServerWebExchange;
@@ -199,27 +197,6 @@ public class GatewayFilterSpec extends UriSpec {
c -> c.setStrategy(Strategy.valueOf(strategy)).setName(headerName)));
}
- /**
- * Wraps the route in a Hystrix command. Depends on @{code
- * org.springframework.cloud::spring-cloud-starter-netflix-hystrix} being on the
- * classpath, {@see https://cloud.spring.io/spring-cloud-netflix/}
- * @param configConsumer a {@link Consumer} which provides configuration for the
- * Hystrix command
- * @return a {@link GatewayFilterSpec} that can be used to apply additional filters
- */
- public GatewayFilterSpec hystrix(
- Consumer configConsumer) {
- HystrixGatewayFilterFactory factory;
- try {
- factory = getBean(HystrixGatewayFilterFactory.class);
- }
- catch (NoSuchBeanDefinitionException e) {
- throw new NoSuchBeanDefinitionException(HystrixGatewayFilterFactory.class,
- "This is probably because Hystrix is missing from the classpath, which can be resolved by adding dependency on 'org.springframework.cloud:spring-cloud-starter-netflix-hystrix'");
- }
- return filter(factory.apply(this.routeBuilder.getId(), configConsumer));
- }
-
public GatewayFilterSpec circuitBreaker(
Consumer configConsumer) {
SpringCloudCircuitBreakerFilterFactory filterFactory;
diff --git a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/support/ConfigurationUtils.java b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/support/ConfigurationUtils.java
deleted file mode 100644
index 621cf998..00000000
--- a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/support/ConfigurationUtils.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright 2013-2019 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
- *
- * https://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.gateway.support;
-
-import java.util.Map;
-
-import org.springframework.boot.context.properties.bind.Bindable;
-import org.springframework.core.convert.ConversionService;
-import org.springframework.validation.Validator;
-
-@Deprecated
-public abstract class ConfigurationUtils {
-
- @Deprecated
- public static void bind(Object o, Map properties,
- String configurationPropertyName, String bindingName, Validator validator) {
- bind(o, properties, configurationPropertyName, bindingName, validator, null);
- }
-
- @Deprecated
- public static void bind(Object o, Map properties,
- String configurationPropertyName, String bindingName, Validator validator,
- ConversionService conversionService) {
- Object toBind = getTargetObject(o);
- Bindable> bindable = Bindable.ofInstance(toBind);
- ConfigurationService.bindOrCreate(bindable, properties,
- configurationPropertyName/* , bindingName */, validator,
- conversionService);
- }
-
- @Deprecated
- @SuppressWarnings("unchecked")
- public static T getTargetObject(Object candidate) {
- return ConfigurationService.getTargetObject(candidate);
- }
-
-}
diff --git a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/support/DefaultClientResponse.java b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/support/DefaultClientResponse.java
deleted file mode 100644
index c215e9d2..00000000
--- a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/support/DefaultClientResponse.java
+++ /dev/null
@@ -1,262 +0,0 @@
-/*
- * Copyright 2013-2019 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
- *
- * https://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.gateway.support;
-
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
-import java.util.Optional;
-import java.util.OptionalLong;
-
-import reactor.core.publisher.Flux;
-import reactor.core.publisher.Mono;
-
-import org.springframework.core.ParameterizedTypeReference;
-import org.springframework.core.io.buffer.DataBufferUtils;
-import org.springframework.http.HttpHeaders;
-import org.springframework.http.HttpStatus;
-import org.springframework.http.MediaType;
-import org.springframework.http.ResponseCookie;
-import org.springframework.http.ResponseEntity;
-import org.springframework.http.client.reactive.ClientHttpResponse;
-import org.springframework.http.codec.HttpMessageReader;
-import org.springframework.http.server.reactive.ServerHttpResponse;
-import org.springframework.util.MultiValueMap;
-import org.springframework.web.reactive.function.BodyExtractor;
-import org.springframework.web.reactive.function.BodyExtractors;
-import org.springframework.web.reactive.function.client.ClientResponse;
-import org.springframework.web.reactive.function.client.ExchangeStrategies;
-import org.springframework.web.reactive.function.client.WebClientResponseException;
-
-/**
- * Default implementation of {@link ClientResponse}.
- *
- * @author Arjen Poutsma
- * @author Brian Clozel
- * @since 5.0
- * @deprecated Will be removed in future release.
- */
-@Deprecated
-public class DefaultClientResponse implements ClientResponse {
-
- private final ClientHttpResponse response;
-
- private final Headers headers;
-
- private final ExchangeStrategies strategies;
-
- public DefaultClientResponse(ClientHttpResponse response,
- ExchangeStrategies strategies) {
- this.response = response;
- this.strategies = strategies;
- this.headers = new DefaultHeaders();
- }
-
- @Override
- public ExchangeStrategies strategies() {
- return this.strategies;
- }
-
- @Override
- public HttpStatus statusCode() {
- return this.response.getStatusCode();
- }
-
- @Override
- public int rawStatusCode() {
- return this.response.getRawStatusCode();
- }
-
- @Override
- public Headers headers() {
- return this.headers;
- }
-
- @Override
- public MultiValueMap cookies() {
- return this.response.getCookies();
- }
-
- @Override
- public T body(BodyExtractor extractor) {
- return extractor.extract(this.response, new BodyExtractor.Context() {
- @Override
- public List> messageReaders() {
- return strategies.messageReaders();
- }
-
- @Override
- public Optional serverResponse() {
- return Optional.empty();
- }
-
- @Override
- public Map hints() {
- return Collections.emptyMap();
- }
- });
- }
-
- @Override
- public Mono bodyToMono(Class extends T> elementClass) {
- if (Void.class.isAssignableFrom(elementClass)) {
- return consumeAndCancel();
- }
- else {
- return body(BodyExtractors.toMono(elementClass));
- }
- }
-
- @Override
- public Mono releaseBody() {
- return body(BodyExtractors.toDataBuffers()).map(DataBufferUtils::release).then();
- }
-
- @Override
- public Mono> toBodilessEntity() {
- return releaseBody().then(toEntityInternal(Mono.empty()));
- }
-
- @Override
- public Mono createException() {
- throw new UnsupportedOperationException();
- }
-
- @SuppressWarnings("unchecked")
- private Mono consumeAndCancel() {
- return (Mono) this.response.getBody().map(buffer -> {
- DataBufferUtils.release(buffer);
- throw new ReadCancellationException();
- }).onErrorResume(ReadCancellationException.class, ex -> Mono.empty()).then();
- }
-
- @Override
- public Mono bodyToMono(ParameterizedTypeReference typeReference) {
- if (Void.class.isAssignableFrom(typeReference.getType().getClass())) {
- return consumeAndCancel();
- }
- else {
- return body(BodyExtractors.toMono(typeReference));
- }
- }
-
- @Override
- public Flux bodyToFlux(Class extends T> elementClass) {
- if (Void.class.isAssignableFrom(elementClass)) {
- return Flux.from(consumeAndCancel());
- }
- else {
- return body(BodyExtractors.toFlux(elementClass));
- }
- }
-
- @Override
- public Flux bodyToFlux(ParameterizedTypeReference typeReference) {
- if (Void.class.isAssignableFrom(typeReference.getType().getClass())) {
- return Flux.from(consumeAndCancel());
- }
- else {
- return body(BodyExtractors.toFlux(typeReference));
- }
- }
-
- @Override
- public Mono> toEntity(Class bodyType) {
- if (Void.class.isAssignableFrom(bodyType)) {
- return toEntityInternal(consumeAndCancel());
- }
- else {
- return toEntityInternal(bodyToMono(bodyType));
- }
- }
-
- @Override
- public Mono> toEntity(
- ParameterizedTypeReference typeReference) {
- if (Void.class.isAssignableFrom(typeReference.getType().getClass())) {
- return toEntityInternal(consumeAndCancel());
- }
- else {
- return toEntityInternal(bodyToMono(typeReference));
- }
- }
-
- private Mono> toEntityInternal(Mono bodyMono) {
- HttpHeaders headers = headers().asHttpHeaders();
- HttpStatus statusCode = statusCode();
- return bodyMono.map(body -> new ResponseEntity<>(body, headers, statusCode))
- .switchIfEmpty(Mono.defer(
- () -> Mono.just(new ResponseEntity<>(headers, statusCode))));
- }
-
- @Override
- public Mono>> toEntityList(Class responseType) {
- return toEntityListInternal(bodyToFlux(responseType));
- }
-
- @Override
- public Mono>> toEntityList(
- ParameterizedTypeReference typeReference) {
- return toEntityListInternal(bodyToFlux(typeReference));
- }
-
- private Mono>> toEntityListInternal(Flux bodyFlux) {
- HttpHeaders headers = headers().asHttpHeaders();
- HttpStatus statusCode = statusCode();
- return bodyFlux.collectList()
- .map(body -> new ResponseEntity<>(body, headers, statusCode));
- }
-
- @SuppressWarnings("serial")
- private static class ReadCancellationException extends RuntimeException {
-
- }
-
- private class DefaultHeaders implements Headers {
-
- private HttpHeaders delegate() {
- return response.getHeaders();
- }
-
- @Override
- public OptionalLong contentLength() {
- return toOptionalLong(delegate().getContentLength());
- }
-
- @Override
- public Optional contentType() {
- return Optional.ofNullable(delegate().getContentType());
- }
-
- @Override
- public List header(String headerName) {
- List headerValues = delegate().get(headerName);
- return (headerValues != null ? headerValues : Collections.emptyList());
- }
-
- @Override
- public HttpHeaders asHttpHeaders() {
- return HttpHeaders.readOnlyHttpHeaders(delegate());
- }
-
- private OptionalLong toOptionalLong(long value) {
- return (value != -1 ? OptionalLong.of(value) : OptionalLong.empty());
- }
-
- }
-
-}
diff --git a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/support/DefaultServerRequest.java b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/support/DefaultServerRequest.java
deleted file mode 100644
index 22bd0c3d..00000000
--- a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/support/DefaultServerRequest.java
+++ /dev/null
@@ -1,311 +0,0 @@
-/*
- * Copyright 2013-2019 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
- *
- * https://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.gateway.support;
-
-import java.net.InetSocketAddress;
-import java.net.URI;
-import java.nio.charset.Charset;
-import java.security.Principal;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import java.util.Locale;
-import java.util.Map;
-import java.util.Optional;
-import java.util.OptionalLong;
-import java.util.function.Function;
-
-import reactor.core.publisher.Flux;
-import reactor.core.publisher.Mono;
-
-import org.springframework.core.ParameterizedTypeReference;
-import org.springframework.http.HttpCookie;
-import org.springframework.http.HttpHeaders;
-import org.springframework.http.HttpRange;
-import org.springframework.http.HttpRequest;
-import org.springframework.http.MediaType;
-import org.springframework.http.codec.HttpMessageReader;
-import org.springframework.http.codec.multipart.Part;
-import org.springframework.http.server.PathContainer;
-import org.springframework.http.server.reactive.ServerHttpRequest;
-import org.springframework.http.server.reactive.ServerHttpResponse;
-import org.springframework.util.MultiValueMap;
-import org.springframework.web.reactive.function.BodyExtractor;
-import org.springframework.web.reactive.function.BodyExtractors;
-import org.springframework.web.reactive.function.UnsupportedMediaTypeException;
-import org.springframework.web.reactive.function.server.HandlerStrategies;
-import org.springframework.web.reactive.function.server.RouterFunctions;
-import org.springframework.web.reactive.function.server.ServerRequest;
-import org.springframework.web.server.ServerWebExchange;
-import org.springframework.web.server.UnsupportedMediaTypeStatusException;
-import org.springframework.web.server.WebSession;
-import org.springframework.web.util.UriBuilder;
-import org.springframework.web.util.UriComponentsBuilder;
-
-/**
- * {@code ServerRequest} implementation based on a {@link ServerWebExchange}.
- *
- * @author Arjen Poutsma
- * @since 5.0
- * @deprecated Will be removed in a future release.
- */
-@Deprecated
-public class DefaultServerRequest implements ServerRequest {
-
- private static final Function ERROR_MAPPER = ex -> (ex
- .getContentType() != null
- ? new UnsupportedMediaTypeStatusException(ex.getContentType(),
- ex.getSupportedMediaTypes())
- : new UnsupportedMediaTypeStatusException(ex.getMessage()));
-
- private final ServerWebExchange exchange;
-
- private final Headers headers;
-
- private final List> messageReaders;
-
- public DefaultServerRequest(ServerWebExchange exchange) {
- this(exchange, HandlerStrategies.withDefaults().messageReaders());
- }
-
- public DefaultServerRequest(ServerWebExchange exchange,
- List> messageReaders) {
- this.exchange = exchange;
- this.messageReaders = Collections
- .unmodifiableList(new ArrayList<>(messageReaders));
- this.headers = new DefaultHeaders();
- }
-
- @Override
- public String methodName() {
- return request().getMethodValue();
- }
-
- @Override
- public URI uri() {
- return request().getURI();
- }
-
- @Override
- public UriBuilder uriBuilder() {
- return UriComponentsBuilder.fromHttpRequest(new ServerRequestAdapter());
- }
-
- @Override
- public PathContainer pathContainer() {
- return request().getPath();
- }
-
- @Override
- public Headers headers() {
- return this.headers;
- }
-
- @Override
- public MultiValueMap cookies() {
- return request().getCookies();
- }
-
- @Override
- public T body(BodyExtractor extractor) {
- return body(extractor, Collections.emptyMap());
- }
-
- @Override
- public Optional remoteAddress() {
- return Optional.of(request().getRemoteAddress());
- }
-
- @Override
- public List> messageReaders() {
- return this.messageReaders;
- }
-
- @Override
- public T body(BodyExtractor extractor,
- Map hints) {
- return extractor.extract(request(), new BodyExtractor.Context() {
- @Override
- public List> messageReaders() {
- return messageReaders;
- }
-
- @Override
- public Optional serverResponse() {
- return Optional.of(exchange().getResponse());
- }
-
- @Override
- public Map hints() {
- return hints;
- }
- });
- }
-
- @Override
- public Mono bodyToMono(Class extends T> elementClass) {
- Mono mono = body(BodyExtractors.toMono(elementClass));
- return mono.onErrorMap(UnsupportedMediaTypeException.class, ERROR_MAPPER);
- }
-
- @Override
- public Mono bodyToMono(ParameterizedTypeReference typeReference) {
- Mono mono = body(BodyExtractors.toMono(typeReference));
- return mono.onErrorMap(UnsupportedMediaTypeException.class, ERROR_MAPPER);
- }
-
- @Override
- public Flux bodyToFlux(Class extends T> elementClass) {
- Flux flux = body(BodyExtractors.toFlux(elementClass));
- return flux.onErrorMap(UnsupportedMediaTypeException.class, ERROR_MAPPER);
- }
-
- @Override
- public Flux bodyToFlux(ParameterizedTypeReference typeReference) {
- Flux flux = body(BodyExtractors.toFlux(typeReference));
- return flux.onErrorMap(UnsupportedMediaTypeException.class, ERROR_MAPPER);
- }
-
- @Override
- public Map attributes() {
- return this.exchange.getAttributes();
- }
-
- @Override
- public MultiValueMap queryParams() {
- return request().getQueryParams();
- }
-
- @Override
- public Map pathVariables() {
- return this.exchange.getAttributeOrDefault(
- RouterFunctions.URI_TEMPLATE_VARIABLES_ATTRIBUTE, Collections.emptyMap());
- }
-
- @Override
- public Mono session() {
- return this.exchange.getSession();
- }
-
- @Override
- public Mono extends Principal> principal() {
- return this.exchange.getPrincipal();
- }
-
- @Override
- public Mono> formData() {
- return this.exchange.getFormData();
- }
-
- @Override
- public Mono> multipartData() {
- return this.exchange.getMultipartData();
- }
-
- private ServerHttpRequest request() {
- return this.exchange.getRequest();
- }
-
- public ServerWebExchange exchange() {
- return this.exchange;
- }
-
- @Override
- public String toString() {
- return String.format("%s %s", method(), path());
- }
-
- private class DefaultHeaders implements Headers {
-
- private HttpHeaders delegate() {
- return request().getHeaders();
- }
-
- @Override
- public List accept() {
- return delegate().getAccept();
- }
-
- @Override
- public List acceptCharset() {
- return delegate().getAcceptCharset();
- }
-
- @Override
- public List acceptLanguage() {
- return delegate().getAcceptLanguage();
- }
-
- @Override
- public OptionalLong contentLength() {
- long value = delegate().getContentLength();
- return (value != -1 ? OptionalLong.of(value) : OptionalLong.empty());
- }
-
- @Override
- public Optional contentType() {
- return Optional.ofNullable(delegate().getContentType());
- }
-
- @Override
- public InetSocketAddress host() {
- return delegate().getHost();
- }
-
- @Override
- public List range() {
- return delegate().getRange();
- }
-
- @Override
- public List header(String headerName) {
- List headerValues = delegate().get(headerName);
- return (headerValues != null ? headerValues : Collections.emptyList());
- }
-
- @Override
- public HttpHeaders asHttpHeaders() {
- return HttpHeaders.readOnlyHttpHeaders(delegate());
- }
-
- @Override
- public String toString() {
- return delegate().toString();
- }
-
- }
-
- private final class ServerRequestAdapter implements HttpRequest {
-
- @Override
- public String getMethodValue() {
- return methodName();
- }
-
- @Override
- public URI getURI() {
- return uri();
- }
-
- @Override
- public HttpHeaders getHeaders() {
- return request().getHeaders();
- }
-
- }
-
-}
diff --git a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/support/DefaultServerResponse.java b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/support/DefaultServerResponse.java
deleted file mode 100644
index d9f175ad..00000000
--- a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/support/DefaultServerResponse.java
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * Copyright 2013-2019 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
- *
- * https://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.gateway.support;
-
-import java.util.List;
-import java.util.Map;
-import java.util.Optional;
-
-import reactor.core.publisher.Mono;
-
-import org.springframework.http.HttpHeaders;
-import org.springframework.http.HttpStatus;
-import org.springframework.http.ResponseCookie;
-import org.springframework.http.codec.HttpMessageWriter;
-import org.springframework.http.server.reactive.ServerHttpRequest;
-import org.springframework.http.server.reactive.ServerHttpResponse;
-import org.springframework.util.Assert;
-import org.springframework.util.MultiValueMap;
-import org.springframework.web.reactive.function.BodyInserter;
-import org.springframework.web.reactive.function.server.HandlerStrategies;
-import org.springframework.web.reactive.function.server.ServerResponse;
-import org.springframework.web.reactive.result.view.ViewResolver;
-import org.springframework.web.server.ServerWebExchange;
-
-@Deprecated
-public class DefaultServerResponse implements ServerResponse {
-
- private final ServerWebExchange exchange;
-
- private final BodyInserter inserter;
-
- private final Map hints;
-
- public DefaultServerResponse(ServerWebExchange exchange,
- BodyInserter body, Map hints) {
- this.exchange = exchange;
- Assert.notNull(exchange, "ServerWebExchange must not be null");
- Assert.notNull(body, "BodyInserter must not be null");
- this.inserter = body;
- this.hints = hints;
- }
-
- private ServerHttpResponse response() {
- return exchange.getResponse();
- }
-
- @Override
- public final HttpStatus statusCode() {
- // TODO: non standard status code
- return HttpStatus.valueOf(response().getStatusCode().value());
- }
-
- @Override
- public int rawStatusCode() {
- return response().getStatusCode().value();
- }
-
- @Override
- public final HttpHeaders headers() {
- return response().getHeaders();
- }
-
- @Override
- public MultiValueMap cookies() {
- return response().getCookies();
- }
-
- @Override
- public final Mono writeTo(ServerWebExchange exchange, Context context) {
- return this.inserter.insert(exchange.getResponse(), new BodyInserter.Context() {
- @Override
- public List> messageWriters() {
- return context.messageWriters();
- }
-
- @Override
- public Optional serverRequest() {
- return Optional.of(exchange.getRequest());
- }
-
- @Override
- public Map hints() {
- return hints;
- }
- });
- }
-
- public static class HandlerStrategiesResponseContext
- implements ServerResponse.Context {
-
- private HandlerStrategies strategies = HandlerStrategies.withDefaults();
-
- public HandlerStrategiesResponseContext() {
- }
-
- public HandlerStrategiesResponseContext(HandlerStrategies strategies) {
- this.strategies = strategies;
- }
-
- @Override
- public List> messageWriters() {
- return this.strategies.messageWriters();
- }
-
- @Override
- public List viewResolvers() {
- return this.strategies.viewResolvers();
- }
-
- }
-
-}
diff --git a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/support/ServerWebExchangeUtils.java b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/support/ServerWebExchangeUtils.java
index ca90c619..678591ff 100644
--- a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/support/ServerWebExchangeUtils.java
+++ b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/support/ServerWebExchangeUtils.java
@@ -122,12 +122,6 @@ public final class ServerWebExchangeUtils {
*/
public static final String ORIGINAL_RESPONSE_CONTENT_TYPE_ATTR = "original_response_content_type";
- /**
- * Hystrix execution exception attribute name.
- */
- public static final String HYSTRIX_EXECUTION_EXCEPTION_ATTR = qualify(
- "hystrixExecutionException");
-
/**
* CircuitBreaker execution exception attribute name.
*/
diff --git a/spring-cloud-gateway-core/src/main/resources/META-INF/spring.factories b/spring-cloud-gateway-core/src/main/resources/META-INF/spring.factories
index 5019e783..989a1afb 100644
--- a/spring-cloud-gateway-core/src/main/resources/META-INF/spring.factories
+++ b/spring-cloud-gateway-core/src/main/resources/META-INF/spring.factories
@@ -2,9 +2,7 @@
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.cloud.gateway.config.GatewayClassPathWarningAutoConfiguration,\
org.springframework.cloud.gateway.config.GatewayAutoConfiguration,\
-org.springframework.cloud.gateway.config.GatewayHystrixCircuitBreakerAutoConfiguration,\
org.springframework.cloud.gateway.config.GatewayResilience4JCircuitBreakerAutoConfiguration,\
-org.springframework.cloud.gateway.config.GatewayLoadBalancerClientAutoConfiguration,\
org.springframework.cloud.gateway.config.GatewayNoLoadBalancerClientAutoConfiguration,\
org.springframework.cloud.gateway.config.GatewayMetricsAutoConfiguration,\
org.springframework.cloud.gateway.config.GatewayRedisAutoConfiguration,\
diff --git a/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/config/GatewayNoLoadBalancerClientAutoConfigurationTests.java b/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/config/GatewayNoLoadBalancerClientAutoConfigurationTests.java
index 7500b225..956c3dcc 100644
--- a/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/config/GatewayNoLoadBalancerClientAutoConfigurationTests.java
+++ b/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/config/GatewayNoLoadBalancerClientAutoConfigurationTests.java
@@ -36,8 +36,7 @@ import org.springframework.test.web.reactive.server.WebTestClient;
import org.springframework.util.SocketUtils;
@RunWith(ModifiedClassPathRunner.class)
-@ClassPathExclusions({ "spring-cloud-netflix-ribbon-*.jar",
- "spring-cloud-loadbalancer-*.jar" })
+@ClassPathExclusions({ "spring-cloud-loadbalancer-*.jar" })
public class GatewayNoLoadBalancerClientAutoConfigurationTests {
private static int port;
@@ -65,7 +64,7 @@ public class GatewayNoLoadBalancerClientAutoConfigurationTests {
public static class Config {
@Bean
- public RouteLocator hystrixRouteLocator(RouteLocatorBuilder builder) {
+ public RouteLocator routeLocator(RouteLocatorBuilder builder) {
return builder.routes()
.route("lb_fail", r -> r.host("**.lbfail.org").uri("lb://fail"))
.build();
diff --git a/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/LoadBalancerClientFilterTests.java b/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/LoadBalancerClientFilterTests.java
deleted file mode 100644
index cd50fb3b..00000000
--- a/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/LoadBalancerClientFilterTests.java
+++ /dev/null
@@ -1,418 +0,0 @@
-/*
- * Copyright 2017-2019 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
- *
- * https://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.gateway.filter;
-
-import java.net.URI;
-import java.util.LinkedHashSet;
-
-import com.netflix.loadbalancer.ILoadBalancer;
-import com.netflix.loadbalancer.Server;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.ArgumentCaptor;
-import org.mockito.Mock;
-import org.mockito.junit.MockitoJUnitRunner;
-import reactor.core.publisher.Mono;
-
-import org.springframework.cloud.client.DefaultServiceInstance;
-import org.springframework.cloud.client.ServiceInstance;
-import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
-import org.springframework.cloud.gateway.config.LoadBalancerProperties;
-import org.springframework.cloud.gateway.support.NotFoundException;
-import org.springframework.cloud.netflix.ribbon.RibbonLoadBalancerClient;
-import org.springframework.cloud.netflix.ribbon.RibbonLoadBalancerContext;
-import org.springframework.cloud.netflix.ribbon.SpringClientFactory;
-import org.springframework.http.HttpMethod;
-import org.springframework.http.HttpStatus;
-import org.springframework.mock.http.server.reactive.MockServerHttpRequest;
-import org.springframework.mock.web.server.MockServerWebExchange;
-import org.springframework.util.StringUtils;
-import org.springframework.web.server.ServerWebExchange;
-import org.springframework.web.util.UriComponentsBuilder;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.verifyNoInteractions;
-import static org.mockito.Mockito.verifyNoMoreInteractions;
-import static org.mockito.Mockito.when;
-import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.GATEWAY_ORIGINAL_REQUEST_URL_ATTR;
-import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR;
-import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.GATEWAY_SCHEME_PREFIX_ATTR;
-
-/**
- * @author Spencer Gibb
- * @author Tim Ysewyn
- */
-@RunWith(MockitoJUnitRunner.class)
-public class LoadBalancerClientFilterTests {
-
- private ServerWebExchange exchange;
-
- private LoadBalancerProperties properties;
-
- @Mock
- private GatewayFilterChain chain;
-
- @Mock
- private LoadBalancerClient loadBalancerClient;
-
- private LoadBalancerClientFilter loadBalancerClientFilter;
-
- @Before
- public void setup() {
- properties = new LoadBalancerProperties();
- loadBalancerClientFilter = new LoadBalancerClientFilter(loadBalancerClient,
- properties);
- exchange = MockServerWebExchange
- .from(MockServerHttpRequest.get("loadbalancerclient.org").build());
- }
-
- @Test
- public void shouldNotFilterWhenGatewayRequestUrlIsMissing() {
- loadBalancerClientFilter.filter(exchange, chain);
-
- verify(chain).filter(exchange);
- verifyNoMoreInteractions(chain);
- verifyNoInteractions(loadBalancerClient);
- }
-
- @Test
- public void shouldNotFilterWhenGatewayRequestUrlSchemeIsNotLb() {
- URI uri = UriComponentsBuilder.fromUriString("http://myservice").build().toUri();
- exchange.getAttributes().put(GATEWAY_REQUEST_URL_ATTR, uri);
-
- loadBalancerClientFilter.filter(exchange, chain);
-
- verify(chain).filter(exchange);
- verifyNoMoreInteractions(chain);
- verifyNoInteractions(loadBalancerClient);
- }
-
- @Test
- public void shouldThrowExceptionWhenNoServiceInstanceIsFound() {
- URI uri = UriComponentsBuilder.fromUriString("lb://myservice").build().toUri();
- exchange.getAttributes().put(GATEWAY_REQUEST_URL_ATTR, uri);
-
- try {
- loadBalancerClientFilter.filter(exchange, chain);
- }
- catch (NotFoundException e) {
- assertThat(e.getStatus()).isEqualTo(HttpStatus.SERVICE_UNAVAILABLE);
- }
- catch (Exception e) {
- throw e;
- }
- }
-
- @Test
- public void shouldThrow4O4ExceptionWhenNoServiceInstanceIsFound() {
- URI uri = UriComponentsBuilder.fromUriString("lb://myservice").build().toUri();
- exchange.getAttributes().put(GATEWAY_REQUEST_URL_ATTR, uri);
- properties.setUse404(true);
- try {
- loadBalancerClientFilter.filter(exchange, chain);
- }
- catch (NotFoundException e) {
- assertThat(e.getStatus()).isEqualTo(HttpStatus.NOT_FOUND);
- }
- catch (Exception e) {
- throw e;
- }
- }
-
- @Test
- public void shouldFilter() {
- URI url = UriComponentsBuilder.fromUriString("lb://myservice").build().toUri();
- exchange.getAttributes().put(GATEWAY_REQUEST_URL_ATTR, url);
-
- ServiceInstance serviceInstance = new DefaultServiceInstance("myservice1",
- "myservice", "localhost", 8080, true);
- when(loadBalancerClient.choose("myservice")).thenReturn(serviceInstance);
-
- URI requestUrl = UriComponentsBuilder.fromUriString("https://localhost:8080")
- .build().toUri();
- when(loadBalancerClient.reconstructURI(any(ServiceInstance.class),
- any(URI.class))).thenReturn(requestUrl);
-
- loadBalancerClientFilter.filter(exchange, chain);
-
- LinkedHashSet attribute = exchange
- .getAttribute(GATEWAY_ORIGINAL_REQUEST_URL_ATTR);
- assertThat(attribute).contains(url);
-
- verify(loadBalancerClient).choose("myservice");
-
- ArgumentCaptor urlArgumentCaptor = ArgumentCaptor.forClass(URI.class);
- verify(loadBalancerClient).reconstructURI(any(), urlArgumentCaptor.capture());
-
- URI uri = urlArgumentCaptor.getValue();
- assertThat(uri).isNotNull();
- assertThat(uri.toString()).isEqualTo("loadbalancerclient.org");
-
- verifyNoMoreInteractions(loadBalancerClient);
-
- assertThat((URI) exchange.getAttribute(GATEWAY_REQUEST_URL_ATTR))
- .isEqualTo(requestUrl);
-
- verify(chain).filter(exchange);
- verifyNoMoreInteractions(chain);
- }
-
- @Test
- public void instanceOverrideNonSecureScheme() {
- MockServerHttpRequest request = MockServerHttpRequest.get("https://localhost")
- .build();
-
- URI lbUri = URI.create("lb://service1");
- ServerWebExchange webExchange = testFilter(request, lbUri);
- URI uri = webExchange.getRequiredAttribute(GATEWAY_REQUEST_URL_ATTR);
- assertThat(uri).hasScheme("http").hasHost("service1-host1");
- }
-
- @Test
- public void instanceOverrideSecureScheme() {
- MockServerHttpRequest request = MockServerHttpRequest.get("http://localhost")
- .build();
-
- URI lbUri = URI.create("lb://service1");
- ServerWebExchange webExchange = testFilter(request, lbUri, 443);
- URI uri = webExchange.getRequiredAttribute(GATEWAY_REQUEST_URL_ATTR);
- assertThat(uri).hasScheme("https").hasHost("service1-host1");
- }
-
- @Test
- public void instanceOverrideSecureSchemePrefix() {
- MockServerHttpRequest request = MockServerHttpRequest.get("https://localhost")
- .build();
-
- URI lbUri = URI.create("http://service1");
- ServerWebExchange exchange = MockServerWebExchange.from(request);
- exchange.getAttributes().put(GATEWAY_SCHEME_PREFIX_ATTR, "lb");
- ServerWebExchange webExchange = testFilter(exchange, lbUri, 443);
- URI uri = webExchange.getRequiredAttribute(GATEWAY_REQUEST_URL_ATTR);
- assertThat(uri).hasScheme("http").hasHost("service1-host1");
- }
-
- @Test
- public void instanceOverrideNonSecureSchemePrefix() {
- MockServerHttpRequest request = MockServerHttpRequest.get("http://localhost")
- .build();
-
- URI lbUri = URI.create("https://service1");
- ServerWebExchange exchange = MockServerWebExchange.from(request);
- exchange.getAttributes().put(GATEWAY_SCHEME_PREFIX_ATTR, "lb");
- ServerWebExchange webExchange = testFilter(exchange, lbUri, 8081);
- URI uri = webExchange.getRequiredAttribute(GATEWAY_REQUEST_URL_ATTR);
- assertThat(uri).hasScheme("https").hasHost("service1-host1");
- }
-
- @Test
- public void happyPath() {
- MockServerHttpRequest request = MockServerHttpRequest
- .get("http://localhost/get?a=b").build();
-
- URI lbUri = URI.create("lb://service1?a=b");
- ServerWebExchange webExchange = testFilter(request, lbUri);
- URI uri = webExchange.getRequiredAttribute(GATEWAY_REQUEST_URL_ATTR);
- assertThat(uri).hasScheme("http").hasHost("service1-host1").hasParameter("a",
- "b");
- }
-
- @Test
- public void noQueryParams() {
- MockServerHttpRequest request = MockServerHttpRequest.get("http://localhost/get")
- .build();
-
- ServerWebExchange webExchange = testFilter(request, URI.create("lb://service1"));
- URI uri = webExchange.getRequiredAttribute(GATEWAY_REQUEST_URL_ATTR);
- assertThat(uri).hasScheme("http").hasHost("service1-host1");
- }
-
- @Test
- public void encodedParameters() {
- URI url = UriComponentsBuilder.fromUriString("http://localhost/get?a=b&c=d[]")
- .buildAndExpand().encode().toUri();
-
- MockServerHttpRequest request = MockServerHttpRequest.method(HttpMethod.GET, url)
- .build();
-
- URI lbUrl = UriComponentsBuilder.fromUriString("lb://service1?a=b&c=d[]")
- .buildAndExpand().encode().toUri();
-
- // prove that it is encoded
- assertThat(lbUrl.getRawQuery()).isEqualTo("a=b&c=d%5B%5D");
-
- assertThat(lbUrl).hasParameter("c", "d[]");
-
- ServerWebExchange webExchange = testFilter(request, lbUrl);
- URI uri = webExchange.getRequiredAttribute(GATEWAY_REQUEST_URL_ATTR);
- assertThat(uri).hasScheme("http").hasHost("service1-host1").hasParameter("a", "b")
- .hasParameter("c", "d[]");
-
- // prove that it is not double encoded
- assertThat(uri.getRawQuery()).isEqualTo("a=b&c=d%5B%5D");
- }
-
- @Test
- public void unencodedParameters() {
- URI url = URI.create("http://localhost/get?a=b&c=d[]");
-
- MockServerHttpRequest request = MockServerHttpRequest.method(HttpMethod.GET, url)
- .build();
-
- URI lbUrl = URI.create("lb://service1?a=b&c=d[]");
-
- // prove that it is unencoded
- assertThat(lbUrl.getRawQuery()).isEqualTo("a=b&c=d[]");
-
- ServerWebExchange webExchange = testFilter(request, lbUrl);
-
- URI uri = webExchange.getRequiredAttribute(GATEWAY_REQUEST_URL_ATTR);
- assertThat(uri).hasScheme("http").hasHost("service1-host1").hasParameter("a", "b")
- .hasParameter("c", "d[]");
-
- // prove that it is NOT encoded
- assertThat(uri.getRawQuery()).isEqualTo("a=b&c=d[]");
- }
-
- @Test
- public void happyPathWithAttributeRatherThanScheme() {
- MockServerHttpRequest request = MockServerHttpRequest
- .get("ws://localhost/get?a=b").build();
-
- URI lbUri = URI.create("ws://service1?a=b");
-
- exchange = MockServerWebExchange.from(request);
- exchange.getAttributes().put(GATEWAY_SCHEME_PREFIX_ATTR, "lb");
-
- ServerWebExchange webExchange = testFilter(exchange, lbUri, 8081);
- URI uri = webExchange.getRequiredAttribute(GATEWAY_REQUEST_URL_ATTR);
- assertThat(uri).hasScheme("ws").hasHost("service1-host1").hasParameter("a", "b");
- }
-
- @Test
- public void shouldNotFilterWhenGatewaySchemePrefixAttrIsNotLb() {
- URI uri = UriComponentsBuilder.fromUriString("http://myservice").build().toUri();
- exchange.getAttributes().put(GATEWAY_REQUEST_URL_ATTR, uri);
- exchange.getAttributes().put(GATEWAY_SCHEME_PREFIX_ATTR, "xx");
-
- loadBalancerClientFilter.filter(exchange, chain);
-
- verify(chain).filter(exchange);
- verifyNoMoreInteractions(chain);
- verifyNoInteractions(loadBalancerClient);
- }
-
- @Test
- public void shouldSelectSpecifiedServer() {
- URI uri1 = UriComponentsBuilder.fromUriString("lb://myservice").port(11111)
- .build().toUri();
- URI uri2 = UriComponentsBuilder.fromUriString("lb://myservice").port(22222)
- .build().toUri();
-
- SpringClientFactory clientFactory = mock(SpringClientFactory.class);
- ILoadBalancer loadBalancer = mock(ILoadBalancer.class);
- when(clientFactory.getLoadBalancerContext("myservice"))
- .thenReturn(new RibbonLoadBalancerContext(loadBalancer));
- when(clientFactory.getLoadBalancer("myservice")).thenReturn(loadBalancer);
-
- when(loadBalancer.chooseServer("11111"))
- .thenReturn(new Server("myservice-host1", 8081));
- when(loadBalancer.chooseServer("22222"))
- .thenReturn(new Server("myservice-host2", 8081));
-
- LoadBalancerClient loadBalancerClient = new RibbonLoadBalancerClient(
- clientFactory) {
- private String loadBalancerKey;
-
- public ServiceInstance choose(String serviceId) {
- String[] strings = serviceId.split("<<>>");
- loadBalancerKey = strings[1];
- return super.choose(strings[0], loadBalancerKey);
- }
-
- protected Server getServer(ILoadBalancer loadBalancer) {
- return loadBalancer == null ? null
- : loadBalancer.chooseServer(StringUtils.isEmpty(loadBalancerKey)
- ? "default" : loadBalancerKey);
- }
- };
-
- LoadBalancerClientFilter loadBalancerClientFilter = new LoadBalancerClientFilter(
- loadBalancerClient, properties) {
- protected ServiceInstance choose(ServerWebExchange exchange) {
- URI attribute = (URI) exchange.getAttribute(GATEWAY_REQUEST_URL_ATTR);
- return loadBalancer
- .choose(attribute.getHost() + "<<>>" + attribute.getPort());
- }
- };
-
- MockServerHttpRequest request = MockServerHttpRequest.get("http://localhost/get")
- .build();
- ServerWebExchange exchange = MockServerWebExchange.from(request);
-
- exchange.getAttributes().put(GATEWAY_REQUEST_URL_ATTR, uri1);
- loadBalancerClientFilter.filter(exchange, chain);
- assertThat(
- ((URI) exchange.getAttributes().get(GATEWAY_REQUEST_URL_ATTR)).getHost())
- .isEqualTo("myservice-host1");
-
- exchange.getAttributes().put(GATEWAY_REQUEST_URL_ATTR, uri2);
- loadBalancerClientFilter.filter(exchange, chain);
- assertThat(
- ((URI) exchange.getAttributes().get(GATEWAY_REQUEST_URL_ATTR)).getHost())
- .isEqualTo("myservice-host2");
- }
-
- private ServerWebExchange testFilter(MockServerHttpRequest request, URI uri) {
- return testFilter(MockServerWebExchange.from(request), uri, 8081);
- }
-
- private ServerWebExchange testFilter(MockServerHttpRequest request, URI uri,
- int port) {
- return testFilter(MockServerWebExchange.from(request), uri, port);
- }
-
- private ServerWebExchange testFilter(ServerWebExchange exchange, URI uri, int port) {
- exchange.getAttributes().put(GATEWAY_REQUEST_URL_ATTR, uri);
-
- ArgumentCaptor captor = ArgumentCaptor
- .forClass(ServerWebExchange.class);
- when(chain.filter(captor.capture())).thenReturn(Mono.empty());
-
- SpringClientFactory clientFactory = mock(SpringClientFactory.class);
- ILoadBalancer loadBalancer = mock(ILoadBalancer.class);
-
- when(clientFactory.getLoadBalancerContext("service1"))
- .thenReturn(new RibbonLoadBalancerContext(loadBalancer));
- when(clientFactory.getLoadBalancer("service1")).thenReturn(loadBalancer);
- when(loadBalancer.chooseServer(any()))
- .thenReturn(new Server("service1-host1", port));
-
- RibbonLoadBalancerClient client = new RibbonLoadBalancerClient(clientFactory);
-
- LoadBalancerClientFilter filter = new LoadBalancerClientFilter(client,
- properties);
- filter.filter(exchange, chain);
-
- return captor.getValue();
- }
-
-}
diff --git a/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/factory/HystrixGatewayFilterFactoryPrincipalTests.java b/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/factory/HystrixGatewayFilterFactoryPrincipalTests.java
deleted file mode 100644
index 2d808de7..00000000
--- a/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/factory/HystrixGatewayFilterFactoryPrincipalTests.java
+++ /dev/null
@@ -1,154 +0,0 @@
-/*
- * Copyright 2013-2019 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
- *
- * https://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.gateway.filter.factory;
-
-import java.security.Principal;
-import java.util.Collections;
-import java.util.Map;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import reactor.core.publisher.Mono;
-
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.boot.SpringBootConfiguration;
-import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
-import org.springframework.boot.test.context.SpringBootTest;
-import org.springframework.cloud.gateway.filter.GatewayFilter;
-import org.springframework.cloud.gateway.filter.ratelimit.KeyResolver;
-import org.springframework.cloud.gateway.filter.ratelimit.PrincipalNameKeyResolver;
-import org.springframework.cloud.gateway.route.RouteLocator;
-import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder;
-import org.springframework.cloud.gateway.test.BaseWebClientTests;
-import org.springframework.cloud.netflix.ribbon.RibbonClient;
-import org.springframework.cloud.netflix.ribbon.RibbonClients;
-import org.springframework.context.annotation.Bean;
-import org.springframework.security.config.web.server.ServerHttpSecurity;
-import org.springframework.security.core.userdetails.MapReactiveUserDetailsService;
-import org.springframework.security.core.userdetails.User;
-import org.springframework.security.core.userdetails.UserDetails;
-import org.springframework.security.web.server.SecurityWebFilterChain;
-import org.springframework.test.annotation.DirtiesContext;
-import org.springframework.test.context.junit4.SpringRunner;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RestController;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT;
-
-@RunWith(SpringRunner.class)
-@SpringBootTest(webEnvironment = RANDOM_PORT, properties = "debug=true")
-@DirtiesContext
-public class HystrixGatewayFilterFactoryPrincipalTests extends BaseWebClientTests {
-
- @Autowired
- private TestPrincipalGatewayFilterFactory testFilterFactory;
-
- @Test
- public void hystrixPrincipalNotLost() {
- testClient.get().uri("/hystrixprincipal").headers(httpHeaders -> {
- httpHeaders.setBasicAuth("user", "password");
- httpHeaders.set("Host", "www.hystrixsecurity.org");
- }).exchange().expectStatus().isOk().expectBody().jsonPath("$.principal")
- .isEqualTo("user");
- assertThat(testFilterFactory.resolvedPrincipal).isEqualTo("user");
- }
-
- @RestController
- @SpringBootConfiguration
- @EnableAutoConfiguration
- @RibbonClients({
- @RibbonClient(name = "testservice", configuration = TestRibbonConfig.class) })
- public static class TestConfig {
-
- @Value("${test.uri}")
- private String uri;
-
- @RequestMapping("/httpbin/hystrixprincipal")
- public Mono
-
- org.springframework.cloud
- spring-cloud-starter-netflix-ribbon
-
org.isomorphism
token-bucket
diff --git a/spring-cloud-gateway-sample/src/test/java/org/springframework/cloud/gateway/sample/GatewaySampleApplicationTests.java b/spring-cloud-gateway-sample/src/test/java/org/springframework/cloud/gateway/sample/GatewaySampleApplicationTests.java
index 1b0127b8..04983cef 100644
--- a/spring-cloud-gateway-sample/src/test/java/org/springframework/cloud/gateway/sample/GatewaySampleApplicationTests.java
+++ b/spring-cloud-gateway-sample/src/test/java/org/springframework/cloud/gateway/sample/GatewaySampleApplicationTests.java
@@ -22,8 +22,6 @@ import java.util.Map;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
-import com.netflix.loadbalancer.Server;
-import com.netflix.loadbalancer.ServerList;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
@@ -34,12 +32,9 @@ import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.web.server.LocalServerPort;
import org.springframework.cloud.gateway.test.HttpBinCompatibleController;
-import org.springframework.cloud.netflix.ribbon.RibbonClient;
-import org.springframework.cloud.netflix.ribbon.StaticServerList;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
-import org.springframework.context.annotation.Primary;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.reactive.server.WebTestClient;
import org.springframework.util.SocketUtils;
@@ -180,7 +175,7 @@ public class GatewaySampleApplicationTests {
@Configuration(proxyBeanMethods = false)
@EnableAutoConfiguration
- @RibbonClient(name = "httpbin", configuration = RibbonConfig.class)
+ //@RibbonClient(name = "httpbin", configuration = LoadBalancerConfig.class)
@Import(GatewaySampleApplication.class)
protected static class TestConfig {
@@ -191,16 +186,16 @@ public class GatewaySampleApplicationTests {
}
- protected static class RibbonConfig {
+ protected static class LoadBalancerConfig {
@LocalServerPort
int port;
- @Bean
- @Primary
- public ServerList ribbonServerList() {
- return new StaticServerList<>(new Server("localhost", port));
- }
+ //@Bean
+ //@Primary
+ //public ServerList serverList() {
+ // return new StaticServerList<>(new Server("localhost", port));
+ //}
}