diff --git a/spring-web/src/main/java/org/springframework/http/client/reactive/JettyClientHttpConnector.java b/spring-web/src/main/java/org/springframework/http/client/reactive/JettyClientHttpConnector.java index 2556b43ebc..75dfdc8260 100644 --- a/spring-web/src/main/java/org/springframework/http/client/reactive/JettyClientHttpConnector.java +++ b/spring-web/src/main/java/org/springframework/http/client/reactive/JettyClientHttpConnector.java @@ -21,7 +21,9 @@ import java.util.function.Consumer; import java.util.function.Function; import org.eclipse.jetty.client.HttpClient; +import org.eclipse.jetty.client.api.Request; import org.eclipse.jetty.reactive.client.ContentChunk; +import org.eclipse.jetty.reactive.client.ReactiveRequest; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; @@ -81,7 +83,8 @@ public class JettyClientHttpConnector implements ClientHttpConnector { * Constructor with an {@link JettyResourceFactory} that will manage shared resources. * @param resourceFactory the {@link JettyResourceFactory} to use * @param customizer the lambda used to customize the {@link HttpClient} - * @deprecated as of 5.2, in favor of {@link JettyClientHttpConnector#JettyClientHttpConnector(HttpClient, JettyResourceFactory)} + * @deprecated as of 5.2, in favor of + * {@link JettyClientHttpConnector#JettyClientHttpConnector(HttpClient, JettyResourceFactory)} */ @Deprecated public JettyClientHttpConnector(JettyResourceFactory resourceFactory, @Nullable Consumer customizer) { @@ -117,14 +120,14 @@ public class JettyClientHttpConnector implements ClientHttpConnector { } } - JettyClientHttpRequest clientHttpRequest = new JettyClientHttpRequest( - this.httpClient.newRequest(uri).method(method.toString()), this.bufferFactory); + Request request = this.httpClient.newRequest(uri).method(method.toString()); - return requestCallback.apply(clientHttpRequest).then(Mono.from( - clientHttpRequest.getReactiveRequest().response((response, chunks) -> { - Flux content = Flux.from(chunks).map(this::toDataBuffer); - return Mono.just(new JettyClientHttpResponse(response, content)); - }))); + return requestCallback.apply(new JettyClientHttpRequest(request, this.bufferFactory)) + .then(Mono.fromDirect(ReactiveRequest.newBuilder(request).build() + .response((reactiveResponse, chunkPublisher) -> { + Flux content = Flux.from(chunkPublisher).map(this::toDataBuffer); + return Mono.just(new JettyClientHttpResponse(reactiveResponse, content)); + }))); } private DataBuffer toDataBuffer(ContentChunk chunk) { diff --git a/spring-web/src/main/java/org/springframework/http/client/reactive/JettyClientHttpRequest.java b/spring-web/src/main/java/org/springframework/http/client/reactive/JettyClientHttpRequest.java index f9b17e5775..3395327bf8 100644 --- a/spring-web/src/main/java/org/springframework/http/client/reactive/JettyClientHttpRequest.java +++ b/spring-web/src/main/java/org/springframework/http/client/reactive/JettyClientHttpRequest.java @@ -24,6 +24,7 @@ import java.util.function.Function; import org.eclipse.jetty.client.api.Request; import org.eclipse.jetty.reactive.client.ContentChunk; import org.eclipse.jetty.reactive.client.ReactiveRequest; +import org.eclipse.jetty.reactive.client.internal.PublisherContentProvider; import org.eclipse.jetty.util.Callback; import org.reactivestreams.Publisher; import reactor.core.publisher.Flux; @@ -33,10 +34,10 @@ import reactor.core.publisher.MonoSink; import org.springframework.core.io.buffer.DataBuffer; import org.springframework.core.io.buffer.DataBufferFactory; import org.springframework.core.io.buffer.DataBufferUtils; +import org.springframework.core.io.buffer.PooledDataBuffer; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; import org.springframework.http.MediaType; -import org.springframework.lang.Nullable; import org.springframework.util.Assert; /** @@ -52,9 +53,6 @@ class JettyClientHttpRequest extends AbstractClientHttpRequest { private final DataBufferFactory bufferFactory; - @Nullable - private ReactiveRequest reactiveRequest; - public JettyClientHttpRequest(Request jettyRequest, DataBufferFactory bufferFactory) { this.jettyRequest = jettyRequest; @@ -93,17 +91,20 @@ class JettyClientHttpRequest extends AbstractClientHttpRequest { @Override public Mono writeWith(Publisher body) { return Mono.create(sink -> { - Flux chunks = Flux.from(body).map(buffer -> toContentChunk(buffer, sink)); - ReactiveRequest.Content content = ReactiveRequest.Content.fromPublisher(chunks, getContentType()); - this.reactiveRequest = ReactiveRequest.newBuilder(this.jettyRequest).content(content).build(); + ReactiveRequest.Content content = Flux.from(body) + .map(buffer -> toContentChunk(buffer, sink)) + .as(chunks -> ReactiveRequest.Content.fromPublisher(chunks, getContentType())); + this.jettyRequest.content(new PublisherContentProvider(content)); sink.success(); }) - .then(doCommit(this::completes)); + .then(doCommit(this::completes)); } @Override public Mono writeAndFlushWith(Publisher> body) { - return writeWith(Flux.from(body).flatMap(Function.identity())); + return writeWith(Flux.from(body) + .flatMap(Function.identity()) + .doOnDiscard(PooledDataBuffer.class, DataBufferUtils::release)); } private String getContentType() { @@ -147,11 +148,4 @@ class JettyClientHttpRequest extends AbstractClientHttpRequest { } } - ReactiveRequest getReactiveRequest() { - if (this.reactiveRequest == null) { - this.reactiveRequest = ReactiveRequest.newBuilder(this.jettyRequest).build(); - } - return this.reactiveRequest; - } - }