diff --git a/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/filter/ForwardRoutingFilter.java b/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/filter/ForwardRoutingFilter.java index 30319a9b4..4191a2647 100644 --- a/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/filter/ForwardRoutingFilter.java +++ b/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/filter/ForwardRoutingFilter.java @@ -28,6 +28,7 @@ import org.springframework.web.reactive.DispatcherHandler; 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.handle; import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.isAlreadyRouted; public class ForwardRoutingFilter implements GlobalFilter, Ordered { @@ -71,7 +72,7 @@ public class ForwardRoutingFilter implements GlobalFilter, Ordered { log.trace("Forwarding to URI: " + requestUrl); } - return this.getDispatcherHandler().handle(exchange); + return handle(this.getDispatcherHandler(), exchange); } } diff --git a/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/filter/factory/SpringCloudCircuitBreakerFilterFactory.java b/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/filter/factory/SpringCloudCircuitBreakerFilterFactory.java index 4044536c3..758d6f3e9 100644 --- a/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/filter/factory/SpringCloudCircuitBreakerFilterFactory.java +++ b/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/filter/factory/SpringCloudCircuitBreakerFilterFactory.java @@ -45,9 +45,9 @@ 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_PREDICATE_PATH_CONTAINER_ATTR; import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR; import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.containsEncodedParts; +import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.handle; import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.reset; /** @@ -109,7 +109,6 @@ public abstract class SpringCloudCircuitBreakerFilterFactory } exchange.getResponse().setStatusCode(null); - reset(exchange); // TODO: copied from RouteToRequestUrlFilter URI uri = exchange.getRequest().getURI(); @@ -124,14 +123,13 @@ public abstract class SpringCloudCircuitBreakerFilterFactory .uri(URI.create(fullFallbackUri)).scheme(null).build(encoded).toUri(); exchange.getAttributes().put(GATEWAY_REQUEST_URL_ATTR, requestUrl); - exchange.getAttributes().remove(GATEWAY_PREDICATE_PATH_CONTAINER_ATTR); addExceptionDetails(t, exchange); // Reset the exchange reset(exchange); ServerHttpRequest request = exchange.getRequest().mutate().uri(requestUrl).build(); - return getDispatcherHandler().handle(exchange.mutate().request(request).build()); + return handle(getDispatcherHandler(), exchange.mutate().request(request).build()); }).onErrorResume(t -> handleErrorWithoutFallback(t, config.isResumeWithoutError())); } diff --git a/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/support/ServerWebExchangeUtils.java b/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/support/ServerWebExchangeUtils.java index dfcc8036d..8ab2b8cd9 100644 --- a/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/support/ServerWebExchangeUtils.java +++ b/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/support/ServerWebExchangeUtils.java @@ -46,6 +46,7 @@ import org.springframework.http.server.reactive.ServerHttpRequest; import org.springframework.http.server.reactive.ServerHttpRequestDecorator; import org.springframework.http.server.reactive.ServerHttpResponse; import org.springframework.util.Assert; +import org.springframework.web.reactive.DispatcherHandler; import org.springframework.web.server.ServerWebExchange; import org.springframework.web.util.UriComponentsBuilder; @@ -411,4 +412,18 @@ public final class ServerWebExchangeUtils { return decorator; } + /** + * One place to handle forwarding using DispatcherHandler. Allows for common code to + * be reused. + * @param handler The DispatcherHandler. + * @param exchange The ServerWebExchange. + * @return value from handler. + */ + public static Mono handle(DispatcherHandler handler, ServerWebExchange exchange) { + // remove attributes that may disrupt the forwarded request + exchange.getAttributes().remove(GATEWAY_PREDICATE_PATH_CONTAINER_ATTR); + + return handler.handle(exchange); + } + } diff --git a/spring-cloud-gateway-server/src/test/java/org/springframework/cloud/gateway/filter/ForwardRoutingFilterStaticIntegrationTests.java b/spring-cloud-gateway-server/src/test/java/org/springframework/cloud/gateway/filter/ForwardRoutingFilterStaticIntegrationTests.java new file mode 100644 index 000000000..e7adf9b94 --- /dev/null +++ b/spring-cloud-gateway-server/src/test/java/org/springframework/cloud/gateway/filter/ForwardRoutingFilterStaticIntegrationTests.java @@ -0,0 +1,50 @@ +/* + * Copyright 2013-2020 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 org.junit.jupiter.api.Test; + +import org.springframework.boot.SpringBootConfiguration; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.cloud.gateway.test.BaseWebClientTests; +import org.springframework.context.annotation.Import; +import org.springframework.test.context.ActiveProfiles; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT; + +@SpringBootTest(webEnvironment = RANDOM_PORT) +@ActiveProfiles("forwardstatic") +public class ForwardRoutingFilterStaticIntegrationTests extends BaseWebClientTests { + + @Test + public void gatewayRequestsMeterFilterHasTags() { + testClient.get().uri("/mydocs").exchange().expectStatus().isOk().expectBody(String.class) + .consumeWith(result -> { + assertThat(result.getResponseBody()).contains("Docs 123"); + }); + } + + @EnableAutoConfiguration + @SpringBootConfiguration + @Import(DefaultTestConfig.class) + public static class CustomConfig { + + } + +} diff --git a/spring-cloud-gateway-server/src/test/java/org/springframework/cloud/gateway/test/RouteConstructionIntegrationTests.java b/spring-cloud-gateway-server/src/test/java/org/springframework/cloud/gateway/test/RouteConstructionIntegrationTests.java index 9d5edb231..13f25d1a0 100644 --- a/spring-cloud-gateway-server/src/test/java/org/springframework/cloud/gateway/test/RouteConstructionIntegrationTests.java +++ b/spring-cloud-gateway-server/src/test/java/org/springframework/cloud/gateway/test/RouteConstructionIntegrationTests.java @@ -31,8 +31,8 @@ public class RouteConstructionIntegrationTests { @Test public void routesWithVerificationShouldFail() { - assertThatThrownBy(() -> new SpringApplicationBuilder(TestConfig.class).profiles("verification-route").run()) - .hasMessageContaining("Stop right now!"); + assertThatThrownBy(() -> new SpringApplicationBuilder(TestConfig.class).profiles("verification-route") + .run("--server.port=0")).hasMessageContaining("Stop right now!"); } @EnableAutoConfiguration diff --git a/spring-cloud-gateway-server/src/test/resources/application-forwardstatic.yml b/spring-cloud-gateway-server/src/test/resources/application-forwardstatic.yml new file mode 100644 index 000000000..35b5b4a0e --- /dev/null +++ b/spring-cloud-gateway-server/src/test/resources/application-forwardstatic.yml @@ -0,0 +1,8 @@ +spring: + cloud: + gateway: + routes: + - uri: forward:/docs.html + id: static_docs_route + predicates: + - Path=/mydocs diff --git a/spring-cloud-gateway-server/src/test/resources/static/httpbin/docs.html b/spring-cloud-gateway-server/src/test/resources/static/httpbin/docs.html new file mode 100644 index 000000000..bcd386b2a --- /dev/null +++ b/spring-cloud-gateway-server/src/test/resources/static/httpbin/docs.html @@ -0,0 +1,21 @@ + + + + +

Docs 123

+ + \ No newline at end of file