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 index 8156c77d..1b3a6104 100644 --- 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 @@ -34,6 +34,7 @@ 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; @@ -134,6 +135,8 @@ public class HystrixGatewayFilterFactory switch (failureType) { case TIMEOUT: return Mono.error(new TimeoutException()); + case SHORTCIRCUIT: + return Mono.error(new ServiceUnavailableException()); case COMMAND_EXCEPTION: { Throwable cause = e.getCause(); diff --git a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/support/ServiceUnavailableException.java b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/support/ServiceUnavailableException.java new file mode 100644 index 00000000..faca510a --- /dev/null +++ b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/support/ServiceUnavailableException.java @@ -0,0 +1,42 @@ +/* + * 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 org.springframework.web.bind.annotation.ResponseStatus; + +import static org.springframework.http.HttpStatus.SERVICE_UNAVAILABLE; + +@ResponseStatus(value = SERVICE_UNAVAILABLE, reason = "Upstream service is temporarily unavailable") +public class ServiceUnavailableException extends Exception { + + public ServiceUnavailableException() { + } + + public ServiceUnavailableException(String message) { + super(message); + } + + /** + * Disables fillInStackTrace for performance reasons. + * @return + */ + @Override + public synchronized Throwable fillInStackTrace() { + return this; + } + +} diff --git a/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/factory/HystrixGatewayFilterFactoryTests.java b/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/factory/HystrixGatewayFilterFactoryTests.java index 73d3a3cd..a0cf4090 100644 --- a/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/factory/HystrixGatewayFilterFactoryTests.java +++ b/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/factory/HystrixGatewayFilterFactoryTests.java @@ -16,6 +16,9 @@ package org.springframework.cloud.gateway.filter.factory; +import com.netflix.config.ConfigurationManager; +import com.netflix.hystrix.Hystrix; +import com.netflix.hystrix.metric.consumer.HealthCountsStream; import org.junit.Test; import org.junit.runner.RunWith; @@ -56,6 +59,22 @@ public class HystrixGatewayFilterFactoryTests extends BaseWebClientTests { .isEqualTo(String.valueOf(HttpStatus.GATEWAY_TIMEOUT.value())); } + @Test + public void hystrixFilterServiceUnavailable() { + HealthCountsStream.reset(); + Hystrix.reset(); + ConfigurationManager.getConfigInstance() + .setProperty("hystrix.command.failcmd.circuitBreaker.forceOpen", true); + + testClient.get().uri("/delay/3").header("Host", "www.hystrixfailure.org") + .exchange().expectStatus().isEqualTo(HttpStatus.SERVICE_UNAVAILABLE); + + HealthCountsStream.reset(); + Hystrix.reset(); + ConfigurationManager.getConfigInstance() + .setProperty("hystrix.command.failcmd.circuitBreaker.forceOpen", false); + } + /* * Tests that timeouts bubbling from the underpinning WebClient are treated the same * as Hystrix timeouts in terms of outside response. (Internally, timeouts from the