aboutsummaryrefslogtreecommitdiff
path: root/ws.go
diff options
context:
space:
mode:
authorDimitri Sokolyuk <demon@dim13.org>2016-03-25 20:04:45 +0100
committerDimitri Sokolyuk <demon@dim13.org>2016-03-25 20:04:45 +0100
commit57c53df2246eb79d77245e8f2cc9efe03f997c14 (patch)
treef1e1bd2bdcf966324b20e2cb7c66c235f6059e2e /ws.go
parent80dbf3cbd4a37979f21116f4f03250c025ea41f1 (diff)
Add (working) stub for WebSocket Proxy
Diffstat (limited to 'ws.go')
-rw-r--r--ws.go68
1 files changed, 68 insertions, 0 deletions
diff --git a/ws.go b/ws.go
new file mode 100644
index 0000000..a8f85b6
--- /dev/null
+++ b/ws.go
@@ -0,0 +1,68 @@
+package main
+
+import (
+ "io"
+ "log"
+ "net"
+ "net/http"
+ "net/url"
+ "strings"
+)
+
+type WebSocketProxy struct {
+ Director func(*http.Request)
+}
+
+func (p *WebSocketProxy) ServeHTTP(w http.ResponseWriter, r *http.Request) {
+ p.Director(r)
+
+ d, err := net.Dial("tcp", r.URL.Host)
+ if err != nil {
+ http.Error(w, err.Error(), http.StatusInternalServerError)
+ return
+ }
+ defer d.Close()
+ hj, ok := w.(http.Hijacker)
+ if !ok {
+ http.Error(w, "Not a hijacker", http.StatusInternalServerError)
+ return
+ }
+ nc, _, err := hj.Hijack()
+ if err != nil {
+ log.Println(err)
+ return
+ }
+ defer nc.Close()
+
+ err = r.Write(d)
+ if err != nil {
+ log.Println(err)
+ return
+ }
+
+ errc := make(chan error, 2)
+ cp := func(dst io.Writer, src io.Reader) {
+ _, err := io.Copy(dst, src)
+ errc <- err
+ }
+ go cp(d, nc)
+ go cp(nc, d)
+ <-errc
+}
+
+func NewWebSocketProxy(target *url.URL) *WebSocketProxy {
+ director := func(req *http.Request) {
+ req.URL.Scheme = target.Scheme
+ req.URL.Host = target.Host
+ }
+ return &WebSocketProxy{Director: director}
+}
+
+func isWebsocket(req *http.Request) bool {
+ conn := req.Header.Get("Connection")
+ if strings.ToLower(conn) == "upgrade" {
+ upgrade := req.Header.Get("Upgrade")
+ return strings.ToLower(upgrade) == "websocket"
+ }
+ return false
+}