From 2fe33218130342e5f87585292bdc8292ccc0e6e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Deleuze?= Date: Tue, 13 Feb 2024 14:24:19 +0100 Subject: [PATCH] Fix pathExtension null-safety in Kotlin DSLs Closes gh-32254 --- .../reactive/function/server/CoRouterFunctionDsl.kt | 4 ++-- .../reactive/function/server/RouterFunctionDsl.kt | 4 ++-- .../function/server/CoRouterFunctionDslTests.kt | 12 ++++++++++++ .../function/server/RouterFunctionDslTests.kt | 12 ++++++++++++ .../web/servlet/function/RouterFunctionDsl.kt | 4 ++-- .../web/servlet/function/RouterFunctionDslTests.kt | 10 ++++++++++ 6 files changed, 40 insertions(+), 6 deletions(-) diff --git a/spring-webflux/src/main/kotlin/org/springframework/web/reactive/function/server/CoRouterFunctionDsl.kt b/spring-webflux/src/main/kotlin/org/springframework/web/reactive/function/server/CoRouterFunctionDsl.kt index b42f30d8d5c..16e67404f03 100644 --- a/spring-webflux/src/main/kotlin/org/springframework/web/reactive/function/server/CoRouterFunctionDsl.kt +++ b/spring-webflux/src/main/kotlin/org/springframework/web/reactive/function/server/CoRouterFunctionDsl.kt @@ -452,7 +452,7 @@ class CoRouterFunctionDsl internal constructor (private val init: (CoRouterFunct * Route to the given handler function if the given pathExtension predicate applies. * @see RouterFunctions.route */ - fun pathExtension(predicate: (String) -> Boolean, f: suspend (ServerRequest) -> ServerResponse) { + fun pathExtension(predicate: (String?) -> Boolean, f: suspend (ServerRequest) -> ServerResponse) { builder.add(RouterFunctions.route(RequestPredicates.pathExtension(predicate), asHandlerFunction(f))) } @@ -461,7 +461,7 @@ class CoRouterFunctionDsl internal constructor (private val init: (CoRouterFunct * predicate. * @see RequestPredicates.pathExtension */ - fun pathExtension(predicate: (String) -> Boolean): RequestPredicate = + fun pathExtension(predicate: (String?) -> Boolean): RequestPredicate = RequestPredicates.pathExtension(predicate) /** diff --git a/spring-webflux/src/main/kotlin/org/springframework/web/reactive/function/server/RouterFunctionDsl.kt b/spring-webflux/src/main/kotlin/org/springframework/web/reactive/function/server/RouterFunctionDsl.kt index dea88b9f20f..ad7e871268e 100644 --- a/spring-webflux/src/main/kotlin/org/springframework/web/reactive/function/server/RouterFunctionDsl.kt +++ b/spring-webflux/src/main/kotlin/org/springframework/web/reactive/function/server/RouterFunctionDsl.kt @@ -569,7 +569,7 @@ class RouterFunctionDsl internal constructor (private val init: RouterFunctionDs * Route to the given handler function if the given pathExtension predicate applies. * @see RouterFunctions.route */ - fun pathExtension(predicate: (String) -> Boolean, f: (ServerRequest) -> Mono) { + fun pathExtension(predicate: (String?) -> Boolean, f: (ServerRequest) -> Mono) { builder.add(RouterFunctions.route(RequestPredicates.pathExtension(predicate), HandlerFunction { f(it).cast(ServerResponse::class.java) })) } @@ -578,7 +578,7 @@ class RouterFunctionDsl internal constructor (private val init: RouterFunctionDs * predicate. * @see RequestPredicates.pathExtension */ - fun pathExtension(predicate: (String) -> Boolean): RequestPredicate = + fun pathExtension(predicate: (String?) -> Boolean): RequestPredicate = RequestPredicates.pathExtension(predicate) /** diff --git a/spring-webflux/src/test/kotlin/org/springframework/web/reactive/function/server/CoRouterFunctionDslTests.kt b/spring-webflux/src/test/kotlin/org/springframework/web/reactive/function/server/CoRouterFunctionDslTests.kt index a443fcedadc..db523a093dc 100644 --- a/spring-webflux/src/test/kotlin/org/springframework/web/reactive/function/server/CoRouterFunctionDslTests.kt +++ b/spring-webflux/src/test/kotlin/org/springframework/web/reactive/function/server/CoRouterFunctionDslTests.kt @@ -112,6 +112,15 @@ class CoRouterFunctionDslTests { .verifyComplete() } + @Test + fun pathExtension() { + val mockRequest = get("https://example.com/test.properties").build() + val request = DefaultServerRequest(MockServerWebExchange.from(mockRequest), emptyList()) + StepVerifier.create(sampleRouter().route(request)) + .expectNextCount(1) + .verifyComplete() + } + @Test fun resource() { val mockRequest = get("https://example.com/response2.txt").build() @@ -324,6 +333,9 @@ class CoRouterFunctionDslTests { null } } + GET("/**", pathExtension { it == "properties" }) { + ok().bodyValueAndAwait("foo=bar") + } path("/baz", ::handle) GET("/rendering") { RenderingResponse.create("index").buildAndAwait() } add(otherRouter) diff --git a/spring-webflux/src/test/kotlin/org/springframework/web/reactive/function/server/RouterFunctionDslTests.kt b/spring-webflux/src/test/kotlin/org/springframework/web/reactive/function/server/RouterFunctionDslTests.kt index 2bbf77566e4..fbdd1877126 100644 --- a/spring-webflux/src/test/kotlin/org/springframework/web/reactive/function/server/RouterFunctionDslTests.kt +++ b/spring-webflux/src/test/kotlin/org/springframework/web/reactive/function/server/RouterFunctionDslTests.kt @@ -110,6 +110,15 @@ class RouterFunctionDslTests { .verifyComplete() } + @Test + fun pathExtension() { + val mockRequest = get("https://example.com/test.properties").build() + val request = DefaultServerRequest(MockServerWebExchange.from(mockRequest), emptyList()) + StepVerifier.create(sampleRouter().route(request)) + .expectNextCount(1) + .verifyComplete() + } + @Test fun resource() { val mockRequest = get("https://example.com/response2.txt").build() @@ -256,6 +265,9 @@ class RouterFunctionDslTests { Mono.empty() } } + GET(pathExtension { it == "properties" }) { + ok().bodyValue("foo=bar") + } path("/baz", ::handle) GET("/rendering") { RenderingResponse.create("index").build() } add(otherRouter) diff --git a/spring-webmvc/src/main/kotlin/org/springframework/web/servlet/function/RouterFunctionDsl.kt b/spring-webmvc/src/main/kotlin/org/springframework/web/servlet/function/RouterFunctionDsl.kt index f44553674ca..befc5b0f942 100644 --- a/spring-webmvc/src/main/kotlin/org/springframework/web/servlet/function/RouterFunctionDsl.kt +++ b/spring-webmvc/src/main/kotlin/org/springframework/web/servlet/function/RouterFunctionDsl.kt @@ -564,7 +564,7 @@ class RouterFunctionDsl internal constructor (private val init: (RouterFunctionD * Route to the given handler function if the given pathExtension predicate applies. * @see RouterFunctions.route */ - fun pathExtension(predicate: (String) -> Boolean, f: (ServerRequest) -> ServerResponse) { + fun pathExtension(predicate: (String?) -> Boolean, f: (ServerRequest) -> ServerResponse) { builder.add(RouterFunctions.route(RequestPredicates.pathExtension(predicate), HandlerFunction(f))) } @@ -573,7 +573,7 @@ class RouterFunctionDsl internal constructor (private val init: (RouterFunctionD * predicate. * @see RequestPredicates.pathExtension */ - fun pathExtension(predicate: (String) -> Boolean): RequestPredicate = + fun pathExtension(predicate: (String?) -> Boolean): RequestPredicate = RequestPredicates.pathExtension(predicate) /** diff --git a/spring-webmvc/src/test/kotlin/org/springframework/web/servlet/function/RouterFunctionDslTests.kt b/spring-webmvc/src/test/kotlin/org/springframework/web/servlet/function/RouterFunctionDslTests.kt index 0a8cdb9d7f7..909d3e38bf3 100644 --- a/spring-webmvc/src/test/kotlin/org/springframework/web/servlet/function/RouterFunctionDslTests.kt +++ b/spring-webmvc/src/test/kotlin/org/springframework/web/servlet/function/RouterFunctionDslTests.kt @@ -88,6 +88,13 @@ class RouterFunctionDslTests { assertThat(sampleRouter().route(request).isPresent).isTrue() } + @Test + fun pathExtension() { + val servletRequest = PathPatternsTestUtils.initRequest("GET", "/test.properties", true) + val request = DefaultServerRequest(servletRequest, emptyList()) + assertThat(sampleRouter().route(request).isPresent).isTrue() + } + @Test fun resource() { val servletRequest = PathPatternsTestUtils.initRequest("GET","/response2.txt", true) @@ -185,6 +192,9 @@ class RouterFunctionDslTests { null } } + GET(pathExtension { it == "properties" }) { + ok().body("foo=bar") + } path("/baz", ::handle) GET("/rendering") { RenderingResponse.create("index").build() } add(otherRouter)