diff --git a/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/filters/addrequestheader.adoc b/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/filters/addrequestheader.adoc index d189f531..0b0921a1 100644 --- a/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/filters/addrequestheader.adoc +++ b/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/filters/addrequestheader.adoc @@ -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 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 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}")); } } ---- diff --git a/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/filters/addrequestheadersifnotpresent.adoc b/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/filters/addrequestheadersifnotpresent.adoc index b4455a6b..fda40278 100644 --- a/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/filters/addrequestheadersifnotpresent.adoc +++ b/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/filters/addrequestheadersifnotpresent.adoc @@ -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 gatewayRouterFunctionsAddReqHeader() { - return route(GET("/red"), http("https://example.org")) - .before(addRequestHeadersIfNotPresent("X-Request-Color-1:blue","X-Request-Color-2:green")); + public RouterFunction 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 gatewayRouterFunctionsAddReqHeader() { - return route(GET("/red/{segment}"), http("https://example.org")) - .before(addRequestHeadersIfNotPresent("X-Request-red", "blue-{segment}")); + public RouterFunction 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} diff --git a/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/filters/addrequestparameter.adoc b/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/filters/addrequestparameter.adoc index 6ce332b4..53d306ad 100644 --- a/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/filters/addrequestparameter.adoc +++ b/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/filters/addrequestparameter.adoc @@ -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 gatewayRouterFunctionsAddReqHeader() { - return route("add_request_parameter_route") - .GET("/anything/addrequestparam", http("https://example.org")) - .before(addRequestParameter("red", "blue")) - .build(); + public RouterFunction 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 gatewayRouterFunctionsAddReqHeader() { - return route("add_request_parameter_route") - .route(host("{segment}.myhost.org"), http("https://example.org")) - .before(addRequestParameter("foo", "bar-{segment}")) - .build(); + public RouterFunction gatewayRouterFunctionsAddReqParameter() { + return route("add_request_parameter_route") + .route(host("{segment}.myhost.org"), http()) + .before(uri("https://example.org")) + .before(addRequestParameter("foo", "bar-{segment}")) + .build(); } } ---- \ No newline at end of file diff --git a/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/filters/addresponseheader.adoc b/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/filters/addresponseheader.adoc index e04ed408..0c678abd 100644 --- a/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/filters/addresponseheader.adoc +++ b/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/filters/addresponseheader.adoc @@ -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 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 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(); } } ---- diff --git a/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/filters/circuitbreaker-filter.adoc b/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/filters/circuitbreaker-filter.adoc index 8ec00ffd..8a1a50c8 100644 --- a/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/filters/circuitbreaker-filter.adoc +++ b/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/filters/circuitbreaker-filter.adoc @@ -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 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 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 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()); } } diff --git a/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/filters/deduperesponseheader.adoc b/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/filters/deduperesponseheader.adoc index 9659f2cf..5f8a7a23 100644 --- a/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/filters/deduperesponseheader.adoc +++ b/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/filters/deduperesponseheader.adoc @@ -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 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(); } diff --git a/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/filters/fallback-headers.adoc b/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/filters/fallback-headers.adoc index 22f4114b..300276ac 100644 --- a/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/filters/fallback-headers.adoc +++ b/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/filters/fallback-headers.adoc @@ -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()); } diff --git a/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/filters/maprequestheader.adoc b/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/filters/maprequestheader.adoc index 2f8f30b6..e85d08b9 100644 --- a/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/filters/maprequestheader.adoc +++ b/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/filters/maprequestheader.adoc @@ -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 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(); } diff --git a/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/filters/modifyrequestbody.adoc b/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/filters/modifyrequestbody.adoc index 963b26f0..a18dbff1 100644 --- a/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/filters/modifyrequestbody.adoc +++ b/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/filters/modifyrequestbody.adoc @@ -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 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 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) { } diff --git a/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/filters/modifyresponsebody.adoc b/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/filters/modifyresponsebody.adoc index eacfd095..b7bd7163 100644 --- a/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/filters/modifyresponsebody.adoc +++ b/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/filters/modifyresponsebody.adoc @@ -23,6 +23,7 @@ public RouterFunction gatewayRouterFunctionsModifyResponseBodySi [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 +33,13 @@ import org.springframework.http.MediaType; class RouteConfiguration { @Bean - public RouterFunction 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, response, s) -> s.toUpperCase())) - .build(); + public RouterFunction 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(); } } diff --git a/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/filters/prefixpath.adoc b/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/filters/prefixpath.adoc index 5bc8b5e8..5a4d1343 100644 --- a/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/filters/prefixpath.adoc +++ b/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/filters/prefixpath.adoc @@ -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 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(); } } ---- diff --git a/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/filters/preservehostheader.adoc b/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/filters/preservehostheader.adoc index 518c0ac3..462cf01f 100644 --- a/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/filters/preservehostheader.adoc +++ b/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/filters/preservehostheader.adoc @@ -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 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(); } } ---- diff --git a/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/filters/ratelimiter.adoc b/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/filters/ratelimiter.adoc index cfde996c..7fa31982 100644 --- a/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/filters/ratelimiter.adoc +++ b/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/filters/ratelimiter.adoc @@ -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 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(); } } ---- diff --git a/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/filters/redirectto.adoc b/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/filters/redirectto.adoc index f1816d36..69f2d538 100644 --- a/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/filters/redirectto.adoc +++ b/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/filters/redirectto.adoc @@ -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 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(); } } ---- diff --git a/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/filters/removerequestheader.adoc b/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/filters/removerequestheader.adoc index c85e8d9a..03150906 100644 --- a/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/filters/removerequestheader.adoc +++ b/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/filters/removerequestheader.adoc @@ -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 gatewayRouterFunctionsremoveRequestHeader() { - return route("removerequestheader_route") - .GET("/**", http("https://example.org")) - .before(removeRequestHeader("X-Request-Foo")) - .build(); + public RouterFunction gatewayRouterFunctionsRemoveRequestHeader() { + return route("removerequestheader_route") + .GET("/**", http()) + .before(uri("https://example.org")) + .before(removeRequestHeader("X-Request-Foo")) + .build(); } } ---- diff --git a/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/filters/removerequestparameter.adoc b/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/filters/removerequestparameter.adoc index 5ff79940..e60eaa9d 100644 --- a/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/filters/removerequestparameter.adoc +++ b/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/filters/removerequestparameter.adoc @@ -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 gatewayRouterFunctionsAddReqHeader() { - return route("removerequestparameter_route") - .GET("/**", http("https://example.org")) - .before(removeRequestParameter("red")) - .build(); + public RouterFunction gatewayRouterFunctionsRemoveRequestParameter() { + return route("removerequestparameter_route") + .GET("/**", http()) + .before(uri("https://example.org")) + .before(removeRequestParameter("red")) + .build(); } } ---- diff --git a/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/filters/removeresponseheader.adoc b/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/filters/removeresponseheader.adoc index fda397b1..d767aba0 100644 --- a/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/filters/removeresponseheader.adoc +++ b/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/filters/removeresponseheader.adoc @@ -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 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(); } } diff --git a/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/filters/requestheadersize.adoc b/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/filters/requestheadersize.adoc index 5f8f4066..e94b2ff0 100644 --- a/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/filters/requestheadersize.adoc +++ b/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/filters/requestheadersize.adoc @@ -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 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(); } } ---- diff --git a/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/filters/requestsize.adoc b/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/filters/requestsize.adoc index 29135ea8..7eb84314 100644 --- a/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/filters/requestsize.adoc +++ b/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/filters/requestsize.adoc @@ -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 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(); } } ---- diff --git a/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/filters/retry.adoc b/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/filters/retry.adoc index 9bf2bf99..ab8d3fa6 100644 --- a/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/filters/retry.adoc +++ b/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/filters/retry.adoc @@ -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 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 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(); } } ---- @@ -79,11 +84,11 @@ Instead, it should throw an `Exception` or signal an error (for example, through NOTE: When using the retry filter, it will retry all filters that come after it. Make sure the results of the filters following the retry filter are as expected when they are executed multiple times. -// 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] diff --git a/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/filters/rewritelocationresponseheader.adoc b/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/filters/rewritelocationresponseheader.adoc index 28918320..6af573a1 100644 --- a/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/filters/rewritelocationresponseheader.adoc +++ b/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/filters/rewritelocationresponseheader.adoc @@ -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 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(); } } ---- diff --git a/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/filters/rewritepath.adoc b/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/filters/rewritepath.adoc index 3b50b615..d423af39 100644 --- a/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/filters/rewritepath.adoc +++ b/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/filters/rewritepath.adoc @@ -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 gatewayRouterFunctionsRewritePath() { - return route("rewritepath_route") - .GET("/red/**", http("https://example.org")) - .before(rewritePath("/red/(?.*)", "/${segment}")) - .build(); + return route("rewritepath_route") + .GET("/red/**", http()) + .before(uri("https://example.org")) + .before(rewritePath("/red/(?.*)", "/${segment}")) + .build(); } } ---- diff --git a/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/filters/rewriterequestparameter.adoc b/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/filters/rewriterequestparameter.adoc index ba7c38c5..7ad61594 100644 --- a/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/filters/rewriterequestparameter.adoc +++ b/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/filters/rewriterequestparameter.adoc @@ -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 gatewayRouterFunctionsAddReqHeader() { - return route("add_request_parameter_route") - .GET("/anything/addrequestparam", http("https://example.org")) - .before(addRequestParameter("red", "blue")) - .build(); + public RouterFunction gatewayRouterFunctionsRewriteRequestParameter() { + return route("rewriterequestparameter_route") + .GET("products", http()) + .before(uri("https://example.org")) + .before(addRequestParameter("red", "blue")) + .build(); } } ---- diff --git a/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/filters/rewriteresponseheader.adoc b/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/filters/rewriteresponseheader.adoc index 7ba0f9b0..7e0cb2c9 100644 --- a/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/filters/rewriteresponseheader.adoc +++ b/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/filters/rewriteresponseheader.adoc @@ -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 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(); } } diff --git a/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/filters/setpath.adoc b/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/filters/setpath.adoc index 9355a068..73624a70 100644 --- a/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/filters/setpath.adoc +++ b/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/filters/setpath.adoc @@ -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 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(); } } ---- diff --git a/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/filters/setrequestheader.adoc b/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/filters/setrequestheader.adoc index f131486a..a2c7676b 100644 --- a/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/filters/setrequestheader.adoc +++ b/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/filters/setrequestheader.adoc @@ -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 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 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(); } } ---- \ No newline at end of file diff --git a/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/filters/setrequesthostheader.adoc b/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/filters/setrequesthostheader.adoc index 3f8faad9..d12b23c6 100644 --- a/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/filters/setrequesthostheader.adoc +++ b/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/filters/setrequesthostheader.adoc @@ -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 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(); } } ---- diff --git a/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/filters/setresponseheader.adoc b/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/filters/setresponseheader.adoc index ee7698e9..55375546 100644 --- a/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/filters/setresponseheader.adoc +++ b/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/filters/setresponseheader.adoc @@ -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 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 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(); } } ---- diff --git a/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/filters/setstatus.adoc b/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/filters/setstatus.adoc index c3022b52..bd9bbe25 100644 --- a/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/filters/setstatus.adoc +++ b/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/filters/setstatus.adoc @@ -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 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()); } } ---- diff --git a/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/filters/stripprefix.adoc b/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/filters/stripprefix.adoc index dc2be798..902974ce 100644 --- a/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/filters/stripprefix.adoc +++ b/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/filters/stripprefix.adoc @@ -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 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. \ No newline at end of file diff --git a/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/filters/tokenrelay.adoc b/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/filters/tokenrelay.adoc index 2bf618aa..086bd3eb 100644 --- a/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/filters/tokenrelay.adoc +++ b/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/filters/tokenrelay.adoc @@ -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 gatewayRouterFunctionsAddReqHeader() { - return route("resource") - .GET("/resource", http("http://localhost:9000")) - .filter(tokenRelay()) - .build(); + public RouterFunction gatewayRouterFunctionsTokenRelay() { + return route("resource") + .GET("/resource", http()) + .before(uri("https://localhost:9000")) + .filter(tokenRelay()) + .build(); } } ---- diff --git a/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/gateway-request-predicates.adoc b/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/gateway-request-predicates.adoc index 1bca61e6..5631cbf8 100644 --- a/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/gateway-request-predicates.adoc +++ b/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/gateway-request-predicates.adoc @@ -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 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 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 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 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 gatewayRouterFunctionsCookie() { - return route("cookie_route") - .route(header("X-Request-Id", "\\d+"), http("https://example.org")) - .build(); + public RouterFunction 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 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 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 gatewayRouterFunctionsMethod() { - return route("method_route") - .GET("/mypath", http("https://example.org")) - .build(); + public RouterFunction 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 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 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 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 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()); } } ---- diff --git a/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/java-routes-api.adoc b/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/java-routes-api.adoc index d15b79e0..f653d36e 100644 --- a/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/java-routes-api.adoc +++ b/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/java-routes-api.adoc @@ -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 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 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`. 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`. 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. \ No newline at end of file diff --git a/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/writing-custom-predicates-and-filters.adoc b/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/writing-custom-predicates-and-filters.adoc index fdabf35d..30aef31e 100644 --- a/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/writing-custom-predicates-and-filters.adoc +++ b/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/writing-custom-predicates-and-filters.adoc @@ -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 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 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 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 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(); } } ---- diff --git a/spring-cloud-gateway-server-mvc/src/main/java/org/springframework/cloud/gateway/server/mvc/config/RouterFunctionHolderFactory.java b/spring-cloud-gateway-server-mvc/src/main/java/org/springframework/cloud/gateway/server/mvc/config/RouterFunctionHolderFactory.java index dcebc7e7..6bc52a52 100644 --- a/spring-cloud-gateway-server-mvc/src/main/java/org/springframework/cloud/gateway/server/mvc/config/RouterFunctionHolderFactory.java +++ b/spring-cloud-gateway-server-mvc/src/main/java/org/springframework/cloud/gateway/server/mvc/config/RouterFunctionHolderFactory.java @@ -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 handlerOperations = handlerDiscoverer.getOperations(); // TODO: cache? // translate handlerFunction @@ -181,13 +171,15 @@ public class RouterFunctionHolderFactory { HandlerFunction handlerFunction = null; // filters added by HandlerDiscoverer need to go last, so save them - List> handlerFilterFunctionFilters = new ArrayList<>(); + List> lowerPrecedenceFilters = new ArrayList<>(); + List> higherPrecedenceFilters = new ArrayList<>(); if (response instanceof HandlerFunction) { handlerFunction = (HandlerFunction) 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 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); diff --git a/spring-cloud-gateway-server-mvc/src/main/java/org/springframework/cloud/gateway/server/mvc/filter/BeforeFilterFunctions.java b/spring-cloud-gateway-server-mvc/src/main/java/org/springframework/cloud/gateway/server/mvc/filter/BeforeFilterFunctions.java index dba4e260..0e95bf82 100644 --- a/spring-cloud-gateway-server-mvc/src/main/java/org/springframework/cloud/gateway/server/mvc/filter/BeforeFilterFunctions.java +++ b/spring-cloud-gateway-server-mvc/src/main/java/org/springframework/cloud/gateway/server/mvc/filter/BeforeFilterFunctions.java @@ -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 uri(String uri) { + return uri(URI.create(uri)); + } + + public static Function uri(URI uri) { + return request -> { + MvcUtils.setRequestUrl(request, uri); + return request; + }; + } + public static class FallbackHeadersConfig { private String executionExceptionTypeHeaderName = CB_EXECUTION_EXCEPTION_TYPE; diff --git a/spring-cloud-gateway-server-mvc/src/main/java/org/springframework/cloud/gateway/server/mvc/filter/FilterFunctions.java b/spring-cloud-gateway-server-mvc/src/main/java/org/springframework/cloud/gateway/server/mvc/filter/FilterFunctions.java index c7cb910f..55b6602c 100644 --- a/spring-cloud-gateway-server-mvc/src/main/java/org/springframework/cloud/gateway/server/mvc/filter/FilterFunctions.java +++ b/spring-cloud-gateway-server-mvc/src/main/java/org/springframework/cloud/gateway/server/mvc/filter/FilterFunctions.java @@ -228,6 +228,15 @@ public interface FilterFunctions { return ofResponseProcessor(AfterFilterFunctions.setStatus(statusCode)); } + static HandlerFilterFunction uri(String uri) { + return ofRequestProcessor(BeforeFilterFunctions.uri(uri)); + } + + @Shortcut + static HandlerFilterFunction uri(URI uri) { + return ofRequestProcessor(BeforeFilterFunctions.uri(uri)); + } + class FilterSupplier extends SimpleFilterSupplier { public FilterSupplier() { diff --git a/spring-cloud-gateway-server-mvc/src/main/java/org/springframework/cloud/gateway/server/mvc/filter/LoadBalancerHandlerSupplier.java b/spring-cloud-gateway-server-mvc/src/main/java/org/springframework/cloud/gateway/server/mvc/filter/LoadBalancerHandlerSupplier.java index 3cedfa35..c2a0ad58 100644 --- a/spring-cloud-gateway-server-mvc/src/main/java/org/springframework/cloud/gateway/server/mvc/filter/LoadBalancerHandlerSupplier.java +++ b/spring-cloud-gateway-server-mvc/src/main/java/org/springframework/cloud/gateway/server/mvc/filter/LoadBalancerHandlerSupplier.java @@ -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()))); } diff --git a/spring-cloud-gateway-server-mvc/src/main/java/org/springframework/cloud/gateway/server/mvc/filter/XForwardedRequestHeadersFilter.java b/spring-cloud-gateway-server-mvc/src/main/java/org/springframework/cloud/gateway/server/mvc/filter/XForwardedRequestHeadersFilter.java index 9b8b9bcb..bee93756 100644 --- a/spring-cloud-gateway-server-mvc/src/main/java/org/springframework/cloud/gateway/server/mvc/filter/XForwardedRequestHeadersFilter.java +++ b/spring-cloud-gateway-server-mvc/src/main/java/org/springframework/cloud/gateway/server/mvc/filter/XForwardedRequestHeadersFilter.java @@ -400,7 +400,7 @@ public class XForwardedRequestHeadersFilter implements HttpHeadersFilter.Request LinkedHashSet 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) { diff --git a/spring-cloud-gateway-server-mvc/src/main/java/org/springframework/cloud/gateway/server/mvc/handler/DefaultHandlerSupplier.java b/spring-cloud-gateway-server-mvc/src/main/java/org/springframework/cloud/gateway/server/mvc/handler/DefaultHandlerSupplier.java new file mode 100644 index 00000000..91304f9f --- /dev/null +++ b/spring-cloud-gateway-server-mvc/src/main/java/org/springframework/cloud/gateway/server/mvc/handler/DefaultHandlerSupplier.java @@ -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 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 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 handlerFunction) { + HandlerFilterFunction setId = setIdFilter(id); + HandlerFilterFunction setRequest = setRequestUrlFilter(uri); + return new HandlerDiscoverer.Result(handlerFunction, Arrays.asList(setId, setRequest), Collections.emptyList()); + } + + private static HandlerFilterFunction setIdFilter(String id) { + return (request, next) -> { + MvcUtils.setRouteId(request, id); + return next.handle(request); + }; + } + + private static HandlerFilterFunction setRequestUrlFilter(URI uri) { + return (request, next) -> { + MvcUtils.setRequestUrl(request, uri); + return next.handle(request); + }; + } + +} diff --git a/spring-cloud-gateway-server-mvc/src/main/java/org/springframework/cloud/gateway/server/mvc/handler/HandlerDiscoverer.java b/spring-cloud-gateway-server-mvc/src/main/java/org/springframework/cloud/gateway/server/mvc/handler/HandlerDiscoverer.java index be0dd7cf..7569842d 100644 --- a/spring-cloud-gateway-server-mvc/src/main/java/org/springframework/cloud/gateway/server/mvc/handler/HandlerDiscoverer.java +++ b/spring-cloud-gateway-server-mvc/src/main/java/org/springframework/cloud/gateway/server/mvc/handler/HandlerDiscoverer.java @@ -37,20 +37,39 @@ public class HandlerDiscoverer extends AbstractGatewayDiscoverer { private final HandlerFunction handlerFunction; - private final List> filters; + private final List> lowerPrecedenceFilters; + private final List> higherPrecedenceFilters; + + @Deprecated public Result(HandlerFunction handlerFunction, List> filters) { + this(handlerFunction, Collections.emptyList(), filters); + } + + public Result(HandlerFunction handlerFunction, + List> lowerPrecedenceFilters, + List> 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 getHandlerFunction() { return handlerFunction; } + @Deprecated public List> getFilters() { - return filters; + return getHigherPrecedenceFilters(); + } + + public List> getLowerPrecedenceFilters() { + return lowerPrecedenceFilters; + } + + public List> getHigherPrecedenceFilters() { + return higherPrecedenceFilters; } } diff --git a/spring-cloud-gateway-server-mvc/src/main/java/org/springframework/cloud/gateway/server/mvc/handler/HandlerFunctions.java b/spring-cloud-gateway-server-mvc/src/main/java/org/springframework/cloud/gateway/server/mvc/handler/HandlerFunctions.java index 9b3d118b..0b9f99ac 100644 --- a/spring-cloud-gateway-server-mvc/src/main/java/org/springframework/cloud/gateway/server/mvc/handler/HandlerFunctions.java +++ b/spring-cloud-gateway-server-mvc/src/main/java/org/springframework/cloud/gateway/server/mvc/handler/HandlerFunctions.java @@ -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 http(String uri) { return http(URI.create(uri)); } + @Deprecated public static HandlerFunction http(URI uri) { return new LookupProxyExchangeHandlerFunction(uri); } + @Deprecated public static HandlerFunction https(URI uri) { return new LookupProxyExchangeHandlerFunction(uri); } @@ -86,6 +89,7 @@ public abstract class HandlerFunctions { static class LookupProxyExchangeHandlerFunction implements HandlerFunction { + @Deprecated private final URI uri; private AtomicReference 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 get() { - return Arrays.asList(HandlerFunctions.class.getMethods()); + return Collections.emptyList(); } } diff --git a/spring-cloud-gateway-server-mvc/src/main/resources/META-INF/spring.factories b/spring-cloud-gateway-server-mvc/src/main/resources/META-INF/spring.factories index ba2cd973..b7002f15 100644 --- a/spring-cloud-gateway-server-mvc/src/main/resources/META-INF/spring.factories +++ b/spring-cloud-gateway-server-mvc/src/main/resources/META-INF/spring.factories @@ -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=\ diff --git a/spring-cloud-gateway-server-mvc/src/test/java/org/springframework/cloud/gateway/server/mvc/ServerMvcIntegrationTests.java b/spring-cloud-gateway-server-mvc/src/test/java/org/springframework/cloud/gateway/server/mvc/ServerMvcIntegrationTests.java index 4188d73a..aaf409af 100644 --- a/spring-cloud-gateway-server-mvc/src/test/java/org/springframework/cloud/gateway/server/mvc/ServerMvcIntegrationTests.java +++ b/spring-cloud-gateway-server-mvc/src/test/java/org/springframework/cloud/gateway/server/mvc/ServerMvcIntegrationTests.java @@ -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 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 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 { diff --git a/spring-cloud-gateway-server-mvc/src/test/java/org/springframework/cloud/gateway/server/mvc/filter/BeforeFilterFunctionsTests.java b/spring-cloud-gateway-server-mvc/src/test/java/org/springframework/cloud/gateway/server/mvc/filter/BeforeFilterFunctionsTests.java index ae6a7ee2..8c8a12ee 100644 --- a/spring-cloud-gateway-server-mvc/src/test/java/org/springframework/cloud/gateway/server/mvc/filter/BeforeFilterFunctionsTests.java +++ b/spring-cloud-gateway-server-mvc/src/test/java/org/springframework/cloud/gateway/server/mvc/filter/BeforeFilterFunctionsTests.java @@ -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/é") diff --git a/spring-cloud-gateway-server-mvc/src/test/java/org/springframework/cloud/gateway/server/mvc/filter/StripPrefixStaticPortTests.java b/spring-cloud-gateway-server-mvc/src/test/java/org/springframework/cloud/gateway/server/mvc/filter/StripPrefixStaticPortTests.java new file mode 100644 index 00000000..4052a3f6 --- /dev/null +++ b/spring-cloud-gateway-server-mvc/src/test/java/org/springframework/cloud/gateway/server/mvc/filter/StripPrefixStaticPortTests.java @@ -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 map = res.getResponseBody(); + Map 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 map = res.getResponseBody(); + Map 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 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(); + } + + } + +} diff --git a/spring-cloud-gateway-server-mvc/src/test/java/org/springframework/cloud/gateway/server/mvc/test/HttpbinTestcontainers.java b/spring-cloud-gateway-server-mvc/src/test/java/org/springframework/cloud/gateway/server/mvc/test/HttpbinTestcontainers.java index e1dc98a4..95345fce 100644 --- a/spring-cloud-gateway-server-mvc/src/test/java/org/springframework/cloud/gateway/server/mvc/test/HttpbinTestcontainers.java +++ b/spring-cloud-gateway-server-mvc/src/test/java/org/springframework/cloud/gateway/server/mvc/test/HttpbinTestcontainers.java @@ -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 map = new HashMap<>(); map.put("httpbin.port", String.valueOf(mappedPort)); diff --git a/spring-cloud-gateway-server-mvc/src/test/resources/application-stripprefixstaticport.yml b/spring-cloud-gateway-server-mvc/src/test/resources/application-stripprefixstaticport.yml new file mode 100644 index 00000000..c27795c3 --- /dev/null +++ b/spring-cloud-gateway-server-mvc/src/test/resources/application-stripprefixstaticport.yml @@ -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