diff --git a/api/src/main/java/io/grpc/Grpc.java b/api/src/main/java/io/grpc/Grpc.java index baa9f5f0ab6..cd25f79041b 100644 --- a/api/src/main/java/io/grpc/Grpc.java +++ b/api/src/main/java/io/grpc/Grpc.java @@ -101,6 +101,35 @@ public static ManagedChannelBuilder newChannelBuilder( return ManagedChannelRegistry.getDefaultRegistry().newChannelBuilder(target, creds); } + /** + * Creates a channel builder with a target string, credentials, and a specific + * name resolver registry. + * + *

This method uses the {@link ManagedChannelRegistry#getDefaultRegistry()} to + * find an appropriate underlying transport provider based on the target and credentials. + * The provided {@code nameResolverRegistry} is used to resolve the target address + * into physical addresses (e.g., DNS or custom schemes). + * + * @param target the target URI for the channel, such as {@code "localhost:8080"} + * or {@code "dns:///example.com"} + * @param creds the channel credentials to use for secure communication + * @param nameResolverRegistry the registry used to look up {@link NameResolver} + * providers for the target + * @return a {@link ManagedChannelBuilder} instance configured with the given parameters + * @throws IllegalArgumentException if no provider is available for the given target + * or credentials + * @since 1.79.0 + */ + public static ManagedChannelBuilder newChannelBuilder( + String target, + ChannelCredentials creds, + NameResolverRegistry nameResolverRegistry) { + return ManagedChannelRegistry.getDefaultRegistry().newChannelBuilder( + nameResolverRegistry, + target, + creds); + } + /** * Creates a channel builder from a host, port, and credentials. The host and port are combined to * form an authority string and then passed to {@link #newChannelBuilder(String, diff --git a/api/src/main/java/io/grpc/ManagedChannelProvider.java b/api/src/main/java/io/grpc/ManagedChannelProvider.java index 42941dfc809..18a4329a146 100644 --- a/api/src/main/java/io/grpc/ManagedChannelProvider.java +++ b/api/src/main/java/io/grpc/ManagedChannelProvider.java @@ -81,6 +81,31 @@ protected NewChannelBuilderResult newChannelBuilder(String target, ChannelCreden return NewChannelBuilderResult.error("ChannelCredentials are unsupported"); } + /** + * Creates a channel builder using the provided target, credentials, and resolution + * components. + * + *

This method allows for fine-grained control over name resolution by providing + * both a {@link NameResolverRegistry} and a specific {@link NameResolverProvider}. + * Unlike the public factory methods, this returns a {@link NewChannelBuilderResult}, + * which may contain an error string if the provided credentials or target are + * not supported by this provider. + * + * @param target the target URI for the channel + * @param creds the channel credentials to use + * @param nameResolverRegistry the registry used for looking up name resolvers + * @param nameResolverProvider a specific provider to use, or {@code null} to + * search the registry + * @return a {@link NewChannelBuilderResult} containing either the builder or an + * error description + * @since 1.79.0 + */ + protected NewChannelBuilderResult newChannelBuilder(String target, ChannelCredentials creds, + NameResolverRegistry nameResolverRegistry, + NameResolverProvider nameResolverProvider) { + return newChannelBuilder(target, creds); + } + /** * Returns the {@link SocketAddress} types this ManagedChannelProvider supports. */ diff --git a/api/src/main/java/io/grpc/ManagedChannelRegistry.java b/api/src/main/java/io/grpc/ManagedChannelRegistry.java index aed5eca9abf..7af4c55c2de 100644 --- a/api/src/main/java/io/grpc/ManagedChannelRegistry.java +++ b/api/src/main/java/io/grpc/ManagedChannelRegistry.java @@ -155,7 +155,6 @@ ManagedChannelBuilder newChannelBuilder(String target, ChannelCredentials cre return newChannelBuilder(NameResolverRegistry.getDefaultRegistry(), target, creds); } - @VisibleForTesting ManagedChannelBuilder newChannelBuilder(NameResolverRegistry nameResolverRegistry, String target, ChannelCredentials creds) { NameResolverProvider nameResolverProvider = null; @@ -192,7 +191,7 @@ ManagedChannelBuilder newChannelBuilder(NameResolverRegistry nameResolverRegi continue; } ManagedChannelProvider.NewChannelBuilderResult result - = provider.newChannelBuilder(target, creds); + = provider.newChannelBuilder(target, creds, nameResolverRegistry, nameResolverProvider); if (result.getChannelBuilder() != null) { return result.getChannelBuilder(); } diff --git a/core/src/main/java/io/grpc/internal/ManagedChannelImplBuilder.java b/core/src/main/java/io/grpc/internal/ManagedChannelImplBuilder.java index 628224b826e..3af1aac4cc1 100644 --- a/core/src/main/java/io/grpc/internal/ManagedChannelImplBuilder.java +++ b/core/src/main/java/io/grpc/internal/ManagedChannelImplBuilder.java @@ -164,6 +164,8 @@ static boolean setRfc3986UrisEnabled(boolean value) { private final List interceptors = new ArrayList<>(); NameResolverRegistry nameResolverRegistry = NameResolverRegistry.getDefaultRegistry(); + @Nullable + NameResolverProvider nameResolverProvider; final List transportFilters = new ArrayList<>(); @@ -445,11 +447,16 @@ public ManagedChannelImplBuilder nameResolverFactory(NameResolver.Factory resolv return this; } - ManagedChannelImplBuilder nameResolverRegistry(NameResolverRegistry resolverRegistry) { + public ManagedChannelImplBuilder nameResolverRegistry(NameResolverRegistry resolverRegistry) { this.nameResolverRegistry = resolverRegistry; return this; } + public ManagedChannelImplBuilder nameResolverProvider(NameResolverProvider provider) { + this.nameResolverProvider = provider; + return this; + } + @Override public ManagedChannelImplBuilder defaultLoadBalancingPolicy(String policy) { Preconditions.checkState(directServerAddress == null, @@ -733,7 +740,7 @@ public ManagedChannel build() { ResolvedNameResolver resolvedResolver = enableRfc3986Uris ? getNameResolverProviderRfc3986(target, nameResolverRegistry) - : getNameResolverProvider(target, nameResolverRegistry); + : getNameResolverProvider(target, nameResolverRegistry, nameResolverProvider); resolvedResolver.checkAddressTypes(clientTransportFactory.getSupportedSocketAddressTypes()); return new ManagedChannelOrphanWrapper(new ManagedChannelImpl( this, @@ -854,7 +861,8 @@ void checkAddressTypes( @VisibleForTesting static ResolvedNameResolver getNameResolverProvider( - String target, NameResolverRegistry nameResolverRegistry) { + String target, NameResolverRegistry nameResolverRegistry, + NameResolverProvider nameResolverProvider) { // Finding a NameResolver. Try using the target string as the URI. If that fails, try prepending // "dns:///". NameResolverProvider provider = null; @@ -869,19 +877,28 @@ static ResolvedNameResolver getNameResolverProvider( if (targetUri != null) { // For "localhost:8080" this would likely cause provider to be null, because "localhost" is // parsed as the scheme. Will hit the next case and try "dns:///localhost:8080". - provider = nameResolverRegistry.getProviderForScheme(targetUri.getScheme()); + provider = nameResolverProvider; + if (provider == null) { + provider = nameResolverRegistry.getProviderForScheme(targetUri.getScheme()); + } } - if (provider == null && !URI_PATTERN.matcher(target).matches()) { - // It doesn't look like a URI target. Maybe it's an authority string. Try with the default - // scheme from the registry. + if (!URI_PATTERN.matcher(target).matches()) { + // It doesn't look like a URI target. Maybe it's an authority string. Try with + // the default scheme from the registry (if provider is not specified) or + // the provider's default scheme (if provider is specified). + String scheme = (provider != null) + ? provider.getDefaultScheme() + : nameResolverRegistry.getDefaultScheme(); try { - targetUri = new URI(nameResolverRegistry.getDefaultScheme(), "", "/" + target, null); + targetUri = new URI(scheme, "", "/" + target, null); } catch (URISyntaxException e) { - // Should not be possible. + // Should not happen because we just validated the URI. throw new IllegalArgumentException(e); } - provider = nameResolverRegistry.getProviderForScheme(targetUri.getScheme()); + if (provider == null) { + provider = nameResolverRegistry.getProviderForScheme(targetUri.getScheme()); + } } if (provider == null) { diff --git a/core/src/test/java/io/grpc/internal/ManagedChannelImplGetNameResolverTest.java b/core/src/test/java/io/grpc/internal/ManagedChannelImplGetNameResolverTest.java index 792f4daca4e..4bfc66beb12 100644 --- a/core/src/test/java/io/grpc/internal/ManagedChannelImplGetNameResolverTest.java +++ b/core/src/test/java/io/grpc/internal/ManagedChannelImplGetNameResolverTest.java @@ -118,7 +118,8 @@ public void validTargetNoProvider() { NameResolverRegistry nameResolverRegistry = new NameResolverRegistry(); try { ManagedChannelImplBuilder.getNameResolverProvider( - "foo.googleapis.com:8080", nameResolverRegistry); + "foo.googleapis.com:8080", nameResolverRegistry, + null); fail("Should fail"); } catch (IllegalArgumentException e) { // expected @@ -130,7 +131,7 @@ public void validTargetProviderAddrTypesNotSupported() { NameResolverRegistry nameResolverRegistry = getTestRegistry("testscheme"); try { ManagedChannelImplBuilder.getNameResolverProvider( - "testscheme:///foo.googleapis.com:8080", nameResolverRegistry) + "testscheme:///foo.googleapis.com:8080", nameResolverRegistry, null) .checkAddressTypes(Collections.singleton(CustomSocketAddress.class)); fail("Should fail"); } catch (IllegalArgumentException e) { @@ -143,7 +144,7 @@ public void validTargetProviderAddrTypesNotSupported() { private void testValidTarget(String target, String expectedUriString, URI expectedUri) { NameResolverRegistry nameResolverRegistry = getTestRegistry(expectedUri.getScheme()); ManagedChannelImplBuilder.ResolvedNameResolver resolved = - ManagedChannelImplBuilder.getNameResolverProvider(target, nameResolverRegistry); + ManagedChannelImplBuilder.getNameResolverProvider(target, nameResolverRegistry, null); assertThat(resolved.provider).isInstanceOf(FakeNameResolverProvider.class); assertThat(resolved.targetUri).isEqualTo(wrap(expectedUri)); assertThat(resolved.targetUri.toString()).isEqualTo(expectedUriString); @@ -154,7 +155,7 @@ private void testInvalidTarget(String target) { try { ManagedChannelImplBuilder.ResolvedNameResolver resolved = - ManagedChannelImplBuilder.getNameResolverProvider(target, nameResolverRegistry); + ManagedChannelImplBuilder.getNameResolverProvider(target, nameResolverRegistry, null); FakeNameResolverProvider nameResolverProvider = (FakeNameResolverProvider) resolved.provider; fail("Should have failed, but got resolver provider " + nameResolverProvider); } catch (IllegalArgumentException e) { diff --git a/netty/src/main/java/io/grpc/netty/NettyChannelBuilder.java b/netty/src/main/java/io/grpc/netty/NettyChannelBuilder.java index 258aa15b005..7b3065e1f95 100644 --- a/netty/src/main/java/io/grpc/netty/NettyChannelBuilder.java +++ b/netty/src/main/java/io/grpc/netty/NettyChannelBuilder.java @@ -38,6 +38,8 @@ import io.grpc.HttpConnectProxiedSocketAddress; import io.grpc.Internal; import io.grpc.ManagedChannelBuilder; +import io.grpc.NameResolverProvider; +import io.grpc.NameResolverRegistry; import io.grpc.internal.AtomicBackoff; import io.grpc.internal.ClientTransportFactory; import io.grpc.internal.ConnectionClientTransport; @@ -708,6 +710,24 @@ NettyChannelBuilder setTransportTracerFactory(TransportTracer.Factory transportT return this; } + /** + * Sets the registry used for looking up name resolvers. + */ + @CanIgnoreReturnValue + public NettyChannelBuilder nameResolverRegistry(NameResolverRegistry registry) { + managedChannelImplBuilder.nameResolverRegistry(registry); + return this; + } + + /** + * Sets the {@link io.grpc.NameResolverProvider} to use. + */ + @CanIgnoreReturnValue + public NettyChannelBuilder nameResolverProvider(NameResolverProvider provider) { + managedChannelImplBuilder.nameResolverProvider(provider); + return this; + } + static Collection> getSupportedSocketAddressTypes() { return Collections.singleton(InetSocketAddress.class); } diff --git a/netty/src/main/java/io/grpc/netty/NettyChannelProvider.java b/netty/src/main/java/io/grpc/netty/NettyChannelProvider.java index 1b22a95a44b..f9ff2409cbb 100644 --- a/netty/src/main/java/io/grpc/netty/NettyChannelProvider.java +++ b/netty/src/main/java/io/grpc/netty/NettyChannelProvider.java @@ -19,6 +19,8 @@ import io.grpc.ChannelCredentials; import io.grpc.Internal; import io.grpc.ManagedChannelProvider; +import io.grpc.NameResolverProvider; +import io.grpc.NameResolverRegistry; import java.net.SocketAddress; import java.util.Collection; @@ -55,6 +57,25 @@ public NewChannelBuilderResult newChannelBuilder(String target, ChannelCredentia new NettyChannelBuilder(target, creds, result.callCredentials, result.negotiator)); } + @Override + public NewChannelBuilderResult newChannelBuilder(String target, ChannelCredentials creds, + NameResolverRegistry nameResolverRegistry, + NameResolverProvider nameResolverProvider) { + ProtocolNegotiators.FromChannelCredentialsResult result = ProtocolNegotiators.from(creds); + if (result.error != null) { + return NewChannelBuilderResult.error(result.error); + } + NettyChannelBuilder builder = new NettyChannelBuilder(target, creds, + result.callCredentials, result.negotiator); + if (nameResolverRegistry != null) { + builder.nameResolverRegistry(nameResolverRegistry); + } + if (nameResolverProvider != null) { + builder.nameResolverProvider(nameResolverProvider); + } + return NewChannelBuilderResult.channelBuilder(builder); + } + @Override protected Collection> getSupportedSocketAddressTypes() { return NettyChannelBuilder.getSupportedSocketAddressTypes(); diff --git a/netty/src/main/java/io/grpc/netty/UdsNettyChannelProvider.java b/netty/src/main/java/io/grpc/netty/UdsNettyChannelProvider.java index 4e9895da0a8..23a09889de0 100644 --- a/netty/src/main/java/io/grpc/netty/UdsNettyChannelProvider.java +++ b/netty/src/main/java/io/grpc/netty/UdsNettyChannelProvider.java @@ -20,6 +20,8 @@ import io.grpc.ChannelCredentials; import io.grpc.Internal; import io.grpc.ManagedChannelProvider; +import io.grpc.NameResolverProvider; +import io.grpc.NameResolverRegistry; import io.grpc.internal.SharedResourcePool; import io.netty.channel.unix.DomainSocketAddress; import java.net.SocketAddress; @@ -62,6 +64,21 @@ public NewChannelBuilderResult newChannelBuilder(String target, ChannelCredentia return result; } + @Override + public NewChannelBuilderResult newChannelBuilder(String target, ChannelCredentials creds, + NameResolverRegistry nameResolverRegistry, + NameResolverProvider nameResolverProvider) { + Preconditions.checkState(isAvailable()); + NewChannelBuilderResult result = new NettyChannelProvider().newChannelBuilder( + target, creds, nameResolverRegistry, nameResolverProvider); + if (result.getChannelBuilder() != null) { + ((NettyChannelBuilder) result.getChannelBuilder()) + .eventLoopGroupPool(SharedResourcePool.forResource(Utils.DEFAULT_WORKER_EVENT_LOOP_GROUP)) + .channelType(Utils.EPOLL_DOMAIN_CLIENT_CHANNEL_TYPE, DomainSocketAddress.class); + } + return result; + } + @Override protected Collection> getSupportedSocketAddressTypes() { return Collections.singleton(DomainSocketAddress.class); diff --git a/netty/src/test/java/io/grpc/netty/NettyChannelProviderTest.java b/netty/src/test/java/io/grpc/netty/NettyChannelProviderTest.java index 86c1389f002..fe5a45848e1 100644 --- a/netty/src/test/java/io/grpc/netty/NettyChannelProviderTest.java +++ b/netty/src/test/java/io/grpc/netty/NettyChannelProviderTest.java @@ -87,4 +87,164 @@ public void newChannelBuilder_fail() { TlsChannelCredentials.newBuilder().requireFakeFeature().build()); assertThat(result.getError()).contains("FAKE"); } + + @Test + public void newChannelBuilder_withRegistry() { + io.grpc.NameResolverRegistry registry = new io.grpc.NameResolverRegistry(); + NewChannelBuilderResult result = provider.newChannelBuilder( + "localhost:443", TlsChannelCredentials.create(), registry, null); + assertThat(result.getChannelBuilder()).isInstanceOf(NettyChannelBuilder.class); + } + + @Test + public void newChannelBuilder_withProvider() { + io.grpc.NameResolverProvider resolverProvider = new io.grpc.NameResolverProvider() { + @Override + protected boolean isAvailable() { + return true; + } + + @Override + protected int priority() { + return 5; + } + + @Override + public String getDefaultScheme() { + return "dns"; + } + + @Override + public io.grpc.NameResolver newNameResolver(java.net.URI targetUri, + io.grpc.NameResolver.Args args) { + return null; + } + }; + NewChannelBuilderResult result = provider.newChannelBuilder( + "localhost:443", TlsChannelCredentials.create(), null, + resolverProvider); + assertThat(result.getChannelBuilder()).isInstanceOf(NettyChannelBuilder.class); + } + + @Test + public void newChannelBuilder_registryPropagation_e2e() { + String scheme = "testscheme"; + final io.grpc.NameResolverRegistry registry = new io.grpc.NameResolverRegistry(); + final java.util.concurrent.atomic.AtomicReference + capturedRegistry = new java.util.concurrent.atomic.AtomicReference<>(); + + final io.grpc.NameResolverProvider resolverProvider = new io.grpc.NameResolverProvider() { + @Override + protected boolean isAvailable() { + return true; + } + + @Override + protected int priority() { + return 5; + } + + @Override + public String getDefaultScheme() { + return scheme; + } + + @Override + public io.grpc.NameResolver newNameResolver(java.net.URI targetUri, + io.grpc.NameResolver.Args args) { + capturedRegistry.set(args.getNameResolverRegistry()); + return new io.grpc.NameResolver() { + @Override + public String getServiceAuthority() { + return "authority"; + } + + @Override + public void start(Listener2 listener) { + } + + @Override + public void shutdown() { + } + }; + } + }; + registry.register(resolverProvider); + + NewChannelBuilderResult result = provider.newChannelBuilder( + scheme + ":///target", TlsChannelCredentials.create(), registry, + null); + assertThat(result.getChannelBuilder()).isInstanceOf(NettyChannelBuilder.class); + // Verify build() succeeds + result.getChannelBuilder().build(); + + // Verify the registry passed to args is the exact same instance + assertSame("Registry should be propagated to NameResolver.Args", registry, + capturedRegistry.get()); + + // Verify default registry (empty) fails + NewChannelBuilderResult defaultResult = provider.newChannelBuilder( + scheme + ":///target", TlsChannelCredentials.create(), + new io.grpc.NameResolverRegistry(), null); + // The provider might still return a builder, but build() should fail if it + // can't find the resolver. + // However, NettyChannelProvider just delegates to NettyChannelBuilder. + // NettyChannelBuilder delegates to ManagedChannelImplBuilder. + // ManagedChannelImplBuilder.build() calls getNameResolverProvider(), which + // throws if not found. + try { + defaultResult.getChannelBuilder().build(); + fail("Should have failed to build() without correct registry"); + } catch (IllegalArgumentException e) { + // Expected + } + } + + @Test + public void newChannelBuilder_providerPropagation_e2e() { + String scheme = "otherscheme"; + final io.grpc.NameResolverProvider resolverProvider = new io.grpc.NameResolverProvider() { + @Override + protected boolean isAvailable() { + return true; + } + + @Override + protected int priority() { + return 5; + } + + @Override + public String getDefaultScheme() { + return scheme; + } + + @Override + public io.grpc.NameResolver newNameResolver(java.net.URI targetUri, + io.grpc.NameResolver.Args args) { + return new io.grpc.NameResolver() { + @Override + public String getServiceAuthority() { + return "authority"; + } + + @Override + public void start(Listener2 listener) { + } + + @Override + public void shutdown() { + } + }; + } + }; + + // Pass explicit provider, null registry + NewChannelBuilderResult result = provider.newChannelBuilder( + scheme + ":///target", TlsChannelCredentials.create(), + null, resolverProvider); + assertThat(result.getChannelBuilder()).isInstanceOf(NettyChannelBuilder.class); + // Should succeed because we passed the specific provider + result.getChannelBuilder().build(); + } } diff --git a/netty/src/test/java/io/grpc/netty/UdsNettyChannelProviderTest.java b/netty/src/test/java/io/grpc/netty/UdsNettyChannelProviderTest.java index e0c3d5a8525..ad26caf1713 100644 --- a/netty/src/test/java/io/grpc/netty/UdsNettyChannelProviderTest.java +++ b/netty/src/test/java/io/grpc/netty/UdsNettyChannelProviderTest.java @@ -108,6 +108,16 @@ public void newChannelBuilder_success() { assertThat(result.getChannelBuilder()).isInstanceOf(NettyChannelBuilder.class); } + @Test + public void newChannelBuilder_withRegistry_success() { + Assume.assumeTrue(Utils.isEpollAvailable()); + NewChannelBuilderResult result = provider.newChannelBuilder("unix:sock.sock", + TlsChannelCredentials.create(), + io.grpc.NameResolverRegistry.getDefaultRegistry(), + new io.grpc.internal.DnsNameResolverProvider()); + assertThat(result.getChannelBuilder()).isInstanceOf(NettyChannelBuilder.class); + } + @Test public void managedChannelRegistry_newChannelBuilder() { Assume.assumeTrue(Utils.isEpollAvailable()); diff --git a/okhttp/src/main/java/io/grpc/okhttp/OkHttpChannelBuilder.java b/okhttp/src/main/java/io/grpc/okhttp/OkHttpChannelBuilder.java index 98f764132fe..abcecd312c6 100644 --- a/okhttp/src/main/java/io/grpc/okhttp/OkHttpChannelBuilder.java +++ b/okhttp/src/main/java/io/grpc/okhttp/OkHttpChannelBuilder.java @@ -35,6 +35,8 @@ import io.grpc.InsecureChannelCredentials; import io.grpc.Internal; import io.grpc.ManagedChannelBuilder; +import io.grpc.NameResolverProvider; +import io.grpc.NameResolverRegistry; import io.grpc.TlsChannelCredentials; import io.grpc.internal.AtomicBackoff; import io.grpc.internal.ClientTransportFactory; @@ -588,6 +590,22 @@ SSLSocketFactory createSslSocketFactory() { } } + /** + * Sets the registry used for looking up name resolvers. + */ + public OkHttpChannelBuilder nameResolverRegistry(NameResolverRegistry registry) { + managedChannelImplBuilder.nameResolverRegistry(registry); + return this; + } + + /** + * Sets the {@link NameResolverProvider} to use. + */ + public OkHttpChannelBuilder nameResolverProvider(NameResolverProvider provider) { + managedChannelImplBuilder.nameResolverProvider(provider); + return this; + } + private static final EnumSet understoodTlsFeatures = EnumSet.of( TlsChannelCredentials.Feature.MTLS, TlsChannelCredentials.Feature.CUSTOM_MANAGERS); diff --git a/okhttp/src/main/java/io/grpc/okhttp/OkHttpChannelProvider.java b/okhttp/src/main/java/io/grpc/okhttp/OkHttpChannelProvider.java index bf2a9be6fee..3fa1f84d02e 100644 --- a/okhttp/src/main/java/io/grpc/okhttp/OkHttpChannelProvider.java +++ b/okhttp/src/main/java/io/grpc/okhttp/OkHttpChannelProvider.java @@ -20,6 +20,8 @@ import io.grpc.Internal; import io.grpc.InternalServiceProviders; import io.grpc.ManagedChannelProvider; +import io.grpc.NameResolverProvider; +import io.grpc.NameResolverRegistry; import java.net.SocketAddress; import java.util.Collection; @@ -60,6 +62,26 @@ public NewChannelBuilderResult newChannelBuilder(String target, ChannelCredentia target, creds, result.callCredentials, result.factory)); } + @Override + public NewChannelBuilderResult newChannelBuilder(String target, ChannelCredentials creds, + NameResolverRegistry nameResolverRegistry, + NameResolverProvider nameResolverProvider) { + OkHttpChannelBuilder.SslSocketFactoryResult result = + OkHttpChannelBuilder.sslSocketFactoryFrom(creds); + if (result.error != null) { + return NewChannelBuilderResult.error(result.error); + } + OkHttpChannelBuilder builder = new OkHttpChannelBuilder( + target, creds, result.callCredentials, result.factory); + if (nameResolverRegistry != null) { + builder.nameResolverRegistry(nameResolverRegistry); + } + if (nameResolverProvider != null) { + builder.nameResolverProvider(nameResolverProvider); + } + return NewChannelBuilderResult.channelBuilder(builder); + } + @Override protected Collection> getSupportedSocketAddressTypes() { return OkHttpChannelBuilder.getSupportedSocketAddressTypes(); diff --git a/okhttp/src/test/java/io/grpc/okhttp/OkHttpChannelProviderTest.java b/okhttp/src/test/java/io/grpc/okhttp/OkHttpChannelProviderTest.java index 363f11e71eb..40cf0a41449 100644 --- a/okhttp/src/test/java/io/grpc/okhttp/OkHttpChannelProviderTest.java +++ b/okhttp/src/test/java/io/grpc/okhttp/OkHttpChannelProviderTest.java @@ -85,4 +85,13 @@ public void newChannelBuilder_fail() { TlsChannelCredentials.newBuilder().requireFakeFeature().build()); assertThat(result.getError()).contains("FAKE"); } + + @Test + public void newChannelBuilder_withRegistry_success() { + NewChannelBuilderResult result = provider.newChannelBuilder("localhost:443", + TlsChannelCredentials.create(), + io.grpc.NameResolverRegistry.getDefaultRegistry(), + new io.grpc.internal.DnsNameResolverProvider()); + assertThat(result.getChannelBuilder()).isInstanceOf(OkHttpChannelBuilder.class); + } }