Description
I originally posted this here but was asked to make a new issue.
Websockets served over ListenAndServeTLS in the example program below fail to initiate SSL connections on nearly every client I have tried. Regular non-TLS connections work fine, and websites served also seem to be working fine over TLS. This is occurring on go version 1.4.2 x64.
Safari (version 9.0) works just great, but Firefox (version 39.0) and Chrome do not (version 43 on OSX). It also appears that javax.websocket gets a 403.
I get this error in Chrome:
WebSocket connection to 'wss://my.domain.com:8000/copyTest' failed: Error during WebSocket handshake: Unexpected response code: 403
Nothing is produced at the go terminal, unless i hit it with javax.websocket - which produces this:
http: TLS handshake error from 127.0.0.1:44249: tls: first record does not look like a TLS handshake
In Safari I get the expected result in the javascript console:
[Log] sent data:test (testClient.html, line 31)
[Log] got data:test (testClient.html, line 19)
in Firefox I get a 403 similar to Chrome and the console shows this:
GET
https://my.domain.com:8000/copyTest [HTTP/1.1 403 Forbidden 3ms]
"got error:" error { target: WebSocket, isTrusted: true, currentTarget: WebSocket, eventPhase: 2, bubbles: false, cancelable: false, defaultPrevented: false, timeStamp: 1435967773819792, originalTarget: WebSocket, explicitOriginalTarget: WebSocket, NONE: 0 } testClient.html:22:5
"got close:" close { target: WebSocket, isTrusted: true, wasClean: false, code: 1006, reason: "", currentTarget: WebSocket, eventPhase: 2, bubbles: false, cancelable: false, defaultPrevented: false, timeStamp: 1435967773821310 } testClient.html:25:5
Here is some go code to serve TLS websockets. sub in your own cert.key and cert.pem files.
package main
import (
"golang.org/x/net/websocket"
"io"
"log"
"net/http"
)
func copyTest(ws *websocket.Conn) {
io.Copy(ws, ws)
}
func main() {
// setup http handler
http.Handle("/copyTest", websocket.Handler(copyTest))
// start secure websocket server
log.Println("Listening for secure websocket connections on localhost port 8000...")
if err := http.ListenAndServeTLS(":8000", "cert.pem", "cert.key", nil); err != nil {
panic("ListenAndServeTLS Error: " + err.Error())
}
}
Here is a javascript client. Sub in the proper domain name for your cert instead of localhost and connect using it. Results will be written to the javascript console.
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>Websocket connector</title>
<script src="http://code.jquery.com/jquery-compat-git.js">
</script>
</head>
<body>
<input id="name" type="text" />
<button id="sendBtn">send</a>
<script>
var ws = new WebSocket("wss://localhost:8000/copyTest");
ws.onmessage = function(e) {
console.log("got data:" + e.data);
};
ws.onerror = function(e) {
console.log("got error:", e);
};
ws.onclose = function(e) {
console.log("got close:", e);
};
$('#sendBtn').click(function(){
var data = $('#name').val();
ws.send(data);
console.log("sent data:" + data);
});
</script>
</body>
</html>