Skip to content

Commit 256a6fe

Browse files
committed
Fix memory leak for ServerSentEventHttpMessageWriter
This commit fixes a memory leak in ServerSentEventHttpMessageWriter that occurs when the input stream contains an error. Test added as well. Issue: SPR-17419
1 parent d28b73a commit 256a6fe

File tree

2 files changed

+26
-5
lines changed

2 files changed

+26
-5
lines changed

spring-web/src/main/java/org/springframework/http/codec/ServerSentEventHttpMessageWriter.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -180,8 +180,8 @@ private <T> Flux<DataBuffer> encodeData(@Nullable T data, ResolvableType valueTy
180180
private Mono<DataBuffer> encodeText(CharSequence text, MediaType mediaType, DataBufferFactory bufferFactory) {
181181
Assert.notNull(mediaType.getCharset(), "Expected MediaType with charset");
182182
byte[] bytes = text.toString().getBytes(mediaType.getCharset());
183-
DataBuffer buffer = bufferFactory.allocateBuffer(bytes.length).write(bytes);
184-
return Mono.just(buffer);
183+
return Mono.defer(() ->
184+
Mono.just(bufferFactory.allocateBuffer(bytes.length).write(bytes)));
185185
}
186186

187187
@Override

spring-web/src/test/java/org/springframework/http/codec/ServerSentEventHttpMessageWriterTests.java

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@
3737
import org.springframework.mock.http.server.reactive.test.MockServerHttpResponse;
3838

3939
import static org.junit.Assert.*;
40-
import static org.springframework.core.ResolvableType.*;
40+
import static org.springframework.core.ResolvableType.forClass;
4141

4242
/**
4343
* Unit tests for {@link ServerSentEventHttpMessageWriter}.
@@ -81,6 +81,24 @@ public void writeServerSentEvent() {
8181
.verify();
8282
}
8383

84+
@Test
85+
@SuppressWarnings("rawtypes")
86+
public void writeServerSentEventError() {
87+
ServerSentEvent<?> event = ServerSentEvent.builder().data("bar").id("c42").event("foo")
88+
.comment("bla\nbla bla\nbla bla bla").retry(Duration.ofMillis(123L)).build();
89+
90+
Flux<ServerSentEvent> source = Flux.concat(
91+
Flux.just(event),
92+
Flux.error(new RuntimeException()));
93+
MockServerHttpResponse outputMessage = new MockServerHttpResponse();
94+
95+
Mono<Void> result = this.messageWriter.write(source, forClass(ServerSentEvent.class),
96+
MediaType.TEXT_EVENT_STREAM, outputMessage, HINTS);
97+
98+
StepVerifier.create(result)
99+
.verifyError(RuntimeException.class);
100+
}
101+
84102
@Test
85103
public void writeString() {
86104
Flux<String> source = Flux.just("foo", "bar");
@@ -172,8 +190,11 @@ private <T> void testWrite(Publisher<T> source, MockServerHttpResponse response,
172190
private <T> void testWrite(
173191
Publisher<T> source, MediaType mediaType, MockServerHttpResponse response, Class<T> clazz) {
174192

175-
this.messageWriter.write(source, forClass(clazz), mediaType, response, HINTS)
176-
.block(Duration.ofMillis(5000));
193+
Mono<Void> result =
194+
this.messageWriter.write(source, forClass(clazz), mediaType, response, HINTS);
195+
196+
StepVerifier.create(result)
197+
.verifyComplete();
177198
}
178199

179200
}

0 commit comments

Comments
 (0)