diff --git a/spring-cloud-gateway-server-webflux/src/main/java/org/springframework/cloud/gateway/filter/NettyRoutingFilter.java b/spring-cloud-gateway-server-webflux/src/main/java/org/springframework/cloud/gateway/filter/NettyRoutingFilter.java index 124c2ce23..ea23f0bef 100644 --- a/spring-cloud-gateway-server-webflux/src/main/java/org/springframework/cloud/gateway/filter/NettyRoutingFilter.java +++ b/spring-cloud-gateway-server-webflux/src/main/java/org/springframework/cloud/gateway/filter/NettyRoutingFilter.java @@ -16,7 +16,9 @@ package org.springframework.cloud.gateway.filter; +import java.net.ConnectException; import java.net.URI; +import java.net.UnknownHostException; import java.time.Duration; import java.util.List; import java.util.Objects; @@ -199,9 +201,20 @@ public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) { th -> new ResponseStatusException(HttpStatus.GATEWAY_TIMEOUT, th.getMessage(), th)); } + responseFlux = responseFlux.onErrorMap(NettyRoutingFilter::isUnavailable, + th -> new ResponseStatusException(HttpStatus.SERVICE_UNAVAILABLE, th.getMessage(), th)); + return responseFlux.then(chain.filter(exchange)); } + private static boolean isUnavailable(Throwable throwable) { + if (throwable instanceof ConnectException || throwable instanceof UnknownHostException) { + return true; + } + Throwable cause = throwable.getCause(); + return cause != null && cause != throwable && isUnavailable(cause); + } + protected ByteBuf getByteBuf(DataBuffer dataBuffer) { if (dataBuffer instanceof NettyDataBuffer) { NettyDataBuffer buffer = (NettyDataBuffer) dataBuffer; diff --git a/spring-cloud-gateway-server-webflux/src/test/java/org/springframework/cloud/gateway/filter/NettyRoutingFilterIntegrationTests.java b/spring-cloud-gateway-server-webflux/src/test/java/org/springframework/cloud/gateway/filter/NettyRoutingFilterIntegrationTests.java index 5d51ac600..ac7984964 100644 --- a/spring-cloud-gateway-server-webflux/src/test/java/org/springframework/cloud/gateway/filter/NettyRoutingFilterIntegrationTests.java +++ b/spring-cloud-gateway-server-webflux/src/test/java/org/springframework/cloud/gateway/filter/NettyRoutingFilterIntegrationTests.java @@ -125,8 +125,16 @@ public void shouldApplyConnectTimeoutPerRoute() { .uri("/connect/delay/2") .exchange() .expectStatus() - .isEqualTo(HttpStatus.INTERNAL_SERVER_ERROR) + .isEqualTo(HttpStatus.SERVICE_UNAVAILABLE) .expectBody() + .jsonPath("$.status") + .isEqualTo(String.valueOf(HttpStatus.SERVICE_UNAVAILABLE.value())) + .jsonPath("$.error") + .isEqualTo(HttpStatus.SERVICE_UNAVAILABLE.getReasonPhrase()) + .jsonPath("$.path") + .isEqualTo("/connect/delay/2") + .jsonPath("$.message") + .exists() .jsonPath("$.message") .value(containsString("Connection refused"));