diff --git a/pkg/netutil/netutil.go b/pkg/netutil/netutil.go index b7bfb2cc7..0add9320d 100644 --- a/pkg/netutil/netutil.go +++ b/pkg/netutil/netutil.go @@ -44,6 +44,8 @@ func AwaitReachable(addr string, maxWait time.Duration) error { // to passing to net.Dial, with the port set as the scheme's default port if // absent. func HostPort(urlStr string) (string, error) { + // TODO: rename this function to URLHostPort instead, like + // ListenHostPort below. u, err := url.Parse(urlStr) if err != nil { return "", fmt.Errorf("could not parse %q as a url: %v", urlStr, err) @@ -69,6 +71,22 @@ func HostPort(urlStr string) (string, error) { return hostPort, nil } +// ListenHostPort maps a listen address into a host:port string. +// If the host part in listenAddr is empty or 0.0.0.0, localhost +// is used instead. +func ListenHostPort(listenAddr string) (string, error) { + hp := listenAddr + if strings.HasPrefix(hp, ":") { + hp = "localhost" + hp + } else if strings.HasPrefix(hp, "0.0.0.0:") { + hp = "localhost:" + hp[len("0.0.0.0:"):] + } + if _, _, err := net.SplitHostPort(hp); err != nil { + return "", err + } + return hp, nil +} + // ListenOnLocalRandomPort returns a TCP listener on a random // localhost port. func ListenOnLocalRandomPort() (net.Listener, error) { diff --git a/pkg/netutil/netutil_test.go b/pkg/netutil/netutil_test.go index 644d7eb6b..3fa2a8ba5 100644 --- a/pkg/netutil/netutil_test.go +++ b/pkg/netutil/netutil_test.go @@ -123,6 +123,29 @@ func TestHostPort(t *testing.T) { } } +func TestListenHostPort(t *testing.T) { + tests := []struct { + in string + want string // or "ERR:" + }{ + {":80", "localhost:80"}, + {"0.0.0.0:80", "localhost:80"}, + {"foo:80", "foo:80"}, + {"foo:0", "foo:0"}, + {"", "ERR"}, + } + for _, tt := range tests { + got, err := ListenHostPort(tt.in) + if err != nil { + got = "ERR" + } + if got != tt.want { + t.Errorf("ListenHostPort(%q) = %q, %v; want %q", tt.in, got, err, tt.want) + } + } + +} + func testLocalhostResolver(t *testing.T, resolve func() net.IP) { ip := resolve() if ip == nil {