diff --git a/packages/grpc-js/src/channel.ts b/packages/grpc-js/src/channel.ts index 85df3cf3..764c7a69 100644 --- a/packages/grpc-js/src/channel.ts +++ b/packages/grpc-js/src/channel.ts @@ -173,6 +173,9 @@ export class ChannelImplementation implements Channel { /* This ensures that the target has a scheme that is registered with the * resolver */ const defaultSchemeMapResult = mapUriDefaultScheme(originalTargetUri); + if (defaultSchemeMapResult === null) { + throw new Error(`Could not find a default scheme for target name "${target}"`); + } if (this.options['grpc.default_authority']) { this.defaultAuthority = this.options['grpc.default_authority'] as string; } else { diff --git a/packages/grpc-js/src/resolver-uds.ts b/packages/grpc-js/src/resolver-uds.ts index c147f637..759cb233 100644 --- a/packages/grpc-js/src/resolver-uds.ts +++ b/packages/grpc-js/src/resolver-uds.ts @@ -18,7 +18,6 @@ import { Resolver, ResolverListener, registerResolver, - registerDefaultResolver, } from './resolver'; import { SubchannelAddress } from './subchannel'; import { GrpcUri } from './uri-parser'; diff --git a/packages/grpc-js/src/resolver.ts b/packages/grpc-js/src/resolver.ts index 6af996a2..7d6d1ad5 100644 --- a/packages/grpc-js/src/resolver.ts +++ b/packages/grpc-js/src/resolver.ts @@ -131,15 +131,16 @@ export function getDefaultAuthority(target: GrpcUri): string { } } -export function mapUriDefaultScheme(target: GrpcUri): GrpcUri { +export function mapUriDefaultScheme(target: GrpcUri): GrpcUri | null { if (target.scheme === undefined || !(target.scheme in registeredResolvers)) { if (defaultScheme !== null) { return { scheme: defaultScheme, + authority: undefined, path: uriToString(target) }; } else { - throw new Error(`Invalid target ${uriToString(target)}`); + return null; } } return target; diff --git a/packages/grpc-js/test/test-resolver.ts b/packages/grpc-js/test/test-resolver.ts index 0ff40ac1..d525d97d 100644 --- a/packages/grpc-js/test/test-resolver.ts +++ b/packages/grpc-js/test/test-resolver.ts @@ -32,7 +32,7 @@ describe('Name Resolver', () => { resolverManager.registerAll(); }); it('Should resolve localhost properly', done => { - const target = parseUri('localhost:50051')!; + const target = resolverManager.mapUriDefaultScheme(parseUri('localhost:50051')!)!; const listener: resolverManager.ResolverListener = { onSuccessfulResolution: ( addressList: SubchannelAddress[], @@ -67,7 +67,7 @@ describe('Name Resolver', () => { resolver.updateResolution(); }); it('Should default to port 443', done => { - const target = parseUri('localhost')!; + const target = resolverManager.mapUriDefaultScheme(parseUri('localhost')!)!; const listener: resolverManager.ResolverListener = { onSuccessfulResolution: ( addressList: SubchannelAddress[], @@ -102,7 +102,7 @@ describe('Name Resolver', () => { resolver.updateResolution(); }); it('Should correctly represent an ipv4 address', done => { - const target = parseUri('1.2.3.4')!; + const target = resolverManager.mapUriDefaultScheme(parseUri('1.2.3.4')!)!; const listener: resolverManager.ResolverListener = { onSuccessfulResolution: ( addressList: SubchannelAddress[], @@ -129,7 +129,7 @@ describe('Name Resolver', () => { resolver.updateResolution(); }); it('Should correctly represent an ipv6 address', done => { - const target = parseUri('::1')!; + const target = resolverManager.mapUriDefaultScheme(parseUri('::1')!)!; const listener: resolverManager.ResolverListener = { onSuccessfulResolution: ( addressList: SubchannelAddress[], @@ -156,7 +156,7 @@ describe('Name Resolver', () => { resolver.updateResolution(); }); it('Should correctly represent a bracketed ipv6 address', done => { - const target = parseUri('[::1]:50051')!; + const target = resolverManager.mapUriDefaultScheme(parseUri('[::1]:50051')!)!; const listener: resolverManager.ResolverListener = { onSuccessfulResolution: ( addressList: SubchannelAddress[], @@ -183,7 +183,7 @@ describe('Name Resolver', () => { resolver.updateResolution(); }); it('Should resolve a public address', done => { - const target = parseUri('example.com')!; + const target = resolverManager.mapUriDefaultScheme(parseUri('example.com')!)!; const listener: resolverManager.ResolverListener = { onSuccessfulResolution: ( addressList: SubchannelAddress[], @@ -203,7 +203,7 @@ describe('Name Resolver', () => { resolver.updateResolution(); }); it('Should resolve a name with multiple dots', done => { - const target = parseUri('loopback4.unittest.grpc.io')!; + const target = resolverManager.mapUriDefaultScheme(parseUri('loopback4.unittest.grpc.io')!)!; const listener: resolverManager.ResolverListener = { onSuccessfulResolution: ( addressList: SubchannelAddress[], @@ -232,7 +232,7 @@ describe('Name Resolver', () => { /* TODO(murgatroid99): re-enable this test, once we can get the IPv6 result * consistently */ it.skip('Should resolve a DNS name to an IPv6 address', done => { - const target = parseUri('loopback6.unittest.grpc.io')!; + const target = resolverManager.mapUriDefaultScheme(parseUri('loopback6.unittest.grpc.io')!)!; const listener: resolverManager.ResolverListener = { onSuccessfulResolution: ( addressList: SubchannelAddress[], @@ -259,7 +259,7 @@ describe('Name Resolver', () => { resolver.updateResolution(); }); it('Should resolve a DNS name to IPv4 and IPv6 addresses', done => { - const target = parseUri('loopback46.unittest.grpc.io')!; + const target = resolverManager.mapUriDefaultScheme(parseUri('loopback46.unittest.grpc.io')!)!; const listener: resolverManager.ResolverListener = { onSuccessfulResolution: ( addressList: SubchannelAddress[], @@ -290,7 +290,7 @@ describe('Name Resolver', () => { it('Should resolve a name with a hyphen', done => { /* TODO(murgatroid99): Find or create a better domain name to test this with. * This is just the first one I found with a hyphen. */ - const target = parseUri('network-tools.com')!; + const target = resolverManager.mapUriDefaultScheme(parseUri('network-tools.com')!)!; const listener: resolverManager.ResolverListener = { onSuccessfulResolution: ( addressList: SubchannelAddress[], @@ -311,8 +311,8 @@ describe('Name Resolver', () => { }); it('Should resolve gRPC interop servers', done => { let completeCount = 0; - const target1 = parseUri('grpc-test.sandbox.googleapis.com')!; - const target2 = parseUri('grpc-test4.sandbox.googleapis.com')!; + const target1 = resolverManager.mapUriDefaultScheme(parseUri('grpc-test.sandbox.googleapis.com')!)!; + const target2 = resolverManager.mapUriDefaultScheme(parseUri('grpc-test4.sandbox.googleapis.com')!)!; const listener: resolverManager.ResolverListener = { onSuccessfulResolution: ( addressList: SubchannelAddress[], @@ -339,7 +339,7 @@ describe('Name Resolver', () => { }); describe('UDS Names', () => { it('Should handle a relative Unix Domain Socket name', done => { - const target = parseUri('unix:socket')!; + const target = resolverManager.mapUriDefaultScheme(parseUri('unix:socket')!)!; const listener: resolverManager.ResolverListener = { onSuccessfulResolution: ( addressList: SubchannelAddress[], @@ -363,7 +363,7 @@ describe('Name Resolver', () => { resolver.updateResolution(); }); it('Should handle an absolute Unix Domain Socket name', done => { - const target = parseUri('unix:///tmp/socket')!; + const target = resolverManager.mapUriDefaultScheme(parseUri('unix:///tmp/socket')!)!; const listener: resolverManager.ResolverListener = { onSuccessfulResolution: ( addressList: SubchannelAddress[], @@ -400,7 +400,7 @@ describe('Name Resolver', () => { } it('Should return the correct authority if a different resolver has been registered', () => { - const target = parseUri('other:name')!; + const target = resolverManager.mapUriDefaultScheme(parseUri('other:name')!)!; console.log(target); resolverManager.registerResolver('other', OtherResolver); diff --git a/packages/grpc-js/test/test-uri-parser.ts b/packages/grpc-js/test/test-uri-parser.ts index 75aa82bf..d04cae53 100644 --- a/packages/grpc-js/test/test-uri-parser.ts +++ b/packages/grpc-js/test/test-uri-parser.ts @@ -17,6 +17,7 @@ import * as assert from 'assert'; import * as uriParser from '../src/uri-parser'; +import * as resolver from '../src/resolver'; describe('URI Parser', function(){ describe('parseUri', function() { @@ -37,6 +38,23 @@ describe('URI Parser', function(){ }); } }); + + describe('parseUri + mapUriDefaultScheme', function() { + const expectationList: {target: string, result: uriParser.GrpcUri | null}[] = [ + {target: 'localhost', result: {scheme: 'dns', authority: undefined, path: 'localhost'}}, + {target: 'localhost:80', result: {scheme: 'dns', authority: undefined, path: 'localhost:80'}}, + {target: 'dns:localhost', result: {scheme: 'dns', authority: undefined, path: 'localhost'}}, + {target: 'dns:///localhost', result: {scheme: 'dns', authority: '', path: 'localhost'}}, + {target: 'dns://authority/localhost', result: {scheme: 'dns', authority: 'authority', path: 'localhost'}}, + {target: 'unix:socket', result: {scheme: 'unix', authority: undefined, path: 'socket'}}, + {target: 'bad:path', result: {scheme: 'dns', authority: undefined, path: 'bad:path'}} + ]; + for (const {target, result} of expectationList) { + it(target, function() { + assert.deepStrictEqual(resolver.mapUriDefaultScheme(uriParser.parseUri(target) ?? {path: 'null'}), result); + }) + } + }); describe('splitHostPort', function() { const expectationList: {path: string, result: uriParser.HostPort | null}[] = [