aboutsummaryrefslogtreecommitdiff
path: root/ws.go
diff options
context:
space:
mode:
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
+}