mirror of
https://github.com/spring-projects/spring-framework.git
synced 2026-09-22 22:19:03 +00:00
Enforce "data: " prefix for outgoing SSE data payloads
Prior to this commit, SSE support in Spring would write payloads with the "data:" prefix (without space). While this is OK with the standard, this makes it harder for implementations to support reading and writing payloads with Spring (the round trip use case). This commit introduces a breaking change and now enforces "data: " in all variants. This has the potential of breaking some low level test suites with text/plain or custom media types, but this should overall make the situation better for developers. Closes gh-37242
This commit is contained in:
+18
-18
@@ -85,7 +85,7 @@ class ServerSentEventHttpMessageWriterTests extends AbstractDataBufferAllocating
|
||||
|
||||
StepVerifier.create(outputMessage.getBody())
|
||||
.consumeNextWith(stringConsumer(
|
||||
"id:c42\nevent:foo\nretry:123\n:bla\n:bla bla\n:bla bla bla\ndata:bar\n\n"))
|
||||
"id:c42\nevent:foo\nretry:123\n:bla\n:bla bla\n:bla bla bla\ndata: bar\n\n"))
|
||||
.expectComplete()
|
||||
.verify();
|
||||
}
|
||||
@@ -99,8 +99,8 @@ class ServerSentEventHttpMessageWriterTests extends AbstractDataBufferAllocating
|
||||
testWrite(source, outputMessage, String.class);
|
||||
|
||||
StepVerifier.create(outputMessage.getBody())
|
||||
.consumeNextWith(stringConsumer("data:foo\n\n"))
|
||||
.consumeNextWith(stringConsumer("data:bar\n\n"))
|
||||
.consumeNextWith(stringConsumer("data: foo\n\n"))
|
||||
.consumeNextWith(stringConsumer("data: bar\n\n"))
|
||||
.expectComplete()
|
||||
.verify();
|
||||
}
|
||||
@@ -114,9 +114,9 @@ class ServerSentEventHttpMessageWriterTests extends AbstractDataBufferAllocating
|
||||
testWrite(source, outputMessage, String.class);
|
||||
|
||||
StepVerifier.create(outputMessage.getBody())
|
||||
.consumeNextWith(stringConsumer("data:first\ndata:second\n\n"))
|
||||
.consumeNextWith(stringConsumer("data:first\ndata:second\n\n"))
|
||||
.consumeNextWith(stringConsumer("data:first\ndata:second\n\n"))
|
||||
.consumeNextWith(stringConsumer("data: first\ndata: second\n\n"))
|
||||
.consumeNextWith(stringConsumer("data: first\ndata: second\n\n"))
|
||||
.consumeNextWith(stringConsumer("data: first\ndata: second\n\n"))
|
||||
.expectComplete()
|
||||
.verify();
|
||||
}
|
||||
@@ -136,7 +136,7 @@ class ServerSentEventHttpMessageWriterTests extends AbstractDataBufferAllocating
|
||||
.consumeNextWith(dataBuffer -> {
|
||||
String value = dataBuffer.toString(charset);
|
||||
DataBufferUtils.release(dataBuffer);
|
||||
assertThat(value).isEqualTo("data:\u00A3\n\n");
|
||||
assertThat(value).isEqualTo("data: \u00A3\n\n");
|
||||
})
|
||||
.expectComplete()
|
||||
.verify();
|
||||
@@ -151,10 +151,10 @@ class ServerSentEventHttpMessageWriterTests extends AbstractDataBufferAllocating
|
||||
testWrite(source, outputMessage, Pojo.class);
|
||||
|
||||
StepVerifier.create(outputMessage.getBody())
|
||||
.consumeNextWith(stringConsumer("data:"))
|
||||
.consumeNextWith(stringConsumer("data: "))
|
||||
.consumeNextWith(stringConsumer("{\"foo\":\"foofoo\",\"bar\":\"barbar\"}"))
|
||||
.consumeNextWith(stringConsumer("\n\n"))
|
||||
.consumeNextWith(stringConsumer("data:"))
|
||||
.consumeNextWith(stringConsumer("data: "))
|
||||
.consumeNextWith(stringConsumer("{\"foo\":\"foofoofoo\",\"bar\":\"barbarbar\"}"))
|
||||
.consumeNextWith(stringConsumer("\n\n"))
|
||||
.expectComplete()
|
||||
@@ -173,19 +173,19 @@ class ServerSentEventHttpMessageWriterTests extends AbstractDataBufferAllocating
|
||||
testWrite(source, outputMessage, Pojo.class);
|
||||
|
||||
StepVerifier.create(outputMessage.getBody())
|
||||
.consumeNextWith(stringConsumer("data:"))
|
||||
.consumeNextWith(stringConsumer("data: "))
|
||||
.consumeNextWith(stringConsumer("""
|
||||
{
|
||||
data: "foo" : "foofoo",
|
||||
data: "bar" : "barbar"
|
||||
data:}"""))
|
||||
data: "foo" : "foofoo",
|
||||
data: "bar" : "barbar"
|
||||
data: }"""))
|
||||
.consumeNextWith(stringConsumer("\n\n"))
|
||||
.consumeNextWith(stringConsumer("data:"))
|
||||
.consumeNextWith(stringConsumer("data: "))
|
||||
.consumeNextWith(stringConsumer("""
|
||||
{
|
||||
data: "foo" : "foofoofoo",
|
||||
data: "bar" : "barbarbar"
|
||||
data:}"""))
|
||||
data: "foo" : "foofoofoo",
|
||||
data: "bar" : "barbarbar"
|
||||
data: }"""))
|
||||
.consumeNextWith(stringConsumer("\n\n"))
|
||||
.expectComplete()
|
||||
.verify();
|
||||
@@ -203,7 +203,7 @@ class ServerSentEventHttpMessageWriterTests extends AbstractDataBufferAllocating
|
||||
|
||||
assertThat(outputMessage.getHeaders().getContentType()).isEqualTo(mediaType);
|
||||
StepVerifier.create(outputMessage.getBody())
|
||||
.consumeNextWith(stringConsumer("data:", charset))
|
||||
.consumeNextWith(stringConsumer("data: ", charset))
|
||||
.consumeNextWith(stringConsumer("{\"foo\":\"foo\uD834\uDD1E\",\"bar\":\"bar\uD834\uDD1E\"}", charset))
|
||||
.consumeNextWith(stringConsumer("\n\n", charset))
|
||||
.expectComplete()
|
||||
|
||||
@@ -51,7 +51,7 @@ class ServerSentEventTests {
|
||||
void supportMultiLineComments(String newLine, String description) {
|
||||
ServerSentEvent<String> event = ServerSentEvent.<String>builder()
|
||||
.comment("foo" + newLine + "bar" + newLine + "baz").data("payload").build();
|
||||
assertThat(event.format()).isEqualTo(":foo\n:bar\n:baz\ndata:");
|
||||
assertThat(event.format()).isEqualTo(":foo\n:bar\n:baz\ndata: ");
|
||||
}
|
||||
|
||||
private static Stream<Arguments> newLineCharacters() {
|
||||
|
||||
+1
-1
@@ -415,7 +415,7 @@ class JacksonJsonHttpMessageConverterTests {
|
||||
MediaType.APPLICATION_JSON, outputMessage, null);
|
||||
String result = outputMessage.getBodyAsString(StandardCharsets.UTF_8);
|
||||
|
||||
assertThat(result).isEqualTo("{\ndata: \"name\" : \"Jason\"\ndata:}");
|
||||
assertThat(result).isEqualTo("{\ndata: \"name\" : \"Jason\"\ndata: }");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
+1
-1
@@ -385,7 +385,7 @@ class MappingJackson2HttpMessageConverterTests {
|
||||
this.converter.writeInternal(bean, null, outputMessage);
|
||||
String result = outputMessage.getBodyAsString(StandardCharsets.UTF_8);
|
||||
|
||||
assertThat(result).isEqualTo("{\ndata: \"name\" : \"Jason\"\ndata:}");
|
||||
assertThat(result).isEqualTo("{\ndata: \"name\" : \"Jason\"\ndata: }");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -44,9 +44,9 @@ class SseUtilsTests {
|
||||
@MethodSource("newLineCharacters")
|
||||
void appendFieldValueReplacesLineSeparatorWithFieldPrefix(String newLine, String description) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("data:");
|
||||
sb.append("data: ");
|
||||
SseUtils.appendFieldValue("data", "first" + newLine + "second", sb);
|
||||
assertThat(sb).hasToString("data:first\ndata:second");
|
||||
assertThat(sb).hasToString("data: first\ndata: second");
|
||||
}
|
||||
|
||||
@ParameterizedTest(name = "{1}")
|
||||
|
||||
Reference in New Issue
Block a user