Browse Source

Adds HandlerFunctions.forward()

See gh-2949
pull/3037/head
sgibb 1 year ago
parent
commit
6f95267317
No known key found for this signature in database
GPG Key ID: 7788A47380690861
  1. 1
      spring-cloud-gateway-server-mvc/src/main/java/org/springframework/cloud/gateway/server/mvc/filter/CircuitBreakerFilterFunctions.java
  2. 18
      spring-cloud-gateway-server-mvc/src/main/java/org/springframework/cloud/gateway/server/mvc/handler/HandlerFunctions.java
  3. 38
      spring-cloud-gateway-server-mvc/src/test/java/org/springframework/cloud/gateway/server/mvc/ServerMvcIntegrationTests.java

1
spring-cloud-gateway-server-mvc/src/main/java/org/springframework/cloud/gateway/server/mvc/filter/CircuitBreakerFilterFunctions.java

@ -101,6 +101,7 @@ public abstract class CircuitBreakerFilterFunctions { @@ -101,6 +101,7 @@ public abstract class CircuitBreakerFilterFunctions {
request.attributes().put(MvcUtils.CIRCUITBREAKER_EXECUTION_EXCEPTION_ATTR, throwable);
// handle fallback
// ok() is wrong, but will be overwritten by the forwarded request
return GatewayServerResponse.ok().build((httpServletRequest, httpServletResponse) -> {
try {
String expandedFallback = MvcUtils.expand(request, config.getFallbackPath());

18
spring-cloud-gateway-server-mvc/src/main/java/org/springframework/cloud/gateway/server/mvc/handler/HandlerFunctions.java

@ -16,12 +16,15 @@ @@ -16,12 +16,15 @@
package org.springframework.cloud.gateway.server.mvc.handler;
import java.io.IOException;
import java.lang.reflect.Method;
import java.net.URI;
import java.util.Arrays;
import java.util.Collection;
import java.util.concurrent.atomic.AtomicReference;
import jakarta.servlet.ServletException;
import org.springframework.cloud.gateway.server.mvc.common.MvcUtils;
import org.springframework.web.servlet.function.HandlerFunction;
import org.springframework.web.servlet.function.ServerRequest;
@ -33,6 +36,21 @@ public abstract class HandlerFunctions { @@ -33,6 +36,21 @@ public abstract class HandlerFunctions {
}
public static HandlerFunction<ServerResponse> forward(String path) {
// ok() is wrong, but can be overridden by the forwarded request.
return request -> GatewayServerResponse.ok().build((httpServletRequest, httpServletResponse) -> {
try {
String expandedFallback = MvcUtils.expand(request, path);
request.servletRequest().getServletContext().getRequestDispatcher(expandedFallback)
.forward(httpServletRequest, httpServletResponse);
return null;
}
catch (ServletException | IOException e) {
throw new RuntimeException(e);
}
});
}
// TODO: current discovery only goes by method name
// so last one wins, so put parameterless last
public static HandlerFunction<ServerResponse> http(URI uri) {

38
spring-cloud-gateway-server-mvc/src/test/java/org/springframework/cloud/gateway/server/mvc/ServerMvcIntegrationTests.java

@ -111,6 +111,7 @@ import static org.springframework.cloud.gateway.server.mvc.filter.FilterFunction @@ -111,6 +111,7 @@ import static org.springframework.cloud.gateway.server.mvc.filter.FilterFunction
import static org.springframework.cloud.gateway.server.mvc.filter.LoadBalancerFilterFunctions.lb;
import static org.springframework.cloud.gateway.server.mvc.filter.RetryFilterFunctions.retry;
import static org.springframework.cloud.gateway.server.mvc.handler.GatewayRouterFunctions.route;
import static org.springframework.cloud.gateway.server.mvc.handler.HandlerFunctions.forward;
import static org.springframework.cloud.gateway.server.mvc.handler.HandlerFunctions.http;
import static org.springframework.cloud.gateway.server.mvc.predicate.GatewayRequestPredicates.cloudFoundryRouteService;
import static org.springframework.cloud.gateway.server.mvc.predicate.GatewayRequestPredicates.cookie;
@ -581,6 +582,17 @@ public class ServerMvcIntegrationTests { @@ -581,6 +582,17 @@ public class ServerMvcIntegrationTests {
"{\"message\":\"HELLO WORLD\"}"));
}
@Test
public void forwardWorks() {
restClient.get().uri("/doforward").exchange().expectStatus().isOk().expectBody(String.class).isEqualTo("Hello");
}
@Test
public void forwardNon200StatusWorks() {
restClient.get().uri("/doforward2").exchange().expectStatus().isCreated().expectBody(String.class)
.isEqualTo("hello2");
}
@SpringBootConfiguration
@EnableAutoConfiguration
@LoadBalancerClient(name = "httpbin", configuration = TestLoadBalancerConfig.Httpbin.class)
@ -612,6 +624,12 @@ public class ServerMvcIntegrationTests { @@ -612,6 +624,12 @@ public class ServerMvcIntegrationTests {
return route(GET("/hello"), testHandler).withAttribute(MvcUtils.GATEWAY_ROUTE_ID_ATTR, "hello");
}
@Bean
public RouterFunction<ServerResponse> nonGatewayRouterFunctions2() {
return route(GET("/hello2"), request -> ServerResponse.status(HttpStatus.CREATED).body("hello2"))
.withAttribute(MvcUtils.GATEWAY_ROUTE_ID_ATTR, "hello2");
}
@Bean
public RouterFunction<ServerResponse> gatewayRouterFunctionsAddReqHeader() {
// @formatter:off
@ -1063,6 +1081,26 @@ public class ServerMvcIntegrationTests { @@ -1063,6 +1081,26 @@ public class ServerMvcIntegrationTests {
// @formatter:on
}
@Bean
public RouterFunction<ServerResponse> gatewayRouterFunctionsForward() {
// @formatter:off
return route("testforward")
.GET("/doforward", forward("/hello"))
.before(new LocalServerPortUriResolver())
.build();
// @formatter:on
}
@Bean
public RouterFunction<ServerResponse> gatewayRouterFunctionsForwardNon200Status() {
// @formatter:off
return route("testforwardnon200status")
.GET("/doforward2", forward("/hello2"))
.before(new LocalServerPortUriResolver())
.build();
// @formatter:on
}
private Predicate<Event> eventPredicate(String foo) {
return new Predicate<>() {
@Override

Loading…
Cancel
Save