package goxy import ( "io" "net" "net/http" "net/url" ) type WebSocketProxy struct { Director func(*http.Request) } 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 (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() // pass first request to upstream err = r.Write(d) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } hj, ok := w.(http.Hijacker) if !ok { http.Error(w, "Not a hijacker", http.StatusInternalServerError) return } conn, _, err := hj.Hijack() if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } defer conn.Close() errc := make(chan error, 2) cp := func(dst io.Writer, src io.Reader) { _, err := io.Copy(dst, src) errc <- err } go cp(d, conn) go cp(conn, d) <-errc }