From b6b65369bbc3a3998d3e1efa0e209e1d327954f9 Mon Sep 17 00:00:00 2001 From: Vladimir Kukushkin Date: Wed, 29 Jul 2026 13:11:03 +0100 Subject: [PATCH 1/3] strip newlines when parsing events --- .../EventStreams/ServerSentEventsEncoding.swift | 11 +++++++++-- .../Test_ServerSentEventsEncoding.swift | 14 ++++++++++++++ 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/Sources/OpenAPIRuntime/EventStreams/ServerSentEventsEncoding.swift b/Sources/OpenAPIRuntime/EventStreams/ServerSentEventsEncoding.swift index 99fe9590..cf6d7336 100644 --- a/Sources/OpenAPIRuntime/EventStreams/ServerSentEventsEncoding.swift +++ b/Sources/OpenAPIRuntime/EventStreams/ServerSentEventsEncoding.swift @@ -167,8 +167,15 @@ extension ServerSentEventsSerializationSequence.Iterator { buffer.append(contentsOf: value.utf8) buffer.append(ASCII.lf) } - if let id = value.id { encodeField(name: "id", value: id) } - if let event = value.event { encodeField(name: "event", value: event) } + // Field values must not contain any newline characters, as they're used to + // delimit fields and events, so strip any that are present. + func removingNewlines(_ value: some StringProtocol) -> String { + value.replacingOccurrences(of: "\r\n", with: "") + .replacingOccurrences(of: "\r", with: "") + .replacingOccurrences(of: "\n", with: "") + } + if let id = value.id { encodeField(name: "id", value: removingNewlines(id)) } + if let event = value.event { encodeField(name: "event", value: removingNewlines(event)) } if let retry = value.retry { encodeField(name: "retry", value: String(retry)) } if let data = value.data { // Normalize the data section by replacing CRLF and CR with just LF. diff --git a/Tests/OpenAPIRuntimeTests/EventStreams/Test_ServerSentEventsEncoding.swift b/Tests/OpenAPIRuntimeTests/EventStreams/Test_ServerSentEventsEncoding.swift index 03f4bf6a..75569978 100644 --- a/Tests/OpenAPIRuntimeTests/EventStreams/Test_ServerSentEventsEncoding.swift +++ b/Tests/OpenAPIRuntimeTests/EventStreams/Test_ServerSentEventsEncoding.swift @@ -74,6 +74,20 @@ final class Test_ServerSentEventsEncoding: Test_Runtime { data: This is a message with an ID. + """# + ) + } + func testIdAndEventStripNewlines() async throws { + // The id and event fields must not contain newlines, as they would otherwise be + // misinterpreted as the start of another field. + try await _test( + input: [.init(id: "123\r\n456", event: "custom\nEvent\r", data: "hello")], + output: #""" + id: 123456 + event: customEvent + data: hello + + """# ) } From 85764c63beb3777a1077cf49ae68997c65b9a593 Mon Sep 17 00:00:00 2001 From: Vladimir Kukushkin Date: Thu, 30 Jul 2026 10:24:59 +0100 Subject: [PATCH 2/3] wat --- .../OpenAPIRuntime/EventStreams/ServerSentEventsEncoding.swift | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Sources/OpenAPIRuntime/EventStreams/ServerSentEventsEncoding.swift b/Sources/OpenAPIRuntime/EventStreams/ServerSentEventsEncoding.swift index cf6d7336..02460379 100644 --- a/Sources/OpenAPIRuntime/EventStreams/ServerSentEventsEncoding.swift +++ b/Sources/OpenAPIRuntime/EventStreams/ServerSentEventsEncoding.swift @@ -170,8 +170,7 @@ extension ServerSentEventsSerializationSequence.Iterator { // Field values must not contain any newline characters, as they're used to // delimit fields and events, so strip any that are present. func removingNewlines(_ value: some StringProtocol) -> String { - value.replacingOccurrences(of: "\r\n", with: "") - .replacingOccurrences(of: "\r", with: "") + value.replacingOccurrences(of: "\r\n", with: "").replacingOccurrences(of: "\r", with: "") .replacingOccurrences(of: "\n", with: "") } if let id = value.id { encodeField(name: "id", value: removingNewlines(id)) } From b8d51c8fba52550779f015e95582f704189a3178 Mon Sep 17 00:00:00 2001 From: Vladimir Kukushkin Date: Thu, 30 Jul 2026 15:35:20 +0100 Subject: [PATCH 3/3] Update Sources/OpenAPIRuntime/EventStreams/ServerSentEventsEncoding.swift Co-authored-by: Honza Dvorsky --- .../OpenAPIRuntime/EventStreams/ServerSentEventsEncoding.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/OpenAPIRuntime/EventStreams/ServerSentEventsEncoding.swift b/Sources/OpenAPIRuntime/EventStreams/ServerSentEventsEncoding.swift index 02460379..eca89e6e 100644 --- a/Sources/OpenAPIRuntime/EventStreams/ServerSentEventsEncoding.swift +++ b/Sources/OpenAPIRuntime/EventStreams/ServerSentEventsEncoding.swift @@ -167,7 +167,7 @@ extension ServerSentEventsSerializationSequence.Iterator { buffer.append(contentsOf: value.utf8) buffer.append(ASCII.lf) } - // Field values must not contain any newline characters, as they're used to + // `id` and `event` values must not contain any newline characters, as they're used to // delimit fields and events, so strip any that are present. func removingNewlines(_ value: some StringProtocol) -> String { value.replacingOccurrences(of: "\r\n", with: "").replacingOccurrences(of: "\r", with: "")