fix: Strip only a single leading space from SSE data field (#5532)
## Issue Closes #5531 ## Change `DefaultServerSentEventParser` applied `content.trim()` to each `data:` field value, removing all leading and trailing whitespace. The WHATWG HTML Living Standard (Server-sent events, "Interpreting an event stream") requires removing only a single leading U+0020 SPACE when present; further leading whitespace and all trailing whitespace must be preserved. The old behavior corrupted values with multiple leading spaces, trailing spaces, or indentation, which matters for LLM token streaming, the module's primary use. This PR replaces `trim()` with a single-leading-space strip on the `data:` branch only; `event:` handling is left unchanged to keep the change minimal. Added unit tests for preserving additional leading whitespace, preserving trailing whitespace, and leaving values with no leading space unchanged. Existing parameterized and multi-line tests remain green (each line still loses one leading space). Could a maintainer confirm whether the original `trim()` was intentional normalization rather than a bug? ## General checklist - [x] There are no breaking changes (API, behaviour) - [x] I have added unit and/or integration tests for my change - [x] The tests cover both positive and negative cases - [x] I have manually run all the unit and integration tests in the module I have added/changed, and they are all green - [ ] I have manually run all the unit and integration tests in the [core](https://github.com/langchain4j/langchain4j/tree/main/langchain4j-core) and [main](https://github.com/langchain4j/langchain4j/tree/main/langchain4j) modules, and they are all green - [ ] I have added/updated the [documentation](https://github.com/langchain4j/langchain4j/tree/main/docs/docs) - [ ] I have added an example in the [examples repo](https://github.com/langchain4j/langchain4j-examples) (only for "big" features) - [ ] I have added/updated [Spring Boot starter(s)](https://github.com/langchain4j/langchain4j-spring) (if applicable) <!-- Not applicable: no new maven module, no embedding store integration changes. -->
This commit is contained in:
parent
6d1af7497a
commit
ba36ad4eeb
|
|
@ -36,10 +36,15 @@ public class DefaultServerSentEventParser implements ServerSentEventParser {
|
|||
event = line.substring("event:".length()).trim();
|
||||
} else if (line.startsWith("data:")) {
|
||||
String content = line.substring("data:".length());
|
||||
// Per the WHATWG HTML Living Standard (Server-sent events), if the field value
|
||||
// starts with a single U+0020 SPACE, only that one space is removed.
|
||||
if (content.startsWith(" ")) {
|
||||
content = content.substring(1);
|
||||
}
|
||||
if (!data.isEmpty()) {
|
||||
data.append("\n");
|
||||
}
|
||||
data.append(content.trim());
|
||||
data.append(content);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -130,6 +130,48 @@ class DefaultServerSentEventParserTest {
|
|||
verify(listener, never()).onEvent(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldPreserveAdditionalLeadingWhitespaceInData() {
|
||||
|
||||
// given
|
||||
String input = "data: indented\n\n";
|
||||
InputStream stream = new ByteArrayInputStream(input.getBytes(UTF_8));
|
||||
|
||||
// when
|
||||
parser.parse(stream, listener);
|
||||
|
||||
// then
|
||||
verify(listener).onEvent(eq(new ServerSentEvent(null, " indented")), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldPreserveTrailingWhitespaceInData() {
|
||||
|
||||
// given
|
||||
String input = "data: trailing \n\n";
|
||||
InputStream stream = new ByteArrayInputStream(input.getBytes(UTF_8));
|
||||
|
||||
// when
|
||||
parser.parse(stream, listener);
|
||||
|
||||
// then
|
||||
verify(listener).onEvent(eq(new ServerSentEvent(null, "trailing ")), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldNotRemoveAnyCharacterWhenDataHasNoLeadingSpace() {
|
||||
|
||||
// given
|
||||
String input = "data:nospace\n\n";
|
||||
InputStream stream = new ByteArrayInputStream(input.getBytes(UTF_8));
|
||||
|
||||
// when
|
||||
parser.parse(stream, listener);
|
||||
|
||||
// then
|
||||
verify(listener).onEvent(eq(new ServerSentEvent(null, "nospace")), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldHandleIOException() {
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue