如何使用Play2 Iteratees来使用具有不同事件名称的流式HTTP?

时间:2015-05-06 00:18:47

标签: scala playframework functional-programming streaming iterate

我想要一种通过HTTP消费服务器发送事件(SSE)的功能方式(或某些人称之为流HTTP)。通过示例(Scala: Receiving Server-Sent-Events)我发现,当事件名称设置为" message时,Play2 Iteratees可以很好地使用其WS客户端。"这是"消息"流看起来像:

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"}
...

但是当我设置"事件"除了" message"之外的其他一些价值Iteratee在读取第一个值后立即返回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)

到目前为止,我只使用了Jersey Java库,其语义与EventSource JavaScript客户端非常相似;但它没有组成,似乎只支持SSE的单线程消费。我更愿意使用Play2 WS + Iteratee库。我怎样才能做到这一点?

0 个答案:

没有答案