mirror of
https://github.com/phfroidmont/scalive.git
synced 2025-12-25 13:36:59 +01:00
Rough websocket responses
This commit is contained in:
parent
fadef26425
commit
ccdd22b61a
3 changed files with 70 additions and 16 deletions
|
|
@ -1,5 +1,7 @@
|
|||
package scalive
|
||||
|
||||
import scalive.SocketMessage.LiveResponse
|
||||
import scalive.SocketMessage.Payload
|
||||
import zio.*
|
||||
import zio.http.*
|
||||
import zio.http.ChannelEvent.Read
|
||||
|
|
@ -22,17 +24,41 @@ class LiveRouter(rootLayout: HtmlElement => HtmlElement, liveRoutes: List[LiveRo
|
|||
|
||||
private val socketApp: WebSocketApp[Any] =
|
||||
Handler.webSocket { channel =>
|
||||
channel.receiveAll {
|
||||
case Read(WebSocketFrame.Text(content)) =>
|
||||
for
|
||||
_ <-
|
||||
content.fromJson[SocketMessage].fold(m => ZIO.logError(m), m => ZIO.log(m.toString))
|
||||
_ <- channel.send(Read(WebSocketFrame.text("bar")))
|
||||
yield ()
|
||||
case _ => ZIO.unit
|
||||
}
|
||||
channel
|
||||
.receiveAll {
|
||||
case Read(WebSocketFrame.Text(content)) =>
|
||||
for
|
||||
message <- ZIO
|
||||
.fromEither(content.fromJson[SocketMessage])
|
||||
.mapError(new IllegalArgumentException(_))
|
||||
reply <- handleMessage(message)
|
||||
_ <- channel.send(Read(WebSocketFrame.text(reply.toJson)))
|
||||
yield ()
|
||||
case _ => ZIO.unit
|
||||
}.tapErrorCause(ZIO.logErrorCause(_))
|
||||
}
|
||||
|
||||
def handleMessage(message: SocketMessage): Task[SocketMessage] =
|
||||
val reply = message.payload match
|
||||
case Payload.Heartbeat => ZIO.succeed(Payload.Reply("ok", LiveResponse.Empty))
|
||||
case Payload.Join(url, session, static, sticky) =>
|
||||
// TODO very rough handling
|
||||
ZIO
|
||||
.fromEither(URL.decode(url)).map(url =>
|
||||
val req = Request(url = url)
|
||||
liveRoutes
|
||||
.collectFirst { route =>
|
||||
val pathParams = route.path.decode(req.path).getOrElse(???)
|
||||
val lv = route.liveviewBuilder(pathParams, req)
|
||||
val s = Socket(lv)
|
||||
Payload.Reply("ok", LiveResponse.InitDiff(s.diff))
|
||||
|
||||
}.getOrElse(???)
|
||||
)
|
||||
case Payload.Reply(_, _) => ZIO.die(new IllegalArgumentException())
|
||||
|
||||
reply.map(SocketMessage(message.joinRef, message.messageRef, message.topic, "phx_reply", _))
|
||||
|
||||
val routes: Routes[Any, Response] =
|
||||
Routes.fromIterable(
|
||||
liveRoutes
|
||||
|
|
@ -41,6 +67,7 @@ class LiveRouter(rootLayout: HtmlElement => HtmlElement, liveRoutes: List[LiveRo
|
|||
Method.GET / "live" / "websocket" -> handler(socketApp.toResponse)
|
||||
)
|
||||
)
|
||||
end LiveRouter
|
||||
|
||||
final case class SocketMessage(
|
||||
// Live session ID, auto increment defined by the client on join
|
||||
|
|
@ -58,8 +85,9 @@ object SocketMessage:
|
|||
Chunk(joinRef, Json.Str(messageRef), Json.Str(topic), Json.Str(eventType), payload)
|
||||
) =>
|
||||
val payloadParsed = eventType match
|
||||
case "phx_join" => payload.as[Payload.Join]
|
||||
case s => Left(s"Unknown event type : $s")
|
||||
case "heartbeat" => Right(Payload.Heartbeat)
|
||||
case "phx_join" => payload.as[Payload.Join]
|
||||
case s => Left(s"Unknown event type : $s")
|
||||
|
||||
payloadParsed.map(
|
||||
SocketMessage(
|
||||
|
|
@ -74,22 +102,41 @@ object SocketMessage:
|
|||
},
|
||||
m =>
|
||||
Json.Arr(
|
||||
m.joinRef.map(Json.Num(_)).getOrElse(Json.Null),
|
||||
Json.Num(m.messageRef),
|
||||
m.joinRef.map(ref => Json.Str(ref.toString)).getOrElse(Json.Null),
|
||||
Json.Str(m.messageRef.toString),
|
||||
Json.Str(m.topic),
|
||||
Json.Str(m.eventType),
|
||||
m.payload.match
|
||||
case p: Payload.Join => p.toJsonAST.getOrElse(throw new IllegalArgumentException())
|
||||
case Payload.Heartbeat => Json.Obj.empty
|
||||
case p: Payload.Join => p.toJsonAST.getOrElse(throw new IllegalArgumentException())
|
||||
case p: Payload.Reply => p.toJsonAST.getOrElse(throw new IllegalArgumentException())
|
||||
)
|
||||
)
|
||||
|
||||
enum Payload:
|
||||
case Heartbeat
|
||||
case Join(
|
||||
url: String,
|
||||
// params: Map[String, String],
|
||||
session: String,
|
||||
static: Option[String],
|
||||
sticky: Boolean)
|
||||
case Reply(status: String, response: LiveResponse)
|
||||
object Payload:
|
||||
given JsonCodec[Payload.Join] = JsonCodec.derived
|
||||
given JsonCodec[Payload.Join] = JsonCodec.derived
|
||||
given JsonEncoder[Payload.Reply] = JsonEncoder.derived
|
||||
|
||||
enum LiveResponse:
|
||||
case Empty
|
||||
case InitDiff(rendered: scalive.Diff)
|
||||
object LiveResponse:
|
||||
given JsonEncoder[LiveResponse] =
|
||||
JsonEncoder[Json].contramap {
|
||||
case Empty => Json.Obj.empty
|
||||
case InitDiff(rendered) =>
|
||||
Json.Obj(
|
||||
"liveview_version" -> Json.Str("1.1.8"),
|
||||
"rendered" -> rendered.toJsonAST.getOrElse(throw new IllegalArgumentException())
|
||||
)
|
||||
}
|
||||
end SocketMessage
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue