resolver/dns: error if target ends with a colon instead of assuming the default port (#2150)
Technically this is a behavior change, but any usage of "host:" or ":" should be considered invalid, since dialing a target with a trailing ":" attempts to dial port zero, which is never valid (and we always used to pass the target directly to `net.Dial`). In https://github.com/grpc/grpc/pull/15618, the target format will be defined as: `host[:port]` -- not: `host[:[port]]`. (This is potentially subject to change.)
This commit is contained in:
Родитель
ba63e52faf
Коммит
0c16dc1c74
|
@ -51,7 +51,13 @@ const (
|
|||
)
|
||||
|
||||
var (
|
||||
errMissingAddr = errors.New("missing address")
|
||||
errMissingAddr = errors.New("dns resolver: missing address")
|
||||
|
||||
// Addresses ending with a colon that is supposed to be the separator
|
||||
// between host and port is not allowed. E.g. "::" is a valid address as
|
||||
// it is an IPv6 address (host only) and "[::]:" is invalid as it ends with
|
||||
// a colon as the host and port separator
|
||||
errEndsWithColon = errors.New("dns resolver: missing port after port-separator colon")
|
||||
)
|
||||
|
||||
// NewBuilder creates a dnsBuilder which is used to factory DNS resolvers.
|
||||
|
@ -297,7 +303,6 @@ func formatIP(addr string) (addrIP string, ok bool) {
|
|||
// target: "ipv4-host:80" returns host: "ipv4-host", port: "80"
|
||||
// target: "[ipv6-host]" returns host: "ipv6-host", port: "443"
|
||||
// target: ":80" returns host: "localhost", port: "80"
|
||||
// target: ":" returns host: "localhost", port: "443"
|
||||
func parseTarget(target string) (host, port string, err error) {
|
||||
if target == "" {
|
||||
return "", "", errMissingAddr
|
||||
|
@ -307,15 +312,15 @@ func parseTarget(target string) (host, port string, err error) {
|
|||
return target, defaultPort, nil
|
||||
}
|
||||
if host, port, err = net.SplitHostPort(target); err == nil {
|
||||
if port == "" {
|
||||
// If the port field is empty (target ends with colon), e.g. "[::1]:", this is an error.
|
||||
return "", "", errEndsWithColon
|
||||
}
|
||||
// target has port, i.e ipv4-host:port, [ipv6-host]:port, host-name:port
|
||||
if host == "" {
|
||||
// Keep consistent with net.Dial(): If the host is empty, as in ":80", the local system is assumed.
|
||||
host = "localhost"
|
||||
}
|
||||
if port == "" {
|
||||
// If the port field is empty(target ends with colon), e.g. "[::1]:", defaultPort is used.
|
||||
port = defaultPort
|
||||
}
|
||||
return host, port, nil
|
||||
}
|
||||
if host, port, err = net.SplitHostPort(target + ":" + defaultPort); err == nil {
|
||||
|
|
|
@ -815,7 +815,7 @@ func testIPResolver(t *testing.T) {
|
|||
{"127.0.0.1:12345", []resolver.Address{{Addr: "127.0.0.1:12345"}}},
|
||||
{"::1", []resolver.Address{{Addr: "[::1]" + colonDefaultPort}}},
|
||||
{"[::1]:12345", []resolver.Address{{Addr: "[::1]:12345"}}},
|
||||
{"[::1]:", []resolver.Address{{Addr: "[::1]:443"}}},
|
||||
{"[::1]", []resolver.Address{{Addr: "[::1]:443"}}},
|
||||
{"2001:db8:85a3::8a2e:370:7334", []resolver.Address{{Addr: "[2001:db8:85a3::8a2e:370:7334]" + colonDefaultPort}}},
|
||||
{"[2001:db8:85a3::8a2e:370:7334]", []resolver.Address{{Addr: "[2001:db8:85a3::8a2e:370:7334]" + colonDefaultPort}}},
|
||||
{"[2001:db8:85a3::8a2e:370:7334]:12345", []resolver.Address{{Addr: "[2001:db8:85a3::8a2e:370:7334]:12345"}}},
|
||||
|
@ -867,6 +867,7 @@ func TestResolveFunc(t *testing.T) {
|
|||
{"www.google.com", nil},
|
||||
{"foo.bar:12345", nil},
|
||||
{"127.0.0.1", nil},
|
||||
{"::", nil},
|
||||
{"127.0.0.1:12345", nil},
|
||||
{"[::1]:80", nil},
|
||||
{"[2001:db8:a0b:12f0::1]:21", nil},
|
||||
|
@ -875,7 +876,8 @@ func TestResolveFunc(t *testing.T) {
|
|||
{"[fe80::1%lo0]:80", nil},
|
||||
{"golang.org:http", nil},
|
||||
{"[2001:db8::1]:http", nil},
|
||||
{":", nil},
|
||||
{"[2001:db8::1]:", errEndsWithColon},
|
||||
{":", errEndsWithColon},
|
||||
{"", errMissingAddr},
|
||||
{"[2001:db8:a0b:12f0::1", errForInvalidTarget},
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче