func HandleClient(w http.ResponseWriter, r *http.Request) { mu.Lock() endpoint, exists := endpoints[r.URL.Path] mu.Unlock() if !exists { http.NotFound(w, r) return } if r.URL.Query().Get("secret") != endpoint.secret { http.Error(w, "Bad secret", http.StatusUnauthorized) return } s := websocket.Server{Handler: func(ws *websocket.Conn) { AcceptHandshake(ws) // TODO handle error routeKey := endpoint.AddClient(ws) log.Println("Endpoint", endpoint.path, "client connected", r.RemoteAddr) for { frameBuf := make([]byte, duplex.MaxFrameSize) n, err := ws.Read(frameBuf) if err != nil { endpoint.DropClient(routeKey) break } var msg duplex.Message err = json.Unmarshal(frameBuf[:n], &msg) if err != nil { // TODO: what happens on decode error panic(err) } var ext map[string]interface{} if msg.Ext == nil { ext = make(map[string]interface{}) } else { ext = msg.Ext.(map[string]interface{}) } ext["route"] = routeKey msg.Ext = ext err = endpoint.SendUpstream(msg) if err != nil { // TODO: handle upstream write error // remove upstream endpoint? break } } }} s.ServeHTTP(w, r) }
func HandleBackend(w http.ResponseWriter, r *http.Request) { if r.URL.Query().Get("secret") == "" { http.Error(w, "Secret required", http.StatusBadRequest) return } s := websocket.Server{Handler: func(ws *websocket.Conn) { endpoint := &Endpoint{ path: ws.Request().URL.Path, secret: ws.Request().URL.Query().Get("secret"), counter: 0, clients: make(map[string]io.Writer), } AcceptHandshake(ws) // TODO handle error endpoint.upstream = ws mu.Lock() old, exists := endpoints[endpoint.path] if exists { old.upstream.Close() } endpoints[endpoint.path] = endpoint mu.Unlock() log.Println("Endpoint", endpoint.path, "backend online") for { frame := make([]byte, duplex.MaxFrameSize) n, err := ws.Read(frame) if err != nil { // TODO: what happens on read error log.Println("read err:", err) break } var msg duplex.Message err = json.Unmarshal(frame[:n], &msg) if err != nil { // TODO: what happens on decode error panic(err) } if msg.Ext == nil { log.Println("no ext") continue } ext, ok := msg.Ext.(map[string]interface{}) if !ok { log.Println("ext not object") continue } routeKey := ext["route"].(string) endpoint.Lock() clientConn, ok := endpoint.clients[routeKey] endpoint.Unlock() if !ok { log.Println("routekey not found") continue } if os.Getenv("DEBUG") != "" { fmt.Println(">>>", string(frame[:n])) } _, err = clientConn.Write(frame[:n]) if err != nil { endpoint.DropClient(routeKey) } } log.Println("Endpoint", endpoint.path, "backend offline") }} s.ServeHTTP(w, r) }