mirror of https://github.com/grpc/grpc-java.git
xds: remove path matcher format requirements and default route requirement for routing enabled (v1.30.x backport) (#7063) (#7070)
Remove requirement for formats of path matchers. Only require the last route to be the default route for the case when routing is disabled.
This commit is contained in:
parent
bd1c256ef5
commit
d71161432a
|
|
@ -444,6 +444,7 @@ final class EnvoyProtoData {
|
||||||
return routeAction;
|
return routeAction;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO(chengyuanzhang): delete and do not use after routing feature is always ON.
|
||||||
boolean isDefaultRoute() {
|
boolean isDefaultRoute() {
|
||||||
return routeMatch.isMatchAll();
|
return routeMatch.isMatchAll();
|
||||||
}
|
}
|
||||||
|
|
@ -553,16 +554,10 @@ final class EnvoyProtoData {
|
||||||
return pathExactMatch;
|
return pathExactMatch;
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean isMatchAll() {
|
// TODO(chengyuanzhang): delete and do not use after routing feature is always ON.
|
||||||
if (pathSafeRegExMatch != null || fractionMatch != null) {
|
private boolean isMatchAll() {
|
||||||
return false;
|
// For backward compatibility, all the other matchers are ignored. When routing is enabled,
|
||||||
}
|
// we should never care if a matcher matches all requests.
|
||||||
if (!headerMatchers.isEmpty()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (pathExactMatch != null) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (pathPrefixMatch != null) {
|
if (pathPrefixMatch != null) {
|
||||||
return pathPrefixMatch.isEmpty() || pathPrefixMatch.equals("/");
|
return pathPrefixMatch.isEmpty() || pathPrefixMatch.equals("/");
|
||||||
}
|
}
|
||||||
|
|
@ -655,27 +650,9 @@ final class EnvoyProtoData {
|
||||||
switch (proto.getPathSpecifierCase()) {
|
switch (proto.getPathSpecifierCase()) {
|
||||||
case PREFIX:
|
case PREFIX:
|
||||||
prefixPathMatch = proto.getPrefix();
|
prefixPathMatch = proto.getPrefix();
|
||||||
// Supported prefix match format:
|
|
||||||
// "", "/" (default)
|
|
||||||
// "/service/"
|
|
||||||
if (!prefixPathMatch.isEmpty() && !prefixPathMatch.equals("/")) {
|
|
||||||
if (!prefixPathMatch.startsWith("/") || !prefixPathMatch.endsWith("/")
|
|
||||||
|| prefixPathMatch.length() < 3) {
|
|
||||||
return StructOrError.fromError(
|
|
||||||
"Invalid format of prefix path match: " + prefixPathMatch);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case PATH:
|
case PATH:
|
||||||
exactPathMatch = proto.getPath();
|
exactPathMatch = proto.getPath();
|
||||||
int lastSlash = exactPathMatch.lastIndexOf('/');
|
|
||||||
// Supported exact match format:
|
|
||||||
// "/service/method"
|
|
||||||
if (!exactPathMatch.startsWith("/") || lastSlash == 0
|
|
||||||
|| lastSlash == exactPathMatch.length() - 1) {
|
|
||||||
return StructOrError.fromError(
|
|
||||||
"Invalid format of exact path match: " + exactPathMatch);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case REGEX:
|
case REGEX:
|
||||||
return StructOrError.fromError("Unsupported path match type: regex");
|
return StructOrError.fromError("Unsupported path match type: regex");
|
||||||
|
|
|
||||||
|
|
@ -858,14 +858,14 @@ final class XdsClientImpl extends XdsClient {
|
||||||
throw new InvalidProtoDataException(
|
throw new InvalidProtoDataException(
|
||||||
"Virtual host [" + virtualHost.getName() + "] contains no usable route");
|
"Virtual host [" + virtualHost.getName() + "] contains no usable route");
|
||||||
}
|
}
|
||||||
// The last route must be a default route.
|
|
||||||
if (!Iterables.getLast(routes).isDefaultRoute()) {
|
|
||||||
throw new InvalidProtoDataException(
|
|
||||||
"Virtual host [" + virtualHost.getName()
|
|
||||||
+ "] contains non-default route as the last route");
|
|
||||||
}
|
|
||||||
if (!enableExperimentalRouting) {
|
if (!enableExperimentalRouting) {
|
||||||
EnvoyProtoData.Route defaultRoute = Iterables.getLast(routes);
|
EnvoyProtoData.Route defaultRoute = Iterables.getLast(routes);
|
||||||
|
if (!defaultRoute.isDefaultRoute()) {
|
||||||
|
throw new InvalidProtoDataException(
|
||||||
|
"Virtual host [" + virtualHost.getName()
|
||||||
|
+ "] contains non-default route as the last route");
|
||||||
|
}
|
||||||
return Collections.singletonList(defaultRoute);
|
return Collections.singletonList(defaultRoute);
|
||||||
}
|
}
|
||||||
return Collections.unmodifiableList(routes);
|
return Collections.unmodifiableList(routes);
|
||||||
|
|
|
||||||
|
|
@ -246,51 +246,6 @@ public class EnvoyProtoDataTest {
|
||||||
assertThat(unsetStruct.getStruct()).isNull();
|
assertThat(unsetStruct.getStruct()).isNull();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void convertRouteMatch_pathMatchFormat() {
|
|
||||||
StructOrError<RouteMatch> struct1 =
|
|
||||||
RouteMatch.fromEnvoyProtoRouteMatch(buildSimpleRouteMatchProto("", null));
|
|
||||||
StructOrError<RouteMatch> struct2 =
|
|
||||||
RouteMatch.fromEnvoyProtoRouteMatch(buildSimpleRouteMatchProto("/", null));
|
|
||||||
StructOrError<RouteMatch> struct3 =
|
|
||||||
RouteMatch.fromEnvoyProtoRouteMatch(buildSimpleRouteMatchProto("/service", null));
|
|
||||||
StructOrError<RouteMatch> struct4 =
|
|
||||||
RouteMatch.fromEnvoyProtoRouteMatch(buildSimpleRouteMatchProto("/service/", null));
|
|
||||||
StructOrError<RouteMatch> struct5 =
|
|
||||||
RouteMatch.fromEnvoyProtoRouteMatch(buildSimpleRouteMatchProto(null, ""));
|
|
||||||
StructOrError<RouteMatch> struct6 =
|
|
||||||
RouteMatch.fromEnvoyProtoRouteMatch(buildSimpleRouteMatchProto(null, "/service/method"));
|
|
||||||
StructOrError<RouteMatch> struct7 =
|
|
||||||
RouteMatch.fromEnvoyProtoRouteMatch(buildSimpleRouteMatchProto(null, "/service/method/"));
|
|
||||||
StructOrError<RouteMatch> struct8 =
|
|
||||||
RouteMatch.fromEnvoyProtoRouteMatch(
|
|
||||||
io.envoyproxy.envoy.api.v2.route.RouteMatch.newBuilder()
|
|
||||||
.setSafeRegex(
|
|
||||||
io.envoyproxy.envoy.type.matcher.RegexMatcher.newBuilder().setRegex("["))
|
|
||||||
.build());
|
|
||||||
|
|
||||||
assertThat(struct1.getStruct()).isNotNull();
|
|
||||||
assertThat(struct2.getStruct()).isNotNull();
|
|
||||||
assertThat(struct3.getStruct()).isNull();
|
|
||||||
assertThat(struct4.getStruct()).isNotNull();
|
|
||||||
assertThat(struct5.getStruct()).isNull();
|
|
||||||
assertThat(struct6.getStruct()).isNotNull();
|
|
||||||
assertThat(struct7.getStruct()).isNull();
|
|
||||||
assertThat(struct8.getStruct()).isNull();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static io.envoyproxy.envoy.api.v2.route.RouteMatch buildSimpleRouteMatchProto(
|
|
||||||
@Nullable String pathPrefix, @Nullable String path) {
|
|
||||||
io.envoyproxy.envoy.api.v2.route.RouteMatch.Builder builder =
|
|
||||||
io.envoyproxy.envoy.api.v2.route.RouteMatch.newBuilder();
|
|
||||||
if (pathPrefix != null) {
|
|
||||||
builder.setPrefix(pathPrefix);
|
|
||||||
} else if (path != null) {
|
|
||||||
builder.setPath(path);
|
|
||||||
}
|
|
||||||
return builder.build();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void convertRouteMatch_withHeaderMatching() {
|
public void convertRouteMatch_withHeaderMatching() {
|
||||||
io.envoyproxy.envoy.api.v2.route.RouteMatch proto =
|
io.envoyproxy.envoy.api.v2.route.RouteMatch proto =
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue