简体   繁体   中英

Response from Server Scala with Play

I'm doing my first application with Scala and Play! Where I use a WebSocket exactly like they do in the chatroom example, so far I can send messages to my server but I don't seem to understand where I can "handle" this messages that I get from my client, also I wanted to know if I can send Json Arrays from my server to my client:

@Singleton
class HomeController @Inject()(cc: ControllerComponents)
                              (implicit actorSystem: ActorSystem,
                               mat: Materializer,
                               executionContext: ExecutionContext) 
                               extends AbstractController(cc) {

  private type WSMessage = String

  private val logger = Logger(getClass)

  private implicit val logging = Logging(actorSystem.eventStream, logger.underlyingLogger.getName)

  // chat room many clients -> merge hub -> broadcasthub -> many clients
  private val (chatSink, chatSource) = {
    // Don't log MergeHub$ProducerFailed as error if the client disconnects.
    // recoverWithRetries -1 is essentially "recoverWith"
    val source = MergeHub.source[WSMessage]
      .log("source")
      .recoverWithRetries(-1, { case _: Exception ⇒ Source.empty })

    val sink = BroadcastHub.sink[WSMessage]
    source.toMat(sink)(Keep.both).run()
  }

  private val userFlow: Flow[WSMessage, WSMessage, _] = {
     Flow.fromSinkAndSource(chatSink, chatSource)
  }

  def index: Action[AnyContent] = Action { implicit request: RequestHeader =>
    val webSocketUrl = routes.HomeController.chat().webSocketURL()
    logger.info(s"index: ")
    Ok(views.html.index(webSocketUrl))
  }

  def chat(): WebSocket = {
    WebSocket.acceptOrResult[WSMessage, WSMessage] {
      case rh if sameOriginCheck(rh) =>
        Future.successful(userFlow).map { flow =>
          Right(flow)
        }.recover {
          case e: Exception =>
            val msg = "Cannot create websocket"
            logger.error(msg, e)
            val result = InternalServerError(msg)
            Left(result)
        }

      case rejected =>
        logger.error(s"Request ${rejected} failed same origin check")
        Future.successful {
          Left(Forbidden("forbidden"))
        }
    }
  }

}

Btw I'm sending the messages from my client through a Jquery function.

Edit The way I want to handle this messages is by passing them as parameters to a function, the function will return an Array of strings or integers which I want to return to the client

All you need to do is add a flow stage to your between your source and sink which can store in DB and return some other message to clients.

Here's how you can fix the above problem:

Do whatever you want with the received message here.

val flow = Flow[WSMessage].map { element =>
  println(s"Message: $element")
  element
}

Note that for persisting messages in the database, you will most likely want to use an async stage, roughly:

val flow = Flow[WSMessage].mapAsync(parallelism) { element =>
  println(s"Message: $element")
  // assuming DB.write() returns a Future[Unit]
  DB.write(element).map(_ => element)
}

And finally, you need to add the flow stage to the stream pipeline.

source.via(flow).toMat(sink)(Keep.both).run()

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM