Как использовать Play2 Iteratees для использования потокового HTTP с разными именами событий?

Мне нужен функциональный способ потребления отправленных сервером событий (SSE) по HTTP (или потокового HTTP, как некоторые его называют). На примерах ( Scala: Receiving Server-Sent-Events) я обнаружил, что итераторы Play2 хорошо работают со своим клиентом WS, когда для имени события установлено "message". Вот как выглядит поток "сообщений":

GET http://streaming.server.com/temperature

event: message
data: {"room":"room1","temp":71,"time":"2015-05-06T00:23:10.203+02:00"}

event: message
data: {"room":"room1","temp":70,"time":"2015-05-06T00:31:18.873+02:00"}
...

А вот как выглядит мой веб-клиент:

import com.ning.http.client.AsyncHttpClientConfig.Builder
import play.api.libs.iteratee.Iteratee
import play.api.libs.iteratee.Execution.Implicits.defaultExecutionContext
import play.api.libs.ws.ning.NingWSClient

object Client extends App {
  val client = new NingWSClient(new Builder().build())
  def print = Iteratee.foreach { chunk: Array[Byte] => println(new String(chunk)) }
  client.url("http://streaming.server.com/temperature").get(_ => print)
}

с выводом, который он напечатал на моей консоли:

$ sbt run
[info] Running Client 
data: {"room":"room1","temp": 70, "time":"2015-05-06T00:31:14.193+02:00"}
data: {"room":"room1","temp": 70, "time":"2015-05-06T00:31:18.873+02:00"}
...

Но когда я устанавливаю для "события" какое-либо иное значение, чем "сообщение", Итератор немедленно возвращает Done сигнал только после чтения первого значения, а затем останавливает поток. Спецификация, которую я должен удовлетворить, использует "event":"put", Ниже приведен пример того, как выглядит поток "put":

GET http://streaming.server.com/temperature

event: put
data: {"room":"room1","temp":71,"time":"2015-05-06T00:39:14.281+02:00"}

event: put
data: {"room":"room1","temp":70,"time":"2015-05-06T00:39:18.778+02:00"}
...

Я обнаружил это, когда я добавил onComplete() обработчик в конце и соответствует на Success бывает так:

client.url("http://streaming.server.com/temperature").get(_ => print).onComplete {
  case Success(s) => println(s)
  case Failure(s) => println(f.getMessage)
}

Этот код теперь печатает:

$ sbt run
[info] Running Client
data: {"room":"room1","temp": 71, "time":"2015-05-06T00:39:14.281+02:00"}
Done((),Empty)

До сих пор я имел успех только с библиотекой Джерси для Java, семантика которой очень похожа на JavaScript-клиент EventSource; однако он не скомпонован и, по-видимому, поддерживает только однопоточное потребление SSE. Я бы предпочел использовать библиотеки Play2 WS+Iteratee. Как мне этого добиться?

0 ответов

Другие вопросы по тегам