示例#1
0
文件: cherry_test.go 项目: xozrc/xo
func TestEcho(t *testing.T) {
	http.Handle("/echo", websocket.Handler(echoServer))
	once.Do(startCherryServer)

	client, err := net.Dial("tcp", serverAddr)
	if err != nil {
		t.Fatal("dialing", err)
	}

	conn, err := websocket.NewClient(newConfig(t, "/echo"), client)
	if err != nil {
		t.Errorf("WebSocket handshake error: %v", err)
		return
	}

	msg := []byte("hello, world\n")
	if _, err := conn.Write(msg); err != nil {
		t.Errorf("Write: %v", err)
	}
	var actual_msg = make([]byte, 512)
	n, err := conn.Read(actual_msg)
	if err != nil {
		t.Errorf("Read: %v", err)
	}
	actual_msg = actual_msg[0:n]
	if !bytes.Equal(msg, actual_msg) {
		t.Errorf("Echo: expected %q got %q", msg, actual_msg)
	}
	conn.Close()
}
示例#2
0
func (st *serverTester) websocket(rp requestParam) (*serverResponse, error) {
	urlstring := st.url + "/echo"

	config, err := websocket.NewConfig(urlstring, st.url)
	if err != nil {
		st.t.Fatalf("websocket.NewConfig(%q, %q) returned error: %v", urlstring, st.url, err)
	}

	config.Header.Add("Test-Case", rp.name)
	for _, h := range rp.header {
		config.Header.Add(h.Name, h.Value)
	}

	ws, err := websocket.NewClient(config, st.conn)
	if err != nil {
		st.t.Fatalf("Error creating websocket client: %v", err)
	}

	if _, err := ws.Write(rp.body); err != nil {
		st.t.Fatalf("ws.Write() returned error: %v", err)
	}

	msg := make([]byte, 1024)
	var n int
	if n, err = ws.Read(msg); err != nil {
		st.t.Fatalf("ws.Read() returned error: %v", err)
	}

	res := &serverResponse{
		body: msg[:n],
	}

	return res, nil
}
示例#3
0
func (s *S) TestServeHTTPWebSocket(c *check.C) {
	var servers []*httptest.Server
	for i := 0; i < 2; i++ {
		msg := fmt.Sprintf("server-%d", i)
		srv := httptest.NewServer(websocket.Handler(func(conn *websocket.Conn) {
			conn.Write([]byte(msg + conn.Request().URL.Path))
			buf := make([]byte, 5)
			conn.Read(buf)
			conn.Write(buf)
		}))
		defer srv.Close()
		servers = append(servers, srv)
	}
	var err error
	_, err = s.redis.Do("RPUSH", "frontend:myfrontend.com", "myfrontend", servers[0].URL, servers[1].URL)
	c.Assert(err, check.IsNil)
	router := Router{}
	err = router.Init()
	c.Assert(err, check.IsNil)
	proxyServer := httptest.NewServer(&router)
	defer proxyServer.Close()
	dialWS := func() *websocket.Conn {
		config, err := websocket.NewConfig("ws://myfrontend.com", "ws://localhost/")
		c.Assert(err, check.IsNil)
		url, _ := url.Parse(proxyServer.URL)
		client, err := net.Dial("tcp", url.Host)
		c.Assert(err, check.IsNil)
		conn, err := websocket.NewClient(config, client)
		c.Assert(err, check.IsNil)
		return conn
	}
	msgBuf := make([]byte, 100)
	conn := dialWS()
	defer conn.Close()
	n, err := conn.Read(msgBuf)
	c.Assert(err, check.IsNil)
	c.Assert(n, check.Equals, 9)
	c.Assert(string(msgBuf[:n]), check.Equals, "server-0/")
	n, err = conn.Write([]byte("12345"))
	c.Assert(err, check.IsNil)
	c.Assert(n, check.Equals, 5)
	n, err = conn.Read(msgBuf)
	c.Assert(err, check.IsNil)
	c.Assert(n, check.Equals, 5)
	c.Assert(string(msgBuf[:n]), check.Equals, "12345")
	conn = dialWS()
	defer conn.Close()
	n, err = conn.Read(msgBuf)
	c.Assert(err, check.IsNil)
	c.Assert(n, check.Equals, 9)
	c.Assert(string(msgBuf[:n]), check.Equals, "server-1/")
	n, err = conn.Write([]byte("12345"))
	c.Assert(err, check.IsNil)
	c.Assert(n, check.Equals, 5)
	n, err = conn.Read(msgBuf)
	c.Assert(err, check.IsNil)
	c.Assert(n, check.Equals, 5)
	c.Assert(string(msgBuf[:n]), check.Equals, "12345")
}
示例#4
0
文件: client.go 项目: gmelika/rack
func (c *Client) proxyWebsocket(config *websocket.Config, proxy string) (*websocket.Conn, error) {
	u, err := url.Parse(proxy)

	if err != nil {
		return nil, err
	}

	host := u.Host

	if !strings.Contains(host, ":") {
		host += ":443"
	}

	conn, err := net.DialTimeout("tcp", u.Host, 3*time.Second)

	if err != nil {
		return nil, err
	}

	if _, err = conn.Write([]byte(fmt.Sprintf("CONNECT %s:443 HTTP/1.1\r\n", c.Host))); err != nil {
		return nil, err
	}

	if _, err = conn.Write([]byte(fmt.Sprintf("Host: %s:443\r\n", c.Host))); err != nil {
		return nil, err
	}

	if auth := u.User; auth != nil {
		enc := base64.StdEncoding.EncodeToString([]byte(auth.String()))

		if _, err = conn.Write([]byte(fmt.Sprintf("Proxy-Authorization: Basic %s\r\n", enc))); err != nil {
			return nil, err
		}
	}

	if _, err = conn.Write([]byte("Proxy-Connection: Keep-Alive\r\n\r\n")); err != nil {
		return nil, err
	}

	data, err := bufio.NewReader(conn).ReadString('\n')

	if err != nil {
		return nil, err
	}

	// need an http 200 response
	if !strings.Contains(string(data), " 200 ") {
		return nil, fmt.Errorf("proxy error: %s", strings.TrimSpace(string(data)))
	}

	return websocket.NewClient(config, tls.Client(conn, config.TlsConfig))
}
示例#5
0
func (h DockerHandler) GetWebSocket(w http.ResponseWriter, r *http.Request) (*websocket.Conn, error) {
	client, err := net.Dial("unix", h.dockerEndpoint)
	if err != nil {
		helpers.ErrorLog("DOCKER", fmt.Sprintf("Following error occured when trying to make request to Docker endpoint %s : %s", h.dockerEndpoint, err.Error()))
		return nil, err
	}
	config := &websocket.Config{}
	config.Version = websocket.ProtocolVersionHybi13
	config.Location = r.URL
	config.Origin = r.URL
	config.Header = r.Header
	return websocket.NewClient(config, client)
}
示例#6
0
// dialSocketListener opens a WebSocket client connection to pl with config.
// config.Location, config.Origin, and config.Version must be set.
func dialSocketListener(pl *pipeListener, config *websocket.Config) (
	conn *websocket.Conn, err error) {

	socket, err := pl.Dial("", "")
	if err != nil {
		return nil, err
	}
	if conn, err = websocket.NewClient(config, socket); err != nil {
		socket.Close()
		return nil, err
	}
	return conn, nil
}
示例#7
0
文件: ws.go 项目: Gaboose/manet-echo
func (w WS) Select(netcon net.Conn, url string) (*websocket.Conn, error) {
	conf, err := websocket.NewConfig(url, url)
	if err != nil {
		return nil, err
	}

	wcon, err := websocket.NewClient(conf, netcon)
	if err != nil {
		return nil, err
	}

	return wcon, nil
}
func (s *DockerSuite) TestGetContainersAttachWebsocket(c *check.C) {
	testRequires(c, DaemonIsLinux)
	out, _ := dockerCmd(c, "run", "-dit", "busybox", "cat")

	rwc, err := sockConn(time.Duration(10*time.Second), "")
	c.Assert(err, checker.IsNil)

	cleanedContainerID := strings.TrimSpace(out)
	config, err := websocket.NewConfig(
		"/containers/"+cleanedContainerID+"/attach/ws?stream=1&stdin=1&stdout=1&stderr=1",
		"http://localhost",
	)
	c.Assert(err, checker.IsNil)

	ws, err := websocket.NewClient(config, rwc)
	c.Assert(err, checker.IsNil)
	defer ws.Close()

	expected := []byte("hello")
	actual := make([]byte, len(expected))

	outChan := make(chan error)
	go func() {
		_, err := io.ReadFull(ws, actual)
		outChan <- err
		close(outChan)
	}()

	inChan := make(chan error)
	go func() {
		_, err := ws.Write(expected)
		inChan <- err
		close(inChan)
	}()

	select {
	case err := <-inChan:
		c.Assert(err, checker.IsNil)
	case <-time.After(5 * time.Second):
		c.Fatal("Timeout writing to ws")
	}

	select {
	case err := <-outChan:
		c.Assert(err, checker.IsNil)
	case <-time.After(5 * time.Second):
		c.Fatal("Timeout reading from ws")
	}

	c.Assert(actual, checker.DeepEquals, expected, check.Commentf("Websocket didn't return the expected data"))
}
示例#9
0
// Connects to the tab/process for sending/recv'ing debug events
func wsConnection(addr, url string) *websocket.Conn {
	conn, err := net.Dial("tcp", addr)
	if err != nil {
		log.Fatal("error dialing ChromeTarget websocket: ", err)
	}
	config, errConfig := websocket.NewConfig(url, "http://localhost")
	if errConfig != nil {
		log.Fatalf("error building websocket config: addr: %s url: %s %v\n", addr, url, err)
	}
	client, errWS := websocket.NewClient(config, conn)
	if errWS != nil {
		log.Fatalf("error during websocket handshake: %v\n", errWS)
	}
	return client
}
示例#10
0
func newClient() (*websocket.Conn, error) {
	//todo
L:
	client, err := net.Dial("tcp", cfg.AgentAddr())
	if err != nil {
		log.Warning("not connected to agent server, try again ...")
		time.Sleep(1 * time.Second)
		goto L
	}
	conn, err := websocket.NewClient(newConfig_("/"), client)
	if err != nil {
		log.Errorf("WebSocket handshake error: %v", err)
		return nil, err
	}
	return conn, nil
}
示例#11
0
文件: cherry_test.go 项目: xozrc/xo
func TestCount(t *testing.T) {
	http.Handle("/count", websocket.Handler(countServer))
	once.Do(startCherryServer)

	// websocket.Dial()
	client, err := net.Dial("tcp", serverAddr)
	if err != nil {
		t.Fatal("dialing", err)
	}
	conn, err := websocket.NewClient(newConfig(t, "/count"), client)
	if err != nil {
		t.Errorf("WebSocket handshake error: %v", err)
		return
	}

	var count Count
	count.S = "hello"
	if err := websocket.JSON.Send(conn, count); err != nil {
		t.Errorf("Write: %v", err)
	}

	if err := websocket.JSON.Receive(conn, &count); err != nil {
		t.Errorf("Read: %v", err)
	}
	if count.N != 1 {
		t.Errorf("count: expected %d got %d", 1, count.N)
	}
	if count.S != "hello" {
		t.Errorf("count: expected %q got %q", "hello", count.S)
	}
	if err := websocket.JSON.Send(conn, count); err != nil {
		t.Errorf("Write: %v", err)
	}
	if err := websocket.JSON.Receive(conn, &count); err != nil {
		t.Errorf("Read: %v", err)
	}
	if count.N != 2 {
		t.Errorf("count: expected %d got %d", 2, count.N)
	}
	if count.S != "hellohello" {
		t.Errorf("count: expected %q got %q", "hellohello", count.S)
	}

	conn.Close()
}
示例#12
0
func newWSConn(originURL, user, pass string) (*wsConn, error) {
	v := url.Values{}
	v.Set("login", user)
	v.Set("password", pass)
	params := v.Encode()
	wsURL := strings.Replace(originURL, "http", "ws", 1) + "?" + params

	wsConfig, err := websocket.NewConfig(wsURL, originURL)
	if err != nil {
		return nil, err
	}
	wsConfig.TlsConfig = &tls.Config{RootCAs: rootCA}

	var wsc *websocket.Conn

	req := http.Request{
		URL: &url.URL{},
	}

	proxyURL, err := getProxy(&req)
	if err != nil {
		return nil, err
	}
	if proxyURL == nil {
		wsc, err = websocket.DialConfig(wsConfig)
		if err != nil {
			return nil, err
		}
	} else {
		conn, err := httpConnect(proxyURL.Host, wsConfig)
		if err != nil {
			return nil, err
		}
		if wsConfig.Location.Scheme == "wss" {
			conn = tls.Client(conn, wsConfig.TlsConfig)
		}

		wsc, err = websocket.NewClient(wsConfig, conn)
		if err != nil {
			return nil, err
		}
	}
	return &wsConn{conn: wsc}, nil
}
示例#13
0
func NewClient(addr string, m ClientModel, out chan string) (*Client, error) {
L:
	client, err := net.Dial("tcp", addr)
	if err != nil {
		log.Warningf("not connected to %+v, try again ...", addr)
		time.Sleep(1 * time.Second)
		goto L
	}
	conn, err := websocket.NewClient(newConfig("/"), client)
	if err != nil {
		log.Errorf("WebSocket handshake error: %v", err)
		return nil, err
	}
	rwc := NewWsReadWriter(conn)
	return &Client{
		ReadWriteCloser: rwc,
		ClientModel:     m,
		send:            make(chan string, 10),
		ctrl:            out,
	}, nil
}
示例#14
0
func addWsClient(t *testing.T, roomID string, clientID string) *websocket.Conn {
	c, err := net.Dial("tcp", serverAddr)
	if err != nil {
		t.Fatalf("net.Dial(tcp, %q) got error: %s, want nil", serverAddr, err.Error())
	}
	config := newConfig(t, "/ws")
	conn, err := websocket.NewClient(config, c)
	if err != nil {
		t.Fatalf("websocket.NewClient(%v, %v) got error: %s, want nil", config, c, err.Error())
	}

	// Registers the client.
	m := wsClientMsg{
		Cmd:      "register",
		ClientID: clientID,
		RoomID:   roomID,
	}
	write(t, conn, m)

	return conn
}
示例#15
0
func Fuzz(data []byte) int {
	cfg, err := websocket.NewConfig("http://golang.org/", "http://golang.org/")
	if err != nil {
		panic(err)
	}
	//	Header:   http.Header{},
	conn := &Conn{data, false}
	ws, err := websocket.NewClient(cfg, conn)
	if err != nil {
		return 0
	}
	ws.Write([]byte("abc"))
	var buf [16]byte
	ws.Read(buf[:])
	ws.Read(buf[:])
	ws.Close()
	if !conn.closed {
		panic("conn is not closed")
	}
	return 1
}
func websocketProxyDial(urlString, origin string) (ws *websocket.Conn, err error) {
	if os.Getenv("HTTP_PROXY") == "" {
		return websocket.Dial(urlString, "", origin)
	}

	purl, err := url.Parse(os.Getenv("HTTP_PROXY"))
	if err != nil {
		return nil, err
	}

	config, err := websocket.NewConfig(urlString, origin)
	if err != nil {
		return nil, err
	}

	client, err := websocketHTTPConnect(purl.Host, urlString)
	if err != nil {
		return nil, err
	}

	switch config.Location.Scheme {
	case "ws":
	case "wss":
		tlsClient := tls.Client(client, &tls.Config{
			ServerName: strings.Split(config.Location.Host, ":")[0],
		})
		err := tlsClient.Handshake()
		if err != nil {
			tlsClient.Close()
			return nil, err
		}
		client = tlsClient

	default:
		return nil, errors.New("invalid websocket schema")
	}

	return websocket.NewClient(config, client)
}
示例#17
0
func connect(localip string) {
	origin := "http://192.168.1.150/"
	url := "ws://192.168.1.150:8080/ws"
	//ws, err = websocket.Dial(url, "", origin)
	config, err := websocket.NewConfig(url, origin)
	if err != nil {
		log.Println(err)
		return
	}
	localaddr := &net.TCPAddr{IP: net.ParseIP(localip)}
	remoteaddr := &net.TCPAddr{IP: net.ParseIP("192.168.1.150"), Port: 8080}
	client, err := net.DialTCP("tcp4", localaddr, remoteaddr)
	if err != nil {
		log.Println(err)
		return
	}
	_, err = websocket.NewClient(config, client)
	if err != nil {
		log.Println(err)
	}
	time.Sleep(time.Second * 100)
	return
}
示例#18
0
func TestServer1(t *testing.T) {
	once.Do(startServer1)

	// websocket.Dial()
	client, err := net.Dial("tcp", serverAddr)
	if err != nil {
		t.Fatal("dialing", err)
	}
	log.Info("t=%v", t)
	conn, err := websocket.NewClient(newConfig_("/agent"), client)
	if err != nil {
		t.Errorf("WebSocket handshake error: %v", err)
		return
	}

	for i := 0; i < 10; i++ {
		msg := []byte("hello, world")
		fw.PrintType(msg, "msg")
		msg = append(msg, byte(i))
		//		append(msg, []byte("\n"))
		if _, err := conn.Write(msg); err != nil {
			t.Errorf("Write: %v", err)
		}
		var actual_msg = make([]byte, 512)
		n, err := conn.Read(actual_msg)
		if err != nil {
			t.Errorf("Read: %v", err)
		}
		actual_msg = actual_msg[0:n]
		if !bytes.Equal(msg, actual_msg) {
			t.Logf("Test: send %q got %q", msg, actual_msg)
		}
	}

	conn.Close()
}
示例#19
0
func sendWebsocketRequest(serverAddr, path, data string, c *C) (received string, err error) {
	client, err := net.DialTimeout("tcp", serverAddr, dialTimeout)
	if err != nil {
		return "", err
	}
	config := newWebsocketConfig(serverAddr, path)
	conn, err := websocket.NewClient(config, client)
	if err != nil {
		return "", err
	}
	defer conn.Close()
	if _, err := conn.Write([]byte(data)); err != nil {
		return "", err
	}
	var msg = make([]byte, 512)
	var n int
	n, err = conn.Read(msg)
	if err != nil {
		return "", err
	}

	received = string(msg[:n])
	return received, nil
}
func (s *DockerSuite) TestGetContainersAttachWebsocket(c *check.C) {
	runCmd := exec.Command(dockerBinary, "run", "-dit", "busybox", "cat")
	out, _, err := runCommandWithOutput(runCmd)
	if err != nil {
		c.Fatalf(out, err)
	}

	rwc, err := sockConn(time.Duration(10 * time.Second))
	if err != nil {
		c.Fatal(err)
	}

	cleanedContainerID := strings.TrimSpace(out)
	config, err := websocket.NewConfig(
		"/containers/"+cleanedContainerID+"/attach/ws?stream=1&stdin=1&stdout=1&stderr=1",
		"http://localhost",
	)
	if err != nil {
		c.Fatal(err)
	}

	ws, err := websocket.NewClient(config, rwc)
	if err != nil {
		c.Fatal(err)
	}
	defer ws.Close()

	expected := []byte("hello")
	actual := make([]byte, len(expected))

	outChan := make(chan error)
	go func() {
		_, err := ws.Read(actual)
		outChan <- err
		close(outChan)
	}()

	inChan := make(chan error)
	go func() {
		_, err := ws.Write(expected)
		inChan <- err
		close(inChan)
	}()

	select {
	case err := <-inChan:
		if err != nil {
			c.Fatal(err)
		}
	case <-time.After(5 * time.Second):
		c.Fatal("Timeout writing to ws")
	}

	select {
	case err := <-outChan:
		if err != nil {
			c.Fatal(err)
		}
	case <-time.After(5 * time.Second):
		c.Fatal("Timeout reading from ws")
	}

	if !bytes.Equal(expected, actual) {
		c.Fatal("Expected output on websocket to match input")
	}
}
示例#21
0
func (s *S) TestHTTPWebsocket(c *C) {
	done := make(chan struct{})
	h := http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
		if req.URL.Path != "/websocket" {
			w.Write([]byte("not a websocket upgrade\n"))
			return
		}
		websocket.Handler(func(conn *websocket.Conn) {
			_, err := conn.Write([]byte("1"))
			c.Assert(err, IsNil)
			res := make([]byte, 1)
			_, err = conn.Read(res)
			c.Assert(err, IsNil)
			c.Assert(res[0], Equals, byte('2'))
			done <- struct{}{}
		}).ServeHTTP(w, req)
	})
	srv := httptest.NewServer(h)
	defer srv.Close()

	l := s.newHTTPListener(c)
	defer l.Close()

	addHTTPRoute(c, l)

	discoverdRegisterHTTP(c, l, srv.Listener.Addr().String())

	tests := []struct {
		afterKeepAlive bool
	}{
		{afterKeepAlive: false},
		{afterKeepAlive: true}, // ensure that upgrade still works on reused conn
	}
	for _, test := range tests {
		conn, err := net.Dial("tcp", l.Addr)
		c.Assert(err, IsNil)
		defer conn.Close()

		if test.afterKeepAlive {
			req, err := http.NewRequest("GET", "http://example.com", nil)
			c.Assert(err, IsNil)
			err = req.Write(conn)
			c.Assert(err, IsNil)
			res, err := http.ReadResponse(bufio.NewReader(conn), req)
			c.Assert(err, IsNil)
			data, err := ioutil.ReadAll(res.Body)
			c.Assert(err, IsNil)
			res.Body.Close()
			c.Assert(res.StatusCode, Equals, 200)
			c.Assert(string(data), Equals, "not a websocket upgrade\n")
		}

		conf, err := websocket.NewConfig("ws://example.com/websocket", "http://example.net")
		c.Assert(err, IsNil)
		wc, err := websocket.NewClient(conf, conn)
		c.Assert(err, IsNil)

		res := make([]byte, 1)
		_, err = wc.Read(res)
		c.Assert(err, IsNil)
		c.Assert(res[0], Equals, byte('1'))
		_, err = wc.Write([]byte("2"))
		c.Assert(err, IsNil)
		<-done
	}
}
示例#22
0
文件: ws.go 项目: rlhatcher/mangos
func (d *dialer) Dial() (mangos.Pipe, error) {
	var w *wsPipe

	pname := d.proto.PeerName() + ".sp.nanomsg.org"
	// We have to supply an origin because Go's websocket
	// implementation seems to require it.  We fake a garbage one.
	// Perhaps we should allow applications to fake this out.
	d.origin = "x://"

	config, err := websocket.NewConfig(d.addr, d.origin)
	if err != nil {
		return nil, err
	}
	config.Protocol = append([]string{}, pname)

	if v, ok := d.opts[mangos.OptionTlsConfig]; ok {
		config.TlsConfig = v.(*tls.Config)
	}

	host := config.Location.Host
	if strings.Index(host, ":") < 0 {
		if d.iswss {
			host = host + ":443"
		} else {
			host = host + ":80"
		}
	}
	taddr, err := net.ResolveTCPAddr("tcp", host)
	if err != nil {
		return nil, err
	}
	tconn, err := net.DialTCP("tcp", nil, taddr)
	if err != nil {
		return nil, err
	}
	laddr := tconn.LocalAddr()

	if v, ok := d.opts[mangos.OptionNoDelay]; ok {
		if err := tconn.SetNoDelay(v.(bool)); err != nil {
			tconn.Close()
			return nil, err
		}
	}
	if v, ok := d.opts[mangos.OptionKeepAlive]; ok {
		if err := tconn.SetKeepAlive(v.(bool)); err != nil {
			tconn.Close()
			return nil, err
		}
	}

	w = &wsPipe{proto: d.proto, addr: d.addr, open: true}
	w.props = make(map[string]interface{})

	var conn net.Conn
	if d.iswss {
		tlsconn := tls.Client(tconn, config.TlsConfig)
		w.props[mangos.PropTlsConnState] = tlsconn.ConnectionState()
		w.iswss = true
		conn = tlsconn
	} else {
		conn = tconn
	}

	if w.ws, err = websocket.NewClient(config, conn); err != nil {
		conn.Close()
		return nil, err
	}

	w.props[mangos.PropLocalAddr] = laddr
	w.props[mangos.PropRemoteAddr] = w.ws.RemoteAddr()

	w.wg.Add(1)
	return w, nil
}
示例#23
0
// getRoute is a utility function for making the web request to a route.
// Protocol is one of http, https, ws, or wss.  If the protocol is https or wss,
// then getRoute will make a secure transport client with InsecureSkipVerify:
// true.  If the protocol is http or ws, then getRoute does an unencrypted HTTP
// client request.  If the protocol is ws or wss, then getRoute will upgrade the
// connection to websockets and then send expectedResponse *to* the route, with
// the expectation that the route will echo back what it receives.  Note that
// getRoute returns only the first len(expectedResponse) bytes of the actual
// response.
func getRoute(routerUrl string, hostName string, protocol string, headers map[string]string, expectedResponse string) (response string, err error) {
	url := protocol + "://" + routerUrl
	var tlsConfig *tls.Config

	routerAddress := getRouteAddress()
	dialer := func(network, addr string) (net.Conn, error) {
		if _, port, err := net.SplitHostPort(addr); err == nil {
			return net.Dial(network, fmt.Sprintf("%s:%s", routerAddress, port))
		}
		return net.Dial(network, fmt.Sprintf("%s:%s", routerAddress, "80"))
	}
	tlsDialer := func(network, addr string, config *tls.Config) (*tls.Conn, error) {
		if _, port, err := net.SplitHostPort(addr); err == nil {
			return tls.Dial(network, fmt.Sprintf("%s:%s", routerAddress, port), config)
		}
		return tls.Dial(network, fmt.Sprintf("%s:%s", routerAddress, "443"), config)
	}

	if protocol == "https" || protocol == "wss" {
		tlsConfig = &tls.Config{
			InsecureSkipVerify: true,
			ServerName:         hostName,
		}
	}

	switch protocol {
	case "http", "https":
		httpClient := &http.Client{Transport: knet.SetTransportDefaults(&http.Transport{
			Dial:            dialer,
			TLSClientConfig: tlsConfig,
		}),
		}
		req, err := http.NewRequest("GET", url, nil)

		if err != nil {
			return "", err
		}

		for name, value := range headers {
			req.Header.Set(name, value)
		}

		req.Host = hostName
		resp, err := httpClient.Do(req)
		if err != nil {
			return "", err
		}
		defer resp.Body.Close()
		switch {
		case resp.StatusCode == 503:
			return "", ErrUnavailable
		case resp.StatusCode == 401:
			return "", ErrUnauthenticated
		case resp.StatusCode >= 400:
			return "", fmt.Errorf("GET of %s returned: %d", url, resp.StatusCode)
		}
		respBody, err := ioutil.ReadAll(resp.Body)
		cookies := resp.Cookies()
		for _, cookie := range cookies {
			if len(cookie.Name) != 32 || len(cookie.Value) != 32 {
				return "", fmt.Errorf("GET of %s returned bad cookie %s=%s", url, cookie.Name, cookie.Value)
			}
		}
		return string(respBody), err

	case "ws", "wss":
		origin := fmt.Sprintf("http://%s/", tr.GetDefaultLocalAddress())
		wsConfig, err := websocket.NewConfig(url, origin)
		if err != nil {
			return "", err
		}

		port := 80
		if protocol == "wss" {
			port = 443
		}
		if _, _, err := net.SplitHostPort(hostName); err == nil {
			wsConfig.Location.Host = hostName
		} else {
			wsConfig.Location.Host = fmt.Sprintf("%s:%d", hostName, port)
		}

		var conn net.Conn
		if tlsConfig == nil {
			conn, err = dialer("tcp", wsConfig.Location.Host)
		} else {
			conn, err = tlsDialer("tcp", wsConfig.Location.Host, tlsConfig)
		}
		if err != nil {
			return "", err
		}
		ws, err := websocket.NewClient(wsConfig, conn)
		if err != nil {
			if err == websocket.ErrBadStatus {
				return "", ErrUnavailable
			}
			return "", err
		}

		_, err = ws.Write([]byte(expectedResponse))
		if err != nil {
			return "", err
		}

		var msg = make([]byte, len(expectedResponse))
		_, err = ws.Read(msg)
		if err != nil {
			return "", err
		}

		return string(msg), nil
	}

	return "", errors.New("Unrecognized protocol in getRoute")
}