Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 10 additions & 2 deletions core/src/main/scala/sttp/model/sse/ServerSentEvent.scala
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,7 @@ object ServerSentEvent {
event.foldLeft(ServerSentEvent()) { (event, line) =>
if (line.startsWith("data:")) combineData(event, removeLeadingSpace(line.substring(5)))
else if (line.startsWith("id:")) event.copy(id = Some(removeLeadingSpace(line.substring(3))))
else if (line.startsWith("retry:"))
event.copy(retry = ParseUtils.toIntOption(removeLeadingSpace(line.substring(6))))
else if (line.startsWith("retry:")) combineRetry(event, removeLeadingSpace(line.substring(6)))
else if (line.startsWith("event:")) event.copy(eventType = Some(removeLeadingSpace(line.substring(6))))
else if (line == "data") combineData(event, "")
else if (line == "id") event.copy(id = Some(""))
Expand All @@ -45,6 +44,15 @@ object ServerSentEvent {
}
}

/** The spec accepts only ASCII digits here, and says to ignore the field otherwise - so a value that isn't accepted
* leaves any previously parsed one in place. `toIntOption` is still needed to reject a value too large for an `Int`,
* and `isDigit` would not do instead of the range check: it, like `toIntOption`, accepts non-ASCII digits.
*/
private def combineRetry(event: ServerSentEvent, newRetry: String): ServerSentEvent =
if (newRetry.nonEmpty && newRetry.forall(c => c >= '0' && c <= '9'))
ParseUtils.toIntOption(newRetry).fold(event)(retry => event.copy(retry = Some(retry)))
else event

private def combineData(event: ServerSentEvent, newData: String): ServerSentEvent = {
event match {
case e @ ServerSentEvent(Some(oldData), _, _, _) => e.copy(data = Some(s"$oldData\n$newData"))
Expand Down
10 changes: 10 additions & 0 deletions core/src/test/scala/sttp/model/sse/ServerSentEventTest.scala
Original file line number Diff line number Diff line change
Expand Up @@ -108,4 +108,14 @@ class ServerSentEventTest extends AnyFlatSpec with Matchers {
val sse = ServerSentEvent(Some("a\n"))
ServerSentEvent.parse(sse.toString.split("\n").toList) shouldBe sse
}

"parse" should "keep an earlier retry value when a later one is not a number" in {
ServerSentEvent.parse(List("retry: 5", "retry: x")).retry shouldBe Some(5)
}

"parse" should "ignore a retry value that is not made up of ASCII digits" in {
ServerSentEvent.parse(List("retry: -1")).retry shouldBe None
ServerSentEvent.parse(List("retry: +5")).retry shouldBe None
ServerSentEvent.parse(List("retry: ٥")).retry shouldBe None
}
}
Loading