diff --git a/spring-web/src/main/java/org/springframework/http/codec/ServerSentEventHttpMessageReader.java b/spring-web/src/main/java/org/springframework/http/codec/ServerSentEventHttpMessageReader.java index b6752741b74..3966bcba7d7 100644 --- a/spring-web/src/main/java/org/springframework/http/codec/ServerSentEventHttpMessageReader.java +++ b/spring-web/src/main/java/org/springframework/http/codec/ServerSentEventHttpMessageReader.java @@ -145,15 +145,15 @@ public class ServerSentEventHttpMessageReader implements HttpMessageReader 5) { int index = (line.charAt(5) != ' ' ? 5 : 6); if (length > index) { - data = (data != null ? data : new StringBuilder()); data.append(line, index, line.length()); - data.append('\n'); } } + data.append('\n'); } else if (shouldWrap) { if (line.startsWith("id:")) { diff --git a/spring-web/src/test/java/org/springframework/http/codec/ServerSentEventHttpMessageReaderTests.java b/spring-web/src/test/java/org/springframework/http/codec/ServerSentEventHttpMessageReaderTests.java index 4bcf7c8c11d..3693bed3755 100644 --- a/spring-web/src/test/java/org/springframework/http/codec/ServerSentEventHttpMessageReaderTests.java +++ b/spring-web/src/test/java/org/springframework/http/codec/ServerSentEventHttpMessageReaderTests.java @@ -67,7 +67,9 @@ class ServerSentEventHttpMessageReaderTests extends AbstractLeakCheckingTests { MockServerHttpRequest request = MockServerHttpRequest.post("/") .body(Mono.just(stringBuffer( "id:c42\nevent:foo\nretry:123\n:bla\n:bla bla\n:bla bla bla\ndata:bar\n\n" + - "id:c43\nevent:bar\nretry:456\ndata:baz\n\ndata:\n\ndata: \n\n"))); + "id:c43\nevent:bar\nretry:456\ndata:baz\n\n" + + "data:\n\n" + + "data: \n\n"))); Flux events = this.reader .read(ResolvableType.forClassWithGenerics(ServerSentEvent.class, String.class), @@ -78,8 +80,8 @@ class ServerSentEventHttpMessageReaderTests extends AbstractLeakCheckingTests { .retry(Duration.ofMillis(123)).comment("bla\nbla bla\nbla bla bla").data("bar").build()) .expectNext(ServerSentEvent.builder().id("c43").event("bar") .retry(Duration.ofMillis(456)).data("baz").build()) - .consumeNextWith(event -> assertThat(event.data()).isNull()) - .consumeNextWith(event -> assertThat(event.data()).isNull()) + .consumeNextWith(event -> assertThat(event.data()).isEqualTo("")) + .consumeNextWith(event -> assertThat(event.data()).isEqualTo("")) .expectComplete() .verify(); } @@ -135,6 +137,18 @@ class ServerSentEventHttpMessageReaderTests extends AbstractLeakCheckingTests { .verify(); } + @Test // gh-35412 + void emptyLines() { + MockServerHttpRequest request = MockServerHttpRequest.post("/") + .body(Mono.just(stringBuffer("id:1\nevent:message\ndata:\ndata:\ndata:\n\n"))); + + Flux data = new ServerSentEventHttpMessageReader() + .read(ResolvableType.forClass(String.class), request, Collections.emptyMap()) + .cast(String.class); + + StepVerifier.create(data).expectNext("\n\n").verifyComplete(); + } + @Test void readPojo() { MockServerHttpRequest request = MockServerHttpRequest.post("/")