From 0274752fe941f5cc260dc4df7024c93afa9cf44a Mon Sep 17 00:00:00 2001 From: Rossen Stoyanchev Date: Wed, 15 May 2019 16:02:28 -0400 Subject: [PATCH] Use singleOrEmpty to avoid upstream cancel Closes gh-22952 --- .../http/codec/EncoderHttpMessageWriter.java | 3 ++- .../codec/EncoderHttpMessageWriterTests.java | 17 ++++++++++++----- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/spring-web/src/main/java/org/springframework/http/codec/EncoderHttpMessageWriter.java b/spring-web/src/main/java/org/springframework/http/codec/EncoderHttpMessageWriter.java index ce4d481429..ce8049a178 100644 --- a/spring-web/src/main/java/org/springframework/http/codec/EncoderHttpMessageWriter.java +++ b/spring-web/src/main/java/org/springframework/http/codec/EncoderHttpMessageWriter.java @@ -120,7 +120,8 @@ public class EncoderHttpMessageWriter implements HttpMessageWriter { if (inputStream instanceof Mono) { HttpHeaders headers = message.getHeaders(); - return Mono.from(body) + return body + .singleOrEmpty() .switchIfEmpty(Mono.defer(() -> { headers.setContentLength(0); return message.setComplete().then(Mono.empty()); diff --git a/spring-web/src/test/java/org/springframework/http/codec/EncoderHttpMessageWriterTests.java b/spring-web/src/test/java/org/springframework/http/codec/EncoderHttpMessageWriterTests.java index 6405ea7088..8d54ea7157 100644 --- a/spring-web/src/test/java/org/springframework/http/codec/EncoderHttpMessageWriterTests.java +++ b/spring-web/src/test/java/org/springframework/http/codec/EncoderHttpMessageWriterTests.java @@ -33,6 +33,7 @@ import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; import reactor.test.StepVerifier; +import org.springframework.core.codec.CharSequenceEncoder; import org.springframework.core.io.buffer.DataBuffer; import org.springframework.core.io.buffer.DefaultDataBufferFactory; import org.springframework.http.MediaType; @@ -131,9 +132,7 @@ public class EncoderHttpMessageWriterTests { @Test public void useNegotiatedMediaTypeCharset() { - MediaType negotiatedMediaType = new MediaType("text", "html", ISO_8859_1); - HttpMessageWriter writer = getWriter(TEXT_PLAIN_UTF_8, TEXT_HTML); writer.write(Mono.just("body"), forClass(String.class), negotiatedMediaType, this.response, NO_HINTS); @@ -143,7 +142,6 @@ public class EncoderHttpMessageWriterTests { @Test public void useHttpOutputMessageMediaType() { - MediaType outputMessageMediaType = MediaType.TEXT_HTML; this.response.getHeaders().setContentType(outputMessageMediaType); @@ -156,16 +154,25 @@ public class EncoderHttpMessageWriterTests { @Test public void setContentLengthForMonoBody() { - DefaultDataBufferFactory factory = new DefaultDataBufferFactory(); DataBuffer buffer = factory.wrap("body".getBytes(StandardCharsets.UTF_8)); HttpMessageWriter writer = getWriter(Flux.just(buffer), MimeTypeUtils.TEXT_PLAIN); - writer.write(Mono.just("body"), forClass(String.class), TEXT_PLAIN, this.response, NO_HINTS).block(); assertEquals(4, this.response.getHeaders().getContentLength()); } + @Test // gh-22952 + public void monoBodyDoesNotCancelEncodedFlux() { + Mono inputStream = Mono.just("body") + .doOnCancel(() -> { + throw new AssertionError("Cancel signal not expected"); + }); + new EncoderHttpMessageWriter<>(CharSequenceEncoder.allMimeTypes()) + .write(inputStream, forClass(String.class), TEXT_PLAIN, this.response, NO_HINTS) + .block(); + } + @Test // SPR-17220 public void emptyBodyWritten() { HttpMessageWriter writer = getWriter(MimeTypeUtils.TEXT_PLAIN);