Browse code

Allow API to bind to ipv6 addresses

Use `net.SplitHostPort` which supports ipv6 rather than relying on
splitting on `:`

Signed-off-by: Brian Goff <cpuguy83@gmail.com>

Brian Goff authored on 2015/10/13 02:40:38
Showing 2 changed files
... ...
@@ -5,6 +5,7 @@ package parsers
5 5
 
6 6
 import (
7 7
 	"fmt"
8
+	"net"
8 9
 	"net/url"
9 10
 	"path"
10 11
 	"runtime"
... ...
@@ -74,26 +75,33 @@ func ParseTCPAddr(tryAddr string, defaultAddr string) (string, error) {
74 74
 	if err != nil {
75 75
 		return "", err
76 76
 	}
77
-	hostParts := strings.Split(u.Host, ":")
78
-	if len(hostParts) != 2 {
77
+
78
+	host, port, err := net.SplitHostPort(u.Host)
79
+	if err != nil {
79 80
 		return "", fmt.Errorf("Invalid bind address format: %s", tryAddr)
80 81
 	}
81
-	defaults := strings.Split(defaultAddr, ":")
82
-	if len(defaults) != 3 {
83
-		return "", fmt.Errorf("Invalid defaults address format: %s", defaultAddr)
82
+
83
+	defaultAddr = strings.TrimPrefix(defaultAddr, "tcp://")
84
+	defaultHost, defaultPort, err := net.SplitHostPort(defaultAddr)
85
+	if err != nil {
86
+		return "", err
84 87
 	}
85 88
 
86
-	host := hostParts[0]
87 89
 	if host == "" {
88
-		host = strings.TrimPrefix(defaults[1], "//")
90
+		host = defaultHost
89 91
 	}
90
-	if hostParts[1] == "" {
91
-		hostParts[1] = defaults[2]
92
+	if port == "" {
93
+		port = defaultPort
92 94
 	}
93
-	p, err := strconv.Atoi(hostParts[1])
95
+	p, err := strconv.Atoi(port)
94 96
 	if err != nil && p == 0 {
95 97
 		return "", fmt.Errorf("Invalid bind address format: %s", tryAddr)
96 98
 	}
99
+
100
+	if net.ParseIP(host).To4() == nil && strings.Contains(host, ":") {
101
+		// This is either an ipv6 address
102
+		host = "[" + host + "]"
103
+	}
97 104
 	return fmt.Sprintf("tcp://%s:%d%s", host, p, u.Path), nil
98 105
 }
99 106
 
... ...
@@ -28,9 +28,13 @@ func TestParseDockerDaemonHost(t *testing.T) {
28 28
 		"fd":   "Invalid bind address format: fd",
29 29
 	}
30 30
 	valids := map[string]string{
31
-		"0.0.0.1:":                "tcp://0.0.0.1:2376",
32
-		"0.0.0.1:5555":            "tcp://0.0.0.1:5555",
33
-		"0.0.0.1:5555/path":       "tcp://0.0.0.1:5555/path",
31
+		"0.0.0.1:":                    "tcp://0.0.0.1:2376",
32
+		"0.0.0.1:5555":                "tcp://0.0.0.1:5555",
33
+		"0.0.0.1:5555/path":           "tcp://0.0.0.1:5555/path",
34
+		"[::1]:":                      "tcp://[::1]:2376",
35
+		"[::1]:5555/path":             "tcp://[::1]:5555/path",
36
+		"[0:0:0:0:0:0:0:1]:":          "tcp://[0:0:0:0:0:0:0:1]:2376",
37
+		"[0:0:0:0:0:0:0:1]:5555/path": "tcp://[0:0:0:0:0:0:0:1]:5555/path",
34 38
 		":6666":                   "tcp://127.0.0.1:6666",
35 39
 		":6666/path":              "tcp://127.0.0.1:6666/path",
36 40
 		"":                        defaultHOST,
... ...
@@ -44,6 +48,9 @@ func TestParseDockerDaemonHost(t *testing.T) {
44 44
 		"unix://":                 "unix:///var/run/docker.sock",
45 45
 		"fd://":                   "fd://",
46 46
 		"fd://something":          "fd://something",
47
+		"localhost:":              "tcp://localhost:2376",
48
+		"localhost:5555":          "tcp://localhost:5555",
49
+		"localhost:5555/path":     "tcp://localhost:5555/path",
47 50
 	}
48 51
 	for invalidAddr, expectedError := range invalids {
49 52
 		if addr, err := ParseDockerDaemonHost(defaultHTTPHost, defaultUnix, invalidAddr); err == nil || err.Error() != expectedError {
... ...
@@ -69,15 +76,24 @@ func TestParseTCP(t *testing.T) {
69 69
 		"udp://127.0.0.1:2375": "Invalid proto, expected tcp: udp://127.0.0.1:2375",
70 70
 	}
71 71
 	valids := map[string]string{
72
-		"":                  defaultHTTPHost,
73
-		"tcp://":            defaultHTTPHost,
74
-		"0.0.0.1:":          "tcp://0.0.0.1:2376",
75
-		"0.0.0.1:5555":      "tcp://0.0.0.1:5555",
76
-		"0.0.0.1:5555/path": "tcp://0.0.0.1:5555/path",
77
-		":6666":             "tcp://127.0.0.1:6666",
78
-		":6666/path":        "tcp://127.0.0.1:6666/path",
79
-		"tcp://:7777":       "tcp://127.0.0.1:7777",
80
-		"tcp://:7777/path":  "tcp://127.0.0.1:7777/path",
72
+		"":                            defaultHTTPHost,
73
+		"tcp://":                      defaultHTTPHost,
74
+		"0.0.0.1:":                    "tcp://0.0.0.1:2376",
75
+		"0.0.0.1:5555":                "tcp://0.0.0.1:5555",
76
+		"0.0.0.1:5555/path":           "tcp://0.0.0.1:5555/path",
77
+		":6666":                       "tcp://127.0.0.1:6666",
78
+		":6666/path":                  "tcp://127.0.0.1:6666/path",
79
+		"tcp://:7777":                 "tcp://127.0.0.1:7777",
80
+		"tcp://:7777/path":            "tcp://127.0.0.1:7777/path",
81
+		"[::1]:":                      "tcp://[::1]:2376",
82
+		"[::1]:5555":                  "tcp://[::1]:5555",
83
+		"[::1]:5555/path":             "tcp://[::1]:5555/path",
84
+		"[0:0:0:0:0:0:0:1]:":          "tcp://[0:0:0:0:0:0:0:1]:2376",
85
+		"[0:0:0:0:0:0:0:1]:5555":      "tcp://[0:0:0:0:0:0:0:1]:5555",
86
+		"[0:0:0:0:0:0:0:1]:5555/path": "tcp://[0:0:0:0:0:0:0:1]:5555/path",
87
+		"localhost:":                  "tcp://localhost:2376",
88
+		"localhost:5555":              "tcp://localhost:5555",
89
+		"localhost:5555/path":         "tcp://localhost:5555/path",
81 90
 	}
82 91
 	for invalidAddr, expectedError := range invalids {
83 92
 		if addr, err := ParseTCPAddr(invalidAddr, defaultHTTPHost); err == nil || err.Error() != expectedError {