When I was using SseEventBuilder in spring mvc 5.3.x, I noticed that no spaces were added when constructing "data:" in the data method of the SseEventBuilderImpl implementation class. As a result, when the output is in markdown format, when the content that starts with a space appears in the segmented interception, the space will be lost on the front end. When reviewing the protocol standards of SSE, it was found that when a space appears after ":" in the content, the space is removed. See server-sent-events 9.2.6, which references
If the line starts with a U+003A COLON character (:) Ignore the line. If the line contains a U+003A COLON character (:) Collect the characters on the line before the first U+003A COLON character (:), and let be that string.field Collect the characters on the line after the first U+003A COLON character (:), and let be that string. If starts with a U+0020 SPACE character, remove it from .valuevaluevalue
So I suggest modifying append("data:")
in the SseEventBuilderImpl.data
method of spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/SseEmitter.java
to append("data: ");
The other versions are modified in the same way
Comment From: quaff
According to the reference, data:value
is same to data: value
, why do you think data:value
is not standards compliant?
Comment From: bclozel
Spring Framework is sending valid SSE chunks. In this case, I think the application is responsible for encoding/escaping the payloads to account for this.
Comment From: icguy
the application is responsible for encoding/escaping the payloads to account for this
I believe this is incorrect. Spring is sending valid SSE chunks but they do not contain the supplied payload. I've implemented a minimal reproduction: https://github.com/icguy/spring33963
val payloads = listOf("These", " words", " should", " arrive", " with", " spaces", " between", " them")
val emitter = SseEmitter()
thread {
for (p in payloads) {
val event = SseEmitter.event().data(p).build()
emitter.send(event)
}
emitter.complete()
}
return emitter
As you can see the payload for most events starts with a space character.
This is the raw response:
data:These
data: words
data: should
data: arrive
data: with
data: spaces
data: between
data: them
But according to the spec during parsing on the client side if value starts with a U+0020 SPACE character, remove it from value.
This is the behavior of the minimal client I wrote to demonstrate the issue (also in the repository) which simply concatenates the values received via an EventSource object:
So in conclusion: no, Spring doesn't send the payload in a standard compliant manner unless the intention was to implicitly drop a leading space from the payload.
Comment From: bclozel
@icguy SseEmitter
can accept many types as data. If you are providing such strings directly, I would argue that managing the space character here should be done by your implementation.