// 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 if protocol == "https" || protocol == "wss" { tlsConfig = &tls.Config{ InsecureSkipVerify: true, ServerName: hostName, } } switch protocol { case "http", "https": httpClient := &http.Client{Transport: &http.Transport{ 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() respBody, err := ioutil.ReadAll(resp.Body) 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 } wsConfig.Location.Host = fmt.Sprintf("%s:%d", hostName, port) wsConfig.TlsConfig = tlsConfig ws, err := websocket.DialConfig(wsConfig) if err != nil { 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") }
// 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") }
// 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 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{ 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) 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 } wsConfig.Location.Host = fmt.Sprintf("%s:%d", hostName, port) wsConfig.TlsConfig = tlsConfig ws, err := websocket.DialConfig(wsConfig) if err != nil { if derr, ok := err.(*websocket.DialError); ok { if derr.Err == websocket.ErrBadStatus { // a better websocket library would know the difference here 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") }