ITADN

ServerSentEvent.encoded silently turns newlines in eventType / id into spaces

#4131Openhaskiindahouse 创建于 2026-05-10
H
haskiindahousecommented
**Describe the bug** Per the [SSE spec](https://html.spec.whatwg.org/multipage/server-sent-events.html#server-sent-events) the `event:` and `id:` fields are single-line — they MUST NOT contain LF or CR. The encoder accepts multi-line values silently and joins the lines with a space, which corrupts the value: ```scala //> using scala 3.8.3 //> using dep dev.zio::zio-http:3.0.x import zio.http.ServerSentEvent @main def repro(): Unit = val ev = ServerSentEvent[String]( data = "hello", eventType = Some("foo\nbar"), id = Some("id1\nid2"), ) println(ev.encoded) ``` Output: ``` event: foo bar data: hello id: id1 id2 ``` A decoder reading that produces `eventType = "foo bar"`, not `"foo\nbar"` — the round-trip is broken, and the data is silently changed. **Source** https://github.com/zio/zio-http/blob/02e1b6b60fc26794cec053d4b0690a64f3c39a9f/zio-http/shared/src/main/scala/zio/http/ServerSentEvent.scala ```scala eventType.foreach { et => sb.append("event: ") val iterator = et.linesIterator var hasNext = iterator.hasNext while (hasNext) { sb.append(iterator.next()) hasNext = iterator.hasNext if (hasNext) sb.append(' ') // space-join, silent corruption } sb.append('\n') } ``` The same shape is used for `id` a few lines down. **Expected behaviour** Either reject multi-line `event` / `id` (throw or surface a `Left`), or strip newlines (`et.replace("\n", "").replace("\r", "")`), or use only the first line. Space-joining is the worst option because the output looks well-formed but means something different. **Additional context** The `data:` field is correctly handled with one `data:` prefix per line, which matches the spec. Only `event` and `id` have the space-join bug. Happy to PR.
0 条评论