繁体   English   中英

akka-http chunked响应连接

[英]akka-http chunked response concatenation

我正在使用akka-http向http服务发出请求,该服务发送回chunked响应。 这就是代码的相关位置:

val httpRequest: HttpRequest = //build the request
val request = Http().singleRequest(httpRequest)
request.flatMap { response =>
    response.entity.dataBytes.runForeach { chunk =>
        println("-----")
        println(chunk.utf8String)
    }
}

并且命令行中生成的输出如下所示:

-----
{"data":
-----
"some text"}

-----
{"data":
-----
"this is a longer
-----
text"}

-----
{"data": "txt"}

-----
...

逻辑数据 - 在这种情况下,json以行尾符号\\r\\n结尾,但问题是,json并不总是适合单个http响应块,如上例所示清晰可见。

我的问题是 - 如何将传入的chunked数据连接成完整的jsons,以便生成的容器类型仍然保持Source[Out,M1]Flow[In,Out,M2] 我想遵循akka-stream

更新:值得一提的是,响应是无止境的,聚合必须是实时完成的

找到了解决方案:

val request: HttpRequest = //build the request
request.flatMap { response =>
    response.entity.dataBytes.scan("")((acc, curr) => if (acc.contains("\r\n")) curr.utf8String else acc + curr.utf8String)
        .filter(_.contains("\r\n"))
        .runForeach { json =>
            println("-----")
            println(json)
        }
}

akka流文档在食谱中有一个条目,用于解决这个问题:“从ByteString流中解析行”。 他们的解决方案非常冗长,但也可以处理单个块可以包含多行的情况。 这似乎更强大,因为块大小可能会变得足够大以处理多个json消息。

response.entity.dataBytes
.via(Framing.delimiter(ByteString("\n"), maximumFrameLength = 8096))
.mapAsyncUnordered(Runtime.getRuntime.availableProcessors()) { data =>
  if (response.status == OK) {
    val event: Future[Event] = Unmarshal(data).to[Event]
    event.foreach(x => log.debug("Received event: {}.", x))
    event.map(Right(_))
  } else {
    Future.successful(data.utf8String)
      .map(Left(_))
  }
}

唯一的要求是您知道一条记录的最大大小。 如果从较小的东西开始,如果记录大于限制,则默认行为将失败。 您可以将其设置为截断而不是失败,但是JSON片段没有任何意义。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM