Fixes routing issue with path filters and static uri (#3747)
* Fixes routing issue with path filters and static uri The problem arises from when MvcUtils.setRequestUrl is called depending on if the route was created via config, using `http(uri)` or having it set in a before filter. To fix this, the uri is now always set in a before filter and the `http(uri)` methods are deprecated in favor of a BeforeFilterFunctions.uri() method. A new DefaultHandlerSupplier was created to use an updated HandlerDiscoverer.Result that has fields for lowerPrecedenceFilters and higherPrecedenceFilters as the `http()` family of Handler methods need associated filters. This results in a more consistent handling of the request url attribute. Existing methods and constructors are deprecated. Fixes gh-3736
This commit is contained in:
@@ -14,6 +14,8 @@ spring:
|
||||
routes:
|
||||
- id: add_request_header_route
|
||||
uri: https://example.org
|
||||
predicates:
|
||||
- Path=/red
|
||||
filters:
|
||||
- AddRequestHeader=X-Request-red, blue
|
||||
----
|
||||
@@ -21,6 +23,7 @@ spring:
|
||||
.GatewaySampleApplication.java
|
||||
[source,java]
|
||||
----
|
||||
import static org.springframework.cloud.gateway.server.mvc.filter.BeforeFilterFunctions.uri;
|
||||
import static org.springframework.cloud.gateway.server.mvc.filter.BeforeFilterFunctions.addRequestHeader;
|
||||
import static org.springframework.cloud.gateway.server.mvc.handler.GatewayRouterFunctions.route;
|
||||
import static org.springframework.cloud.gateway.server.mvc.handler.HandlerFunctions.http;
|
||||
@@ -30,8 +33,10 @@ class RouteConfiguration {
|
||||
|
||||
@Bean
|
||||
public RouterFunction<ServerResponse> gatewayRouterFunctionsAddReqHeader() {
|
||||
return route(GET("/red"), http("https://example.org"))
|
||||
.before(addRequestHeader("X-Request-red", "blue"));
|
||||
return route("add_request_header_route")
|
||||
.GET("/red", http())
|
||||
.before(uri("https://example.org"))
|
||||
.before(addRequestHeader("X-Request-red", "blue"));
|
||||
}
|
||||
}
|
||||
----
|
||||
@@ -45,13 +50,20 @@ The following example configures an `AddRequestHeader` filter that uses a variab
|
||||
.GatewaySampleApplication.java
|
||||
[source,java]
|
||||
----
|
||||
import static org.springframework.cloud.gateway.server.mvc.filter.BeforeFilterFunctions.uri;
|
||||
import static org.springframework.cloud.gateway.server.mvc.filter.BeforeFilterFunctions.addRequestHeader;
|
||||
import static org.springframework.cloud.gateway.server.mvc.handler.GatewayRouterFunctions.route;
|
||||
import static org.springframework.cloud.gateway.server.mvc.handler.HandlerFunctions.http;
|
||||
|
||||
@Configuration
|
||||
class RouteConfiguration {
|
||||
|
||||
@Bean
|
||||
public RouterFunction<ServerResponse> gatewayRouterFunctionsAddReqHeader() {
|
||||
return route(GET("/red/{segment}"), http("https://example.org"))
|
||||
.before(addRequestHeader("X-Request-red", "blue-{segment}"));
|
||||
return route("add_request_header_route")
|
||||
.GET("/red/{segment}", http())
|
||||
.before(uri("https://example.org"))
|
||||
.before(addRequestHeader("X-Request-red", "blue-{segment}"));
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
@@ -12,8 +12,10 @@ spring:
|
||||
gateway:
|
||||
mvc:
|
||||
routes:
|
||||
- id: add_request_headers_route
|
||||
- id: add_request_headers_route_inp
|
||||
uri: https://example.org
|
||||
predicates:
|
||||
- Path=/red
|
||||
filters:
|
||||
- AddRequestHeadersIfNotPresent=X-Request-Color-1:blue,X-Request-Color-2:green
|
||||
----
|
||||
@@ -21,6 +23,7 @@ spring:
|
||||
.GatewaySampleApplication.java
|
||||
[source,java]
|
||||
----
|
||||
import static org.springframework.cloud.gateway.server.mvc.filter.BeforeFilterFunctions.uri;
|
||||
import static org.springframework.cloud.gateway.server.mvc.filter.BeforeFilterFunctions.addRequestHeadersIfNotPresent;
|
||||
import static org.springframework.cloud.gateway.server.mvc.handler.GatewayRouterFunctions.route;
|
||||
import static org.springframework.cloud.gateway.server.mvc.handler.HandlerFunctions.http;
|
||||
@@ -29,9 +32,11 @@ import static org.springframework.cloud.gateway.server.mvc.handler.HandlerFuncti
|
||||
class RouteConfiguration {
|
||||
|
||||
@Bean
|
||||
public RouterFunction<ServerResponse> gatewayRouterFunctionsAddReqHeader() {
|
||||
return route(GET("/red"), http("https://example.org"))
|
||||
.before(addRequestHeadersIfNotPresent("X-Request-Color-1:blue","X-Request-Color-2:green"));
|
||||
public RouterFunction<ServerResponse> gatewayRouterFunctionsAddReqHeaderInp() {
|
||||
return route("add_request_headers_route_inp")
|
||||
.GET("/red", http())
|
||||
.before(uri("https://example.org"))
|
||||
.before(addRequestHeadersIfNotPresent("X-Request-Color-1:blue","X-Request-Color-2:green"));
|
||||
}
|
||||
}
|
||||
----
|
||||
@@ -49,13 +54,20 @@ The following example configures an `AddRequestHeadersIfNotPresent` filter that
|
||||
.GatewaySampleApplication.java
|
||||
[source,java]
|
||||
----
|
||||
import static org.springframework.cloud.gateway.server.mvc.filter.BeforeFilterFunctions.addRequestHeadersIfNotPresent;
|
||||
import static org.springframework.cloud.gateway.server.mvc.filter.BeforeFilterFunctions.uri;
|
||||
import static org.springframework.cloud.gateway.server.mvc.handler.GatewayRouterFunctions.route;
|
||||
import static org.springframework.cloud.gateway.server.mvc.handler.HandlerFunctions.http;
|
||||
|
||||
@Configuration
|
||||
class RouteConfiguration {
|
||||
|
||||
@Bean
|
||||
public RouterFunction<ServerResponse> gatewayRouterFunctionsAddReqHeader() {
|
||||
return route(GET("/red/{segment}"), http("https://example.org"))
|
||||
.before(addRequestHeadersIfNotPresent("X-Request-red", "blue-{segment}"));
|
||||
public RouterFunction<ServerResponse> gatewayRouterFunctionsAddReqHeaderInp() {
|
||||
return route("add_request_header_route_inp")
|
||||
.GET("/red/{segment}", http())
|
||||
.before(uri("https://example.org"))
|
||||
.before(addRequestHeadersIfNotPresent("X-Request-red", "blue-{segment}"));
|
||||
}
|
||||
}
|
||||
----
|
||||
@@ -66,7 +78,7 @@ spring:
|
||||
cloud:
|
||||
gateway:
|
||||
routes:
|
||||
- id: add_request_header_route
|
||||
- id: add_request_header_route_inp
|
||||
uri: https://example.org
|
||||
predicates:
|
||||
- Path=/red/{segment}
|
||||
|
||||
@@ -14,6 +14,8 @@ spring:
|
||||
routes:
|
||||
- id: add_request_parameter_route
|
||||
uri: https://example.org
|
||||
predicates:
|
||||
- Path=/anything/addrequestparam
|
||||
filters:
|
||||
- AddRequestParameter=red, blue
|
||||
----
|
||||
@@ -21,6 +23,7 @@ spring:
|
||||
.GatewaySampleApplication.java
|
||||
[source,java]
|
||||
----
|
||||
import static org.springframework.cloud.gateway.server.mvc.filter.BeforeFilterFunctions.uri;
|
||||
import static org.springframework.cloud.gateway.server.mvc.filter.BeforeFilterFunctions.addRequestParameter;
|
||||
import static org.springframework.cloud.gateway.server.mvc.handler.GatewayRouterFunctions.route;
|
||||
import static org.springframework.cloud.gateway.server.mvc.handler.HandlerFunctions.http;
|
||||
@@ -29,11 +32,12 @@ import static org.springframework.cloud.gateway.server.mvc.handler.HandlerFuncti
|
||||
class RouteConfiguration {
|
||||
|
||||
@Bean
|
||||
public RouterFunction<ServerResponse> gatewayRouterFunctionsAddReqHeader() {
|
||||
return route("add_request_parameter_route")
|
||||
.GET("/anything/addrequestparam", http("https://example.org"))
|
||||
.before(addRequestParameter("red", "blue"))
|
||||
.build();
|
||||
public RouterFunction<ServerResponse> gatewayRouterFunctionsAddReqParameter() {
|
||||
return route("add_request_parameter_route")
|
||||
.GET("/anything/addrequestparam", http())
|
||||
.before(uri("https://example.org"))
|
||||
.before(addRequestParameter("red", "blue"))
|
||||
.build();
|
||||
}
|
||||
}
|
||||
----
|
||||
@@ -47,6 +51,7 @@ The following example configures an `AddRequestParameter` filter that uses a var
|
||||
.GatewaySampleApplication.java
|
||||
[source,java]
|
||||
----
|
||||
import static org.springframework.cloud.gateway.server.mvc.filter.BeforeFilterFunctions.uri;
|
||||
import static org.springframework.cloud.gateway.server.mvc.filter.BeforeFilterFunctions.addRequestParameter;
|
||||
import static org.springframework.cloud.gateway.server.mvc.handler.GatewayRouterFunctions.route;
|
||||
import static org.springframework.cloud.gateway.server.mvc.handler.HandlerFunctions.http;
|
||||
@@ -56,11 +61,12 @@ import static org.springframework.cloud.gateway.server.mvc.predicate.GatewayRequ
|
||||
class RouteConfiguration {
|
||||
|
||||
@Bean
|
||||
public RouterFunction<ServerResponse> gatewayRouterFunctionsAddReqHeader() {
|
||||
return route("add_request_parameter_route")
|
||||
.route(host("{segment}.myhost.org"), http("https://example.org"))
|
||||
.before(addRequestParameter("foo", "bar-{segment}"))
|
||||
.build();
|
||||
public RouterFunction<ServerResponse> gatewayRouterFunctionsAddReqParameter() {
|
||||
return route("add_request_parameter_route")
|
||||
.route(host("{segment}.myhost.org"), http())
|
||||
.before(uri("https://example.org"))
|
||||
.before(addRequestParameter("foo", "bar-{segment}"))
|
||||
.build();
|
||||
}
|
||||
}
|
||||
----
|
||||
@@ -14,6 +14,8 @@ spring:
|
||||
routes:
|
||||
- id: add_response_header_route
|
||||
uri: https://example.org
|
||||
predicates:
|
||||
- Path=/anything/addresheader
|
||||
filters:
|
||||
- AddResponseHeader=X-Response-Red, Blue
|
||||
----
|
||||
@@ -21,6 +23,7 @@ spring:
|
||||
.GatewaySampleApplication.java
|
||||
[source,java]
|
||||
----
|
||||
import static org.springframework.cloud.gateway.server.mvc.filter.BeforeFilterFunctions.uri;
|
||||
import static org.springframework.cloud.gateway.server.mvc.filter.AfterFilterFunctions.addResponseHeader;
|
||||
import static org.springframework.cloud.gateway.server.mvc.handler.GatewayRouterFunctions.route;
|
||||
import static org.springframework.cloud.gateway.server.mvc.handler.HandlerFunctions.http;
|
||||
@@ -30,9 +33,10 @@ class RouteConfiguration {
|
||||
|
||||
@Bean
|
||||
public RouterFunction<ServerResponse> gatewayRouterFunctionsAddRespHeader() {
|
||||
return route("addresponseheader")
|
||||
.GET("/anything/addresheader", http("https://example.org"))
|
||||
.after(addResponseHeader("X-Response-Red", "Blue"))
|
||||
return route("add_response_header_route")
|
||||
.GET("/anything/addresheader", http())
|
||||
.before(uri("https://example.org"))
|
||||
.after(addResponseHeader("X-Response-Red", "Blue"))
|
||||
.build();
|
||||
}
|
||||
}
|
||||
@@ -47,6 +51,7 @@ The following example configures an `AddResponseHeader` filter that uses a varia
|
||||
.GatewaySampleApplication.java
|
||||
[source,java]
|
||||
----
|
||||
import static org.springframework.cloud.gateway.server.mvc.filter.BeforeFilterFunctions.uri;
|
||||
import static org.springframework.cloud.gateway.server.mvc.filter.AfterFilterFunctions.addResponseHeader;
|
||||
import static org.springframework.cloud.gateway.server.mvc.handler.GatewayRouterFunctions.route;
|
||||
import static org.springframework.cloud.gateway.server.mvc.handler.HandlerFunctions.http;
|
||||
@@ -57,10 +62,11 @@ class RouteConfiguration {
|
||||
|
||||
@Bean
|
||||
public RouterFunction<ServerResponse> gatewayRouterFunctionsAddRespHeader() {
|
||||
return route("add_response_header_route")
|
||||
.route(host("{segment}.myhost.org"), http("https://example.org"))
|
||||
.after(addResponseHeader("foo", "bar-{segment}"))
|
||||
.build();
|
||||
return route("add_response_header_route")
|
||||
.route(host("{segment}.myhost.org"), http())
|
||||
.before(uri("https://example.org"))
|
||||
.after(addResponseHeader("foo", "bar-{segment}"))
|
||||
.build();
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
@@ -15,14 +15,17 @@ spring:
|
||||
gateway:
|
||||
mvc:
|
||||
routes:
|
||||
- id: circuitbreaker_route
|
||||
- id: circuitbreakernofallback
|
||||
uri: https://example.org
|
||||
predicates:
|
||||
- Path=/anything/circuitbreakernofallback
|
||||
filters:
|
||||
- CircuitBreaker=myCircuitBreaker
|
||||
----
|
||||
.GatewaySampleApplication.java
|
||||
[source,java]
|
||||
----
|
||||
import static org.springframework.cloud.gateway.server.mvc.filter.BeforeFilterFunctions.uri;
|
||||
import static org.springframework.cloud.gateway.server.mvc.filter.CircuitBreakerFilterFunctions.circuitBreaker;
|
||||
import static org.springframework.cloud.gateway.server.mvc.handler.GatewayRouterFunctions.route;
|
||||
import static org.springframework.cloud.gateway.server.mvc.handler.HandlerFunctions.http;
|
||||
@@ -33,9 +36,10 @@ class RouteConfiguration {
|
||||
@Bean
|
||||
public RouterFunction<ServerResponse> gatewayRouterFunctionsCircuitBreakerNoFallback() {
|
||||
return route("circuitbreakernofallback")
|
||||
.route(path("/anything/circuitbreakernofallback"), http("https://example.org"))
|
||||
.filter(circuitBreaker("mycb3"))
|
||||
.build();
|
||||
.route(path("/anything/circuitbreakernofallback"), http())
|
||||
.before(uri("https://example.org"))
|
||||
.filter(circuitBreaker("myCircuitBreaker"))
|
||||
.build();
|
||||
}
|
||||
}
|
||||
----
|
||||
@@ -74,6 +78,7 @@ The following listing does the same thing in Java:
|
||||
[source,java]
|
||||
----
|
||||
import java.net.URI;
|
||||
import static org.springframework.cloud.gateway.server.mvc.filter.BeforeFilterFunctions.uri;
|
||||
import static org.springframework.cloud.gateway.server.mvc.filter.CircuitBreakerFilterFunctions.circuitBreaker;
|
||||
import static org.springframework.cloud.gateway.server.mvc.handler.GatewayRouterFunctions.route;
|
||||
import static org.springframework.cloud.gateway.server.mvc.handler.HandlerFunctions.http;
|
||||
@@ -84,9 +89,10 @@ class RouteConfiguration {
|
||||
@Bean
|
||||
public RouterFunction<ServerResponse> gatewayRouterFunctionsCircuitBreakerFallback() {
|
||||
return route("circuitbreaker_route")
|
||||
.route(path("/consumingServiceEndpoint"), http("https://example.org"))
|
||||
.filter(circuitBreaker("myCircuitBreaker", URI.create("forward:/inCaseOfFailureUseThis")))
|
||||
.build();
|
||||
.route(path("/consumingServiceEndpoint"), http())
|
||||
.before(uri("https://example.org"))
|
||||
.filter(circuitBreaker("myCircuitBreaker", URI.create("forward:/inCaseOfFailureUseThis")))
|
||||
.build();
|
||||
}
|
||||
}
|
||||
----
|
||||
@@ -102,6 +108,7 @@ In the example below the call `consumingServiceEndpoint/users/1` will be redirec
|
||||
[source,java]
|
||||
----
|
||||
import java.net.URI;
|
||||
import static org.springframework.cloud.gateway.server.mvc.filter.BeforeFilterFunctions.uri;
|
||||
import static org.springframework.cloud.gateway.server.mvc.filter.CircuitBreakerFilterFunctions.circuitBreaker;
|
||||
import static org.springframework.cloud.gateway.server.mvc.handler.GatewayRouterFunctions.route;
|
||||
import static org.springframework.cloud.gateway.server.mvc.handler.HandlerFunctions.http;
|
||||
@@ -112,9 +119,10 @@ class RouteConfiguration {
|
||||
@Bean
|
||||
public RouterFunction<ServerResponse> gatewayRouterFunctionsCircuitBreakerFallback() {
|
||||
return route("circuitbreaker_route")
|
||||
.route(path("/consumingServiceEndpoint/{*segments}"), http("https://example.org"))
|
||||
.filter(circuitBreaker("myCircuitBreaker", URI.create("forward:/inCaseOfFailureUseThis/{segments}")))
|
||||
.build();
|
||||
.route(path("/consumingServiceEndpoint/{*segments}"), http())
|
||||
.before(uri("https://example.org"))
|
||||
.filter(circuitBreaker("myCircuitBreaker", URI.create("forward:/inCaseOfFailureUseThis/{segments}")))
|
||||
.build();
|
||||
}
|
||||
}
|
||||
----
|
||||
@@ -126,6 +134,7 @@ However, you can also reroute the request to a controller or handler in an exter
|
||||
.GatewaySampleApplication.java
|
||||
[source,java]
|
||||
----
|
||||
import static org.springframework.cloud.gateway.server.mvc.filter.BeforeFilterFunctions.uri;
|
||||
import static org.springframework.cloud.gateway.server.mvc.filter.CircuitBreakerFilterFunctions.circuitBreaker;
|
||||
import static org.springframework.cloud.gateway.server.mvc.filter.LoadBalancerFilterFunctions.lb;
|
||||
import static org.springframework.cloud.gateway.server.mvc.handler.GatewayRouterFunctions.route;
|
||||
@@ -142,7 +151,8 @@ class RouteConfiguration {
|
||||
.filter(circuitBreaker("fetchIngredients", URI.create("forward:/fallback")))
|
||||
.build()
|
||||
.and(route("ingredients-fallback")
|
||||
.route(path("/fallback"), http("http://localhost:9994"))
|
||||
.route(path("/fallback"), http())
|
||||
.before(uri("https://localhost:9994"))
|
||||
.build());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,6 +14,8 @@ spring:
|
||||
routes:
|
||||
- id: dedupe_response_header_route
|
||||
uri: https://example.org
|
||||
predicates:
|
||||
- Path=/hello
|
||||
filters:
|
||||
- DedupeResponseHeader=Access-Control-Allow-Credentials Access-Control-Allow-Origin
|
||||
----
|
||||
@@ -21,18 +23,19 @@ spring:
|
||||
[source,java]
|
||||
----
|
||||
import static org.springframework.cloud.gateway.server.mvc.filter.AfterFilterFunctions.dedupeResponseHeader;
|
||||
import static org.springframework.cloud.gateway.server.mvc.filter.BeforeFilterFunctions.uri;
|
||||
import static org.springframework.cloud.gateway.server.mvc.handler.GatewayRouterFunctions.route;
|
||||
import static org.springframework.cloud.gateway.server.mvc.handler.HandlerFunctions.http;
|
||||
import static org.springframework.web.servlet.function.RequestPredicates.path;
|
||||
|
||||
|
||||
@Configuration
|
||||
class RouteConfiguration {
|
||||
|
||||
@Bean
|
||||
public RouterFunction<ServerResponse> gatewayRouterFunctionsDedupeResponseHeader() {
|
||||
return route("dedupe_response_header_route")
|
||||
.route(path("/hello"), http("https://example.org"))
|
||||
.route(path("/hello"), http())
|
||||
.before(uri("https://example.org"))
|
||||
.after(dedupeResponseHeader("Access-Control-Allow-Credentials Access-Control-Allow-Origin"))
|
||||
.build();
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ spring:
|
||||
- id: ingredients
|
||||
uri: lb://ingredients
|
||||
predicates:
|
||||
- Path=//ingredients/**
|
||||
- Path=/ingredients/**
|
||||
filters:
|
||||
- name: CircuitBreaker
|
||||
args:
|
||||
@@ -33,8 +33,9 @@ spring:
|
||||
.GatewaySampleApplication.java
|
||||
[source,java]
|
||||
----
|
||||
import static org.springframework.cloud.gateway.server.mvc.filter.CircuitBreakerFilterFunctions.circuitBreaker;
|
||||
import static org.springframework.cloud.gateway.server.mvc.filter.BeforeFilterFunctions.fallbackHeaders;
|
||||
import static org.springframework.cloud.gateway.server.mvc.filter.BeforeFilterFunctions.uri;
|
||||
import static org.springframework.cloud.gateway.server.mvc.filter.CircuitBreakerFilterFunctions.circuitBreaker;
|
||||
import static org.springframework.cloud.gateway.server.mvc.filter.LoadBalancerFilterFunctions.lb;
|
||||
import static org.springframework.cloud.gateway.server.mvc.handler.GatewayRouterFunctions.route;
|
||||
import static org.springframework.cloud.gateway.server.mvc.handler.HandlerFunctions.http;
|
||||
@@ -50,7 +51,8 @@ class RouteConfiguration {
|
||||
.filter(circuitBreaker("fetchIngredients", URI.create("forward:/fallback")))
|
||||
.build()
|
||||
.and(route("ingredients-fallback")
|
||||
.route(path("/fallback"), http("http://localhost:9994"))
|
||||
.route(path("/fallback"), http())
|
||||
.before(uri("http://localhost:9994"))
|
||||
.before(fallbackHeaders())
|
||||
.build());
|
||||
}
|
||||
|
||||
@@ -17,6 +17,8 @@ spring:
|
||||
routes:
|
||||
- id: map_request_header_route
|
||||
uri: https://example.org
|
||||
predicates:
|
||||
- Path=/mypath
|
||||
filters:
|
||||
- MapRequestHeader=Blue, X-Request-Red
|
||||
----
|
||||
@@ -24,7 +26,8 @@ spring:
|
||||
.GatewaySampleApplication.java
|
||||
[source,java]
|
||||
----
|
||||
import static org.springframework.cloud.gateway.server.mvc.filter.BeforeFilterFunctions.addRequestParameter;
|
||||
import static org.springframework.cloud.gateway.server.mvc.filter.BeforeFilterFunctions.mapRequestHeader;
|
||||
import static org.springframework.cloud.gateway.server.mvc.filter.BeforeFilterFunctions.uri;
|
||||
import static org.springframework.cloud.gateway.server.mvc.handler.GatewayRouterFunctions.route;
|
||||
import static org.springframework.cloud.gateway.server.mvc.handler.HandlerFunctions.http;
|
||||
|
||||
@@ -34,7 +37,8 @@ class RouteConfiguration {
|
||||
@Bean
|
||||
public RouterFunction<ServerResponse> gatewayRouterFunctionsMapRequestHeader() {
|
||||
return route("map_request_header_route")
|
||||
.GET("/mypath", http("https://example.org"))
|
||||
.GET("/mypath", http())
|
||||
.before(uri("https://example.org"))
|
||||
.before(mapRequestHeader("Blue", "X-Request-Red"))
|
||||
.build();
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ The following listing shows how to modify a request body filter:
|
||||
[source,java]
|
||||
----
|
||||
import static org.springframework.cloud.gateway.server.mvc.filter.BeforeFilterFunctions.modifyRequestBody;
|
||||
import static org.springframework.cloud.gateway.server.mvc.filter.BeforeFilterFunctions.uri;
|
||||
import static org.springframework.cloud.gateway.server.mvc.handler.GatewayRouterFunctions.route;
|
||||
import static org.springframework.cloud.gateway.server.mvc.handler.HandlerFunctions.http;
|
||||
import static org.springframework.cloud.gateway.server.mvc.predicate.GatewayRequestPredicates.host;
|
||||
@@ -20,12 +21,13 @@ import org.springframework.http.MediaType;
|
||||
class RouteConfiguration {
|
||||
|
||||
@Bean
|
||||
public RouterFunction<ServerResponse> gatewayRouterFunctionsAddReqHeader() {
|
||||
return route("rewrite_request_obj")
|
||||
.route(host("*.rewriterequestobj.org"), http("https://example.org"))
|
||||
.before(modifyRequestBody(String.class, Hello.class, MediaType.APPLICATION_JSON_VALUE,
|
||||
(request, s) -> new Hello(s.toUpperCase())))
|
||||
.build();
|
||||
public RouterFunction<ServerResponse> gatewayRouterFunctionsModifyRequestBody() {
|
||||
return route("modify_request_body")
|
||||
.route(host("*.modifyrequestbody.org"), http())
|
||||
.before(uri("https://example.org"))
|
||||
.before(modifyRequestBody(String.class, Hello.class, MediaType.APPLICATION_JSON_VALUE,
|
||||
(request, s) -> new Hello(s.toUpperCase())))
|
||||
.build();
|
||||
}
|
||||
|
||||
record Hello(String message) { }
|
||||
|
||||
@@ -7,22 +7,11 @@ NOTE: This filter can be configured only by using the Java DSL.
|
||||
|
||||
The following listing shows how to modify a response body filter:
|
||||
|
||||
[source,java]
|
||||
----
|
||||
@Bean
|
||||
public RouteLocator routes(RouteLocatorBuilder builder) {
|
||||
return builder.routes()
|
||||
.route("rewrite_response_upper", r -> r.host("*.rewriteresponseupper.org")
|
||||
.filters(f -> f.prefixPath("/httpbin")
|
||||
.modifyResponseBody(String.class, String.class,
|
||||
(exchange, s) -> Mono.just(s.toUpperCase()))).uri(uri))
|
||||
.build();
|
||||
}
|
||||
----
|
||||
.GatewaySampleApplication.java
|
||||
[source,java]
|
||||
----
|
||||
import static org.springframework.cloud.gateway.server.mvc.filter.AfterFilterFunctions.modifyResponseBody;
|
||||
import static org.springframework.cloud.gateway.server.mvc.filter.BeforeFilterFunctions.uri;
|
||||
import static org.springframework.cloud.gateway.server.mvc.handler.GatewayRouterFunctions.route;
|
||||
import static org.springframework.cloud.gateway.server.mvc.handler.HandlerFunctions.http;
|
||||
import static org.springframework.cloud.gateway.server.mvc.predicate.GatewayRequestPredicates.host;
|
||||
@@ -32,11 +21,13 @@ import org.springframework.http.MediaType;
|
||||
class RouteConfiguration {
|
||||
|
||||
@Bean
|
||||
public RouterFunction<ServerResponse> gatewayRouterFunctionsAddReqHeader() {
|
||||
return route("rewrite_request_obj")
|
||||
.route(host("*.rewriterequestobj.org"), http("https://example.org"))
|
||||
.before(modifyResponseBody(String.class, String.class, MediaType.APPLICATION_JSON_VALUE, (request, s) -> s.toUpperCase()))
|
||||
.build();
|
||||
public RouterFunction<ServerResponse> gatewayRouterFunctionsModifyResponseBody() {
|
||||
return route("modify_response_bodu")
|
||||
.route(host("*.modifyresponsebodu.org"), http())
|
||||
.before(uri("https://example.org"))
|
||||
.after(modifyResponseBody(String.class, String.class, MediaType.APPLICATION_JSON_VALUE,
|
||||
(request, s) -> s.toUpperCase()))
|
||||
.build();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -15,6 +15,8 @@ spring:
|
||||
routes:
|
||||
- id: prefixpath_route
|
||||
uri: https://example.org
|
||||
predicates:
|
||||
- Path=/**
|
||||
filters:
|
||||
- PrefixPath=/mypath
|
||||
----
|
||||
@@ -22,6 +24,7 @@ spring:
|
||||
.GatewaySampleApplication.java
|
||||
[source,java]
|
||||
----
|
||||
import static org.springframework.cloud.gateway.server.mvc.filter.BeforeFilterFunctions.uri;
|
||||
import static org.springframework.cloud.gateway.server.mvc.filter.BeforeFilterFunctions.prefixPath;
|
||||
import static org.springframework.cloud.gateway.server.mvc.handler.GatewayRouterFunctions.route;
|
||||
import static org.springframework.cloud.gateway.server.mvc.handler.HandlerFunctions.http;
|
||||
@@ -31,10 +34,11 @@ class RouteConfiguration {
|
||||
|
||||
@Bean
|
||||
public RouterFunction<ServerResponse> gatewayRouterFunctionsPrefixPath() {
|
||||
return route("prefixpath_route")
|
||||
.GET("/**", http("https://example.org"))
|
||||
.before(prefixPath("/mypath"))
|
||||
.build();
|
||||
return route("prefixpath_route")
|
||||
.GET("/**", http())
|
||||
.before(uri("https://example.org"))
|
||||
.before(prefixPath("/mypath"))
|
||||
.build();
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
@@ -16,6 +16,8 @@ spring:
|
||||
routes:
|
||||
- id: preserve_host_route
|
||||
uri: https://example.org
|
||||
predicates:
|
||||
- Path=/**
|
||||
filters:
|
||||
- PreserveHostHeader
|
||||
----
|
||||
@@ -23,6 +25,7 @@ spring:
|
||||
.GatewaySampleApplication.java
|
||||
[source,java]
|
||||
----
|
||||
import static org.springframework.cloud.gateway.server.mvc.filter.BeforeFilterFunctions.uri;
|
||||
import static org.springframework.cloud.gateway.server.mvc.filter.BeforeFilterFunctions.preserveHostHeader;
|
||||
import static org.springframework.cloud.gateway.server.mvc.handler.GatewayRouterFunctions.route;
|
||||
import static org.springframework.cloud.gateway.server.mvc.handler.HandlerFunctions.http;
|
||||
@@ -32,10 +35,11 @@ class RouteConfiguration {
|
||||
|
||||
@Bean
|
||||
public RouterFunction<ServerResponse> gatewayRouterFunctionsPreserveHostHeader() {
|
||||
return route("preserve_host_route")
|
||||
.GET("/**", http("https://example.org"))
|
||||
.before(preserveHostHeader())
|
||||
.build();
|
||||
return route("preserve_host_route")
|
||||
.GET("/**", http())
|
||||
.before(uri("https://example.org"))
|
||||
.before(preserveHostHeader())
|
||||
.build();
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
@@ -47,6 +47,7 @@ The following is an example of configuring a route with rate limiting:
|
||||
.RouteConfiguration.java
|
||||
[source,java]
|
||||
----
|
||||
import static org.springframework.cloud.gateway.server.mvc.filter.BeforeFilterFunctions.uri;
|
||||
import static org.springframework.cloud.gateway.server.mvc.filter.Bucket4jFilterFunctions.rateLimit;
|
||||
import static org.springframework.cloud.gateway.server.mvc.handler.GatewayRouterFunctions.route;
|
||||
import static org.springframework.cloud.gateway.server.mvc.handler.HandlerFunctions.http;
|
||||
@@ -56,12 +57,13 @@ class RouteConfiguration {
|
||||
|
||||
@Bean
|
||||
public RouterFunction<ServerResponse> gatewayRouterFunctionsRateLimited() {
|
||||
return route("rate_limited_route")
|
||||
.GET("/api/**", http("https://example.org"))
|
||||
.filter(rateLimit(c -> c.setCapacity(100)
|
||||
.setPeriod(Duration.ofMinutes(1))
|
||||
.setKeyResolver(request -> request.servletRequest().getUserPrincipal().getName())))
|
||||
.build();
|
||||
return route("rate_limited_route")
|
||||
.GET("/api/**", http())
|
||||
.before(uri("https://example.org"))
|
||||
.filter(rateLimit(c -> c.setCapacity(100)
|
||||
.setPeriod(Duration.ofMinutes(1))
|
||||
.setKeyResolver(request -> request.servletRequest().getUserPrincipal().getName())))
|
||||
.build();
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
@@ -18,6 +18,8 @@ spring:
|
||||
routes:
|
||||
- id: redirectto_route
|
||||
uri: https://example.org
|
||||
predicates:
|
||||
- Path=/**
|
||||
filters:
|
||||
- RedirectTo=302, https://acme.org
|
||||
----
|
||||
@@ -25,6 +27,7 @@ spring:
|
||||
.GatewaySampleApplication.java
|
||||
[source,java]
|
||||
----
|
||||
import static org.springframework.cloud.gateway.server.mvc.filter.BeforeFilterFunctions.uri;
|
||||
import static org.springframework.cloud.gateway.server.mvc.filter.FilterFunctions.redirectTo;
|
||||
import static org.springframework.cloud.gateway.server.mvc.handler.GatewayRouterFunctions.route;
|
||||
import static org.springframework.cloud.gateway.server.mvc.handler.HandlerFunctions.http;
|
||||
@@ -34,10 +37,11 @@ class RouteConfiguration {
|
||||
|
||||
@Bean
|
||||
public RouterFunction<ServerResponse> gatewayRouterFunctionsRedirectTo() {
|
||||
return route("redirectto_route")
|
||||
.GET("/**", http("https://example.org"))
|
||||
.filter(redirectTo(302, URI.create("acme.org")))
|
||||
.build();
|
||||
return route("redirectto_route")
|
||||
.GET("/**", http())
|
||||
.before(uri("https://example.org"))
|
||||
.filter(redirectTo(302, URI.create("acme.org")))
|
||||
.build();
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
@@ -16,6 +16,8 @@ spring:
|
||||
routes:
|
||||
- id: removerequestheader_route
|
||||
uri: https://example.org
|
||||
predicates:
|
||||
- Path=/**
|
||||
filters:
|
||||
- RemoveRequestHeader=X-Request-Foo
|
||||
----
|
||||
@@ -23,6 +25,7 @@ spring:
|
||||
.GatewaySampleApplication.java
|
||||
[source,java]
|
||||
----
|
||||
import static org.springframework.cloud.gateway.server.mvc.filter.BeforeFilterFunctions.uri;
|
||||
import static org.springframework.cloud.gateway.server.mvc.filter.BeforeFilterFunctions.removeRequestHeader;
|
||||
import static org.springframework.cloud.gateway.server.mvc.handler.GatewayRouterFunctions.route;
|
||||
import static org.springframework.cloud.gateway.server.mvc.handler.HandlerFunctions.http;
|
||||
@@ -31,11 +34,12 @@ import static org.springframework.cloud.gateway.server.mvc.handler.HandlerFuncti
|
||||
class RouteConfiguration {
|
||||
|
||||
@Bean
|
||||
public RouterFunction<ServerResponse> gatewayRouterFunctionsremoveRequestHeader() {
|
||||
return route("removerequestheader_route")
|
||||
.GET("/**", http("https://example.org"))
|
||||
.before(removeRequestHeader("X-Request-Foo"))
|
||||
.build();
|
||||
public RouterFunction<ServerResponse> gatewayRouterFunctionsRemoveRequestHeader() {
|
||||
return route("removerequestheader_route")
|
||||
.GET("/**", http())
|
||||
.before(uri("https://example.org"))
|
||||
.before(removeRequestHeader("X-Request-Foo"))
|
||||
.build();
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
@@ -16,6 +16,8 @@ spring:
|
||||
routes:
|
||||
- id: removerequestparameter_route
|
||||
uri: https://example.org
|
||||
predicates:
|
||||
- Path=/**
|
||||
filters:
|
||||
- RemoveRequestParameter=red
|
||||
----
|
||||
@@ -23,7 +25,8 @@ spring:
|
||||
.GatewaySampleApplication.java
|
||||
[source,java]
|
||||
----
|
||||
import static org.springframework.cloud.gateway.server.mvc.filter.BeforeFilterFunctions.addRequestParameter;
|
||||
import static org.springframework.cloud.gateway.server.mvc.filter.BeforeFilterFunctions.uri;
|
||||
import static org.springframework.cloud.gateway.server.mvc.filter.BeforeFilterFunctions.removeRequestParameter;
|
||||
import static org.springframework.cloud.gateway.server.mvc.handler.GatewayRouterFunctions.route;
|
||||
import static org.springframework.cloud.gateway.server.mvc.handler.HandlerFunctions.http;
|
||||
|
||||
@@ -31,11 +34,12 @@ import static org.springframework.cloud.gateway.server.mvc.handler.HandlerFuncti
|
||||
class RouteConfiguration {
|
||||
|
||||
@Bean
|
||||
public RouterFunction<ServerResponse> gatewayRouterFunctionsAddReqHeader() {
|
||||
return route("removerequestparameter_route")
|
||||
.GET("/**", http("https://example.org"))
|
||||
.before(removeRequestParameter("red"))
|
||||
.build();
|
||||
public RouterFunction<ServerResponse> gatewayRouterFunctionsRemoveRequestParameter() {
|
||||
return route("removerequestparameter_route")
|
||||
.GET("/**", http())
|
||||
.before(uri("https://example.org"))
|
||||
.before(removeRequestParameter("red"))
|
||||
.build();
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
@@ -15,6 +15,8 @@ spring:
|
||||
routes:
|
||||
- id: removeresponseheader_route
|
||||
uri: https://example.org
|
||||
predicates:
|
||||
- Path=/anything/removeresponseheader
|
||||
filters:
|
||||
- RemoveResponseHeader=X-Response-Foo
|
||||
----
|
||||
@@ -22,6 +24,7 @@ spring:
|
||||
.GatewaySampleApplication.java
|
||||
[source,java]
|
||||
----
|
||||
import static org.springframework.cloud.gateway.server.mvc.filter.BeforeFilterFunctions.uri;
|
||||
import static org.springframework.cloud.gateway.server.mvc.filter.AfterFilterFunctions.removeResponseHeader;
|
||||
import static org.springframework.cloud.gateway.server.mvc.handler.GatewayRouterFunctions.route;
|
||||
import static org.springframework.cloud.gateway.server.mvc.handler.HandlerFunctions.http;
|
||||
@@ -31,9 +34,10 @@ class RouteConfiguration {
|
||||
|
||||
@Bean
|
||||
public RouterFunction<ServerResponse> gatewayRouterFunctionsRemoveResponseHeader() {
|
||||
return route("addresponseheader")
|
||||
.GET("/anything/addresheader", http("https://example.org"))
|
||||
.after(removeResponseHeader("X-Response-Foo"))
|
||||
return route("removeresponseheader_route")
|
||||
.GET("/anything/removeresponseheader", http())
|
||||
.before(uri("https://example.org"))
|
||||
.after(removeResponseHeader("X-Response-Foo"))
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,8 @@ spring:
|
||||
routes:
|
||||
- id: requestheadersize_route
|
||||
uri: https://example.org
|
||||
predicates:
|
||||
- Path=/**
|
||||
filters:
|
||||
- RequestHeaderSize=1000B
|
||||
----
|
||||
@@ -23,6 +25,7 @@ spring:
|
||||
.GatewaySampleApplication.java
|
||||
[source,java]
|
||||
----
|
||||
import static org.springframework.cloud.gateway.server.mvc.filter.BeforeFilterFunctions.uri;
|
||||
import static org.springframework.cloud.gateway.server.mvc.filter.BeforeFilterFunctions.requestHeaderSize;
|
||||
import static org.springframework.cloud.gateway.server.mvc.handler.GatewayRouterFunctions.route;
|
||||
import static org.springframework.cloud.gateway.server.mvc.handler.HandlerFunctions.http;
|
||||
@@ -32,10 +35,11 @@ class RouteConfiguration {
|
||||
|
||||
@Bean
|
||||
public RouterFunction<ServerResponse> gatewayRouterFunctionsRequestHeaderSize() {
|
||||
return route("requestheadersize_route")
|
||||
.GET("/**", http("https://example.org"))
|
||||
.before(requestHeaderSize("1000B"))
|
||||
.build();
|
||||
return route("requestheadersize_route")
|
||||
.GET("/**", http())
|
||||
.before(uri("https://example.org"))
|
||||
.before(requestHeaderSize("1000B"))
|
||||
.build();
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
@@ -28,6 +28,7 @@ spring:
|
||||
.GatewaySampleApplication.java
|
||||
[source,java]
|
||||
----
|
||||
import static org.springframework.cloud.gateway.server.mvc.filter.BeforeFilterFunctions.uri;
|
||||
import static org.springframework.cloud.gateway.server.mvc.filter.BeforeFilterFunctions.requestSize;
|
||||
import static org.springframework.cloud.gateway.server.mvc.handler.GatewayRouterFunctions.route;
|
||||
import static org.springframework.cloud.gateway.server.mvc.handler.HandlerFunctions.http;
|
||||
@@ -37,10 +38,11 @@ class RouteConfiguration {
|
||||
|
||||
@Bean
|
||||
public RouterFunction<ServerResponse> gatewayRouterFunctionsRequestSize() {
|
||||
return route("request_size_route")
|
||||
.GET("/upload", http("http://localhost:8080"))
|
||||
.before(requestSize("5000000"))
|
||||
.build();
|
||||
return route("request_size_route")
|
||||
.GET("/upload", http())
|
||||
.before(uri("http://localhost:8080"))
|
||||
.before(requestSize("5000000"))
|
||||
.build();
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
@@ -36,7 +36,7 @@ spring:
|
||||
gateway:
|
||||
mvc:
|
||||
routes:
|
||||
- id: retry_test
|
||||
- id: retry_route
|
||||
uri: http://localhost:8080/flakey
|
||||
predicates:
|
||||
- Host=*.retry.com
|
||||
@@ -53,6 +53,7 @@ spring:
|
||||
.GatewaySampleApplication.java
|
||||
[source,java]
|
||||
----
|
||||
import static org.springframework.cloud.gateway.server.mvc.filter.BeforeFilterFunctions.uri;
|
||||
import static org.springframework.cloud.gateway.server.mvc.filter.FilterFunctions.adaptCachedBody;
|
||||
import static org.springframework.cloud.gateway.server.mvc.filter.RetryFilterFunctions.retry;
|
||||
import static org.springframework.cloud.gateway.server.mvc.handler.GatewayRouterFunctions.route;
|
||||
@@ -63,12 +64,16 @@ import static org.springframework.cloud.gateway.server.mvc.predicate.GatewayRequ
|
||||
class RouteConfiguration {
|
||||
|
||||
@Bean
|
||||
public RouterFunction<ServerResponse> gatewayRouterFunctionsAddReqHeader() {
|
||||
return route("add_request_parameter_route")
|
||||
.route(host("*.retry.com"), http("https://example.org"))
|
||||
.filter(retry(config -> config.setRetries(3).setSeries(Set.of(HttpStatus.Series.SERVER_ERROR)).setMethods(Set.of(HttpMethod.GET, HttpMethod.POST)).setCacheBody(true)))
|
||||
.filter(adaptCachedBody())
|
||||
.build();
|
||||
public RouterFunction<ServerResponse> gatewayRouterFunctionsRetry() {
|
||||
return route("retry_route")
|
||||
.route(host("*.retry.com"), http())
|
||||
.before(uri("http://localhost:8080/flakey"))
|
||||
.filter(retry(config -> config.setRetries(3)
|
||||
.setSeries(Set.of(HttpStatus.Series.SERVER_ERROR))
|
||||
.setMethods(Set.of(HttpMethod.GET, HttpMethod.POST))
|
||||
.setCacheBody(true)))
|
||||
.filter(adaptCachedBody())
|
||||
.build();
|
||||
}
|
||||
}
|
||||
----
|
||||
@@ -77,11 +82,11 @@ NOTE: When using the retry filter with a `forward:` prefixed URL, the target end
|
||||
For example, if the target endpoint is an annotated controller, the target controller method should not return `ResponseEntity` with an error status code.
|
||||
Instead, it should throw an `Exception` or signal an error (for example, through a `Mono.error(ex)` return value), which the retry filter can be configured to handle by retrying.
|
||||
|
||||
// WARNING: When using the retry filter with any HTTP method with a body, the body will be cached and the gateway will become memory constrained. The body is cached in a request attribute defined by `ServerWebExchangeUtils.CACHED_REQUEST_BODY_ATTR`. The type of the object is `org.springframework.core.io.buffer.DataBuffer`.
|
||||
WARNING: When using the retry filter with any HTTP method with a body and `cacheBody=true`, the body will be cached and the gateway will become memory constrained. The body is cached in a request attribute defined by `MvcUtils.CACHED_REQUEST_BODY_ATT`. The type of the object is `ByteArrayInputStream`.
|
||||
|
||||
A simplified "shortcut" notation can be added with a single `status` and `method`.
|
||||
|
||||
The following two examples are equivalent:
|
||||
The following two example routes are equivalent:
|
||||
|
||||
.application.yml
|
||||
[source,yaml]
|
||||
|
||||
@@ -15,6 +15,8 @@ spring:
|
||||
routes:
|
||||
- id: rewritelocationresponseheader_route
|
||||
uri: http://example.org
|
||||
predicates:
|
||||
- Path=/**
|
||||
filters:
|
||||
- RewriteLocationResponseHeader=AS_IN_REQUEST, Location, ,
|
||||
----
|
||||
@@ -22,7 +24,8 @@ spring:
|
||||
.GatewaySampleApplication.java
|
||||
[source,java]
|
||||
----
|
||||
import static org.springframework.cloud.gateway.server.mvc.filter.AfterFilterFunctions.addResponseHeader;
|
||||
import static org.springframework.cloud.gateway.server.mvc.filter.BeforeFilterFunctions.uri;
|
||||
import static org.springframework.cloud.gateway.server.mvc.filter.RewriteLocationResponseHeaderFilterFunctions.rewriteLocationResponseHeader;
|
||||
import static org.springframework.cloud.gateway.server.mvc.filter.RewriteLocationResponseHeaderFilterFunctions.StripVersion;
|
||||
import static org.springframework.cloud.gateway.server.mvc.handler.GatewayRouterFunctions.route;
|
||||
import static org.springframework.cloud.gateway.server.mvc.handler.HandlerFunctions.http;
|
||||
@@ -33,9 +36,11 @@ class RouteConfiguration {
|
||||
@Bean
|
||||
public RouterFunction<ServerResponse> gatewayRouterFunctionsRewriteLocationResponseHeader() {
|
||||
return route("rewritelocationresponseheader_route")
|
||||
.GET("/**", http("https://example.org"))
|
||||
.after(rewriteLocationResponseHeader(config -> config.setLocationHeaderName("Location").setStripVersion(StripVersion.AS_IN_REQUEST)))
|
||||
.build();
|
||||
.GET("/**", http())
|
||||
.before(uri("https://example.org"))
|
||||
.after(rewriteLocationResponseHeader(config -> config.setLocationHeaderName("Location")
|
||||
.setStripVersion(StripVersion.AS_IN_REQUEST)))
|
||||
.build();
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
@@ -25,6 +25,7 @@ spring:
|
||||
[source,java]
|
||||
----
|
||||
import static org.springframework.cloud.gateway.server.mvc.filter.BeforeFilterFunctions.rewritePath;
|
||||
import static org.springframework.cloud.gateway.server.mvc.filter.BeforeFilterFunctions.uri;
|
||||
import static org.springframework.cloud.gateway.server.mvc.handler.GatewayRouterFunctions.route;
|
||||
import static org.springframework.cloud.gateway.server.mvc.handler.HandlerFunctions.http;
|
||||
|
||||
@@ -33,10 +34,11 @@ class RouteConfiguration {
|
||||
|
||||
@Bean
|
||||
public RouterFunction<ServerResponse> gatewayRouterFunctionsRewritePath() {
|
||||
return route("rewritepath_route")
|
||||
.GET("/red/**", http("https://example.org"))
|
||||
.before(rewritePath("/red/(?<segment>.*)", "/${segment}"))
|
||||
.build();
|
||||
return route("rewritepath_route")
|
||||
.GET("/red/**", http())
|
||||
.before(uri("https://example.org"))
|
||||
.before(rewritePath("/red/(?<segment>.*)", "/${segment}"))
|
||||
.build();
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
@@ -26,6 +26,7 @@ spring:
|
||||
[source,java]
|
||||
----
|
||||
import static org.springframework.cloud.gateway.server.mvc.filter.BeforeFilterFunctions.addRequestParameter;
|
||||
import static org.springframework.cloud.gateway.server.mvc.filter.BeforeFilterFunctions.uri;
|
||||
import static org.springframework.cloud.gateway.server.mvc.handler.GatewayRouterFunctions.route;
|
||||
import static org.springframework.cloud.gateway.server.mvc.handler.HandlerFunctions.http;
|
||||
|
||||
@@ -33,11 +34,12 @@ import static org.springframework.cloud.gateway.server.mvc.handler.HandlerFuncti
|
||||
class RouteConfiguration {
|
||||
|
||||
@Bean
|
||||
public RouterFunction<ServerResponse> gatewayRouterFunctionsAddReqHeader() {
|
||||
return route("add_request_parameter_route")
|
||||
.GET("/anything/addrequestparam", http("https://example.org"))
|
||||
.before(addRequestParameter("red", "blue"))
|
||||
.build();
|
||||
public RouterFunction<ServerResponse> gatewayRouterFunctionsRewriteRequestParameter() {
|
||||
return route("rewriterequestparameter_route")
|
||||
.GET("products", http())
|
||||
.before(uri("https://example.org"))
|
||||
.before(addRequestParameter("red", "blue"))
|
||||
.build();
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
@@ -16,14 +16,17 @@ spring:
|
||||
routes:
|
||||
- id: rewriteresponseheader_route
|
||||
uri: https://example.org
|
||||
predicates:
|
||||
- Path=/**
|
||||
filters:
|
||||
- RewriteResponseHeader=X-Response-Red, , password=[^&]+, password=***
|
||||
- RewriteResponseHeader=X-Response-Red, password=[^&]+, password=***
|
||||
----
|
||||
|
||||
.GatewaySampleApplication.java
|
||||
[source,java]
|
||||
----
|
||||
import static org.springframework.cloud.gateway.server.mvc.filter.AfterFilterFunctions.addResponseHeader;
|
||||
import static org.springframework.cloud.gateway.server.mvc.filter.AfterFilterFunctions.rewriteResponseHeader;
|
||||
import static org.springframework.cloud.gateway.server.mvc.filter.BeforeFilterFunctions.uri;
|
||||
import static org.springframework.cloud.gateway.server.mvc.handler.GatewayRouterFunctions.route;
|
||||
import static org.springframework.cloud.gateway.server.mvc.handler.HandlerFunctions.http;
|
||||
|
||||
@@ -33,8 +36,9 @@ class RouteConfiguration {
|
||||
@Bean
|
||||
public RouterFunction<ServerResponse> gatewayRouterFunctionsRewriteResponseHeader() {
|
||||
return route("rewriteresponseheader_route")
|
||||
.GET("/**", http("https://example.org"))
|
||||
.after(rewriteResponseHeader("X-Request-Red", "password=[^&]+", "password=***"))
|
||||
.GET("/**", http())
|
||||
.before(uri("https://example.org"))
|
||||
.after(rewriteResponseHeader("X-Request-Red", "password=[^&]+", "password=***"))
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,6 +27,7 @@ spring:
|
||||
[source,java]
|
||||
----
|
||||
import static org.springframework.cloud.gateway.server.mvc.filter.BeforeFilterFunctions.setPath;
|
||||
import static org.springframework.cloud.gateway.server.mvc.filter.BeforeFilterFunctions.uri;
|
||||
import static org.springframework.cloud.gateway.server.mvc.handler.GatewayRouterFunctions.route;
|
||||
import static org.springframework.cloud.gateway.server.mvc.handler.HandlerFunctions.http;
|
||||
|
||||
@@ -35,10 +36,11 @@ class RouteConfiguration {
|
||||
|
||||
@Bean
|
||||
public RouterFunction<ServerResponse> gatewayRouterFunctionsSetPath() {
|
||||
return route("add_request_parameter_route")
|
||||
.GET("/red/{segment}", http("https://example.org"))
|
||||
.before(setPath("/{segment"))
|
||||
.build();
|
||||
return route("setpath_route")
|
||||
.GET("/red/{segment}", http())
|
||||
.before(uri("https://example.org"))
|
||||
.before(setPath("/{segment"))
|
||||
.build();
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
@@ -14,6 +14,8 @@ spring:
|
||||
routes:
|
||||
- id: setrequestheader_route
|
||||
uri: https://example.org
|
||||
predicates:
|
||||
- Path=/**
|
||||
filters:
|
||||
- SetRequestHeader=X-Request-Red, Blue
|
||||
----
|
||||
@@ -22,6 +24,7 @@ spring:
|
||||
[source,java]
|
||||
----
|
||||
import static org.springframework.cloud.gateway.server.mvc.filter.BeforeFilterFunctions.setRequestHostHeader;
|
||||
import static org.springframework.cloud.gateway.server.mvc.filter.BeforeFilterFunctions.uri;
|
||||
import static org.springframework.cloud.gateway.server.mvc.handler.GatewayRouterFunctions.route;
|
||||
import static org.springframework.cloud.gateway.server.mvc.handler.HandlerFunctions.http;
|
||||
|
||||
@@ -30,10 +33,11 @@ class RouteConfiguration {
|
||||
|
||||
@Bean
|
||||
public RouterFunction<ServerResponse> gatewayRouterFunctionsSetRequestHeader() {
|
||||
return route("add_request_parameter_route")
|
||||
.GET("/**", http("https://example.org"))
|
||||
.before(setRequestHostHeader("X-Request-Red", "Blue"))
|
||||
.build();
|
||||
return route("setrequestheader_route")
|
||||
.GET("/**", http())
|
||||
.before(uri("https://example.org"))
|
||||
.before(setRequestHostHeader("X-Request-Red", "Blue"))
|
||||
.build();
|
||||
}
|
||||
}
|
||||
----
|
||||
@@ -64,19 +68,21 @@ spring:
|
||||
[source,java]
|
||||
----
|
||||
import static org.springframework.cloud.gateway.server.mvc.filter.BeforeFilterFunctions.setRequestHostHeader;
|
||||
import static org.springframework.cloud.gateway.server.mvc.filter.BeforeFilterFunctions.uri;
|
||||
import static org.springframework.cloud.gateway.server.mvc.handler.GatewayRouterFunctions.route;
|
||||
import static org.springframework.cloud.gateway.server.mvc.handler.HandlerFunctions.http;
|
||||
import static import static org.springframework.cloud.gateway.server.mvc.predicate.GatewayRequestPredicates.host;
|
||||
import static org.springframework.cloud.gateway.server.mvc.predicate.GatewayRequestPredicates.host;
|
||||
|
||||
@Configuration
|
||||
class RouteConfiguration {
|
||||
|
||||
@Bean
|
||||
public RouterFunction<ServerResponse> gatewayRouterFunctionsSetRequestHeader() {
|
||||
return route("add_request_parameter_route")
|
||||
.route(host("{segment}.myhost.org"), http("https://example.org"))
|
||||
.before(setRequestHostHeader("X-Request-Red", "Blue-{segment}"))
|
||||
.build();
|
||||
return route("setrequestheader_route")
|
||||
.route(host("{segment}.myhost.org"), http())
|
||||
.before(uri("https://example.org"))
|
||||
.before(setRequestHostHeader("X-Request-Red", "Blue-{segment}"))
|
||||
.build();
|
||||
}
|
||||
}
|
||||
----
|
||||
@@ -26,6 +26,7 @@ spring:
|
||||
.GatewaySampleApplication.java
|
||||
[source,java]
|
||||
----
|
||||
import static org.springframework.cloud.gateway.server.mvc.filter.BeforeFilterFunctions.uri;
|
||||
import static org.springframework.cloud.gateway.server.mvc.filter.BeforeFilterFunctions.setRequestHostHeader;
|
||||
import static org.springframework.cloud.gateway.server.mvc.handler.GatewayRouterFunctions.route;
|
||||
import static org.springframework.cloud.gateway.server.mvc.handler.HandlerFunctions.http;
|
||||
@@ -35,10 +36,11 @@ class RouteConfiguration {
|
||||
|
||||
@Bean
|
||||
public RouterFunction<ServerResponse> gatewayRouterFunctionsSetRequestHostHeader() {
|
||||
return route("set_request_host_header_route")
|
||||
.GET("/headers", http("http://localhost:8080"))
|
||||
.before(setRequestHostHeader("example.org"))
|
||||
.build();
|
||||
return route("set_request_host_header_route")
|
||||
.GET("/headers", http())
|
||||
.before(uri("http://localhost:8080"))
|
||||
.before(setRequestHostHeader("example.org"))
|
||||
.build();
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
@@ -14,6 +14,8 @@ spring:
|
||||
routes:
|
||||
- id: setresponseheader_route
|
||||
uri: https://example.org
|
||||
predicates:
|
||||
- Path=/anything/setresponseheader
|
||||
filters:
|
||||
- SetResponseHeader=X-Response-Red, Blue
|
||||
----
|
||||
@@ -22,6 +24,7 @@ spring:
|
||||
[source,java]
|
||||
----
|
||||
import static org.springframework.cloud.gateway.server.mvc.filter.AfterFilterFunctions.setResponseHeader;
|
||||
import static org.springframework.cloud.gateway.server.mvc.filter.BeforeFilterFunctions.uri;
|
||||
import static org.springframework.cloud.gateway.server.mvc.handler.GatewayRouterFunctions.route;
|
||||
import static org.springframework.cloud.gateway.server.mvc.handler.HandlerFunctions.http;
|
||||
|
||||
@@ -30,9 +33,10 @@ class RouteConfiguration {
|
||||
|
||||
@Bean
|
||||
public RouterFunction<ServerResponse> gatewayRouterFunctionsSetResponseHeader() {
|
||||
return route("addresponseheader")
|
||||
.GET("/anything/addresheader", http("https://example.org"))
|
||||
.after(setResponseHeader("X-Response-Red", "Blue"))
|
||||
return route("setresponseheader_route")
|
||||
.GET("/anything/setresponseheader", http())
|
||||
.before(uri("https://example.org"))
|
||||
.after(setResponseHeader("X-Response-Red", "Blue"))
|
||||
.build();
|
||||
}
|
||||
}
|
||||
@@ -64,6 +68,7 @@ spring:
|
||||
[source,java]
|
||||
----
|
||||
import static org.springframework.cloud.gateway.server.mvc.filter.AfterFilterFunctions.setResponseHeader;
|
||||
import static org.springframework.cloud.gateway.server.mvc.filter.BeforeFilterFunctions.uri;
|
||||
import static org.springframework.cloud.gateway.server.mvc.handler.GatewayRouterFunctions.route;
|
||||
import static org.springframework.cloud.gateway.server.mvc.handler.HandlerFunctions.http;
|
||||
import static org.springframework.cloud.gateway.server.mvc.predicate.GatewayRequestPredicates.host;
|
||||
@@ -73,10 +78,11 @@ class RouteConfiguration {
|
||||
|
||||
@Bean
|
||||
public RouterFunction<ServerResponse> gatewayRouterFunctionsSetResponseHeader() {
|
||||
return route("add_response_header_route")
|
||||
.route(host("{segment}.myhost.org"), http("https://example.org"))
|
||||
.after(setResponseHeader("foo", "bar-{segment}"))
|
||||
.build();
|
||||
return route("setresponseheader_route")
|
||||
.route(host("{segment}.myhost.org"), http())
|
||||
.before(uri("https://example.org"))
|
||||
.after(setResponseHeader("foo", "bar-{segment}"))
|
||||
.build();
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
@@ -16,10 +16,14 @@ spring:
|
||||
routes:
|
||||
- id: setstatusstring_route
|
||||
uri: https://example.org
|
||||
predicates:
|
||||
- Path=/path1
|
||||
filters:
|
||||
- SetStatus=UNAUTHORIZED
|
||||
- id: setstatusint_route
|
||||
uri: https://example.org
|
||||
predicates:
|
||||
- Path=/path2
|
||||
filters:
|
||||
- SetStatus=401
|
||||
----
|
||||
@@ -28,6 +32,7 @@ spring:
|
||||
[source,java]
|
||||
----
|
||||
import static org.springframework.cloud.gateway.server.mvc.filter.AfterFilterFunctions.setStatus;
|
||||
import static org.springframework.cloud.gateway.server.mvc.filter.BeforeFilterFunctions.uri;
|
||||
import static org.springframework.cloud.gateway.server.mvc.handler.GatewayRouterFunctions.route;
|
||||
import static org.springframework.cloud.gateway.server.mvc.handler.HandlerFunctions.http;
|
||||
|
||||
@@ -37,13 +42,15 @@ class RouteConfiguration {
|
||||
@Bean
|
||||
public RouterFunction<ServerResponse> gatewayRouterFunctionsSetStatus() {
|
||||
return route("setstatus_route")
|
||||
.GET("/path1", http("https://example.org"))
|
||||
.GET("/path1", http())
|
||||
.before(uri("https://example.org"))
|
||||
// setStatus("UNAUTHORIZED") works as well
|
||||
.after(setStatus(HttpStatus.UNAUTHORIZED))
|
||||
.build().and(route("setstatusint_route")
|
||||
.GET("/path2", http("https://example.org"))
|
||||
.before(uri("https://example.org"))
|
||||
.GET("/path2", http())
|
||||
.after(setStatus("401"))
|
||||
.build());
|
||||
.build());
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
@@ -13,8 +13,8 @@ spring:
|
||||
gateway:
|
||||
mvc:
|
||||
routes:
|
||||
- id: nameRoot
|
||||
uri: https://nameservice
|
||||
- id: strip_prefix_route
|
||||
uri: https://example.org
|
||||
predicates:
|
||||
- Path=/name/**
|
||||
filters:
|
||||
@@ -25,6 +25,7 @@ spring:
|
||||
[source,java]
|
||||
----
|
||||
import static org.springframework.cloud.gateway.server.mvc.filter.BeforeFilterFunctions.stripPrefix;
|
||||
import static org.springframework.cloud.gateway.server.mvc.filter.BeforeFilterFunctions.uri;
|
||||
import static org.springframework.cloud.gateway.server.mvc.handler.GatewayRouterFunctions.route;
|
||||
import static org.springframework.cloud.gateway.server.mvc.handler.HandlerFunctions.http;
|
||||
|
||||
@@ -33,14 +34,15 @@ class RouteConfiguration {
|
||||
|
||||
@Bean
|
||||
public RouterFunction<ServerResponse> gatewayRouterFunctionsStripPrefix() {
|
||||
return route("nameRoot")
|
||||
.GET("/name/**", http("https://example.org"))
|
||||
.before(stripPrefix(2))
|
||||
.build();
|
||||
return route("strip_prefix_route")
|
||||
.GET("/name/**", http())
|
||||
.before(uri("https://example.org"))
|
||||
.before(stripPrefix(2))
|
||||
.build();
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
When a request is made through the gateway to `/name/blue/red`, the request made to `nameservice` looks like `https://nameservice/red`.
|
||||
When a request is made through the gateway to `/name/blue/red`, the full request url looks like `https://example.org/red`.
|
||||
|
||||
WARNING: If using the `lb()` filter, it needs to be after the `stripPrefix()` filter, otherwise the resulting url could be incorrect. The `lb:` scheme handler in configuration, automatically puts the filter in the highest precedence order.
|
||||
@@ -54,6 +54,7 @@ Spring Cloud Gateway Server MVC can forward the OAuth2 access token of the curre
|
||||
.RouteConfiguration.java
|
||||
[source,java]
|
||||
----
|
||||
import static org.springframework.cloud.gateway.server.mvc.filter.BeforeFilterFunctions.uri;
|
||||
import static org.springframework.cloud.gateway.server.mvc.filter.TokenRelayFilterFunctions.tokenRelay;
|
||||
import static org.springframework.cloud.gateway.server.mvc.handler.GatewayRouterFunctions.route;
|
||||
import static org.springframework.cloud.gateway.server.mvc.handler.HandlerFunctions.http;
|
||||
@@ -62,11 +63,12 @@ import static org.springframework.cloud.gateway.server.mvc.handler.HandlerFuncti
|
||||
class RouteConfiguration {
|
||||
|
||||
@Bean
|
||||
public RouterFunction<ServerResponse> gatewayRouterFunctionsAddReqHeader() {
|
||||
return route("resource")
|
||||
.GET("/resource", http("http://localhost:9000"))
|
||||
.filter(tokenRelay())
|
||||
.build();
|
||||
public RouterFunction<ServerResponse> gatewayRouterFunctionsTokenRelay() {
|
||||
return route("resource")
|
||||
.GET("/resource", http())
|
||||
.before(uri("https://localhost:9000"))
|
||||
.filter(tokenRelay())
|
||||
.build();
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
@@ -31,6 +31,7 @@ spring:
|
||||
[source,java]
|
||||
----
|
||||
import java.time.ZonedDateTime;
|
||||
import static org.springframework.cloud.gateway.server.mvc.filter.BeforeFilterFunctions.uri;
|
||||
import static org.springframework.cloud.gateway.server.mvc.handler.GatewayRouterFunctions.route;
|
||||
import static org.springframework.cloud.gateway.server.mvc.handler.HandlerFunctions.http;
|
||||
import static org.springframework.cloud.gateway.server.mvc.predicate.GatewayRequestPredicates.after;
|
||||
@@ -40,9 +41,10 @@ class RouteConfiguration {
|
||||
|
||||
@Bean
|
||||
public RouterFunction<ServerResponse> gatewayRouterFunctionsAfter() {
|
||||
return route("after_route")
|
||||
.route(after(ZonedDateTime.parse("2017-01-20T17:42:47.789-07:00[America/Denver]")), http("https://example.org"))
|
||||
.build();
|
||||
return route("after_route")
|
||||
.route(after(ZonedDateTime.parse("2017-01-20T17:42:47.789-07:00[America/Denver]")), http())
|
||||
.before(uri("https://example.org"))
|
||||
.build();
|
||||
}
|
||||
}
|
||||
----
|
||||
@@ -74,6 +76,7 @@ spring:
|
||||
[source,java]
|
||||
----
|
||||
import java.time.ZonedDateTime;
|
||||
import static org.springframework.cloud.gateway.server.mvc.filter.BeforeFilterFunctions.uri;
|
||||
import static org.springframework.cloud.gateway.server.mvc.handler.GatewayRouterFunctions.route;
|
||||
import static org.springframework.cloud.gateway.server.mvc.handler.HandlerFunctions.http;
|
||||
import static org.springframework.cloud.gateway.server.mvc.predicate.GatewayRequestPredicates.before;
|
||||
@@ -83,9 +86,10 @@ class RouteConfiguration {
|
||||
|
||||
@Bean
|
||||
public RouterFunction<ServerResponse> gatewayRouterFunctionsBefore() {
|
||||
return route("before_route")
|
||||
.route(before(ZonedDateTime.parse("2017-01-20T17:42:47.789-07:00[America/Denver]")), http("https://example.org"))
|
||||
.build();
|
||||
return route("before_route")
|
||||
.route(before(ZonedDateTime.parse("2017-01-20T17:42:47.789-07:00[America/Denver]")), http()
|
||||
.before(uri("https://example.org"))
|
||||
.build();
|
||||
}
|
||||
}
|
||||
----
|
||||
@@ -119,6 +123,7 @@ spring:
|
||||
[source,java]
|
||||
----
|
||||
import java.time.ZonedDateTime;
|
||||
import static org.springframework.cloud.gateway.server.mvc.filter.BeforeFilterFunctions.uri;
|
||||
import static org.springframework.cloud.gateway.server.mvc.handler.GatewayRouterFunctions.route;
|
||||
import static org.springframework.cloud.gateway.server.mvc.handler.HandlerFunctions.http;
|
||||
import static org.springframework.cloud.gateway.server.mvc.predicate.GatewayRequestPredicates.between;
|
||||
@@ -128,9 +133,11 @@ class RouteConfiguration {
|
||||
|
||||
@Bean
|
||||
public RouterFunction<ServerResponse> gatewayRouterFunctionsBetween() {
|
||||
return route("between_route")
|
||||
.route(between(ZonedDateTime.parse("2017-01-20T17:42:47.789-07:00[America/Denver]"), ZonedDateTime.parse("2017-01-21T17:42:47.789-07:00[America/Denver]")), http("https://example.org"))
|
||||
.build();
|
||||
return route("between_route")
|
||||
.route(between(ZonedDateTime.parse("2017-01-20T17:42:47.789-07:00[America/Denver]"),
|
||||
ZonedDateTime.parse("2017-01-21T17:42:47.789-07:00[America/Denver]")), http())
|
||||
.before(uri("https://example.org"))
|
||||
.build();
|
||||
}
|
||||
}
|
||||
----
|
||||
@@ -162,18 +169,20 @@ spring:
|
||||
.GatewaySampleApplication.java
|
||||
[source,java]
|
||||
----
|
||||
import static org.springframework.cloud.gateway.server.mvc.filter.BeforeFilterFunctions.uri;
|
||||
import static org.springframework.cloud.gateway.server.mvc.handler.GatewayRouterFunctions.route;
|
||||
import static org.springframework.cloud.gateway.server.mvc.handler.HandlerFunctions.http;
|
||||
import static org.springframework.cloud.gateway.server.mvc.predicate.GatewayRequestPredicates.between;
|
||||
import static org.springframework.cloud.gateway.server.mvc.predicate.GatewayRequestPredicates.cookie;
|
||||
|
||||
@Configuration
|
||||
class RouteConfiguration {
|
||||
|
||||
@Bean
|
||||
public RouterFunction<ServerResponse> gatewayRouterFunctionsCookie() {
|
||||
return route("cookie_route")
|
||||
.route(cookie("chocolate", "ch.p"), http("https://example.org"))
|
||||
.build();
|
||||
return route("cookie_route")
|
||||
.route(cookie("chocolate", "ch.p"), http())
|
||||
.before(uri("https://example.org"))
|
||||
.build();
|
||||
}
|
||||
}
|
||||
----
|
||||
@@ -204,6 +213,7 @@ spring:
|
||||
.GatewaySampleApplication.java
|
||||
[source,java]
|
||||
----
|
||||
import static org.springframework.cloud.gateway.server.mvc.filter.BeforeFilterFunctions.uri;
|
||||
import static org.springframework.cloud.gateway.server.mvc.handler.GatewayRouterFunctions.route;
|
||||
import static org.springframework.cloud.gateway.server.mvc.handler.HandlerFunctions.http;
|
||||
import static org.springframework.cloud.gateway.server.mvc.predicate.GatewayRequestPredicates.header;
|
||||
@@ -212,10 +222,11 @@ import static org.springframework.cloud.gateway.server.mvc.predicate.GatewayRequ
|
||||
class RouteConfiguration {
|
||||
|
||||
@Bean
|
||||
public RouterFunction<ServerResponse> gatewayRouterFunctionsCookie() {
|
||||
return route("cookie_route")
|
||||
.route(header("X-Request-Id", "\\d+"), http("https://example.org"))
|
||||
.build();
|
||||
public RouterFunction<ServerResponse> gatewayRouterFunctionsHeader() {
|
||||
return route("header_route")
|
||||
.route(header("X-Request-Id", "\\d+"), http())
|
||||
.before(uri("https://example.org"))
|
||||
.build();
|
||||
}
|
||||
}
|
||||
----
|
||||
@@ -247,6 +258,7 @@ spring:
|
||||
.GatewaySampleApplication.java
|
||||
[source,java]
|
||||
----
|
||||
import static org.springframework.cloud.gateway.server.mvc.filter.BeforeFilterFunctions.uri;
|
||||
import static org.springframework.cloud.gateway.server.mvc.handler.GatewayRouterFunctions.route;
|
||||
import static org.springframework.cloud.gateway.server.mvc.handler.HandlerFunctions.http;
|
||||
import static org.springframework.cloud.gateway.server.mvc.predicate.GatewayRequestPredicates.host;
|
||||
@@ -256,9 +268,10 @@ class RouteConfiguration {
|
||||
|
||||
@Bean
|
||||
public RouterFunction<ServerResponse> gatewayRouterFunctionsHost() {
|
||||
return route("host_route")
|
||||
.route(host("**.somehost.org", "**.anotherhost.org"), http("https://example.org"))
|
||||
.build();
|
||||
return route("host_route")
|
||||
.route(host("**.somehost.org", "**.anotherhost.org"), http())
|
||||
.before(uri("https://example.org"))
|
||||
.build();
|
||||
}
|
||||
}
|
||||
----
|
||||
@@ -296,6 +309,7 @@ spring:
|
||||
[source,java]
|
||||
----
|
||||
import org.springframework.http.HttpMethod;
|
||||
import static org.springframework.cloud.gateway.server.mvc.filter.BeforeFilterFunctions.uri;
|
||||
import static org.springframework.cloud.gateway.server.mvc.handler.GatewayRouterFunctions.route;
|
||||
import static org.springframework.cloud.gateway.server.mvc.handler.HandlerFunctions.http;
|
||||
import static org.springframework.cloud.gateway.server.mvc.predicate.GatewayRequestPredicates.method;
|
||||
@@ -305,9 +319,10 @@ class RouteConfiguration {
|
||||
|
||||
@Bean
|
||||
public RouterFunction<ServerResponse> gatewayRouterFunctionsMethod() {
|
||||
return route("method_route")
|
||||
.route(method(HttpMethod.GET, HttpMethod.POST), http("https://example.org"))
|
||||
.build();
|
||||
return route("method_route")
|
||||
.route(method(HttpMethod.GET, HttpMethod.POST), http())
|
||||
.before(uri("https://example.org"))
|
||||
.build();
|
||||
}
|
||||
}
|
||||
----
|
||||
@@ -319,19 +334,19 @@ This route matches if the request method was a `GET` or a `POST`.
|
||||
.GatewaySampleApplication.java
|
||||
[source,java]
|
||||
----
|
||||
import org.springframework.http.HttpMethod;
|
||||
import static org.springframework.cloud.gateway.server.mvc.filter.BeforeFilterFunctions.uri;
|
||||
import static org.springframework.cloud.gateway.server.mvc.handler.GatewayRouterFunctions.route;
|
||||
import static org.springframework.cloud.gateway.server.mvc.handler.HandlerFunctions.http;
|
||||
import static org.springframework.cloud.gateway.server.mvc.predicate.GatewayRequestPredicates.methods;
|
||||
|
||||
@Configuration
|
||||
class RouteConfiguration {
|
||||
|
||||
@Bean
|
||||
public RouterFunction<ServerResponse> gatewayRouterFunctionsMethod() {
|
||||
return route("method_route")
|
||||
.GET("/mypath", http("https://example.org"))
|
||||
.build();
|
||||
public RouterFunction<ServerResponse> gatewayRouterFunctionsMethodAndPath() {
|
||||
return route("method_and_path_route")
|
||||
.GET("/mypath", http())
|
||||
.before(uri("https://example.org"))
|
||||
.build();
|
||||
}
|
||||
}
|
||||
----
|
||||
@@ -363,19 +378,20 @@ spring:
|
||||
.GatewaySampleApplication.java
|
||||
[source,java]
|
||||
----
|
||||
import org.springframework.http.HttpMethod;
|
||||
import static org.springframework.cloud.gateway.server.mvc.filter.BeforeFilterFunctions.uri;
|
||||
import static org.springframework.cloud.gateway.server.mvc.handler.GatewayRouterFunctions.route;
|
||||
import static org.springframework.cloud.gateway.server.mvc.handler.HandlerFunctions.http;
|
||||
import static org.springframework.cloud.gateway.server.mvc.predicate.GatewayRequestPredicates.method;
|
||||
import static org.springframework.cloud.gateway.server.mvc.predicate.GatewayRequestPredicates.path;
|
||||
|
||||
@Configuration
|
||||
class RouteConfiguration {
|
||||
|
||||
@Bean
|
||||
public RouterFunction<ServerResponse> gatewayRouterFunctionsPath() {
|
||||
return route("path_route")
|
||||
.route(path("/red/{segment}", "/blue/{segment}"), http("https://example.org"))
|
||||
.build();
|
||||
return route("path_route")
|
||||
.route(path("/red/{segment}", "/blue/{segment}"), http())
|
||||
.before(uri("https://example.org"))
|
||||
.build();
|
||||
}
|
||||
}
|
||||
----
|
||||
@@ -421,7 +437,7 @@ spring:
|
||||
.GatewaySampleApplication.java
|
||||
[source,java]
|
||||
----
|
||||
import org.springframework.http.HttpMethod;
|
||||
import static org.springframework.cloud.gateway.server.mvc.filter.BeforeFilterFunctions.uri;
|
||||
import static org.springframework.cloud.gateway.server.mvc.handler.GatewayRouterFunctions.route;
|
||||
import static org.springframework.cloud.gateway.server.mvc.handler.HandlerFunctions.http;
|
||||
import static org.springframework.cloud.gateway.server.mvc.predicate.GatewayRequestPredicates.query;
|
||||
@@ -431,9 +447,10 @@ class RouteConfiguration {
|
||||
|
||||
@Bean
|
||||
public RouterFunction<ServerResponse> gatewayRouterFunctionsQuery() {
|
||||
return route("query_route")
|
||||
.route(query("green"), http("https://example.org"))
|
||||
.build();
|
||||
return route("query_route")
|
||||
.route(query("green"), http())
|
||||
.before(uri("https://example.org"))
|
||||
.build();
|
||||
}
|
||||
}
|
||||
----
|
||||
@@ -457,7 +474,7 @@ spring:
|
||||
.GatewaySampleApplication.java
|
||||
[source,java]
|
||||
----
|
||||
import org.springframework.http.HttpMethod;
|
||||
import static org.springframework.cloud.gateway.server.mvc.filter.BeforeFilterFunctions.uri;
|
||||
import static org.springframework.cloud.gateway.server.mvc.handler.GatewayRouterFunctions.route;
|
||||
import static org.springframework.cloud.gateway.server.mvc.handler.HandlerFunctions.http;
|
||||
import static org.springframework.cloud.gateway.server.mvc.predicate.GatewayRequestPredicates.query;
|
||||
@@ -467,9 +484,10 @@ class RouteConfiguration {
|
||||
|
||||
@Bean
|
||||
public RouterFunction<ServerResponse> gatewayRouterFunctionsQuery() {
|
||||
return route("query_route")
|
||||
.route(query("red", "gree."), http("https://example.org"))
|
||||
.build();
|
||||
return route("query_route")
|
||||
.route(query("red", "gree."), http())
|
||||
.before(uri("https://example.org"))
|
||||
.build();
|
||||
}
|
||||
}
|
||||
----
|
||||
@@ -585,22 +603,25 @@ spring:
|
||||
.GatewaySampleApplication.java
|
||||
[source,java]
|
||||
----
|
||||
import org.springframework.http.HttpMethod;
|
||||
import static org.springframework.cloud.gateway.server.mvc.filter.BeforeFilterFunctions.uri;
|
||||
import static org.springframework.cloud.gateway.server.mvc.handler.GatewayRouterFunctions.route;
|
||||
import static org.springframework.cloud.gateway.server.mvc.handler.HandlerFunctions.http;
|
||||
import static org.springframework.cloud.gateway.server.mvc.predicate.GatewayRequestPredicates.method;
|
||||
import static org.springframework.cloud.gateway.server.mvc.predicate.GatewayRequestPredicates.path;
|
||||
import static org.springframework.cloud.gateway.server.mvc.predicate.GatewayRequestPredicates.weight;
|
||||
|
||||
@Configuration
|
||||
class RouteConfiguration {
|
||||
|
||||
@Bean
|
||||
public RouterFunction<ServerResponse> gatewayRouterFunctionsWeights() {
|
||||
return route("weight_high")
|
||||
.route(weight("group1", 8).and(path("/**")), http("https://weighthigh.org"))
|
||||
.build().and(
|
||||
route("weight_low")
|
||||
.route(weight("group1", 2).and(path("/**")), http("https://weightlow.org"))
|
||||
.build());
|
||||
return route("weight_high")
|
||||
.route(weight("group1", 8).and(path("/**")), http())
|
||||
.before(uri("https://weighthigh.org"))
|
||||
.build().and(
|
||||
route("weight_low")
|
||||
.route(weight("group1", 2).and(path("/**")), http())
|
||||
.before(uri("https://weightlow.org"))
|
||||
.build());
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
@@ -9,12 +9,15 @@ A https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springfra
|
||||
[source,java]
|
||||
----
|
||||
import static org.springframework.web.servlet.function.RouterFunctions.route;
|
||||
import static org.springframework.cloud.gateway.server.mvc.filter.BeforeFilterFunctions.uri;
|
||||
import static org.springframework.cloud.gateway.server.mvc.handler.HandlerFunctions.http;
|
||||
|
||||
class SimpleGateway {
|
||||
@Bean
|
||||
public RouterFunction<ServerResponse> getRoute() {
|
||||
return route().GET("/get", http("https://httpbin.org")).build();
|
||||
return route().GET("/get", http())
|
||||
.before(uri("https://example.org"))
|
||||
.build();
|
||||
}
|
||||
}
|
||||
----
|
||||
@@ -29,13 +32,16 @@ Some advanced filters require some metadata to be added to request attributes. T
|
||||
.GatewaySampleApplication.java
|
||||
[source,java]
|
||||
----
|
||||
import static org.springframework.cloud.gateway.server.mvc.filter.BeforeFilterFunctions.uri;
|
||||
import static org.springframework.cloud.gateway.server.mvc.handler.GatewayRouterFunctions.route;
|
||||
import static org.springframework.cloud.gateway.server.mvc.handler.HandlerFunctions.http;
|
||||
|
||||
class SimpleGateway {
|
||||
@Bean
|
||||
public RouterFunction<ServerResponse> getRoute() {
|
||||
return route("simple_route").GET("/get", http("https://httpbin.org")).build();
|
||||
return route("simple_route").GET("/get", http())
|
||||
.before(uri("https://example.org"))
|
||||
.build();
|
||||
}
|
||||
}
|
||||
----
|
||||
@@ -43,4 +49,6 @@ class SimpleGateway {
|
||||
[[gateway-handlerfunctions]]
|
||||
== Gateway MVC Handler Functions
|
||||
|
||||
Various `RouterFunctions.Builder` methods require a `HandlerFunction<ServerResponse>`. To create a route that is proxied by the MVC Gateway, `HandlerFunction` implementations are supplied in `org.springframework.cloud.gateway.server.mvc.handler.HandlerFunctions`. The most basic is the `http()` `HandlerFunction`. If a `URI` is supplied as a parameter, that is the `URI` used as the downstream target for sending the HTTP requests (as seen in the example above). If no parameter is passed, the function looks for a `URI` in the `org.springframework.cloud.gateway.server.mvc.common.MvcUtils.GATEWAY_REQUEST_URL_ATTR` request attribute. This allows for dynamic targets such as load balancing to set the `URI`.
|
||||
Various `RouterFunctions.Builder` methods require a `HandlerFunction<ServerResponse>`. To create a route that is proxied by the MVC Gateway, `HandlerFunction` implementations are supplied in `org.springframework.cloud.gateway.server.mvc.handler.HandlerFunctions`. The most basic is the `http()` `HandlerFunction`. The function looks for a `URI` in the `org.springframework.cloud.gateway.server.mvc.common.MvcUtils.GATEWAY_REQUEST_URL_ATTR` request attribute. This allows for dynamic targets such as load balancing to set the `URI`.
|
||||
|
||||
WARNING: As of version 4.1.7, `HandlerFunctions.http(String)` and `HandlerFunctions.http(URI)` are now deprecated. Please use `HandlerFunctions.http()` in combination with the `BeforeFilterFunctions.uri()` filter instead. This fixes inconsistencies in dealing with the route url request attribute.
|
||||
@@ -48,6 +48,7 @@ To use our new `headerExists` `RequestPredicate`, we need to plug it in to an ap
|
||||
[source,java]
|
||||
----
|
||||
import static SampleRequestPredicates.headerExists;
|
||||
import static org.springframework.cloud.gateway.server.mvc.filter.BeforeFilterFunctions.uri;
|
||||
import static org.springframework.cloud.gateway.server.mvc.handler.GatewayRouterFunctions.route;
|
||||
import static org.springframework.cloud.gateway.server.mvc.handler.HandlerFunctions.http;
|
||||
|
||||
@@ -56,9 +57,10 @@ class RouteConfiguration {
|
||||
|
||||
@Bean
|
||||
public RouterFunction<ServerResponse> headerExistsRoute() {
|
||||
return route("header_exists_route")
|
||||
.route(headerExists("X-Green"), http("https://example.org"))
|
||||
.build();
|
||||
return route("header_exists_route")
|
||||
.route(headerExists("X-Green"), http())
|
||||
.before(uri("https://example.org"))
|
||||
.build();
|
||||
}
|
||||
}
|
||||
----
|
||||
@@ -111,6 +113,7 @@ First, a new `ServerRequest` is created from the existing request. This allows u
|
||||
[source,java]
|
||||
----
|
||||
import static SampleHandlerFilterFunctions.instrument;
|
||||
import static org.springframework.cloud.gateway.server.mvc.filter.BeforeFilterFunctions.uri;
|
||||
import static org.springframework.cloud.gateway.server.mvc.handler.GatewayRouterFunctions.route;
|
||||
import static org.springframework.cloud.gateway.server.mvc.handler.HandlerFunctions.http;
|
||||
|
||||
@@ -120,9 +123,10 @@ class RouteConfiguration {
|
||||
@Bean
|
||||
public RouterFunction<ServerResponse> instrumentRoute() {
|
||||
return route("instrument_route")
|
||||
.GET("/**", http("https://example.org"))
|
||||
.filter(instrument("X-Request-Id", "X-Response-Id"))
|
||||
.build();
|
||||
.GET("/**", http())
|
||||
.filter(instrument("X-Request-Id", "X-Response-Id"))
|
||||
.before(uri("https://example.org"))
|
||||
.build();
|
||||
}
|
||||
}
|
||||
----
|
||||
@@ -160,6 +164,7 @@ A new `ServerRequest` is created from the existing request. This allows us to ad
|
||||
[source,java]
|
||||
----
|
||||
import static SampleBeforeFilterFunctions.instrument;
|
||||
import static org.springframework.cloud.gateway.server.mvc.filter.BeforeFilterFunctions.uri;
|
||||
import static org.springframework.cloud.gateway.server.mvc.handler.GatewayRouterFunctions.route;
|
||||
import static org.springframework.cloud.gateway.server.mvc.handler.HandlerFunctions.http;
|
||||
|
||||
@@ -168,10 +173,10 @@ class RouteConfiguration {
|
||||
|
||||
@Bean
|
||||
public RouterFunction<ServerResponse> instrumentRoute() {
|
||||
return route("instrument_route")
|
||||
.GET("/**", http("https://example.org"))
|
||||
.before(instrument("X-Request-Id"))
|
||||
.build();
|
||||
return route("instrument_route").GET("/**", http())
|
||||
.before(uri("https://example.org"))
|
||||
.before(instrument("X-Request-Id"))
|
||||
.build();
|
||||
}
|
||||
}
|
||||
----
|
||||
@@ -213,6 +218,7 @@ In this case we simply add the header to the response and return it.
|
||||
[source,java]
|
||||
----
|
||||
import static SampleAfterFilterFunctions.instrument;
|
||||
import static org.springframework.cloud.gateway.server.mvc.filter.BeforeFilterFunctions.uri;
|
||||
import static org.springframework.cloud.gateway.server.mvc.handler.GatewayRouterFunctions.route;
|
||||
import static org.springframework.cloud.gateway.server.mvc.handler.HandlerFunctions.http;
|
||||
|
||||
@@ -221,10 +227,11 @@ class RouteConfiguration {
|
||||
|
||||
@Bean
|
||||
public RouterFunction<ServerResponse> instrumentRoute() {
|
||||
return route("instrument_route")
|
||||
.GET("/**", http("https://example.org"))
|
||||
.after(instrument("X-Response-Id"))
|
||||
.build();
|
||||
return route("instrument_route")
|
||||
.GET("/**", http())
|
||||
.before(uri("https://example.org"))
|
||||
.after(instrument("X-Response-Id"))
|
||||
.build();
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
@@ -39,7 +39,6 @@ import org.springframework.boot.context.properties.source.ConfigurationPropertyS
|
||||
import org.springframework.boot.context.properties.source.MapConfigurationPropertySource;
|
||||
import org.springframework.cloud.gateway.server.mvc.common.Configurable;
|
||||
import org.springframework.cloud.gateway.server.mvc.common.MvcUtils;
|
||||
import org.springframework.cloud.gateway.server.mvc.filter.BeforeFilterFunctions;
|
||||
import org.springframework.cloud.gateway.server.mvc.filter.FilterDiscoverer;
|
||||
import org.springframework.cloud.gateway.server.mvc.handler.HandlerDiscoverer;
|
||||
import org.springframework.cloud.gateway.server.mvc.invoke.InvocationContext;
|
||||
@@ -150,15 +149,6 @@ public class RouterFunctionHolderFactory {
|
||||
|
||||
RouterFunctions.Builder builder = route(routeId);
|
||||
|
||||
// MVC.fn users won't need this anonymous filter as url will be set directly.
|
||||
// Put this function first, so if a filter from a handler changes the url
|
||||
// it is after this one.
|
||||
builder.filter((request, next) -> {
|
||||
MvcUtils.setRequestUrl(request, routeProperties.getUri());
|
||||
return next.handle(request);
|
||||
});
|
||||
builder.before(BeforeFilterFunctions.routeId(routeId));
|
||||
|
||||
MultiValueMap<String, OperationMethod> handlerOperations = handlerDiscoverer.getOperations();
|
||||
// TODO: cache?
|
||||
// translate handlerFunction
|
||||
@@ -181,13 +171,15 @@ public class RouterFunctionHolderFactory {
|
||||
HandlerFunction<ServerResponse> handlerFunction = null;
|
||||
|
||||
// filters added by HandlerDiscoverer need to go last, so save them
|
||||
List<HandlerFilterFunction<ServerResponse, ServerResponse>> handlerFilterFunctionFilters = new ArrayList<>();
|
||||
List<HandlerFilterFunction<ServerResponse, ServerResponse>> lowerPrecedenceFilters = new ArrayList<>();
|
||||
List<HandlerFilterFunction<ServerResponse, ServerResponse>> higherPrecedenceFilters = new ArrayList<>();
|
||||
if (response instanceof HandlerFunction<?>) {
|
||||
handlerFunction = (HandlerFunction<ServerResponse>) response;
|
||||
}
|
||||
else if (response instanceof HandlerDiscoverer.Result result) {
|
||||
handlerFunction = result.getHandlerFunction();
|
||||
handlerFilterFunctionFilters.addAll(result.getFilters());
|
||||
lowerPrecedenceFilters.addAll(result.getLowerPrecedenceFilters());
|
||||
higherPrecedenceFilters.addAll(result.getHigherPrecedenceFilters());
|
||||
}
|
||||
if (handlerFunction == null) {
|
||||
throw new IllegalStateException(
|
||||
@@ -218,6 +210,9 @@ public class RouterFunctionHolderFactory {
|
||||
builder.route(predicate.get(), handlerFunction);
|
||||
predicate.set(null);
|
||||
|
||||
// HandlerDiscoverer filters needing lower priority, so put them first
|
||||
lowerPrecedenceFilters.forEach(builder::filter);
|
||||
|
||||
// translate filters
|
||||
MultiValueMap<String, OperationMethod> filterOperations = filterDiscoverer.getOperations();
|
||||
routeProperties.getFilters().forEach(filterProperties -> {
|
||||
@@ -226,7 +221,7 @@ public class RouterFunctionHolderFactory {
|
||||
});
|
||||
|
||||
// HandlerDiscoverer filters need higher priority, so put them last
|
||||
handlerFilterFunctionFilters.forEach(builder::filter);
|
||||
higherPrecedenceFilters.forEach(builder::filter);
|
||||
|
||||
builder.withAttribute(MvcUtils.GATEWAY_ROUTE_ID_ATTR, routeId);
|
||||
|
||||
|
||||
@@ -196,7 +196,6 @@ public abstract class BeforeFilterFunctions {
|
||||
String newPath = uri.getRawPath() + request.uri().getRawPath();
|
||||
|
||||
URI prefixedUri = UriComponentsBuilder.fromUri(request.uri()).replacePath(newPath).build().toUri();
|
||||
MvcUtils.setRequestUrl(request, prefixedUri);
|
||||
return ServerRequest.from(request).uri(prefixedUri).build();
|
||||
};
|
||||
}
|
||||
@@ -340,7 +339,6 @@ public abstract class BeforeFilterFunctions {
|
||||
|
||||
ServerRequest modified = ServerRequest.from(request).uri(rewrittenUri).build();
|
||||
|
||||
MvcUtils.setRequestUrl(request, rewrittenUri);
|
||||
return modified;
|
||||
};
|
||||
}
|
||||
@@ -361,7 +359,6 @@ public abstract class BeforeFilterFunctions {
|
||||
URI uri = uriTemplate.expand(uriVariables);
|
||||
|
||||
URI newUri = UriComponentsBuilder.fromUri(request.uri()).replacePath(uri.getRawPath()).build(true).toUri();
|
||||
MvcUtils.setRequestUrl(request, newUri);
|
||||
return ServerRequest.from(request).uri(newUri).build();
|
||||
};
|
||||
}
|
||||
@@ -419,12 +416,22 @@ public abstract class BeforeFilterFunctions {
|
||||
.replacePath(newPath.toString())
|
||||
.build(true)
|
||||
.toUri();
|
||||
MvcUtils.setRequestUrl(request, prefixedUri);
|
||||
|
||||
return ServerRequest.from(request).uri(prefixedUri).build();
|
||||
};
|
||||
}
|
||||
|
||||
public static Function<ServerRequest, ServerRequest> uri(String uri) {
|
||||
return uri(URI.create(uri));
|
||||
}
|
||||
|
||||
public static Function<ServerRequest, ServerRequest> uri(URI uri) {
|
||||
return request -> {
|
||||
MvcUtils.setRequestUrl(request, uri);
|
||||
return request;
|
||||
};
|
||||
}
|
||||
|
||||
public static class FallbackHeadersConfig {
|
||||
|
||||
private String executionExceptionTypeHeaderName = CB_EXECUTION_EXCEPTION_TYPE;
|
||||
|
||||
@@ -228,6 +228,15 @@ public interface FilterFunctions {
|
||||
return ofResponseProcessor(AfterFilterFunctions.setStatus(statusCode));
|
||||
}
|
||||
|
||||
static HandlerFilterFunction<ServerResponse, ServerResponse> uri(String uri) {
|
||||
return ofRequestProcessor(BeforeFilterFunctions.uri(uri));
|
||||
}
|
||||
|
||||
@Shortcut
|
||||
static HandlerFilterFunction<ServerResponse, ServerResponse> uri(URI uri) {
|
||||
return ofRequestProcessor(BeforeFilterFunctions.uri(uri));
|
||||
}
|
||||
|
||||
class FilterSupplier extends SimpleFilterSupplier {
|
||||
|
||||
public FilterSupplier() {
|
||||
|
||||
@@ -40,7 +40,7 @@ public class LoadBalancerHandlerSupplier implements HandlerSupplier {
|
||||
|
||||
public static HandlerDiscoverer.Result lb(URI uri) {
|
||||
// TODO: how to do something other than http
|
||||
return new HandlerDiscoverer.Result(HandlerFunctions.http(),
|
||||
return new HandlerDiscoverer.Result(HandlerFunctions.http(), Collections.emptyList(),
|
||||
Collections.singletonList(LoadBalancerFilterFunctions.lb(uri.getHost())));
|
||||
}
|
||||
|
||||
|
||||
@@ -400,7 +400,7 @@ public class XForwardedRequestHeadersFilter implements HttpHeadersFilter.Request
|
||||
|
||||
LinkedHashSet<URI> originalUris = MvcUtils.getAttribute(request,
|
||||
MvcUtils.GATEWAY_ORIGINAL_REQUEST_URL_ATTR);
|
||||
URI requestUri = MvcUtils.getAttribute(request, MvcUtils.GATEWAY_REQUEST_URL_ATTR);
|
||||
URI requestUri = request.uri();
|
||||
|
||||
if (originalUris != null && requestUri != null) {
|
||||
|
||||
|
||||
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
* Copyright 2013-2025 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.server.mvc.handler;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.net.URI;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
|
||||
import org.springframework.cloud.gateway.server.mvc.common.MvcUtils;
|
||||
import org.springframework.cloud.gateway.server.mvc.config.RouteProperties;
|
||||
import org.springframework.web.servlet.function.HandlerFilterFunction;
|
||||
import org.springframework.web.servlet.function.HandlerFunction;
|
||||
import org.springframework.web.servlet.function.ServerResponse;
|
||||
|
||||
class DefaultHandlerSupplier implements HandlerSupplier {
|
||||
|
||||
@Override
|
||||
public Collection<Method> get() {
|
||||
return Arrays.asList(getClass().getMethods());
|
||||
}
|
||||
|
||||
public static HandlerDiscoverer.Result forward(RouteProperties routeProperties) {
|
||||
return forward(routeProperties.getId(), routeProperties.getUri());
|
||||
}
|
||||
|
||||
public static HandlerDiscoverer.Result forward(String id, URI uri) {
|
||||
return new HandlerDiscoverer.Result(HandlerFunctions.forward(uri.getPath()), Collections.emptyList());
|
||||
}
|
||||
|
||||
public static HandlerDiscoverer.Result http(RouteProperties routeProperties) {
|
||||
return http(routeProperties.getId(), routeProperties.getUri());
|
||||
}
|
||||
|
||||
public static HandlerDiscoverer.Result http(String id, URI uri) {
|
||||
HandlerFunction<ServerResponse> http = HandlerFunctions.http();
|
||||
return getResult(id, uri, http);
|
||||
}
|
||||
|
||||
public static HandlerDiscoverer.Result https(RouteProperties routeProperties) {
|
||||
return https(routeProperties.getId(), routeProperties.getUri());
|
||||
}
|
||||
|
||||
public static HandlerDiscoverer.Result https(String id, URI uri) {
|
||||
return getResult(id, uri, HandlerFunctions.https());
|
||||
}
|
||||
|
||||
public static HandlerDiscoverer.Result no(RouteProperties routeProperties) {
|
||||
return no(routeProperties.getId(), routeProperties.getUri());
|
||||
}
|
||||
|
||||
public static HandlerDiscoverer.Result no(String id, URI uri) {
|
||||
return getResult(id, uri, HandlerFunctions.no());
|
||||
}
|
||||
|
||||
private static HandlerDiscoverer.Result getResult(String id, URI uri,
|
||||
HandlerFunction<ServerResponse> handlerFunction) {
|
||||
HandlerFilterFunction<ServerResponse, ServerResponse> setId = setIdFilter(id);
|
||||
HandlerFilterFunction<ServerResponse, ServerResponse> setRequest = setRequestUrlFilter(uri);
|
||||
return new HandlerDiscoverer.Result(handlerFunction, Arrays.asList(setId, setRequest), Collections.emptyList());
|
||||
}
|
||||
|
||||
private static HandlerFilterFunction<ServerResponse, ServerResponse> setIdFilter(String id) {
|
||||
return (request, next) -> {
|
||||
MvcUtils.setRouteId(request, id);
|
||||
return next.handle(request);
|
||||
};
|
||||
}
|
||||
|
||||
private static HandlerFilterFunction<ServerResponse, ServerResponse> setRequestUrlFilter(URI uri) {
|
||||
return (request, next) -> {
|
||||
MvcUtils.setRequestUrl(request, uri);
|
||||
return next.handle(request);
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
@@ -37,20 +37,39 @@ public class HandlerDiscoverer extends AbstractGatewayDiscoverer {
|
||||
|
||||
private final HandlerFunction<ServerResponse> handlerFunction;
|
||||
|
||||
private final List<HandlerFilterFunction<ServerResponse, ServerResponse>> filters;
|
||||
private final List<HandlerFilterFunction<ServerResponse, ServerResponse>> lowerPrecedenceFilters;
|
||||
|
||||
private final List<HandlerFilterFunction<ServerResponse, ServerResponse>> higherPrecedenceFilters;
|
||||
|
||||
@Deprecated
|
||||
public Result(HandlerFunction<ServerResponse> handlerFunction,
|
||||
List<HandlerFilterFunction<ServerResponse, ServerResponse>> filters) {
|
||||
this(handlerFunction, Collections.emptyList(), filters);
|
||||
}
|
||||
|
||||
public Result(HandlerFunction<ServerResponse> handlerFunction,
|
||||
List<HandlerFilterFunction<ServerResponse, ServerResponse>> lowerPrecedenceFilters,
|
||||
List<HandlerFilterFunction<ServerResponse, ServerResponse>> higherPrecedenceFilters) {
|
||||
this.handlerFunction = handlerFunction;
|
||||
this.filters = Objects.requireNonNullElse(filters, Collections.emptyList());
|
||||
this.lowerPrecedenceFilters = Objects.requireNonNullElse(lowerPrecedenceFilters, Collections.emptyList());
|
||||
this.higherPrecedenceFilters = Objects.requireNonNullElse(higherPrecedenceFilters, Collections.emptyList());
|
||||
}
|
||||
|
||||
public HandlerFunction<ServerResponse> getHandlerFunction() {
|
||||
return handlerFunction;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public List<HandlerFilterFunction<ServerResponse, ServerResponse>> getFilters() {
|
||||
return filters;
|
||||
return getHigherPrecedenceFilters();
|
||||
}
|
||||
|
||||
public List<HandlerFilterFunction<ServerResponse, ServerResponse>> getLowerPrecedenceFilters() {
|
||||
return lowerPrecedenceFilters;
|
||||
}
|
||||
|
||||
public List<HandlerFilterFunction<ServerResponse, ServerResponse>> getHigherPrecedenceFilters() {
|
||||
return higherPrecedenceFilters;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -19,8 +19,8 @@ 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.Collections;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
import jakarta.servlet.ServletException;
|
||||
@@ -60,14 +60,17 @@ public abstract class HandlerFunctions {
|
||||
|
||||
// TODO: current discovery only goes by method name
|
||||
// so last one wins, so put parameterless last
|
||||
@Deprecated
|
||||
public static HandlerFunction<ServerResponse> http(String uri) {
|
||||
return http(URI.create(uri));
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public static HandlerFunction<ServerResponse> http(URI uri) {
|
||||
return new LookupProxyExchangeHandlerFunction(uri);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public static HandlerFunction<ServerResponse> https(URI uri) {
|
||||
return new LookupProxyExchangeHandlerFunction(uri);
|
||||
}
|
||||
@@ -86,6 +89,7 @@ public abstract class HandlerFunctions {
|
||||
|
||||
static class LookupProxyExchangeHandlerFunction implements HandlerFunction<ServerResponse> {
|
||||
|
||||
@Deprecated
|
||||
private final URI uri;
|
||||
|
||||
private AtomicReference<ProxyExchangeHandlerFunction> proxyExchangeHandlerFunction = new AtomicReference<>();
|
||||
@@ -94,6 +98,7 @@ public abstract class HandlerFunctions {
|
||||
this.uri = null;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
LookupProxyExchangeHandlerFunction(URI uri) {
|
||||
this.uri = uri;
|
||||
}
|
||||
@@ -101,12 +106,15 @@ public abstract class HandlerFunctions {
|
||||
@Override
|
||||
public ServerResponse handle(ServerRequest serverRequest) {
|
||||
if (uri != null) {
|
||||
// TODO: in 2 places now, here and
|
||||
// GatewayMvcPropertiesBeanDefinitionRegistrar
|
||||
MvcUtils.putAttribute(serverRequest, MvcUtils.GATEWAY_REQUEST_URL_ATTR, uri);
|
||||
// TODO: log warning of deprecated usage
|
||||
MvcUtils.setRequestUrl(serverRequest, uri);
|
||||
}
|
||||
this.proxyExchangeHandlerFunction.compareAndSet(null, lookup(serverRequest));
|
||||
return proxyExchangeHandlerFunction.get().handle(serverRequest);
|
||||
return proxyExchangeHandlerFunction.updateAndGet(function -> {
|
||||
if (function == null) {
|
||||
return lookup(serverRequest);
|
||||
}
|
||||
return function;
|
||||
}).handle(serverRequest);
|
||||
}
|
||||
|
||||
private static ProxyExchangeHandlerFunction lookup(ServerRequest request) {
|
||||
@@ -124,12 +132,13 @@ public abstract class HandlerFunctions {
|
||||
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public static class HandlerSupplier
|
||||
implements org.springframework.cloud.gateway.server.mvc.handler.HandlerSupplier {
|
||||
|
||||
@Override
|
||||
public Collection<Method> get() {
|
||||
return Arrays.asList(HandlerFunctions.class.getMethods());
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ org.springframework.cloud.gateway.server.mvc.filter.FilterSupplier=\
|
||||
org.springframework.cloud.gateway.server.mvc.filter.FilterFunctions.FilterSupplier
|
||||
|
||||
org.springframework.cloud.gateway.server.mvc.handler.HandlerSupplier=\
|
||||
org.springframework.cloud.gateway.server.mvc.handler.HandlerFunctions.HandlerSupplier,\
|
||||
org.springframework.cloud.gateway.server.mvc.handler.DefaultHandlerSupplier,\
|
||||
org.springframework.cloud.gateway.server.mvc.filter.LoadBalancerHandlerSupplier
|
||||
|
||||
org.springframework.cloud.gateway.server.mvc.predicate.PredicateSupplier=\
|
||||
|
||||
@@ -76,6 +76,7 @@ import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.util.LinkedMultiValueMap;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
import org.springframework.util.StreamUtils;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
@@ -107,6 +108,7 @@ import static org.springframework.cloud.gateway.server.mvc.filter.BeforeFilterFu
|
||||
import static org.springframework.cloud.gateway.server.mvc.filter.BeforeFilterFunctions.requestHeaderToRequestUri;
|
||||
import static org.springframework.cloud.gateway.server.mvc.filter.BeforeFilterFunctions.requestSize;
|
||||
import static org.springframework.cloud.gateway.server.mvc.filter.BeforeFilterFunctions.routeId;
|
||||
import static org.springframework.cloud.gateway.server.mvc.filter.BeforeFilterFunctions.uri;
|
||||
import static org.springframework.cloud.gateway.server.mvc.filter.Bucket4jFilterFunctions.rateLimit;
|
||||
import static org.springframework.cloud.gateway.server.mvc.filter.CircuitBreakerFilterFunctions.circuitBreaker;
|
||||
import static org.springframework.cloud.gateway.server.mvc.filter.FilterFunctions.addRequestHeader;
|
||||
@@ -298,7 +300,7 @@ public class ServerMvcIntegrationTests {
|
||||
XForwardedRequestHeadersFilter.X_FORWARDED_FOR_HEADER);
|
||||
assertThat(headers).containsEntry(XForwardedRequestHeadersFilter.X_FORWARDED_PREFIX_HEADER,
|
||||
"/long/path/to");
|
||||
assertThat(headers).containsEntry("X-Test", "stripPrefix");
|
||||
assertThat(headers).containsEntry("X-Test", "stripPrefixLb");
|
||||
});
|
||||
}
|
||||
|
||||
@@ -418,7 +420,8 @@ public class ServerMvcIntegrationTests {
|
||||
public void circuitBreakerInvalidFallbackThrowsException() {
|
||||
// @formatter:off
|
||||
Assertions.assertThatThrownBy(() -> route("testcircuitbreakergatewayfallback")
|
||||
.route(path("/anything/circuitbreakergatewayfallback"), http(URI.create("https://nonexistantdomain.com1234")))
|
||||
.route(path("/anything/circuitbreakergatewayfallback"), http())
|
||||
.before(uri("https://nonexistantdomain.com1234"))
|
||||
.filter(circuitBreaker("mycb2", URI.create("http://example.com")))
|
||||
.build()).isInstanceOf(IllegalArgumentException.class);
|
||||
// @formatter:on
|
||||
@@ -1016,6 +1019,11 @@ public class ServerMvcIntegrationTests {
|
||||
@LoadBalancerClient(name = "httpbin", configuration = TestLoadBalancerConfig.Httpbin.class)
|
||||
protected static class TestConfiguration {
|
||||
|
||||
@Bean
|
||||
StaticPortController staticPortController() {
|
||||
return new StaticPortController();
|
||||
}
|
||||
|
||||
@Bean
|
||||
TestHandler testHandler() {
|
||||
return new TestHandler();
|
||||
@@ -1132,7 +1140,7 @@ public class ServerMvcIntegrationTests {
|
||||
return route("teststripprefix")
|
||||
.route(GET("/long/path/to/get").and(host("**.stripprefixlb.org")), http())
|
||||
.filter(stripPrefix(3))
|
||||
.filter(addRequestHeader("X-Test", "stripPrefix"))
|
||||
.filter(addRequestHeader("X-Test", "stripPrefixLb"))
|
||||
.filter(lb("httpbin"))
|
||||
.build();
|
||||
// @formatter:on
|
||||
@@ -1185,7 +1193,8 @@ public class ServerMvcIntegrationTests {
|
||||
public RouterFunction<ServerResponse> gatewayRouterFunctionsCircuitBreakerFallback() {
|
||||
// @formatter:off
|
||||
return route("testcircuitbreakerfallback")
|
||||
.route(path("/anything/circuitbreakerfallback"), http(URI.create("https://nonexistantdomain.com1234")))
|
||||
.route(path("/anything/circuitbreakerfallback"), http())
|
||||
.before(uri("https://nonexistantdomain.com1234"))
|
||||
.filter(circuitBreaker("mycb1", "/hello"))
|
||||
.build();
|
||||
// @formatter:on
|
||||
@@ -1195,7 +1204,8 @@ public class ServerMvcIntegrationTests {
|
||||
public RouterFunction<ServerResponse> gatewayRouterFunctionsCircuitBreakerFallbackToGatewayRoute() {
|
||||
// @formatter:off
|
||||
return route("testcircuitbreakergatewayfallback")
|
||||
.route(path("/anything/circuitbreakergatewayfallback"), http(URI.create("https://nonexistantdomain.com1234")))
|
||||
.route(path("/anything/circuitbreakergatewayfallback"), http())
|
||||
.before(uri("https://nonexistantdomain.com1234"))
|
||||
.filter(circuitBreaker("mycb2", URI.create("forward:/anything/gatewayfallback")))
|
||||
.build()
|
||||
.and(route("testgatewayfallback")
|
||||
@@ -1686,6 +1696,16 @@ public class ServerMvcIntegrationTests {
|
||||
|
||||
}
|
||||
|
||||
@RestController
|
||||
protected static class StaticPortController {
|
||||
|
||||
@GetMapping(path = "/anything/staticport", produces = MediaType.APPLICATION_JSON_VALUE)
|
||||
public ResponseEntity<?> messageEvents() {
|
||||
return ResponseEntity.status(HttpStatus.NOT_ACCEPTABLE).build();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@RestController
|
||||
protected static class EventController {
|
||||
|
||||
|
||||
@@ -156,6 +156,18 @@ class BeforeFilterFunctionsTests {
|
||||
assertThat(result.uri().toString()).hasToString("http://localhost/depth3");
|
||||
}
|
||||
|
||||
@Test
|
||||
void stripPrefixWithPort() {
|
||||
MockHttpServletRequest servletRequest = MockMvcRequestBuilders.get("http://localhost:77/depth1/depth2/depth3")
|
||||
.buildRequest(null);
|
||||
|
||||
ServerRequest request = ServerRequest.create(servletRequest, Collections.emptyList());
|
||||
|
||||
ServerRequest result = BeforeFilterFunctions.stripPrefix(2).apply(request);
|
||||
|
||||
assertThat(result.uri().toString()).hasToString("http://localhost:77/depth3");
|
||||
}
|
||||
|
||||
@Test
|
||||
void stripPrefixWithEncodedPath() {
|
||||
MockHttpServletRequest servletRequest = MockMvcRequestBuilders.get("http://localhost/depth1/depth2/depth3/é")
|
||||
|
||||
@@ -0,0 +1,141 @@
|
||||
/*
|
||||
* Copyright 2013-2025 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.server.mvc.filter;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.SpringBootConfiguration;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
|
||||
import org.springframework.cloud.gateway.server.mvc.test.HttpbinTestcontainers;
|
||||
import org.springframework.cloud.gateway.server.mvc.test.TestLoadBalancerConfig;
|
||||
import org.springframework.cloud.gateway.server.mvc.test.client.TestRestClient;
|
||||
import org.springframework.cloud.loadbalancer.annotation.LoadBalancerClient;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.test.context.ActiveProfiles;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.servlet.function.RouterFunction;
|
||||
import org.springframework.web.servlet.function.ServerResponse;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.springframework.cloud.gateway.server.mvc.filter.FilterFunctions.stripPrefix;
|
||||
import static org.springframework.cloud.gateway.server.mvc.filter.FilterFunctions.uri;
|
||||
import static org.springframework.cloud.gateway.server.mvc.handler.GatewayRouterFunctions.route;
|
||||
import static org.springframework.cloud.gateway.server.mvc.handler.HandlerFunctions.http;
|
||||
import static org.springframework.cloud.gateway.server.mvc.test.TestUtils.getMap;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@SpringBootTest(properties = {}, webEnvironment = WebEnvironment.RANDOM_PORT)
|
||||
@ActiveProfiles("stripprefixstaticport")
|
||||
@ContextConfiguration(initializers = HttpbinTestcontainers.class)
|
||||
public class StripPrefixStaticPortTests {
|
||||
|
||||
@Autowired
|
||||
TestRestClient restClient;
|
||||
|
||||
@BeforeAll
|
||||
static void beforeAll() {
|
||||
HttpbinTestcontainers.initializeSystemProperties();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void stripPrefixStaticPort() {
|
||||
restClient.get()
|
||||
.uri("/long/path/to/anything/staticport")
|
||||
.exchange()
|
||||
.expectStatus()
|
||||
.isOk()
|
||||
.expectBody(Map.class)
|
||||
.consumeWith(res -> {
|
||||
Map<String, Object> map = res.getResponseBody();
|
||||
Map<String, Object> headers = getMap(map, "headers");
|
||||
assertThat(headers)
|
||||
.containsKeys(XForwardedRequestHeadersFilter.X_FORWARDED_PREFIX_HEADER,
|
||||
XForwardedRequestHeadersFilter.X_FORWARDED_HOST_HEADER,
|
||||
XForwardedRequestHeadersFilter.X_FORWARDED_PORT_HEADER,
|
||||
XForwardedRequestHeadersFilter.X_FORWARDED_PROTO_HEADER,
|
||||
XForwardedRequestHeadersFilter.X_FORWARDED_FOR_HEADER)
|
||||
.containsEntry(XForwardedRequestHeadersFilter.X_FORWARDED_PREFIX_HEADER, "/long/path/to");
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void stripPrefixStaticPortDsl() {
|
||||
restClient.get()
|
||||
.uri("/long/path/to/anything/staticportdsl")
|
||||
.exchange()
|
||||
.expectStatus()
|
||||
.isOk()
|
||||
.expectBody(Map.class)
|
||||
.consumeWith(res -> {
|
||||
Map<String, Object> map = res.getResponseBody();
|
||||
Map<String, Object> headers = getMap(map, "headers");
|
||||
assertThat(headers)
|
||||
.containsKeys(XForwardedRequestHeadersFilter.X_FORWARDED_PREFIX_HEADER,
|
||||
XForwardedRequestHeadersFilter.X_FORWARDED_HOST_HEADER,
|
||||
XForwardedRequestHeadersFilter.X_FORWARDED_PORT_HEADER,
|
||||
XForwardedRequestHeadersFilter.X_FORWARDED_PROTO_HEADER,
|
||||
XForwardedRequestHeadersFilter.X_FORWARDED_FOR_HEADER)
|
||||
.containsEntry(XForwardedRequestHeadersFilter.X_FORWARDED_PREFIX_HEADER, "/long/path/to");
|
||||
});
|
||||
}
|
||||
|
||||
@SpringBootConfiguration
|
||||
@EnableAutoConfiguration
|
||||
@LoadBalancerClient(name = "httpbin", configuration = TestLoadBalancerConfig.Httpbin.class)
|
||||
protected static class TestConfiguration {
|
||||
|
||||
@Bean
|
||||
StaticPortController staticPortController() {
|
||||
return new StaticPortController();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public RouterFunction<ServerResponse> gatewayRouterFunctionsStripPrefixStaticPortDsl(Environment env) {
|
||||
// @formatter:off
|
||||
return route("teststripprefixstaticportdsl")
|
||||
.GET("/long/path/to/anything/staticportdsl", http())
|
||||
.filter(uri(env.getProperty("strip.prefix.static.uri")))
|
||||
.filter(stripPrefix(3))
|
||||
.build();
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@RestController
|
||||
protected static class StaticPortController {
|
||||
|
||||
@GetMapping(path = "/anything/staticport", produces = MediaType.APPLICATION_JSON_VALUE)
|
||||
public ResponseEntity<?> messageEvents() {
|
||||
return ResponseEntity.status(HttpStatus.NOT_ACCEPTABLE).build();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -18,8 +18,6 @@ package org.springframework.cloud.gateway.server.mvc.test;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.testcontainers.containers.GenericContainer;
|
||||
import org.testcontainers.containers.wait.strategy.HttpWaitStrategy;
|
||||
import org.testcontainers.utility.DockerImageName;
|
||||
@@ -35,8 +33,6 @@ public class HttpbinTestcontainers implements ApplicationContextInitializer<Conf
|
||||
// https://hub.docker.com/r/mccutchen/go-httpbin
|
||||
private static final DockerImageName DEFAULT_IMAGE_NAME = DockerImageName.parse("mccutchen/go-httpbin");
|
||||
|
||||
static final Logger logger = LoggerFactory.getLogger(HttpbinTestcontainers.class);
|
||||
|
||||
/**
|
||||
* Default httpbin port.
|
||||
*/
|
||||
@@ -59,7 +55,6 @@ public class HttpbinTestcontainers implements ApplicationContextInitializer<Conf
|
||||
MutablePropertySources sources = context.getEnvironment().getPropertySources();
|
||||
|
||||
if (!sources.contains("httpbinTestcontainer")) {
|
||||
boolean running = container.isRunning();
|
||||
Integer mappedPort = container.getMappedPort(DEFAULT_PORT);
|
||||
HashMap<String, Object> map = new HashMap<>();
|
||||
map.put("httpbin.port", String.valueOf(mappedPort));
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
strip.prefix.static.uri: http://${httpbin.host}:${httpbin.port}
|
||||
spring.cloud.gateway.mvc:
|
||||
routes:
|
||||
- id: strip_prefix_static_port_config
|
||||
uri: ${strip.prefix.static.uri}
|
||||
predicates:
|
||||
- Path=/long/path/to/anything/staticport
|
||||
filters:
|
||||
- StripPrefix=3
|
||||
logging:
|
||||
level:
|
||||
org.springframework.cloud.gateway.server.mvc: TRACE
|
||||
Reference in New Issue
Block a user