diff options
author | Chengyuan Zhang <chengyuanzhang@google.com> | 2020-07-17 22:29:46 +0000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-07-17 15:29:46 -0700 |
commit | 72de6eaaa1ce9fffa1e1fdae5319b59e65a8804d (patch) | |
tree | 99208b1edf2e654de7604f488121e5fa65c1f11c | |
parent | 7047209ba35d35fc04f7425a21882ed15e228097 (diff) | |
download | grpc-grpc-java-72de6eaaa1ce9fffa1e1fdae5319b59e65a8804d.tar.gz |
xds: perform header matching on concatenated values (v1.31.x backport) (#7215) (#7225)
Combine values of header fields with the same key to a comma-separated string before performing header matching.
-rw-r--r-- | xds/src/main/java/io/grpc/xds/RouteMatch.java | 42 | ||||
-rw-r--r-- | xds/src/main/java/io/grpc/xds/XdsRoutingLoadBalancer.java | 9 | ||||
-rw-r--r-- | xds/src/test/java/io/grpc/xds/RouteMatchTest.java | 23 |
3 files changed, 36 insertions, 38 deletions
diff --git a/xds/src/main/java/io/grpc/xds/RouteMatch.java b/xds/src/main/java/io/grpc/xds/RouteMatch.java index 75cbaa9e5..5b52e71c2 100644 --- a/xds/src/main/java/io/grpc/xds/RouteMatch.java +++ b/xds/src/main/java/io/grpc/xds/RouteMatch.java @@ -17,6 +17,7 @@ package io.grpc.xds; import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.Joiner; import com.google.common.base.MoreObjects; import com.google.common.base.MoreObjects.ToStringHelper; import com.google.re2j.Pattern; @@ -25,7 +26,6 @@ import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Objects; -import java.util.Set; import javax.annotation.Nullable; /** @@ -60,7 +60,7 @@ final class RouteMatch { * * <p>Match is not deterministic if a runtime fraction match rule presents in this RouteMatch. */ - boolean matches(String path, Map<String, Set<String>> headers) { + boolean matches(String path, Map<String, Iterable<String>> headers) { if (!pathMatch.matches(path)) { return false; } @@ -229,35 +229,31 @@ final class RouteMatch { this.isInvertedMatch = isInvertedMatch; } - private boolean matchesValue(@Nullable Set<String> values) { + private boolean matchesValue(@Nullable Iterable<String> values) { if (presentMatch != null) { return (values == null) == presentMatch.equals(isInvertedMatch); } if (values == null) { return false; } - boolean baseMatch = false; - for (String value : values) { - if (exactMatch != null) { - baseMatch = exactMatch.equals(value); - } else if (safeRegExMatch != null) { - baseMatch = safeRegExMatch.matches(value); - } else if (rangeMatch != null) { - long numValue; - try { - numValue = Long.parseLong(value); - } catch (NumberFormatException ignored) { - continue; - } + String valueStr = Joiner.on(",").join(values); + boolean baseMatch; + if (exactMatch != null) { + baseMatch = exactMatch.equals(valueStr); + } else if (safeRegExMatch != null) { + baseMatch = safeRegExMatch.matches(valueStr); + } else if (rangeMatch != null) { + long numValue; + try { + numValue = Long.parseLong(valueStr); baseMatch = rangeMatch.contains(numValue); - } else if (prefixMatch != null) { - baseMatch = value.startsWith(prefixMatch); - } else { - baseMatch = value.endsWith(suffixMatch); - } - if (baseMatch) { - break; + } catch (NumberFormatException ignored) { + baseMatch = false; } + } else if (prefixMatch != null) { + baseMatch = valueStr.startsWith(prefixMatch); + } else { + baseMatch = valueStr.endsWith(suffixMatch); } return baseMatch != isInvertedMatch; } diff --git a/xds/src/main/java/io/grpc/xds/XdsRoutingLoadBalancer.java b/xds/src/main/java/io/grpc/xds/XdsRoutingLoadBalancer.java index 428164ec4..1cd504505 100644 --- a/xds/src/main/java/io/grpc/xds/XdsRoutingLoadBalancer.java +++ b/xds/src/main/java/io/grpc/xds/XdsRoutingLoadBalancer.java @@ -42,7 +42,6 @@ import io.grpc.xds.XdsRoutingLoadBalancerProvider.Route; import io.grpc.xds.XdsRoutingLoadBalancerProvider.XdsRoutingConfig; import io.grpc.xds.XdsSubchannelPickers.ErrorPicker; import java.util.HashMap; -import java.util.HashSet; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; @@ -264,18 +263,14 @@ final class XdsRoutingLoadBalancer extends LoadBalancer { @Override public PickResult pickSubchannel(PickSubchannelArgs args) { // Index ASCII headers by keys. - Map<String, Set<String>> asciiHeaders = new HashMap<>(); + Map<String, Iterable<String>> asciiHeaders = new HashMap<>(); Metadata headers = args.getHeaders(); for (String headerName : headers.keys()) { if (headerName.endsWith(Metadata.BINARY_HEADER_SUFFIX)) { continue; } - Set<String> headerValues = new HashSet<>(); Metadata.Key<String> key = Metadata.Key.of(headerName, Metadata.ASCII_STRING_MARSHALLER); - for (String value : headers.getAll(key)) { - headerValues.add(value); - } - asciiHeaders.put(headerName, headerValues); + asciiHeaders.put(headerName, headers.getAll(key)); } for (Map.Entry<RouteMatch, SubchannelPicker> entry : routePickers.entrySet()) { RouteMatch routeMatch = entry.getKey(); diff --git a/xds/src/test/java/io/grpc/xds/RouteMatchTest.java b/xds/src/test/java/io/grpc/xds/RouteMatchTest.java index 222a4a1de..712758e11 100644 --- a/xds/src/test/java/io/grpc/xds/RouteMatchTest.java +++ b/xds/src/test/java/io/grpc/xds/RouteMatchTest.java @@ -26,9 +26,7 @@ import io.grpc.xds.RouteMatch.PathMatcher; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; -import java.util.HashSet; import java.util.Map; -import java.util.Set; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -38,15 +36,15 @@ import org.junit.runners.JUnit4; @RunWith(JUnit4.class) public class RouteMatchTest { - private final Map<String, Set<String>> headers = new HashMap<>(); + private final Map<String, Iterable<String>> headers = new HashMap<>(); @Before public void setUp() { - headers.put("content-type", Collections.singleton("application/grpc")); - headers.put("grpc-encoding", Collections.singleton("gzip")); - headers.put("user-agent", Collections.singleton("gRPC-Java")); - headers.put("content-length", Collections.singleton("1000")); - headers.put("custom-key", new HashSet<>(Arrays.asList("custom-value1", "custom-value2"))); + headers.put("content-type", Collections.singletonList("application/grpc")); + headers.put("grpc-encoding", Collections.singletonList("gzip")); + headers.put("user-agent", Collections.singletonList("gRPC-Java")); + headers.put("content-length", Collections.singletonList("1000")); + headers.put("custom-key", Arrays.asList("custom-value1", "custom-value2")); } @Test @@ -135,6 +133,15 @@ public class RouteMatchTest { null, true)), null); assertThat(routeMatch6.matches("/FooService/barMethod", headers)).isFalse(); + + RouteMatch routeMatch7 = new RouteMatch( + new PathMatcher("/FooService/barMethod", null, null), + Collections.singletonList( + new HeaderMatcher( + "custom-key", "custom-value1,custom-value2", null, null, null, null, + null, false)), + null); + assertThat(routeMatch7.matches("/FooService/barMethod", headers)).isTrue(); } @Test |