Ejemplo n.º 1
0
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)
}
Ejemplo n.º 2
0
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)
}