Hello.
I have a socket server using Tapir+ZIO HTTP
val createRoom: PublicEndpoint[
(PlayerName, RoomName),
Unit,
Stream[Throwable, ClientMessage] => Stream[Throwable, ServerMessage],
ZioStreams & WebSockets
] =
root
.in("create")
.in(query[PlayerName]("playerName"))
.in(query[RoomName]("roomName"))
.get
.out(webSocketBody[ClientMessage, CodecFormat.Json, ServerMessage, CodecFormat.Json](ZioStreams)(using ClientMessage.wsFrameCodec, ServerMessage.wsFrameCodec))
ApiEndpoints.createRoom.zServerLogic(createRoom)
def createRoom(playerName: PlayerName, roomName: RoomName): UIO[Stream[Throwable, ClientMessage] => Stream[Throwable, ServerMessage]] =
for
...
yield roomSocket(id, playerName, room)
def roomSocket(
id: RoomId,
player: PlayerName,
room: Room
)(clientMessages: Stream[Throwable, ClientMessage]): Stream[Throwable, ServerMessage] =
val handler = handleMessage(id, player, room.hub)
clientMessages.tap(Console.printLine(_)).flatMap(handler)
I am using a custom codec for ClientMessage
:
given wsFrameCodec: Codec[WebSocketFrame, ClientMessage, CodecFormat.Json] =
val frameJsonCodec = Codec.textWebSocketFrame(using zioCodec[ClientMessage])
Codec.fromDecodeAndMeta[WebSocketFrame, ClientMessage, CodecFormat.Json](CodecFormat.Json()) {
case WebSocketFrame.Close(code, reason) => DecodeResult.Value(Leave(code, reason))
case frame => frameJsonCodec.decode(frame)
} {
case Leave(code, reason) => WebSocketFrame.Close(code, reason)
case msg => frameJsonCodec.encode(msg)
}
Everything work fine except for ClientMessage.Leave
. It seems to be correctly sent by the client and encoded as close frame but it is not received by the server in clientMessages
. Adding a print in the right case clause of wsFrameCodec
shows that the code in the match case is not executed.
Is this the expected behaviour or am I doing something wrong?