diff --git a/framework-platform/framework-platform.gradle b/framework-platform/framework-platform.gradle index 713693887dff..4cb3cd55c61e 100644 --- a/framework-platform/framework-platform.gradle +++ b/framework-platform/framework-platform.gradle @@ -56,7 +56,7 @@ dependencies { api("io.r2dbc:r2dbc-spi:1.0.0.RELEASE") api("io.reactivex.rxjava3:rxjava:3.1.9") api("io.smallrye.reactive:mutiny:1.10.0") - api("io.undertow:undertow-core:2.3.17.Final") + api("io.undertow:undertow-core:2.3.18.Final") api("io.undertow:undertow-servlet:2.3.17.Final") api("io.undertow:undertow-websockets-jsr:2.3.17.Final") api("io.vavr:vavr:0.10.4") diff --git a/spring-web/src/main/java/org/springframework/http/server/reactive/UndertowHttpHandlerAdapter.java b/spring-web/src/main/java/org/springframework/http/server/reactive/UndertowHttpHandlerAdapter.java index 8c58eb159d8c..4517bc413247 100644 --- a/spring-web/src/main/java/org/springframework/http/server/reactive/UndertowHttpHandlerAdapter.java +++ b/spring-web/src/main/java/org/springframework/http/server/reactive/UndertowHttpHandlerAdapter.java @@ -66,25 +66,27 @@ public DataBufferFactory getDataBufferFactory() { @Override public void handleRequest(HttpServerExchange exchange) { - UndertowServerHttpRequest request = null; - try { - request = new UndertowServerHttpRequest(exchange, getDataBufferFactory()); - } - catch (URISyntaxException ex) { - if (logger.isWarnEnabled()) { - logger.debug("Failed to get request URI: " + ex.getMessage()); + exchange.dispatch(() -> { + UndertowServerHttpRequest request = null; + try { + request = new UndertowServerHttpRequest(exchange, getDataBufferFactory()); } - exchange.setStatusCode(400); - return; - } - ServerHttpResponse response = new UndertowServerHttpResponse(exchange, getDataBufferFactory(), request); + catch (URISyntaxException ex) { + if (logger.isWarnEnabled()) { + logger.debug("Failed to get request URI: " + ex.getMessage()); + } + exchange.setStatusCode(400); + return; + } + ServerHttpResponse response = new UndertowServerHttpResponse(exchange, getDataBufferFactory(), request); - if (request.getMethod() == HttpMethod.HEAD) { - response = new HttpHeadResponseDecorator(response); - } + if (request.getMethod() == HttpMethod.HEAD) { + response = new HttpHeadResponseDecorator(response); + } - HandlerResultSubscriber resultSubscriber = new HandlerResultSubscriber(exchange, request); - this.httpHandler.handle(request, response).subscribe(resultSubscriber); + HandlerResultSubscriber resultSubscriber = new HandlerResultSubscriber(exchange, request); + this.httpHandler.handle(request, response).subscribe(resultSubscriber); + }); } diff --git a/spring-webflux/src/test/java/org/springframework/web/reactive/result/method/annotation/RequestMappingMessageConversionIntegrationTests.java b/spring-webflux/src/test/java/org/springframework/web/reactive/result/method/annotation/RequestMappingMessageConversionIntegrationTests.java index 582a086d9252..f5f2ff938f45 100644 --- a/spring-webflux/src/test/java/org/springframework/web/reactive/result/method/annotation/RequestMappingMessageConversionIntegrationTests.java +++ b/spring-webflux/src/test/java/org/springframework/web/reactive/result/method/annotation/RequestMappingMessageConversionIntegrationTests.java @@ -17,6 +17,7 @@ package org.springframework.web.reactive.result.method.annotation; import java.nio.ByteBuffer; +import java.time.Duration; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; @@ -331,6 +332,17 @@ void personTransformWithFlux(HttpServer httpServer) throws Exception { assertThat(performPost("/person-transform/flux", JSON, req, JSON, PERSON_LIST).getBody()).isEqualTo(res); } + @ParameterizedHttpServerTest // see gh-33885 + void personTransformWithFluxDelayed(HttpServer httpServer) throws Exception { + startServer(httpServer); + + List req = asList(new Person("Robert"), new Person("Marie")); + List res = asList(new Person("ROBERT"), new Person("MARIE")); + assertThat(performPost("/person-transform/flux-delayed", JSON, req, JSON, PERSON_LIST)) + .satisfies(r -> assertThat(r.getBody()).isEqualTo(res)) + .satisfies(r -> assertThat(r.getHeaders().getContentLength()).isNotZero()); + } + @ParameterizedHttpServerTest void personTransformWithObservable(HttpServer httpServer) throws Exception { startServer(httpServer); @@ -632,6 +644,11 @@ Flux transformFlux(@RequestBody Flux persons) { return persons.map(person -> new Person(person.getName().toUpperCase())); } + @PostMapping("/flux-delayed") + Flux transformDelayed(@RequestBody Flux persons) { + return transformFlux(persons).delayElements(Duration.ofMillis(10)); + } + @PostMapping("/observable") Observable transformObservable(@RequestBody Observable persons) { return persons.map(person -> new Person(person.getName().toUpperCase()));