Merge branch '5.1.x'
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
* Copyright 2002-2019 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.
|
||||
@@ -81,8 +81,16 @@ class ReactorClientHttpRequest extends AbstractClientHttpRequest implements Zero
|
||||
@Override
|
||||
public Mono<Void> writeWith(Publisher<? extends DataBuffer> body) {
|
||||
return doCommit(() -> {
|
||||
Flux<ByteBuf> byteBufFlux = Flux.from(body).map(NettyDataBufferFactory::toByteBuf);
|
||||
return this.outbound.send(byteBufFlux).then();
|
||||
// Send as Mono if possible as an optimization hint to Reactor Netty
|
||||
if (body instanceof Mono) {
|
||||
Mono<ByteBuf> byteBufMono = Mono.from(body).map(NettyDataBufferFactory::toByteBuf);
|
||||
return this.outbound.send(byteBufMono).then();
|
||||
|
||||
}
|
||||
else {
|
||||
Flux<ByteBuf> byteBufFlux = Flux.from(body).map(NettyDataBufferFactory::toByteBuf);
|
||||
return this.outbound.send(byteBufFlux).then();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -125,16 +125,14 @@ public class EncoderHttpMessageWriter<T> implements HttpMessageWriter<T> {
|
||||
}))
|
||||
.flatMap(buffer -> {
|
||||
headers.setContentLength(buffer.readableByteCount());
|
||||
return message.writeWith(
|
||||
Mono.fromCallable(() -> buffer)
|
||||
.doOnDiscard(PooledDataBuffer.class, PooledDataBuffer::release));
|
||||
return message.writeWith(Mono.just(buffer)
|
||||
.doOnDiscard(PooledDataBuffer.class, PooledDataBuffer::release));
|
||||
});
|
||||
}
|
||||
|
||||
if (isStreamingMediaType(contentType)) {
|
||||
return message.writeAndFlushWith(body.map(buffer ->
|
||||
Mono.fromCallable(() -> buffer)
|
||||
.doOnDiscard(PooledDataBuffer.class, PooledDataBuffer::release)));
|
||||
Mono.just(buffer).doOnDiscard(PooledDataBuffer.class, PooledDataBuffer::release)));
|
||||
}
|
||||
|
||||
return message.writeWith(body);
|
||||
|
||||
@@ -28,6 +28,8 @@ import reactor.core.publisher.Mono;
|
||||
|
||||
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.HttpLogging;
|
||||
import org.springframework.http.HttpStatus;
|
||||
@@ -172,9 +174,16 @@ public abstract class AbstractServerHttpResponse implements ServerHttpResponse {
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public final Mono<Void> writeWith(Publisher<? extends DataBuffer> body) {
|
||||
return new ChannelSendOperator<>(body,
|
||||
writePublisher -> doCommit(() -> writeWithInternal(writePublisher)))
|
||||
// Write as Mono if possible as an optimization hint to Reactor Netty
|
||||
// ChannelSendOperator not necessary for Mono
|
||||
if (body instanceof Mono) {
|
||||
return ((Mono<? extends DataBuffer>) body).flatMap(buffer ->
|
||||
doCommit(() -> writeWithInternal(Mono.just(buffer)))
|
||||
.doOnDiscard(PooledDataBuffer.class, DataBufferUtils::release));
|
||||
}
|
||||
return new ChannelSendOperator<>(body, inner -> doCommit(() -> writeWithInternal(inner)))
|
||||
.doOnError(t -> removeContentLength());
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
* Copyright 2002-2019 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.
|
||||
@@ -85,8 +85,7 @@ public class FormHttpMessageWriterTests extends AbstractLeakCheckingTestCase {
|
||||
|
||||
String expected = "name+1=value+1&name+2=value+2%2B1&name+2=value+2%2B2&name+3";
|
||||
StepVerifier.create(response.getBody())
|
||||
.consumeNextWith(stringConsumer(
|
||||
expected))
|
||||
.consumeNextWith(stringConsumer(expected))
|
||||
.expectComplete()
|
||||
.verify();
|
||||
HttpHeaders headers = response.getHeaders();
|
||||
@@ -96,8 +95,7 @@ public class FormHttpMessageWriterTests extends AbstractLeakCheckingTestCase {
|
||||
|
||||
private Consumer<DataBuffer> stringConsumer(String expected) {
|
||||
return dataBuffer -> {
|
||||
String value =
|
||||
DataBufferTestUtils.dumpString(dataBuffer, StandardCharsets.UTF_8);
|
||||
String value = DataBufferTestUtils.dumpString(dataBuffer, StandardCharsets.UTF_8);
|
||||
DataBufferUtils.release(dataBuffer);
|
||||
assertEquals(expected, value);
|
||||
};
|
||||
|
||||
@@ -24,7 +24,6 @@ import java.util.List;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import io.netty.buffer.ByteBufAllocator;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.reactivestreams.Publisher;
|
||||
@@ -38,7 +37,6 @@ import reactor.test.StepVerifier;
|
||||
|
||||
import org.springframework.core.io.buffer.DataBuffer;
|
||||
import org.springframework.core.io.buffer.LeakAwareDataBufferFactory;
|
||||
import org.springframework.core.io.buffer.NettyDataBufferFactory;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
@@ -135,8 +133,7 @@ public class ChannelSendOperatorTests {
|
||||
|
||||
@Test // gh-22720
|
||||
public void cancelWhileItemCached() {
|
||||
NettyDataBufferFactory delegate = new NettyDataBufferFactory(ByteBufAllocator.DEFAULT);
|
||||
LeakAwareDataBufferFactory bufferFactory = new LeakAwareDataBufferFactory(delegate);
|
||||
LeakAwareDataBufferFactory bufferFactory = new LeakAwareDataBufferFactory();
|
||||
|
||||
ChannelSendOperator<DataBuffer> operator = new ChannelSendOperator<>(
|
||||
Mono.fromCallable(() -> {
|
||||
@@ -164,8 +161,7 @@ public class ChannelSendOperatorTests {
|
||||
// 2. writeFunction applied and writeCompletionBarrier subscribed to it
|
||||
// 3. Write Publisher fails right after that and before request(n) from server
|
||||
|
||||
NettyDataBufferFactory delegate = new NettyDataBufferFactory(ByteBufAllocator.DEFAULT);
|
||||
LeakAwareDataBufferFactory bufferFactory = new LeakAwareDataBufferFactory(delegate);
|
||||
LeakAwareDataBufferFactory bufferFactory = new LeakAwareDataBufferFactory();
|
||||
ZeroDemandSubscriber writeSubscriber = new ZeroDemandSubscriber();
|
||||
|
||||
ChannelSendOperator<DataBuffer> operator = new ChannelSendOperator<>(
|
||||
@@ -200,8 +196,7 @@ public class ChannelSendOperatorTests {
|
||||
// 2. writeFunction applied and writeCompletionBarrier subscribed to it
|
||||
// 3. writeFunction fails, e.g. to flush status and headers, before request(n) from server
|
||||
|
||||
NettyDataBufferFactory delegate = new NettyDataBufferFactory(ByteBufAllocator.DEFAULT);
|
||||
LeakAwareDataBufferFactory bufferFactory = new LeakAwareDataBufferFactory(delegate);
|
||||
LeakAwareDataBufferFactory bufferFactory = new LeakAwareDataBufferFactory();
|
||||
|
||||
ChannelSendOperator<DataBuffer> operator = new ChannelSendOperator<>(
|
||||
Flux.create(sink -> {
|
||||
|
||||
@@ -25,6 +25,7 @@ import java.util.function.Function;
|
||||
import org.reactivestreams.Publisher;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
import reactor.core.publisher.MonoProcessor;
|
||||
|
||||
import org.springframework.core.io.buffer.DataBuffer;
|
||||
import org.springframework.core.io.buffer.DataBufferFactory;
|
||||
@@ -61,8 +62,11 @@ public class MockServerHttpResponse extends AbstractServerHttpResponse {
|
||||
public MockServerHttpResponse(DataBufferFactory dataBufferFactory) {
|
||||
super(dataBufferFactory);
|
||||
this.writeHandler = body -> {
|
||||
this.body = body.cache();
|
||||
return this.body.then();
|
||||
// Avoid .then() which causes data buffers to be released
|
||||
MonoProcessor<Void> completion = MonoProcessor.create();
|
||||
this.body = body.doOnComplete(completion::onComplete).doOnError(completion::onError).cache();
|
||||
this.body.subscribe();
|
||||
return completion;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user