From ad9e53ada63659da8aba06c40008f08e6723928a Mon Sep 17 00:00:00 2001 From: James Sharp Date: Fri, 22 Nov 2019 12:28:57 +0000 Subject: [PATCH] grpc-js: fix explicit ipv6 addresses not resolving correctly --- packages/grpc-js/src/resolver-dns.ts | 9 ++-- packages/grpc-js/test/test-resolver.ts | 57 ++++++++++++++++++++++++++ 2 files changed, 62 insertions(+), 4 deletions(-) diff --git a/packages/grpc-js/src/resolver-dns.ts b/packages/grpc-js/src/resolver-dns.ts index 528529c9..9f91d70a 100644 --- a/packages/grpc-js/src/resolver-dns.ts +++ b/packages/grpc-js/src/resolver-dns.ts @@ -115,14 +115,15 @@ const dnsLookupPromise = util.promisify(dns.lookup); function parseIP(target: string): string[] | null { /* These three regular expressions are all mutually exclusive, so we just * want the first one that matches the target string, if any do. */ + const ipv4Match = IPV4_REGEX.exec(target); const match = - IPV4_REGEX.exec(target) || - IPV6_REGEX.exec(target) || - IPV6_BRACKET_REGEX.exec(target); + ipv4Match || IPV6_REGEX.exec(target) || IPV6_BRACKET_REGEX.exec(target); if (match === null) { return null; } - const addr = match[1]; + + // ipv6 addresses should be bracketed + const addr = ipv4Match ? match[1] : `[${match[1]}]`; let port: string; if (match[2]) { port = match[2]; diff --git a/packages/grpc-js/test/test-resolver.ts b/packages/grpc-js/test/test-resolver.ts index 6e3a6b1b..951291a6 100644 --- a/packages/grpc-js/test/test-resolver.ts +++ b/packages/grpc-js/test/test-resolver.ts @@ -67,6 +67,63 @@ describe('Name Resolver', () => { const resolver = resolverManager.createResolver(target, listener); resolver.updateResolution(); }); + it('Should correctly represent an ipv4 address', done => { + const target = '1.2.3.4'; + const listener: resolverManager.ResolverListener = { + onSuccessfulResolution: ( + addressList: string[], + serviceConfig: ServiceConfig | null, + serviceConfigError: StatusObject | null + ) => { + assert(addressList.includes('1.2.3.4:443')); + // We would check for the IPv6 address but it needs to be omitted on some Node versions + done(); + }, + onError: (error: StatusObject) => { + done(new Error(`Failed with status ${error.details}`)); + }, + }; + const resolver = resolverManager.createResolver(target, listener); + resolver.updateResolution(); + }); + it('Should correctly represent an ipv6 address', done => { + const target = '::1'; + const listener: resolverManager.ResolverListener = { + onSuccessfulResolution: ( + addressList: string[], + serviceConfig: ServiceConfig | null, + serviceConfigError: StatusObject | null + ) => { + assert(addressList.includes('[::1]:443')); + // We would check for the IPv6 address but it needs to be omitted on some Node versions + done(); + }, + onError: (error: StatusObject) => { + done(new Error(`Failed with status ${error.details}`)); + }, + }; + const resolver = resolverManager.createResolver(target, listener); + resolver.updateResolution(); + }); + it('Should correctly represent a bracketed ipv6 address', done => { + const target = '[::1]:50051'; + const listener: resolverManager.ResolverListener = { + onSuccessfulResolution: ( + addressList: string[], + serviceConfig: ServiceConfig | null, + serviceConfigError: StatusObject | null + ) => { + assert(addressList.includes('[::1]:50051')); + // We would check for the IPv6 address but it needs to be omitted on some Node versions + done(); + }, + onError: (error: StatusObject) => { + done(new Error(`Failed with status ${error.details}`)); + }, + }; + const resolver = resolverManager.createResolver(target, listener); + resolver.updateResolution(); + }); it('Should resolve a public address', done => { const target = 'example.com'; const listener: resolverManager.ResolverListener = {