可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I cannot use wss://
in my simple WebSocket app created with Play!Framework 2.2. It echoes the message back. The endpoint is like this
def indexWS2 = WebSocket.using[String] { request => { println("got connection to indexWS2") var channel: Option[Concurrent.Channel[String]] = None val outEnumerator: Enumerator[String] = Concurrent.unicast(c => channel = Some(c)) // Log events to the console val myIteratee: Iteratee[String, Unit] = Iteratee.foreach[String] {gotString => { println("received: " + gotString) // send string back channel.foreach(_.push("echoing back \"" + gotString + "\"")) }} (myIteratee, outEnumerator) } }
and the route is described as
GET /ws2 controllers.Application.indexWS2
I create a connection from a JS client like this
myWebSocket = new WebSocket("ws://localhost:9000/ws2");
and everything works fine. But if I change ws://
into wss://
in order to use TLS, it fails and I get the following Netty exception:
[error] p.nettyException - Exception caught in Netty java.lang.IllegalArgumentException: empty text
How can I make this work? Thanks.
回答1:
I really wanted to figure this out for you! But I didn't like the answer. It appears there's no Play support yet for SSL for websockets. Saw mention of it here and no sign of progress since: http://grokbase.com/t/gg/play-framework/12cd53wst9/2-1-https-and-wss-secure-websocket-clarifications-and-documentation
However, there's hope! You can use nginx as a secure websocket (wss) endpoint, to forward to a internal play app with a insecure websocket endpoint:
The page http://siriux.net/2013/06/nginx-and-websockets/ provided this explanation and sample proxy config for nginx:
Goal: WSS SSL Endpoint: forwards wss|https://ws.example.com to ws|http://ws1.example.com:10080
"The proxy is also an SSL endpoint for WSS and HTTPS connections. So the clients can use wss:// connections (e.g. from pages served via HTTPS) which work better with broken proxy servers, etc."
server { listen 443; server_name ws.example.com; ssl on; ssl_certificate ws.example.com.bundle.crt; ssl_certificate_key ws.example.com.key; ssl_session_timeout 5m; ssl_protocols SSLv2 SSLv3 TLSv1; ssl_ciphers HIGH:!aNULL:!MD5; ssl_prefer_server_ciphers on; location / { # like above } }
Nginx is so lightweight and fun. Would not hesitate to go with this option.
回答2:
Did you try enabling https support on the Play server? It looks like you're trying to connect to the http port using wss, that can never work, you need to enable https, and then change the URL not just to wss, but also to use the https port.
To start a Play server with ssl turned on:
activator run -Dhttps.port=9443
Then connect to wss://localhost:9443/ws2
.
回答3:
Another option is to use SockJS as the Websocket layer, SockJS implementation for Play2 can be found at https://github.com/fdimuccio/play2-sockjs
When HTTPS is enabled an wss endpoind is created by SockJS over the HTTPS channel. Play2-sockjs also supports the Actor pattern as with native Play websockets.
If you don't want to use SockJS in the clientside but rather force browser websocket implementation, you can use explicit websocket endpoint wss:////websocket