2017-08-24 34 views
0

在Play 2.6中編寫WebSocket代理(基於Websocket Proxy using Play 2.6 and akka streams)時,我遇到了處理流式文本的問題。使用Akka播放2.6 WebSocket代理 - 如何處理流式傳輸文本與嚴格文本

關注代碼:

def proxySocket: WebSocket = WebSocket.accept[String, String] { _ => 
    Flow[String].map(s => TextMessage(s)) 
    .via(websocketFlow) 
    .map(_.asTextMessage.getStrictText) 
} 

這是工作代理到本地的WebSocket服務器。但是,儘管代理到遠程服務器,它會導致以下錯誤:

java.lang.IllegalStateException: Cannot get strict text for streamed message.

我們可以通過_.asTextMessage.getStreamedText獲得流的消息,但我無法弄清楚如何將其轉化成String

回答

1

由於documentation的阿卡HTTP(在遊戲底層引擎)指出,人們不能指望該消息永遠是Strict

When receiving data from the network connection the WebSocket implementation tries to create a Strict message whenever possible, i.e. when the complete data was received in one chunk. However, the actual chunking of messages over a network connection and through the various streaming abstraction layers is not deterministic from the perspective of the application. Therefore, application code must be able to handle both streamed and strict messages and not expect certain messages to be strict. (Particularly, note that tests against localhost will behave differently than tests against remote peers where data is received over a physical network connection.)

同時處理StrictStreamed消息,你可以做些什麼如下圖(受此啓發answer):

def proxySocket: WebSocket = WebSocket.accept[String, String] { _ => 
    Flow[String] 
    .map(TextMessage(_)) 
    .via(websocketFlow) 
    .collect { 
     case TextMessage.Strict(text) => 
     Future.successful(text) 
     case TextMessage.Streamed(textStream) => 
     textStream 
      .limit(100) 
      .completionTimeout(10 seconds) 
      .runFold("")(_ + _) 
      .flatMap(x => Future.successful(x)) 
    } 
    .mapAsync(parallelism = 3)(identity) 
}