mirror of https://github.com/grpc/grpc-java.git
xds: support case insensitive path matching (#7506)
This commit is contained in:
parent
67b54608da
commit
ef90da036d
|
|
@ -919,16 +919,6 @@ final class EnvoyProtoData {
|
|||
return routeAction;
|
||||
}
|
||||
|
||||
// TODO(chengyuanzhang): delete and do not use after routing feature is always ON.
|
||||
boolean isDefaultRoute() {
|
||||
// For backward compatibility, all the other matchers are ignored.
|
||||
String prefix = routeMatch.getPathMatch().getPrefix();
|
||||
if (prefix != null) {
|
||||
return prefix.isEmpty() || prefix.equals("/");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
|
|
@ -993,17 +983,12 @@ final class EnvoyProtoData {
|
|||
}
|
||||
|
||||
@VisibleForTesting
|
||||
@SuppressWarnings("deprecation")
|
||||
@Nullable
|
||||
static StructOrError<RouteMatch> convertEnvoyProtoRouteMatch(
|
||||
io.envoyproxy.envoy.config.route.v3.RouteMatch proto) {
|
||||
if (proto.getQueryParametersCount() != 0) {
|
||||
return null;
|
||||
}
|
||||
if (proto.hasCaseSensitive() && !proto.getCaseSensitive().getValue()) {
|
||||
return StructOrError.fromError("Unsupported match option: case insensitive");
|
||||
}
|
||||
|
||||
StructOrError<PathMatcher> pathMatch = convertEnvoyProtoPathMatcher(proto);
|
||||
if (pathMatch.getErrorDetail() != null) {
|
||||
return StructOrError.fromError(pathMatch.getErrorDetail());
|
||||
|
|
@ -1033,32 +1018,28 @@ final class EnvoyProtoData {
|
|||
pathMatch.getStruct(), Collections.unmodifiableList(headerMatchers), fractionMatch));
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
private static StructOrError<PathMatcher> convertEnvoyProtoPathMatcher(
|
||||
io.envoyproxy.envoy.config.route.v3.RouteMatch proto) {
|
||||
String path = null;
|
||||
String prefix = null;
|
||||
Pattern safeRegEx = null;
|
||||
boolean caseSensitive = proto.getCaseSensitive().getValue();
|
||||
switch (proto.getPathSpecifierCase()) {
|
||||
case PREFIX:
|
||||
prefix = proto.getPrefix();
|
||||
break;
|
||||
return StructOrError.fromStruct(
|
||||
PathMatcher.fromPrefix(proto.getPrefix(), caseSensitive));
|
||||
case PATH:
|
||||
path = proto.getPath();
|
||||
break;
|
||||
return StructOrError.fromStruct(PathMatcher.fromPath(proto.getPath(), caseSensitive));
|
||||
case SAFE_REGEX:
|
||||
String rawPattern = proto.getSafeRegex().getRegex();
|
||||
Pattern safeRegEx;
|
||||
try {
|
||||
safeRegEx = Pattern.compile(rawPattern);
|
||||
} catch (PatternSyntaxException e) {
|
||||
return StructOrError.fromError("Malformed safe regex pattern: " + e.getMessage());
|
||||
}
|
||||
break;
|
||||
return StructOrError.fromStruct(PathMatcher.fromRegEx(safeRegEx));
|
||||
case PATHSPECIFIER_NOT_SET:
|
||||
default:
|
||||
return StructOrError.fromError("Unknown path match type");
|
||||
}
|
||||
return StructOrError.fromStruct(new PathMatcher(path, prefix, safeRegEx));
|
||||
}
|
||||
|
||||
private static StructOrError<FractionMatcher> convertEnvoyProtoFraction(
|
||||
|
|
|
|||
|
|
@ -45,10 +45,8 @@ final class RouteMatch {
|
|||
this.headerMatchers = headerMatchers;
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
RouteMatch(@Nullable String pathPrefixMatch, @Nullable String pathExactMatch) {
|
||||
this(
|
||||
new PathMatcher(pathExactMatch, pathPrefixMatch, null),
|
||||
static RouteMatch withPathExactOnly(String pathExact) {
|
||||
return new RouteMatch(PathMatcher.fromPath(pathExact, true),
|
||||
Collections.<HeaderMatcher>emptyList(), null);
|
||||
}
|
||||
|
||||
|
|
@ -82,19 +80,6 @@ final class RouteMatch {
|
|||
return fractionMatch == null || fractionMatch.matches();
|
||||
}
|
||||
|
||||
PathMatcher getPathMatch() {
|
||||
return pathMatch;
|
||||
}
|
||||
|
||||
List<HeaderMatcher> getHeaderMatchers() {
|
||||
return Collections.unmodifiableList(headerMatchers);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
FractionMatcher getFractionMatch() {
|
||||
return fractionMatch;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
|
|
@ -132,37 +117,39 @@ final class RouteMatch {
|
|||
private final String prefix;
|
||||
@Nullable
|
||||
private final Pattern regEx;
|
||||
private final boolean caseSensitive;
|
||||
|
||||
PathMatcher(@Nullable String path, @Nullable String prefix, @Nullable Pattern regEx) {
|
||||
private PathMatcher(@Nullable String path, @Nullable String prefix, @Nullable Pattern regEx,
|
||||
boolean caseSensitive) {
|
||||
this.path = path;
|
||||
this.prefix = prefix;
|
||||
this.regEx = regEx;
|
||||
this.caseSensitive = caseSensitive;
|
||||
}
|
||||
|
||||
private boolean matches(String fullMethodName) {
|
||||
static PathMatcher fromPath(String path, boolean caseSensitive) {
|
||||
return new PathMatcher(path, null, null, caseSensitive);
|
||||
}
|
||||
|
||||
static PathMatcher fromPrefix(String prefix, boolean caseSensitive) {
|
||||
return new PathMatcher(null, prefix, null, caseSensitive);
|
||||
}
|
||||
|
||||
static PathMatcher fromRegEx(Pattern regEx) {
|
||||
return new PathMatcher(null, null, regEx, false /* doesn't matter */);
|
||||
}
|
||||
|
||||
boolean matches(String fullMethodName) {
|
||||
if (path != null) {
|
||||
return path.equals(fullMethodName);
|
||||
return caseSensitive ? path.equals(fullMethodName) : path.equalsIgnoreCase(fullMethodName);
|
||||
} else if (prefix != null) {
|
||||
return fullMethodName.startsWith(prefix);
|
||||
return caseSensitive
|
||||
? fullMethodName.startsWith(prefix)
|
||||
: fullMethodName.toLowerCase().startsWith(prefix.toLowerCase());
|
||||
}
|
||||
return regEx.matches(fullMethodName);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
String getPath() {
|
||||
return path;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
String getPrefix() {
|
||||
return prefix;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
Pattern getRegEx() {
|
||||
return regEx;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
|
|
@ -174,6 +161,7 @@ final class RouteMatch {
|
|||
PathMatcher that = (PathMatcher) o;
|
||||
return Objects.equals(path, that.path)
|
||||
&& Objects.equals(prefix, that.prefix)
|
||||
&& Objects.equals(caseSensitive, that.caseSensitive)
|
||||
&& Objects.equals(
|
||||
regEx == null ? null : regEx.pattern(),
|
||||
that.regEx == null ? null : that.regEx.pattern());
|
||||
|
|
@ -181,7 +169,7 @@ final class RouteMatch {
|
|||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(path, prefix, regEx == null ? null : regEx.pattern());
|
||||
return Objects.hash(path, prefix, caseSensitive, regEx == null ? null : regEx.pattern());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -189,10 +177,10 @@ final class RouteMatch {
|
|||
ToStringHelper toStringHelper =
|
||||
MoreObjects.toStringHelper(this);
|
||||
if (path != null) {
|
||||
toStringHelper.add("path", path);
|
||||
toStringHelper.add("path", path).add("caseSensitive", caseSensitive);
|
||||
}
|
||||
if (prefix != null) {
|
||||
toStringHelper.add("prefix", prefix);
|
||||
toStringHelper.add("prefix", prefix).add("caseSensitive", caseSensitive);
|
||||
}
|
||||
if (regEx != null) {
|
||||
toStringHelper.add("regEx", regEx.pattern());
|
||||
|
|
|
|||
|
|
@ -50,7 +50,6 @@ import io.grpc.xds.RouteMatch.PathMatcher;
|
|||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import javax.annotation.Nullable;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.JUnit4;
|
||||
|
|
@ -211,7 +210,7 @@ public class EnvoyProtoDataTest {
|
|||
assertThat(struct1.getStruct())
|
||||
.isEqualTo(
|
||||
new Route(
|
||||
new RouteMatch(new PathMatcher("/service/method", null, null),
|
||||
new RouteMatch(PathMatcher.fromPath("/service/method", false),
|
||||
Collections.<HeaderMatcher>emptyList(), null),
|
||||
new RouteAction(TimeUnit.SECONDS.toNanos(15L), "cluster-foo", null)));
|
||||
|
||||
|
|
@ -259,38 +258,6 @@ public class EnvoyProtoDataTest {
|
|||
assertThat(Route.fromEnvoyProtoRoute(proto)).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isDefaultRoute() {
|
||||
StructOrError<Route> struct1 = Route.fromEnvoyProtoRoute(buildSimpleRouteProto("", null));
|
||||
StructOrError<Route> struct2 = Route.fromEnvoyProtoRoute(buildSimpleRouteProto("/", null));
|
||||
StructOrError<Route> struct3 =
|
||||
Route.fromEnvoyProtoRoute(buildSimpleRouteProto("/service/", null));
|
||||
StructOrError<Route> struct4 =
|
||||
Route.fromEnvoyProtoRoute(buildSimpleRouteProto(null, "/service/method"));
|
||||
|
||||
assertThat(struct1.getStruct().isDefaultRoute()).isTrue();
|
||||
assertThat(struct2.getStruct().isDefaultRoute()).isTrue();
|
||||
assertThat(struct3.getStruct().isDefaultRoute()).isFalse();
|
||||
assertThat(struct4.getStruct().isDefaultRoute()).isFalse();
|
||||
}
|
||||
|
||||
private static io.envoyproxy.envoy.config.route.v3.Route buildSimpleRouteProto(
|
||||
@Nullable String pathPrefix, @Nullable String path) {
|
||||
io.envoyproxy.envoy.config.route.v3.Route.Builder routeBuilder =
|
||||
io.envoyproxy.envoy.config.route.v3.Route.newBuilder()
|
||||
.setName("simple-route")
|
||||
.setRoute(io.envoyproxy.envoy.config.route.v3.RouteAction.newBuilder()
|
||||
.setCluster("simple-cluster"));
|
||||
if (pathPrefix != null) {
|
||||
routeBuilder.setMatch(io.envoyproxy.envoy.config.route.v3.RouteMatch.newBuilder()
|
||||
.setPrefix(pathPrefix));
|
||||
} else if (path != null) {
|
||||
routeBuilder.setMatch(io.envoyproxy.envoy.config.route.v3.RouteMatch.newBuilder()
|
||||
.setPath(path));
|
||||
}
|
||||
return routeBuilder.build();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void convertRouteMatch_pathMatching() {
|
||||
// path_specifier = prefix
|
||||
|
|
@ -300,7 +267,13 @@ public class EnvoyProtoDataTest {
|
|||
assertThat(struct1.getErrorDetail()).isNull();
|
||||
assertThat(struct1.getStruct()).isEqualTo(
|
||||
new RouteMatch(
|
||||
new PathMatcher(null, "/", null), Collections.<HeaderMatcher>emptyList(), null));
|
||||
PathMatcher.fromPrefix("/", false), Collections.<HeaderMatcher>emptyList(), null));
|
||||
|
||||
proto1 = proto1.toBuilder().setCaseSensitive(BoolValue.newBuilder().setValue(true)).build();
|
||||
struct1 = Route.convertEnvoyProtoRouteMatch(proto1);
|
||||
assertThat(struct1.getStruct()).isEqualTo(
|
||||
new RouteMatch(
|
||||
PathMatcher.fromPrefix("/", true), Collections.<HeaderMatcher>emptyList(), null));
|
||||
|
||||
// path_specifier = path
|
||||
io.envoyproxy.envoy.config.route.v3.RouteMatch proto2 =
|
||||
|
|
@ -311,7 +284,14 @@ public class EnvoyProtoDataTest {
|
|||
assertThat(struct2.getErrorDetail()).isNull();
|
||||
assertThat(struct2.getStruct()).isEqualTo(
|
||||
new RouteMatch(
|
||||
new PathMatcher("/service/method", null, null),
|
||||
PathMatcher.fromPath("/service/method", false),
|
||||
Collections.<HeaderMatcher>emptyList(), null));
|
||||
|
||||
proto2 = proto2.toBuilder().setCaseSensitive(BoolValue.newBuilder().setValue(true)).build();
|
||||
struct2 = Route.convertEnvoyProtoRouteMatch(proto2);
|
||||
assertThat(struct2.getStruct()).isEqualTo(
|
||||
new RouteMatch(
|
||||
PathMatcher.fromPath("/service/method", true),
|
||||
Collections.<HeaderMatcher>emptyList(), null));
|
||||
|
||||
// path_specifier = safe_regex
|
||||
|
|
@ -323,18 +303,9 @@ public class EnvoyProtoDataTest {
|
|||
assertThat(struct4.getErrorDetail()).isNull();
|
||||
assertThat(struct4.getStruct()).isEqualTo(
|
||||
new RouteMatch(
|
||||
new PathMatcher(null, null, Pattern.compile(".")),
|
||||
PathMatcher.fromRegEx(Pattern.compile(".")),
|
||||
Collections.<HeaderMatcher>emptyList(), null));
|
||||
|
||||
// case_sensitive = false
|
||||
io.envoyproxy.envoy.config.route.v3.RouteMatch proto5 =
|
||||
io.envoyproxy.envoy.config.route.v3.RouteMatch.newBuilder()
|
||||
.setCaseSensitive(BoolValue.newBuilder().setValue(false))
|
||||
.build();
|
||||
StructOrError<RouteMatch> struct5 = Route.convertEnvoyProtoRouteMatch(proto5);
|
||||
assertThat(struct5.getErrorDetail()).isNotNull();
|
||||
assertThat(struct5.getStruct()).isNull();
|
||||
|
||||
// query_parameters is set
|
||||
io.envoyproxy.envoy.config.route.v3.RouteMatch proto6 =
|
||||
io.envoyproxy.envoy.config.route.v3.RouteMatch.newBuilder()
|
||||
|
|
@ -370,7 +341,7 @@ public class EnvoyProtoDataTest {
|
|||
assertThat(struct.getStruct())
|
||||
.isEqualTo(
|
||||
new RouteMatch(
|
||||
new PathMatcher(null, "", null),
|
||||
PathMatcher.fromPrefix("", false),
|
||||
Arrays.asList(
|
||||
new HeaderMatcher(":scheme", null, null, null, null, "http", null, false),
|
||||
new HeaderMatcher(":method", "PUT", null, null, null, null, null, false)),
|
||||
|
|
@ -394,7 +365,7 @@ public class EnvoyProtoDataTest {
|
|||
assertThat(struct.getStruct())
|
||||
.isEqualTo(
|
||||
new RouteMatch(
|
||||
new PathMatcher(null, "", null), Collections.<HeaderMatcher>emptyList(),
|
||||
PathMatcher.fromPrefix( "", false), Collections.<HeaderMatcher>emptyList(),
|
||||
new FractionMatcher(30, 100)));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -51,14 +51,14 @@ public class RouteMatchTest {
|
|||
public void routeMatching_pathOnly() {
|
||||
RouteMatch routeMatch1 =
|
||||
new RouteMatch(
|
||||
new PathMatcher("/FooService/barMethod", null, null),
|
||||
PathMatcher.fromPath("/FooService/barMethod", true),
|
||||
Collections.<HeaderMatcher>emptyList(), null);
|
||||
assertThat(routeMatch1.matches("/FooService/barMethod", headers)).isTrue();
|
||||
assertThat(routeMatch1.matches("/FooService/bazMethod", headers)).isFalse();
|
||||
|
||||
RouteMatch routeMatch2 =
|
||||
new RouteMatch(
|
||||
new PathMatcher(null, "/FooService/", null),
|
||||
PathMatcher.fromPrefix("/FooService/", true),
|
||||
Collections.<HeaderMatcher>emptyList(), null);
|
||||
assertThat(routeMatch2.matches("/FooService/barMethod", headers)).isTrue();
|
||||
assertThat(routeMatch2.matches("/FooService/bazMethod", headers)).isTrue();
|
||||
|
|
@ -66,15 +66,25 @@ public class RouteMatchTest {
|
|||
|
||||
RouteMatch routeMatch3 =
|
||||
new RouteMatch(
|
||||
new PathMatcher(null, null, Pattern.compile(".*Foo.*")),
|
||||
PathMatcher.fromRegEx(Pattern.compile(".*Foo.*")),
|
||||
Collections.<HeaderMatcher>emptyList(), null);
|
||||
assertThat(routeMatch3.matches("/FooService/barMethod", headers)).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void pathMatching_caseInsensitive() {
|
||||
PathMatcher pathMatcher1 = PathMatcher.fromPath("/FooService/barMethod", false);
|
||||
assertThat(pathMatcher1.matches("/fooservice/barmethod")).isTrue();
|
||||
|
||||
PathMatcher pathMatcher2 = PathMatcher.fromPrefix("/FooService", false);
|
||||
assertThat(pathMatcher2.matches("/fooservice/barmethod")).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void routeMatching_withHeaders() {
|
||||
PathMatcher pathMatcher = PathMatcher.fromPath("/FooService/barMethod", true);
|
||||
RouteMatch routeMatch1 = new RouteMatch(
|
||||
new PathMatcher("/FooService/barMethod", null, null),
|
||||
pathMatcher,
|
||||
Arrays.asList(
|
||||
new HeaderMatcher(
|
||||
"grpc-encoding", "gzip", null, null, null, null, null, false),
|
||||
|
|
@ -90,7 +100,7 @@ public class RouteMatchTest {
|
|||
assertThat(routeMatch1.matches("/FooService/barMethod", headers)).isTrue();
|
||||
|
||||
RouteMatch routeMatch2 = new RouteMatch(
|
||||
new PathMatcher("/FooService/barMethod", null, null),
|
||||
pathMatcher,
|
||||
Collections.singletonList(
|
||||
new HeaderMatcher(
|
||||
"authority", null, Pattern.compile(".*googleapis.*"), null, null, null,
|
||||
|
|
@ -99,7 +109,7 @@ public class RouteMatchTest {
|
|||
assertThat(routeMatch2.matches("/FooService/barMethod", headers)).isFalse();
|
||||
|
||||
RouteMatch routeMatch3 = new RouteMatch(
|
||||
new PathMatcher("/FooService/barMethod", null, null),
|
||||
pathMatcher,
|
||||
Collections.singletonList(
|
||||
new HeaderMatcher(
|
||||
"user-agent", "gRPC-Go", null, null, null, null,
|
||||
|
|
@ -108,7 +118,7 @@ public class RouteMatchTest {
|
|||
assertThat(routeMatch3.matches("/FooService/barMethod", headers)).isFalse();
|
||||
|
||||
RouteMatch routeMatch4 = new RouteMatch(
|
||||
new PathMatcher("/FooService/barMethod", null, null),
|
||||
pathMatcher,
|
||||
Collections.singletonList(
|
||||
new HeaderMatcher(
|
||||
"user-agent", null, null, null, false, null,
|
||||
|
|
@ -117,7 +127,7 @@ public class RouteMatchTest {
|
|||
assertThat(routeMatch4.matches("/FooService/barMethod", headers)).isFalse();
|
||||
|
||||
RouteMatch routeMatch5 = new RouteMatch(
|
||||
new PathMatcher("/FooService/barMethod", null, null),
|
||||
pathMatcher,
|
||||
Collections.singletonList(
|
||||
new HeaderMatcher(
|
||||
"user-agent", null, null, null, false, null,
|
||||
|
|
@ -126,7 +136,7 @@ public class RouteMatchTest {
|
|||
assertThat(routeMatch5.matches("/FooService/barMethod", headers)).isTrue();
|
||||
|
||||
RouteMatch routeMatch6 = new RouteMatch(
|
||||
new PathMatcher("/FooService/barMethod", null, null),
|
||||
pathMatcher,
|
||||
Collections.singletonList(
|
||||
new HeaderMatcher(
|
||||
"user-agent", null, null, null, true, null,
|
||||
|
|
@ -135,7 +145,7 @@ public class RouteMatchTest {
|
|||
assertThat(routeMatch6.matches("/FooService/barMethod", headers)).isFalse();
|
||||
|
||||
RouteMatch routeMatch7 = new RouteMatch(
|
||||
new PathMatcher("/FooService/barMethod", null, null),
|
||||
pathMatcher,
|
||||
Collections.singletonList(
|
||||
new HeaderMatcher(
|
||||
"custom-key", "custom-value1,custom-value2", null, null, null, null,
|
||||
|
|
@ -146,16 +156,17 @@ public class RouteMatchTest {
|
|||
|
||||
@Test
|
||||
public void routeMatching_withRuntimeFraction() {
|
||||
PathMatcher pathMatcher = PathMatcher.fromPath("/FooService/barMethod", true);
|
||||
RouteMatch routeMatch1 =
|
||||
new RouteMatch(
|
||||
new PathMatcher("/FooService/barMethod", null, null),
|
||||
pathMatcher,
|
||||
Collections.<HeaderMatcher>emptyList(),
|
||||
new FractionMatcher(100, 1000, new FakeRandom(50)));
|
||||
assertThat(routeMatch1.matches("/FooService/barMethod", headers)).isTrue();
|
||||
|
||||
RouteMatch routeMatch2 =
|
||||
new RouteMatch(
|
||||
new PathMatcher("/FooService/barMethod", null, null),
|
||||
pathMatcher,
|
||||
Collections.<HeaderMatcher>emptyList(),
|
||||
new FractionMatcher(100, 1000, new FakeRandom(100)));
|
||||
assertThat(routeMatch2.matches("/FooService/barMethod", headers)).isFalse();
|
||||
|
|
@ -163,11 +174,12 @@ public class RouteMatchTest {
|
|||
|
||||
@Test
|
||||
public void headerMatching_specialCaseGrpcHeaders() {
|
||||
PathMatcher pathMatcher = PathMatcher.fromPath("/FooService/barMethod", true);
|
||||
Map<String, Iterable<String>> headers = new HashMap<>();
|
||||
headers.put("grpc-previous-rpc-attempts", Collections.singletonList("0"));
|
||||
|
||||
RouteMatch routeMatch1 =
|
||||
new RouteMatch(new PathMatcher("/FooService/barMethod", null, null),
|
||||
new RouteMatch(pathMatcher,
|
||||
Arrays.asList(
|
||||
new HeaderMatcher(
|
||||
"grpc-previous-rpc-attempts", "0", null, null, null, null,
|
||||
|
|
@ -176,7 +188,7 @@ public class RouteMatchTest {
|
|||
assertThat(routeMatch1.matches("/FooService/barMethod", headers)).isFalse();
|
||||
|
||||
RouteMatch routeMatch2 =
|
||||
new RouteMatch(new PathMatcher("/FooService/barMethod", null, null),
|
||||
new RouteMatch(pathMatcher,
|
||||
Arrays.asList(
|
||||
new HeaderMatcher(
|
||||
"content-type", "application/grpc", null, null, null, null,
|
||||
|
|
|
|||
|
|
@ -280,9 +280,9 @@ public class XdsNameResolverTest {
|
|||
}
|
||||
|
||||
private List<VirtualHost> buildUnmatchedVirtualHosts() {
|
||||
Route route1 = new Route(new RouteMatch(null, call2.getFullMethodNameForPath()),
|
||||
Route route1 = new Route(RouteMatch.withPathExactOnly(call2.getFullMethodNameForPath()),
|
||||
new RouteAction(TimeUnit.SECONDS.toNanos(15L), cluster2, null));
|
||||
Route route2 = new Route(new RouteMatch(null, call1.getFullMethodNameForPath()),
|
||||
Route route2 = new Route(RouteMatch.withPathExactOnly(call1.getFullMethodNameForPath()),
|
||||
new RouteAction(TimeUnit.SECONDS.toNanos(15L), cluster1, null));
|
||||
return Arrays.asList(
|
||||
new VirtualHost("virtualhost-foo", Collections.singletonList("hello.googleapis.com"),
|
||||
|
|
@ -324,10 +324,10 @@ public class XdsNameResolverTest {
|
|||
AUTHORITY,
|
||||
Arrays.asList(
|
||||
new Route(
|
||||
new RouteMatch(null, call1.getFullMethodNameForPath()),
|
||||
RouteMatch.withPathExactOnly(call1.getFullMethodNameForPath()),
|
||||
new RouteAction(TimeUnit.SECONDS.toNanos(20L), "another-cluster", null)),
|
||||
new Route(
|
||||
new RouteMatch(null, call2.getFullMethodNameForPath()),
|
||||
RouteMatch.withPathExactOnly(call2.getFullMethodNameForPath()),
|
||||
new RouteAction(TimeUnit.SECONDS.toNanos(15L), cluster2, null))));
|
||||
verify(mockListener).onResult(resolutionResultCaptor.capture());
|
||||
ResolutionResult result = resolutionResultCaptor.getValue();
|
||||
|
|
@ -359,10 +359,10 @@ public class XdsNameResolverTest {
|
|||
AUTHORITY,
|
||||
Arrays.asList(
|
||||
new Route(
|
||||
new RouteMatch(null, call1.getFullMethodNameForPath()),
|
||||
RouteMatch.withPathExactOnly(call1.getFullMethodNameForPath()),
|
||||
new RouteAction(TimeUnit.SECONDS.toNanos(20L), "another-cluster", null)),
|
||||
new Route(
|
||||
new RouteMatch(null, call2.getFullMethodNameForPath()),
|
||||
RouteMatch.withPathExactOnly(call2.getFullMethodNameForPath()),
|
||||
new RouteAction(TimeUnit.SECONDS.toNanos(15L), cluster2, null))));
|
||||
// Two consecutive service config updates: one for removing clcuster1,
|
||||
// one for adding "another=cluster".
|
||||
|
|
@ -390,10 +390,10 @@ public class XdsNameResolverTest {
|
|||
AUTHORITY,
|
||||
Arrays.asList(
|
||||
new Route(
|
||||
new RouteMatch(null, call1.getFullMethodNameForPath()),
|
||||
RouteMatch.withPathExactOnly(call1.getFullMethodNameForPath()),
|
||||
new RouteAction(TimeUnit.SECONDS.toNanos(20L), "another-cluster", null)),
|
||||
new Route(
|
||||
new RouteMatch(null, call2.getFullMethodNameForPath()),
|
||||
RouteMatch.withPathExactOnly(call2.getFullMethodNameForPath()),
|
||||
new RouteAction(TimeUnit.SECONDS.toNanos(15L), cluster2, null))));
|
||||
|
||||
verify(mockListener).onResult(resolutionResultCaptor.capture());
|
||||
|
|
@ -406,10 +406,10 @@ public class XdsNameResolverTest {
|
|||
AUTHORITY,
|
||||
Arrays.asList(
|
||||
new Route(
|
||||
new RouteMatch(null, call1.getFullMethodNameForPath()),
|
||||
RouteMatch.withPathExactOnly(call1.getFullMethodNameForPath()),
|
||||
new RouteAction(TimeUnit.SECONDS.toNanos(15L), "another-cluster", null)),
|
||||
new Route(
|
||||
new RouteMatch(null, call2.getFullMethodNameForPath()),
|
||||
RouteMatch.withPathExactOnly(call2.getFullMethodNameForPath()),
|
||||
new RouteAction(TimeUnit.SECONDS.toNanos(15L), cluster2, null))));
|
||||
verifyNoMoreInteractions(mockListener); // no cluster added/deleted
|
||||
assertCallSelectResult(call1, configSelector, "another-cluster", 15.0);
|
||||
|
|
@ -424,16 +424,16 @@ public class XdsNameResolverTest {
|
|||
AUTHORITY,
|
||||
Collections.singletonList(
|
||||
new Route(
|
||||
new RouteMatch(null, call2.getFullMethodNameForPath()),
|
||||
RouteMatch.withPathExactOnly(call2.getFullMethodNameForPath()),
|
||||
new RouteAction(TimeUnit.SECONDS.toNanos(15L), cluster2, null))));
|
||||
xdsClient.deliverRoutesViaLds(
|
||||
AUTHORITY,
|
||||
Arrays.asList(
|
||||
new Route(
|
||||
new RouteMatch(null, call1.getFullMethodNameForPath()),
|
||||
RouteMatch.withPathExactOnly(call1.getFullMethodNameForPath()),
|
||||
new RouteAction(TimeUnit.SECONDS.toNanos(15L), cluster1, null)),
|
||||
new Route(
|
||||
new RouteMatch(null, call2.getFullMethodNameForPath()),
|
||||
RouteMatch.withPathExactOnly(call2.getFullMethodNameForPath()),
|
||||
new RouteAction(TimeUnit.SECONDS.toNanos(15L), cluster2, null))));
|
||||
result.getCommittedCallback().run();
|
||||
verifyNoMoreInteractions(mockListener);
|
||||
|
|
@ -449,7 +449,7 @@ public class XdsNameResolverTest {
|
|||
AUTHORITY,
|
||||
Arrays.asList(
|
||||
new Route(
|
||||
new RouteMatch(null, call1.getFullMethodNameForPath()),
|
||||
RouteMatch.withPathExactOnly(call1.getFullMethodNameForPath()),
|
||||
new RouteAction(
|
||||
TimeUnit.SECONDS.toNanos(20L), null,
|
||||
Arrays.asList(
|
||||
|
|
@ -505,10 +505,10 @@ public class XdsNameResolverTest {
|
|||
AUTHORITY,
|
||||
Arrays.asList(
|
||||
new Route(
|
||||
new RouteMatch(null, call1.getFullMethodNameForPath()),
|
||||
RouteMatch.withPathExactOnly(call1.getFullMethodNameForPath()),
|
||||
new RouteAction(TimeUnit.SECONDS.toNanos(15L), cluster1, null)),
|
||||
new Route(
|
||||
new RouteMatch(null, call2.getFullMethodNameForPath()),
|
||||
RouteMatch.withPathExactOnly(call2.getFullMethodNameForPath()),
|
||||
new RouteAction(TimeUnit.SECONDS.toNanos(15L), cluster2, null))));
|
||||
verify(mockListener).onResult(resolutionResultCaptor.capture());
|
||||
ResolutionResult result = resolutionResultCaptor.getValue();
|
||||
|
|
|
|||
Loading…
Reference in New Issue