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?