diff --git a/langchain4j-http-client/src/main/java/dev/langchain4j/http/client/sse/DefaultServerSentEventParser.java b/langchain4j-http-client/src/main/java/dev/langchain4j/http/client/sse/DefaultServerSentEventParser.java index 271c0a0dd4..c7988c3f64 100644 --- a/langchain4j-http-client/src/main/java/dev/langchain4j/http/client/sse/DefaultServerSentEventParser.java +++ b/langchain4j-http-client/src/main/java/dev/langchain4j/http/client/sse/DefaultServerSentEventParser.java @@ -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); } } diff --git a/langchain4j-http-client/src/test/java/dev/langchain4j/http/client/sse/DefaultServerSentEventParserTest.java b/langchain4j-http-client/src/test/java/dev/langchain4j/http/client/sse/DefaultServerSentEventParserTest.java index ec5212c98e..25d093a90f 100644 --- a/langchain4j-http-client/src/test/java/dev/langchain4j/http/client/sse/DefaultServerSentEventParserTest.java +++ b/langchain4j-http-client/src/test/java/dev/langchain4j/http/client/sse/DefaultServerSentEventParserTest.java @@ -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() {