From 19561b96d501cf30c103dfffacc6ac2076d6c910 Mon Sep 17 00:00:00 2001 From: Brian Goff Date: Mon, 12 Oct 2015 13:40:38 -0400 Subject: [PATCH] Allow API to bind to ipv6 addresses Use `net.SplitHostPort` which supports ipv6 rather than relying on splitting on `:` Signed-off-by: Brian Goff --- parsers/parsers.go | 30 +++++++++++++++++++----------- parsers/parsers_test.go | 40 ++++++++++++++++++++++++++++------------ 2 files changed, 47 insertions(+), 23 deletions(-) diff --git a/parsers/parsers.go b/parsers/parsers.go index 75d54c5..14f4b75 100644 --- a/parsers/parsers.go +++ b/parsers/parsers.go @@ -5,6 +5,7 @@ package parsers import ( "fmt" + "net" "net/url" "path" "runtime" @@ -74,26 +75,33 @@ func ParseTCPAddr(tryAddr string, defaultAddr string) (string, error) { if err != nil { return "", err } - hostParts := strings.Split(u.Host, ":") - if len(hostParts) != 2 { + + host, port, err := net.SplitHostPort(u.Host) + if err != nil { return "", fmt.Errorf("Invalid bind address format: %s", tryAddr) } - defaults := strings.Split(defaultAddr, ":") - if len(defaults) != 3 { - return "", fmt.Errorf("Invalid defaults address format: %s", defaultAddr) - } - host := hostParts[0] + defaultAddr = strings.TrimPrefix(defaultAddr, "tcp://") + defaultHost, defaultPort, err := net.SplitHostPort(defaultAddr) + if err != nil { + return "", err + } + if host == "" { - host = strings.TrimPrefix(defaults[1], "//") + host = defaultHost } - if hostParts[1] == "" { - hostParts[1] = defaults[2] + if port == "" { + port = defaultPort } - p, err := strconv.Atoi(hostParts[1]) + p, err := strconv.Atoi(port) if err != nil && p == 0 { return "", fmt.Errorf("Invalid bind address format: %s", tryAddr) } + + if net.ParseIP(host).To4() == nil && strings.Contains(host, ":") { + // This is either an ipv6 address + host = "[" + host + "]" + } return fmt.Sprintf("tcp://%s:%d%s", host, p, u.Path), nil } diff --git a/parsers/parsers_test.go b/parsers/parsers_test.go index 49cbdb1..b6fe50a 100644 --- a/parsers/parsers_test.go +++ b/parsers/parsers_test.go @@ -28,9 +28,13 @@ func TestParseDockerDaemonHost(t *testing.T) { "fd": "Invalid bind address format: fd", } valids := map[string]string{ - "0.0.0.1:": "tcp://0.0.0.1:2376", - "0.0.0.1:5555": "tcp://0.0.0.1:5555", - "0.0.0.1:5555/path": "tcp://0.0.0.1:5555/path", + "0.0.0.1:": "tcp://0.0.0.1:2376", + "0.0.0.1:5555": "tcp://0.0.0.1:5555", + "0.0.0.1:5555/path": "tcp://0.0.0.1:5555/path", + "[::1]:": "tcp://[::1]:2376", + "[::1]:5555/path": "tcp://[::1]:5555/path", + "[0:0:0:0:0:0:0:1]:": "tcp://[0:0:0:0:0:0:0:1]:2376", + "[0:0:0:0:0:0:0:1]:5555/path": "tcp://[0:0:0:0:0:0:0:1]:5555/path", ":6666": "tcp://127.0.0.1:6666", ":6666/path": "tcp://127.0.0.1:6666/path", "": defaultHOST, @@ -44,6 +48,9 @@ func TestParseDockerDaemonHost(t *testing.T) { "unix://": "unix:///var/run/docker.sock", "fd://": "fd://", "fd://something": "fd://something", + "localhost:": "tcp://localhost:2376", + "localhost:5555": "tcp://localhost:5555", + "localhost:5555/path": "tcp://localhost:5555/path", } for invalidAddr, expectedError := range invalids { if addr, err := ParseDockerDaemonHost(defaultHTTPHost, defaultUnix, invalidAddr); err == nil || err.Error() != expectedError { @@ -69,15 +76,24 @@ func TestParseTCP(t *testing.T) { "udp://127.0.0.1:2375": "Invalid proto, expected tcp: udp://127.0.0.1:2375", } valids := map[string]string{ - "": defaultHTTPHost, - "tcp://": defaultHTTPHost, - "0.0.0.1:": "tcp://0.0.0.1:2376", - "0.0.0.1:5555": "tcp://0.0.0.1:5555", - "0.0.0.1:5555/path": "tcp://0.0.0.1:5555/path", - ":6666": "tcp://127.0.0.1:6666", - ":6666/path": "tcp://127.0.0.1:6666/path", - "tcp://:7777": "tcp://127.0.0.1:7777", - "tcp://:7777/path": "tcp://127.0.0.1:7777/path", + "": defaultHTTPHost, + "tcp://": defaultHTTPHost, + "0.0.0.1:": "tcp://0.0.0.1:2376", + "0.0.0.1:5555": "tcp://0.0.0.1:5555", + "0.0.0.1:5555/path": "tcp://0.0.0.1:5555/path", + ":6666": "tcp://127.0.0.1:6666", + ":6666/path": "tcp://127.0.0.1:6666/path", + "tcp://:7777": "tcp://127.0.0.1:7777", + "tcp://:7777/path": "tcp://127.0.0.1:7777/path", + "[::1]:": "tcp://[::1]:2376", + "[::1]:5555": "tcp://[::1]:5555", + "[::1]:5555/path": "tcp://[::1]:5555/path", + "[0:0:0:0:0:0:0:1]:": "tcp://[0:0:0:0:0:0:0:1]:2376", + "[0:0:0:0:0:0:0:1]:5555": "tcp://[0:0:0:0:0:0:0:1]:5555", + "[0:0:0:0:0:0:0:1]:5555/path": "tcp://[0:0:0:0:0:0:0:1]:5555/path", + "localhost:": "tcp://localhost:2376", + "localhost:5555": "tcp://localhost:5555", + "localhost:5555/path": "tcp://localhost:5555/path", } for invalidAddr, expectedError := range invalids { if addr, err := ParseTCPAddr(invalidAddr, defaultHTTPHost); err == nil || err.Error() != expectedError {