package main
import (
"bytes"
"code.google.com/p/go.net/websocket"
"fmt"
"io"
"io/ioutil"
"net/http"
"os"
"os/exec"
"time"
)
func startNodeProxyServer() *os.Process {
if err := ioutil.WriteFile("/tmp/proxy.js", []byte(NODE_PROXY_CODE), os.ModePerm); err != nil {
panic(err)
}
ioutil.WriteFile("/tmp/cert.pem", []byte(CERT), os.ModePerm)
ioutil.WriteFile("/tmp/key.pem", []byte(KEY), os.ModePerm)
cmd := exec.Command("node", "/tmp/proxy.js") // download and pre-install "node" executable at http://nodejs.org/download/
if err := cmd.Start(); err != nil {
panic(err)
}
return cmd.Process
}
func main() {
proxyServer := startNodeProxyServer()
defer proxyServer.Kill()
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
defer r.Body.Close()
switch r.URL.Path {
case "/":
http.ServeContent(w, r, "index.html", time.Now(), bytes.NewReader([]byte(Content("wss://localhost:8090/sock"))))
case "/sock":
websocket.Handler(EchoHandler).ServeHTTP(w, r)
default:
http.NotFound(w, r)
}
})
done := make(chan bool)
go func() {
fmt.Println(http.ListenAndServe(":8080", nil))
done <- true
}()
<-done
}
func EchoHandler(ws *websocket.Conn) {
io.Copy(ws, ws)
}
func Content(ws string) string {
return fmt.Sprintf(`
websocket test
go-lang / chrome websocket test at %s:
`, ws, ws)
}
const (
NODE_PROXY_CODE = `
var net = require('net');
var tls = require('tls');
var fs = require('fs');
var clientOptions = {
host: 'localhost',
port: 8080
};
var serverOptions = {
key: fs.readFileSync('/tmp/key.pem'),
cert: fs.readFileSync('/tmp/cert.pem')
}
var server = tls.createServer(serverOptions, function(c) {
console.log("connection");
var client = net.connect(clientOptions, function() {
client.pipe(c)
});
c.on("error",function(e) {
console.log("oops, connection error:",e);
});
client.on("error",function(e) {
console.log("client error:",e);
c.write("HTTP/1.1 503 service unavailable\n");
c.write("Content-Type: text/plain\n");
c.write("\n");
c.write("service unavailable\n");
c.end()
});
c.pipe(client)
});
server.on("error",function(e) {
console.log("oops, server error:",e);
});
server.listen(8090, function() {
console.log('server bound');
});
`
CERT = `-----BEGIN CERTIFICATE-----
MIIC4zCCAc2gAwIBAgIBADALBgkqhkiG9w0BAQUwEjEQMA4GA1UEChMHQWNtZSBD
bzAeFw0xMzA4MTIxOTUzNTdaFw0xNDA4MTIxOTUzNTdaMBIxEDAOBgNVBAoTB0Fj
bWUgQ28wggEgMAsGCSqGSIb3DQEBAQOCAQ8AMIIBCgKCAQEAw917qyvQTFtr65LQ
MimR7obQzOc05YvqH/ytdtqSyPqQsvnOLi0Jk2/t33RpqIGb36dIMGDV3X5SpiLW
9TReidxtz22YbZ1CTRUgdcF5XJiq3CO5a+1vGvi/fIBIqzPb6CQwgG/eFm6xdvgf
IRodZgM6ym6cglm6ndhoB4/TpIni/i+bo757LUxfu78/mkUBfsQK0VDaqq59ZkZW
An8E/4DBeDdg8jq9i+4VuOTSulfiLu06eIWoAhfBeWX6uGaEK44xW5NJpp1y4CKX
BOvVKuz+Dv4jz/vp1e8p1zFqkUzbrtdVv+Z3olfTHQWe1qMpt9l01tedxuPTEHas
HTQiRwIDAQABo0owSDAOBgNVHQ8BAf8EBAMCAKAwEwYDVR0lBAwwCgYIKwYBBQUH
AwEwDAYDVR0TAQH/BAIwADATBgNVHREEDDAKggh4dXZhLmNvbTALBgkqhkiG9w0B
AQUDggEBAFppIRxB25BRCK1w//9U73sddEnw2Q/MUR+V4twB5qVGnnY6VJW+u9W3
9dNs4teemAxUJh7ZBOR2xEj1N6Q9D0H3BFupUNRa9jIxWam+E+mNCF1jQRlTxCur
WHk56ZmsqWyb8yXIB3ymHyAXnJziAUO/US6e8xeMKcvIZCtCzCsaOLI5G35h9xoJ
+mKedqOW7tGmT3suqj/bx2hEq1nPRW/H9XmyLkDMvIiUaU8iopKzShuyG/kosRXY
WsoDWrkv3a0O1crnlQLZXg1IH0/bQg7OwJz5P8qDSNR1uiBzGkmbOFpp0IVCdVIk
UwKAnERUK1MkYu6jh5hXj6mb0fW01/o=
-----END CERTIFICATE-----`
KEY = `-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEAw917qyvQTFtr65LQMimR7obQzOc05YvqH/ytdtqSyPqQsvnO
Li0Jk2/t33RpqIGb36dIMGDV3X5SpiLW9TReidxtz22YbZ1CTRUgdcF5XJiq3CO5
a+1vGvi/fIBIqzPb6CQwgG/eFm6xdvgfIRodZgM6ym6cglm6ndhoB4/TpIni/i+b
o757LUxfu78/mkUBfsQK0VDaqq59ZkZWAn8E/4DBeDdg8jq9i+4VuOTSulfiLu06
eIWoAhfBeWX6uGaEK44xW5NJpp1y4CKXBOvVKuz+Dv4jz/vp1e8p1zFqkUzbrtdV
v+Z3olfTHQWe1qMpt9l01tedxuPTEHasHTQiRwIDAQABAoIBAA22+4rf1YUTPbpQ
HG32xTYrkIFYizarlmhI/Ch/Y5nZGbq+jTZkhvAg/UoRT7ix4qVFhGOG1FLfHpBt
jhm7YgdLPREyPmMmiNb27L/yHTpjoksp4Tjydj4wPtBL90qtpe9aYV8M9kMh2yFW
fG+H8ZkMDtjP5/ukptGYrqgg5RP3SGacLGdmdCakesCP/+bjSjKVyHsBThybr5oy
zSsLaGocU6JL7k6x1lbnbToSwQo5ORRgWzsVIc68qm4Nc4+Nn9lrhMqlucYMtrxf
EyNpcCUFuO1BMz1jJwP5zttY0ZRKWitaDRpVyZhKMonUSsYIfRV+kM9+qKatZGbW
Tuh9dLkCgYEA3pSRWsyCHxmVDXpTAw0EPSZISaAqq5RSZoBtJkKBGpqxs245RI4E
FQN2d3oPpI3qBf3J6+lLRy4W0Hju+UxSzqdCHONmngdxbzOuMdoianjwviwr+ZjM
e8kmFtQ72KK6rEYsaywYxH7NVutXmmK3eXkH3MD6/0fwMSFVBwJ1piMCgYEA4UYM
/KOHzosscvGNPFW8U8b+5yNTh/Vm2CVBCe+ZwUA6WEE+nwGh4FVE5tmxzlXOr91h
I6LJ3WeV/byUl+5wAwAe4cBGwSrjOeR5VOgI+zXCH7LzKZG0EMTxhzRKs/R89gWi
zVL8noy1VomNLo2C+O9YBTLYF6S3Uu3PCmwda40CgYEAvwW4XbnILtKwxjlmRucD
7UsOnQl1tX183nV3t286B9AdlAWT5o8PV815/X3nMO2OnAe8JNg6f+NBNzeiuJfV
NX/8UHilGBkBNFOhOy2ffcs/qaaVMwf87nuqUcthdUHrfXBYLL5Sn0jIB8HAlEIG
fpztr3p7r11Y+YFGzNZCjAsCgYAo5qoW+K4Arz4rxHWrPbnK0DeZyc0xwzmgBuuP
HUSiVMIDIh13izlT3Md8zou89dFoFt67NKRIIbWW8zVbfHwz30K8JEf0bJADA9uP
se1nhvQvAzOpGX5DCS79KF5j3AEQPie39dhOBSgrhR/wEttzzSkDEJ8xc8OhN/I+
ZzDURQKBgAS8tKXfammEZBhLc1NGphBYf5HLXQEMm3Uqy7xW82YLjz6KN27x1fhz
YcZbFvY6KAsisGqZFUwlTecbZC8teFkFfoMWtu99fpPuLnlSr1MgLTchqnm1P70f
wWHpDR5CmggfYMrt/Hw1UQkRsDxuYnp6lnD8BOVZPo8jiMpUJmI8
-----END RSA PRIVATE KEY-----`
)