Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

add WebSocket support to prototype.

  • Loading branch information...
commit f34c20517421a7e46473235c1debe74dd7004f68 1 parent e53d3af
@akrennmair akrennmair authored
Showing with 94 additions and 12 deletions.
  1. +94 −12 main.go
View
106 main.go
@@ -2,40 +2,122 @@ package main
import (
"net/http"
+ "net"
"log"
"io"
"os"
"fmt"
+ "bufio"
)
+func Copy(dest *bufio.ReadWriter, src *bufio.ReadWriter) {
+ buf := make([]byte, 40*1024)
+ for {
+ n, err := src.Read(buf)
+ if err != nil && err != io.EOF {
+ log.Printf("Read failed: %v", err)
+ return
+ }
+ if n == 0 {
+ return
+ }
+ dest.Write(buf[0:n])
+ dest.Flush()
+ }
+}
+
+func CopyBidir(conn1 io.ReadWriteCloser, rw1 *bufio.ReadWriter, conn2 io.ReadWriteCloser, rw2 *bufio.ReadWriter) {
+ finished := make(chan bool)
+
+ go func() {
+ Copy(rw2, rw1)
+ conn2.Close()
+ finished <- true
+ }()
+ go func() {
+ Copy(rw1, rw2)
+ conn1.Close()
+ finished <- true
+ }()
+
+ <-finished
+ <-finished
+}
+
type RequestHandler struct {
Transport *http.Transport
}
func (h *RequestHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
- log.Printf("incoming request: %#v", *r)
+ //log.Printf("incoming request: %#v", *r)
r.RequestURI = ""
r.URL.Scheme = "http"
r.URL.Host = "127.0.0.1:8000"
- resp, err := h.Transport.RoundTrip(r)
- if err != nil {
- w.WriteHeader(http.StatusServiceUnavailable)
- fmt.Fprintf(w, "Error: %v", err)
- return
+ conn_hdr := ""
+ conn_hdrs := r.Header["Connection"]
+ log.Printf("Connection headers: %v", conn_hdrs)
+ if len(conn_hdrs) > 0 {
+ conn_hdr = conn_hdrs[0]
}
- for k, v := range resp.Header {
- for _, vv := range v {
- w.Header().Add(k, vv)
+ upgrade_websocket := false
+ if conn_hdr == "Upgrade" {
+ log.Printf("got Connection: Upgrade")
+ upgrade_hdrs := r.Header["Upgrade"]
+ log.Printf("Upgrade headers: %v", upgrade_hdrs)
+ if len(upgrade_hdrs) > 0 {
+ upgrade_websocket = (upgrade_hdrs[0] == "websocket")
}
}
- w.WriteHeader(resp.StatusCode)
+ if upgrade_websocket {
+ hj, ok := w.(http.Hijacker)
+
+ if !ok {
+ http.Error(w, "webserver doesn't support hijacking", http.StatusInternalServerError)
+ return
+ }
+
+ conn, bufrw, err := hj.Hijack()
+ defer conn.Close()
- io.Copy(w, resp.Body)
- resp.Body.Close()
+ conn2, err := net.Dial("tcp", "127.0.0.1:8000")
+ if err != nil {
+ http.Error(w, "couldn't connect to backend server", http.StatusServiceUnavailable)
+ return
+ }
+ defer conn2.Close()
+
+ err = r.Write(conn2)
+ if err != nil {
+ log.Printf("writing WebSocket request to backend server failed: %v", err)
+ return
+ }
+
+ CopyBidir(conn, bufrw, conn2, bufio.NewReadWriter(bufio.NewReader(conn2), bufio.NewWriter(conn2)))
+
+ } else {
+
+ resp, err := h.Transport.RoundTrip(r)
+ if err != nil {
+ w.WriteHeader(http.StatusServiceUnavailable)
+ fmt.Fprintf(w, "Error: %v", err)
+ return
+ }
+
+ for k, v := range resp.Header {
+ for _, vv := range v {
+ w.Header().Add(k, vv)
+ }
+ }
+
+ w.WriteHeader(resp.StatusCode)
+
+ io.Copy(w, resp.Body)
+ resp.Body.Close()
+ }
}
func main() {
Please sign in to comment.
Something went wrong with that request. Please try again.