Scala Play WebSocket - one actor, several types of messages

What I want to do is basically 1: 1: Scala Play Websocket - use one of the participants to send both: Array [Byte] and String messages

Unfortunately, the API has changed a lot since 2.4 (now I'm on 2.6.0-M4).

What I tried (does not compile for obvious reasons):

WebSocket.accept[WSMessage, WSMessage]
    {
      request =>
        ActorFlow.actorRef
        {
          out => WebSocketActor.props(out)
        }
    }


  sealed trait WSMessage
  case class StringMessage(s: String) extends WSMessage
  case class BinaryMessage(a: Array[Byte]) extends WSMessage
  case class JsonMessage(js: JsValue) extends WSMessage

  object MyMessageFlowTransformer
  {
    implicit val WSMessageFlowTransformer: MessageFlowTransformer[WSMessage, WSMessage] =
    {
      new MessageFlowTransformer[WSMessage, WSMessage]
      {
        def transform(flow: Flow[WSMessage, WSMessage, _]) =
        {
          AkkaStreams.bypassWith[Message, WSMessage, Message](Flow[Message] collect
          {
            case StringMessage(s) => Left(s)
            case BinaryMessage(b) => Left(b)
            case JsonMessage(j) => Left(j)
            case _ => Right(CloseMessage(Some(CloseCodes.Unacceptable)))
          })(flow map WSMessage.apply)
        }
      }
    }
  }

I'm a little lost. play.api.http.websocket.Messageis a sealed sign and probably for a good reason ...

+4
source share
1 answer

Define MessageFlowTransformer[Either[String, Array[Byte]], Either[String, Array[Byte]]]:

type WSMessage = Either[String, Array[Byte]]

implicit val mixedMessageFlowTransformer: MessageFlowTransformer[WSMessage, WSMessage] = {
  new MessageFlowTransformer[WSMessage, WSMessage] {
    def transform(flow: Flow[WSMessage, WSMessage, _]) = {
      AkkaStreams.bypassWith[Message, WSMessage, Message](Flow[Message].collect {
        case BinaryMessage(data) => Left(Right(data.toArray))
        case TextMessage(text) => Left(Left(text))
      })(flow map {
        case Right(data) => BinaryMessage.apply(ByteString.apply(data))
        case Left(text) => TextMessage.apply(text)
      })
    }
  }
}
+2
source

Source: https://habr.com/ru/post/1677080/


All Articles