我正在从Play迁移到Akka HTTP。我有jar依赖项代码,我无法更改它接受
Flow[Array[Byte],Array[Byte],Any]
这是Play为WebSocket连接提供的。 在Akka HTTP中,定义为
Flow[Message,Message,Any]
我需要两个定义之间的转换。我是Akka http的新手,所以我不确定如何继续。在玩游戏时,我也在使用ActorFlow.actorRef
handleWebSocketMessages(wsFlow)
def wsFlow: Flow[Message, Message, Any] = {
ActorFlow.actorRef(websocket => MyBridgeActor.props(websocket))
}
ActorFlow代码仅依赖于akka,因此我刚刚将文件复制到了自己的代码库中。 https://github.com/playframework/playframework/blob/master/framework/src/play-streams/src/main/scala/play/api/libs/streams/ActorFlow.scala
我想一个解决方案是创建一个CustomActorFlow,其中包括从Message到Array [Byte]的转换。 MyBridgeActor接受Flow [Array [Byte],Array [Byte],Any]格式的WebSocket。
答案 0 :(得分:1)
使用akka流API,您可以像这样转换流:
import akka.http.scaladsl.model.ws.{BinaryMessage, Message, TextMessage}
import akka.stream.Materializer
import akka.stream.scaladsl.{Flow, Sink}
import akka.util.ByteString
import scala.concurrent.Future
handleWebSocketMessages(msgFlow)
def msgFlow: Flow[Message, Message, Any] = convertFlow(bytesFlow)
def bytesFlow: Flow[Array[Byte], Array[Byte], Any] = {
// Can just copy ActorFlow over, no need to customize
ActorFlow.actorRef[Array[Byte], Array[Byte]](...)
}
def covertFlow(msgs: Flow[Array[Byte], Array[Byte], Any])(implicit materializer: Materializer): Flow[Message, Message, Any] =
Flow[Message]
.mapAsync(2)(msgToBytes)
.via(msgs)
.map(bytesToMsg)
def bytesToMsg(bytes: Array[Byte]): Message = {
// This depends on your application:
// is the outgoing message text or binary?
val isText = true
if (isText) {
TextMessage(new String(bytes, "UTF-8"))
} else {
BinaryMessage(ByteString(bytes))
}
}
def msgToBytes(msg: Message)(implicit materializer: Materializer): Future[Array[Byte]] = {
msg match {
case TextMessage.Strict(data) =>
Future.successful(data.getBytes("UTF-8"))
case TextMessage.Streamed(stream) =>
stream.fold("")(_ + _).map(_.getBytes("UTF-8")).runWith(Sink.head)
case BinaryMessage.Strict(data) =>
Future.successful(data.toArray[Byte])
case BinaryMessage.Streamed(stream) =>
stream.fold(ByteString.empty)(_ ++ _).map(_.toArray[Byte]).runWith(Sink.head)
}
}