Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 11 additions & 2 deletions xds/src/main/java/io/grpc/xds/RoutingUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -92,15 +92,24 @@ static VirtualHost findVirtualHostForHostName(List<VirtualHost> virtualHosts, St
* </ol>
*/
private static boolean matchHostName(String hostName, String pattern) {
checkArgument(hostName.length() != 0 && !hostName.startsWith(".") && !hostName.endsWith("."),
checkArgument(hostName.length() != 0 && !hostName.startsWith("."),
"Invalid host name");
checkArgument(pattern.length() != 0 && !pattern.startsWith(".") && !pattern.endsWith("."),
checkArgument(pattern.length() != 0 && !pattern.startsWith("."),
"Invalid pattern/domain name");

hostName = hostName.toLowerCase(Locale.US);
pattern = pattern.toLowerCase(Locale.US);
// hostName and pattern are now in lower case -- domain names are case-insensitive.

// Strip trailing dot to normalize FQDN (e.g. "example.com.") to a relative form,
// as per RFC 1034 Section 3.1 the two are semantically equivalent.
if (hostName.endsWith(".")) {
hostName = hostName.substring(0, hostName.length() - 1);
}
if (pattern.endsWith(".")) {
pattern = pattern.substring(0, pattern.length() - 1);
}

if (!pattern.contains("*")) {
// Not a wildcard pattern -- hostName and pattern must match exactly.
return hostName.equals(pattern);
Expand Down
13 changes: 11 additions & 2 deletions xds/src/main/java/io/grpc/xds/XdsNameResolver.java
Original file line number Diff line number Diff line change
Expand Up @@ -354,15 +354,24 @@ private void updateResolutionResult(XdsConfig xdsConfig) {
*/
@VisibleForTesting
static boolean matchHostName(String hostName, String pattern) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This method is actually unused now for some time. Can you remove it and its calling tests? Instead make unit tests for RoutingUtils which is the actively used code.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have applied the requested changes.

All CI checks have passed, with the exception of grpc-java-testing-pr (grpc-testing), which indicates that it needs a /gcbrun command from a collaborator.

Please let me know if there are any other points I should address.

checkArgument(hostName.length() != 0 && !hostName.startsWith(".") && !hostName.endsWith("."),
checkArgument(hostName.length() != 0 && !hostName.startsWith("."),
"Invalid host name");
checkArgument(pattern.length() != 0 && !pattern.startsWith(".") && !pattern.endsWith("."),
checkArgument(pattern.length() != 0 && !pattern.startsWith("."),
"Invalid pattern/domain name");

hostName = hostName.toLowerCase(Locale.US);
pattern = pattern.toLowerCase(Locale.US);
// hostName and pattern are now in lower case -- domain names are case-insensitive.

// Strip trailing dot to normalize FQDN (e.g. "example.com.") to a relative form,
// as per RFC 1034 Section 3.1 the two are semantically equivalent.
if (hostName.endsWith(".")) {
hostName = hostName.substring(0, hostName.length() - 1);
}
if (pattern.endsWith(".")) {
pattern = pattern.substring(0, pattern.length() - 1);
}

if (!pattern.contains("*")) {
// Not a wildcard pattern -- hostName and pattern must match exactly.
return hostName.equals(pattern);
Expand Down
48 changes: 48 additions & 0 deletions xds/src/test/java/io/grpc/xds/RoutingUtilsTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,54 @@ public void findVirtualHostForHostName_asteriskMatchAnyDomain() {
.isEqualTo(vHost1);
}

@Test
public void findVirtualHostForHostName_trailingDot() {
// FQDN (trailing dot) is semantically equivalent to the relative form
// per RFC 1034 Section 3.1.
List<Route> routes = Collections.emptyList();
VirtualHost vHost1 = VirtualHost.create("virtualhost01.googleapis.com",
Collections.singletonList("a.googleapis.com"), routes,
ImmutableMap.of());
VirtualHost vHost2 = VirtualHost.create("virtualhost02.googleapis.com",
Collections.singletonList("*.googleapis.com"), routes,
ImmutableMap.of());
VirtualHost vHost3 = VirtualHost.create("virtualhost03.googleapis.com",
Collections.singletonList("*"), routes,
ImmutableMap.of());
List<VirtualHost> virtualHosts = Arrays.asList(vHost1, vHost2, vHost3);

// Trailing dot in hostName, exact match.
assertThat(RoutingUtils.findVirtualHostForHostName(
virtualHosts, "a.googleapis.com.")).isEqualTo(vHost1);
// Trailing dot in hostName, wildcard match.
assertThat(RoutingUtils.findVirtualHostForHostName(
virtualHosts, "b.googleapis.com.")).isEqualTo(vHost2);

// Trailing dot in domain pattern, exact match.
VirtualHost vHost4 = VirtualHost.create("virtualhost04.googleapis.com",
Collections.singletonList("a.googleapis.com."), routes,
ImmutableMap.of());
List<VirtualHost> virtualHosts2 =
Arrays.asList(vHost4, vHost2, vHost3);
assertThat(RoutingUtils.findVirtualHostForHostName(
virtualHosts2, "a.googleapis.com")).isEqualTo(vHost4);

// Trailing dot in both hostName and domain pattern.
assertThat(RoutingUtils.findVirtualHostForHostName(
virtualHosts2, "a.googleapis.com.")).isEqualTo(vHost4);

// Trailing dot in domain pattern, wildcard match.
VirtualHost vHost5 = VirtualHost.create("virtualhost05.googleapis.com",
Collections.singletonList("*.googleapis.com."), routes,
ImmutableMap.of());
List<VirtualHost> virtualHosts3 =
Arrays.asList(vHost5, vHost3);
assertThat(RoutingUtils.findVirtualHostForHostName(
virtualHosts3, "b.googleapis.com")).isEqualTo(vHost5);
assertThat(RoutingUtils.findVirtualHostForHostName(
virtualHosts3, "b.googleapis.com.")).isEqualTo(vHost5);
}

@Test
public void routeMatching_pathOnly() {
Metadata headers = new Metadata();
Expand Down
23 changes: 23 additions & 0 deletions xds/src/test/java/io/grpc/xds/XdsNameResolverTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -2062,6 +2062,29 @@ public void matchHostName_postfixWildCard() {
assertThat(XdsNameResolver.matchHostName("foo-bar", pattern)).isTrue();
}

@Test
public void matchHostName_trailingDot() {
// FQDN (trailing dot) is semantically equivalent to the relative form per RFC 1034 Section 3.1.
assertThat(XdsNameResolver.matchHostName("foo.googleapis.com.", "foo.googleapis.com")).isTrue();
assertThat(XdsNameResolver.matchHostName("foo.googleapis.com", "foo.googleapis.com.")).isTrue();
assertThat(XdsNameResolver.matchHostName("foo.googleapis.com.", "foo.googleapis.com."))
.isTrue();
assertThat(XdsNameResolver.matchHostName("bar.googleapis.com.", "foo.googleapis.com"))
.isFalse();

// Wildcard + trailing dot combinations.
String pattern = "*.foo.googleapis.com";
assertThat(XdsNameResolver.matchHostName("bar.foo.googleapis.com.", pattern)).isTrue();
assertThat(XdsNameResolver.matchHostName("bar.foo.googleapis.com", pattern + ".")).isTrue();
assertThat(XdsNameResolver.matchHostName("bar.foo.googleapis.com.", pattern + ".")).isTrue();
assertThat(XdsNameResolver.matchHostName("foo.googleapis.com.", pattern)).isFalse();

pattern = "foo.*";
assertThat(XdsNameResolver.matchHostName("foo.googleapis.com.", pattern)).isTrue();
assertThat(XdsNameResolver.matchHostName("foo.com.", pattern)).isTrue();
assertThat(XdsNameResolver.matchHostName("bar.googleapis.com.", pattern)).isFalse();
}

@Test
public void resolved_faultAbortInLdsUpdate() {
resolver.start(mockListener);
Expand Down