Remove routed attribute when executing fallbacks in circuit breakers. Fixes #1421
This commit is contained in:
@@ -50,6 +50,7 @@ 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_ALREADY_ROUTED_ATTR;
|
||||
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;
|
||||
@@ -272,6 +273,10 @@ public class HystrixGatewayFilterFactory
|
||||
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
|
||||
mutated.getAttributes().remove(GATEWAY_ALREADY_ROUTED_ATTR);
|
||||
return RxReactiveStreams.toObservable(getDispatcherHandler().handle(mutated));
|
||||
}
|
||||
|
||||
|
||||
@@ -37,6 +37,7 @@ 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.CIRCUITBREAKER_EXECUTION_EXCEPTION_ATTR;
|
||||
import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.GATEWAY_ALREADY_ROUTED_ATTR;
|
||||
import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR;
|
||||
import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.containsEncodedParts;
|
||||
|
||||
@@ -99,6 +100,11 @@ public abstract class SpringCloudCircuitBreakerFilterFactory extends
|
||||
exchange.getAttributes().put(GATEWAY_REQUEST_URL_ATTR, requestUrl);
|
||||
addExceptionDetails(t, exchange);
|
||||
|
||||
// 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
|
||||
exchange.getAttributes().remove(GATEWAY_ALREADY_ROUTED_ATTR);
|
||||
|
||||
ServerHttpRequest request = exchange.getRequest().mutate()
|
||||
.uri(requestUrl).build();
|
||||
return getDispatcherHandler()
|
||||
|
||||
@@ -139,4 +139,11 @@ public class HystrixGatewayFilterFactoryTests extends BaseWebClientTests {
|
||||
assertThat(filter.toString()).contains("myname").contains("forward:/myfallback");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void filterFallbackForward() {
|
||||
testClient.get().uri("/delay/3?a=c").header("Host", "www.hystrixforward.org")
|
||||
.exchange().expectStatus().isOk().expectBody()
|
||||
.json("{\"from\":\"hystrixfallbackcontroller3\"}");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -66,12 +66,23 @@ public class HystrixTestConfig {
|
||||
return Collections.singletonMap("from", "fallbackcontroller2");
|
||||
}
|
||||
|
||||
@RequestMapping("/hystrixFallbackController3")
|
||||
public Map<String, String> fallbackcontroller3() {
|
||||
return Collections.singletonMap("from", "hystrixfallbackcontroller3");
|
||||
}
|
||||
|
||||
@Bean
|
||||
public RouteLocator hystrixRouteLocator(RouteLocatorBuilder builder) {
|
||||
return builder.routes().route("hystrix_java", r -> r.host("**.hystrixjava.org")
|
||||
.filters(f -> f.prefixPath("/httpbin").hystrix(
|
||||
config -> config.setFallbackUri("forward:/fallbackcontroller2")))
|
||||
.uri(uri))
|
||||
.route("hystrix_fallback_forward", r -> r.host("**.hystrixforward.org")
|
||||
.filters(f -> f.hystrix(
|
||||
config -> config.setFallbackUri("forward:/fallback")))
|
||||
.uri(uri))
|
||||
.route("hystrix_fallback_controller_3", r -> r.path("/fallback")
|
||||
.filters(f -> f.setPath("/hystrixFallbackController3")).uri(uri))
|
||||
.route("hystrix_connection_failure",
|
||||
r -> r.host("**.hystrixconnectfail.org")
|
||||
.filters(f -> f.prefixPath("/httpbin").hystrix(config -> {
|
||||
|
||||
@@ -96,4 +96,12 @@ public abstract class SpringCloudCircuitBreakerFilterFactoryTests
|
||||
.isNotEmpty().jsonPath("$.error").isEqualTo("Internal Server Error");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void filterFallbackForward() {
|
||||
testClient.get().uri("/delay/3?a=c")
|
||||
.header("Host", "www.circuitbreakerforward.org").exchange().expectStatus()
|
||||
.isOk().expectBody()
|
||||
.json("{\"from\":\"circuitbreakerfallbackcontroller3\"}");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -64,9 +64,22 @@ public class SpringCloudCircuitBreakerTestConfig {
|
||||
return Collections.singletonMap("from", "circuitbreakerfallbackcontroller2");
|
||||
}
|
||||
|
||||
@RequestMapping("/circuitbreakerFallbackController3")
|
||||
public Map<String, String> fallbackcontroller3() {
|
||||
return Collections.singletonMap("from", "circuitbreakerfallbackcontroller3");
|
||||
}
|
||||
|
||||
@Bean
|
||||
public RouteLocator circuitBreakerRouteLocator(RouteLocatorBuilder builder) {
|
||||
return builder.routes()
|
||||
return builder.routes().route("circuitbreaker_fallback_forward",
|
||||
r -> r.host("**.circuitbreakerforward.org")
|
||||
.filters(f -> f.circuitBreaker(
|
||||
config -> config.setFallbackUri("forward:/fallback")))
|
||||
.uri(uri))
|
||||
.route("fallback_controller_3",
|
||||
r -> r.path("/fallback").filters(
|
||||
f -> f.setPath("/circuitbreakerFallbackController3"))
|
||||
.uri(uri))
|
||||
.route("circuitbreaker_java", r -> r.host("**.circuitbreakerjava.org")
|
||||
.filters(f -> f.prefixPath("/httpbin")
|
||||
.circuitBreaker(config -> config.setFallbackUri(
|
||||
|
||||
Reference in New Issue
Block a user