From 4ee1db1d52c4196ab25ae1ebe8c78a00cd33bd15 Mon Sep 17 00:00:00 2001 From: John Cormie Date: Fri, 17 Apr 2026 14:48:06 -0700 Subject: [PATCH] api: Turn on RFC 3986 parsing by default and update javadoc. --- api/src/main/java/io/grpc/FeatureFlags.java | 2 +- api/src/main/java/io/grpc/Grpc.java | 25 ++++++++++------ .../java/io/grpc/ManagedChannelBuilder.java | 30 ++++++++++--------- 3 files changed, 33 insertions(+), 24 deletions(-) diff --git a/api/src/main/java/io/grpc/FeatureFlags.java b/api/src/main/java/io/grpc/FeatureFlags.java index 0e414ed7b31..36fec1b9a59 100644 --- a/api/src/main/java/io/grpc/FeatureFlags.java +++ b/api/src/main/java/io/grpc/FeatureFlags.java @@ -20,7 +20,7 @@ import com.google.common.base.Strings; class FeatureFlags { - private static boolean enableRfc3986Uris = getFlag("GRPC_ENABLE_RFC3986_URIS", false); + private static boolean enableRfc3986Uris = getFlag("GRPC_ENABLE_RFC3986_URIS", true); /** Whether to parse targets as RFC 3986 URIs (true), or use {@link java.net.URI} (false). */ @VisibleForTesting diff --git a/api/src/main/java/io/grpc/Grpc.java b/api/src/main/java/io/grpc/Grpc.java index a45c613fd18..37852cf9418 100644 --- a/api/src/main/java/io/grpc/Grpc.java +++ b/api/src/main/java/io/grpc/Grpc.java @@ -73,11 +73,10 @@ private Grpc() { public @interface TransportAttr {} /** - * Creates a channel builder with a target string and credentials. The target can be either a - * valid {@link NameResolver}-compliant URI, or an authority string. + * Creates a channel builder with a target string and credentials. The target can be either an RFC + * 3986 URI, or an authority string. * - *

A {@code NameResolver}-compliant URI is an absolute hierarchical URI as defined by {@link - * java.net.URI}. Example URIs: + *

Example URIs: *

* - *

An authority string will be converted to a {@code NameResolver}-compliant URI, which has - * the scheme from the name resolver with the highest priority (e.g. {@code "dns"}), - * no authority, and the original authority string as its path after properly escaped. - * We recommend libraries to specify the schema explicitly if it is known, since libraries cannot - * know which NameResolver will be default during runtime. + *

An authority string will be converted to a URI having the scheme of the name resolver with + * the highest priority (e.g. {@code "dns"}), the empty string as the authority, and 'target' as + * its path. We recommend libraries specify the scheme explicitly if it is known, since libraries + * cannot know which NameResolver will be default at runtime. * Example authority strings: *

+ * + *

We strongly recommend the URI form of `target` because the alternative is ambiguous. For + * example, the target string `foo:8080` is a valid authority string with host `foo` and port + * `8080` but it is also a valid RFC 3986 URI with scheme `foo` and path `8080`. {@code + * NameResolver}s are discovered dynamically from your classpath using SPI, so it's hard to be + * sure in advance how such a target will be resolved. A {@code NameResolver} for scheme `foo` + * might someday make a host named `foo` unreachable! On the other hand, the 'dns:///foo:8080' + * target will always behave the same. */ public static ManagedChannelBuilder newChannelBuilder( String target, ChannelCredentials creds) { diff --git a/api/src/main/java/io/grpc/ManagedChannelBuilder.java b/api/src/main/java/io/grpc/ManagedChannelBuilder.java index 3f370ab3003..a3c940735b2 100644 --- a/api/src/main/java/io/grpc/ManagedChannelBuilder.java +++ b/api/src/main/java/io/grpc/ManagedChannelBuilder.java @@ -45,11 +45,10 @@ public static ManagedChannelBuilder forAddress(String name, int port) { } /** - * Creates a channel with a target string, which can be either a valid {@link - * NameResolver}-compliant URI, or an authority string. + * Creates a channel with a target string, which can be either an RFC 3986 URI, or an authority + * string. * - *

A {@code NameResolver}-compliant URI is an absolute hierarchical URI as defined by {@link - * java.net.URI}. Example URIs: + *

Example URIs: *

* - *

An authority string will be converted to a {@code NameResolver}-compliant URI, which has - * the scheme from the name resolver with the highest priority (e.g. {@code "dns"}), - * no authority, and the original authority string as its path after properly escaped. - * We recommend libraries to specify the schema explicitly if it is known, since libraries cannot - * know which NameResolver will be default during runtime. + *

An authority string will be converted to a URI having the scheme of the name resolver with + * the highest priority (e.g. {@code "dns"}), the empty string as the authority, and 'target' as + * its path. We recommend libraries specify the scheme explicitly if it is known, since libraries + * cannot know which NameResolver will be default at runtime. * Example authority strings: *

* - *

Note that there is an open JDK bug on {@link java.net.URI} class parsing an ipv6 scope ID: - * bugs.openjdk.org/browse/JDK-8199396. This method is exposed to this bug. If you experience an - * issue, a work-around is to convert the scope ID to its numeric form (e.g. by using - * Inet6Address.getScopeId()) before calling this method. - * + *

We strongly recommend the URI form of `target` because the alternative is ambiguous. For + * example, the target string `foo:8080` is a valid authority string with host `foo` and port + * `8080` but it is also a valid RFC 3986 URI with scheme `foo` and path `8080`. {@code + * NameResolver}s are discovered dynamically from your classpath using SPI, so it's hard to be + * sure in advance how such a target will be resolved. A {@code NameResolver} for scheme `foo` + * might someday make a host named `foo` unreachable! On the other hand, the 'dns:///foo:8080' + * target will always behave the same. + * * @since 1.0.0 */ public static ManagedChannelBuilder forTarget(String target) {