The following seems to work. Note. I implemented both a server socket and a proxy socket in one controller, but you can split them or deploy the same controller in separate instances. The ws URL for the "top" service will need to be updated in both cases.
package controllers import javax.inject._ import akka.actor.{Actor, ActorRef, ActorSystem, Props} import akka.http.scaladsl.Http import akka.http.scaladsl.model.ws.{Message, TextMessage, WebSocketRequest, WebSocketUpgradeResponse} import akka.stream.Materializer import akka.stream.scaladsl.Flow import play.api.libs.streams.ActorFlow import play.api.mvc._ import scala.concurrent.{ExecutionContext, Future} import scala.language.postfixOps @Singleton class SomeController @Inject()(implicit exec: ExecutionContext, actorSystem: ActorSystem, materializer: Materializer) extends Controller { def websocketFlow: Flow[Message, Message, Future[WebSocketUpgradeResponse]] = Http().webSocketClientFlow(WebSocketRequest("ws://localhost:9000/upper-socket")) def proxySocket: WebSocket = WebSocket.accept[String, String] { _ => Flow[String].map(s => TextMessage(s)) .via(websocketFlow) .map(_.asTextMessage.getStrictText) } class UpperService(socket: ActorRef) extends Actor { override def receive: Receive = { case s: String => socket ! s.toUpperCase() case _ => } } object UpperService { def props(socket: ActorRef): Props = Props(new UpperService(socket)) } def upperSocket: WebSocket = WebSocket.accept[String, String] { _ => ActorFlow.actorRef(out => UpperService.props(out)) } }
You will need routes that need to be configured as follows:
GET /upper-socket controllers.SomeController.upperSocket GET /proxy-socket controllers.SomeController.proxySocket
You can test by sending a line to ws: // localhost: 9000 / proxy-socket. The response will be an uppercase string.
After 1 minute of inactivity there will be a timeout:
akka.stream.scaladsl.TcpIdleTimeoutException: TCP idle-timeout encountered on connection to [localhost:9000], no bytes passed in the last 1 minute
But see: http://doc.akka.io/docs/akka-http/current/scala/http/common/timeouts.html on how to configure this.
source share