Skip to content

xds: Implementation of Unified Matcher#12640

Open
shivaspeaks wants to merge 26 commits into
grpc:masterfrom
shivaspeaks:xds-unified-matcher-and-cel
Open

xds: Implementation of Unified Matcher#12640
shivaspeaks wants to merge 26 commits into
grpc:masterfrom
shivaspeaks:xds-unified-matcher-and-cel

Conversation

@shivaspeaks

@shivaspeaks shivaspeaks commented Feb 3, 2026

Copy link
Copy Markdown
Member

Implements gRFC A106: xDS Unified Matcher
grpc/proposal#520

@shivaspeaks shivaspeaks force-pushed the xds-unified-matcher-and-cel branch from 082243d to f472c63 Compare February 3, 2026 10:11
@shivaspeaks shivaspeaks marked this pull request as ready for review February 8, 2026 09:01

@l46kok l46kok left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Sorry about the drive-by -- I happened to notice this while putting together an unrelated PR in CEL-Java. I'll hold off on submitting it on our end.

Comment thread gradle/libs.versions.toml Outdated
Comment thread xds/src/main/java/io/grpc/xds/internal/matcher/CelCommon.java Outdated
* Compiles the CEL expression string into a CelMatcher.
*/
@VisibleForTesting
public static CelMatcher compile(String expression)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Move this to the testing code so we don't need a dependency on the Cel compiler. It looks unused for production.

Comment thread gradle/libs.versions.toml Outdated
Comment on lines +57 to +58
String id = over.toString();
return !id.equals("ADD_STRING") && !id.equals("ADD_LIST");

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

You should be able to compare directly against the overload enum instead of the stringified form (ex: over != AddOverload.ADD_STRING).

copybara-service Bot pushed a commit to cel-expr/cel-java that referenced this pull request Feb 18, 2026
copybara-service Bot pushed a commit to cel-expr/cel-java that referenced this pull request Feb 18, 2026
copybara-service Bot pushed a commit to cel-expr/cel-java that referenced this pull request Feb 18, 2026
copybara-service Bot pushed a commit to cel-expr/cel-java that referenced this pull request Feb 18, 2026
Also removes antlr dependency from `dev.cel:runtime` artifact

Fixes: #566
See also grpc/grpc-java#12640
PiperOrigin-RevId: 871541021
copybara-service Bot pushed a commit to cel-expr/cel-java that referenced this pull request Feb 18, 2026
Also removes antlr dependency from `dev.cel:runtime` artifact

Fixes: #566
See also grpc/grpc-java#12640
PiperOrigin-RevId: 871541021
copybara-service Bot pushed a commit to cel-expr/cel-java that referenced this pull request Feb 18, 2026
Also removes antlr dependency from `dev.cel:runtime` artifact

Fixes: #566
See also grpc/grpc-java#12640
PiperOrigin-RevId: 871541021
copybara-service Bot pushed a commit to cel-expr/cel-java that referenced this pull request Feb 18, 2026
Also removes antlr dependency from `dev.cel:runtime` artifact

Fixes: #566
See also grpc/grpc-java#12640
PiperOrigin-RevId: 871541021
copybara-service Bot pushed a commit to cel-expr/cel-java that referenced this pull request Feb 18, 2026
Also removes antlr dependency from `dev.cel:runtime` artifact

Fixes: #566
See also grpc/grpc-java#12640
PiperOrigin-RevId: 871541021
copybara-service Bot pushed a commit to cel-expr/cel-java that referenced this pull request Feb 18, 2026
Also removes antlr dependency from `dev.cel:runtime` artifact

Fixes: #566
See also grpc/grpc-java#12640
PiperOrigin-RevId: 871541021
copybara-service Bot pushed a commit to cel-expr/cel-java that referenced this pull request Feb 18, 2026
Also removes antlr dependency from `dev.cel:runtime` artifact

Fixes: #566
See also grpc/grpc-java#12640
PiperOrigin-RevId: 871541021
copybara-service Bot pushed a commit to cel-expr/cel-java that referenced this pull request Feb 18, 2026
Also removes antlr dependency from `dev.cel:runtime` artifact

Fixes: #566
See also grpc/grpc-java#12640
PiperOrigin-RevId: 871541021
copybara-service Bot pushed a commit to cel-expr/cel-java that referenced this pull request Feb 18, 2026
Also removes antlr dependency from `dev.cel:runtime` artifact

Fixes: #566
See also grpc/grpc-java#12640
PiperOrigin-RevId: 871541021
copybara-service Bot pushed a commit to cel-expr/cel-java that referenced this pull request Feb 18, 2026
Also removes antlr dependency from `dev.cel:runtime` artifact

Fixes: #566
See also grpc/grpc-java#12640
PiperOrigin-RevId: 872010923
@ejona86 ejona86 requested a review from sergiitk February 23, 2026 18:02
String id = over.toString();
return !id.equals("ADD_STRING") && !id.equals("ADD_LIST");
return !over.equals(
(Object) dev.cel.runtime.standard.AddOperator.AddOverload.ADD_STRING)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Why are we needing to cast to Object? If you're working around ErrorProne, then something seems broken and casting to Object is just hiding it.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Yes it was an errorProne workaround.
over is statically known as a StandardOverload interface, but ADD_STRING is an AddOverload enum. ErrorProne threw an [EqualsIncompatibleType] build error so we need to cast the ADD_STRING enum specifically to (Object) before passing it into equals.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

ADD_STRING is a CelStandardOverload, which isn't a StandardOverload. It seems ErrorProne is correct; these will never be equal.

You should comment cases like this. If this were a bug in ErrorProne we'd probably want to file a bug with ErrorProne, but even if not, the comment helps us know when it is no longer necessary. (We don't have to guess why it was done, so we can confirm if that is no longer the case.)

It looks like that has been adjusted on cel-java master, as the function is now passed CelStandardOverload.

@sergiitk, the interface change looks like a breaking API change. That's surprising since I thought we were using stable APIs. Is this PR using an API that it shouldn't be, was this a known change that just hadn't been released yet, or should we be concerned about the actual stability of the API?

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

This is a relatively new API that didn't exist when API stabilization doc was made (go/cel-api-stabilization). It's stable now (I'll update the doc when I get a chance). Reason why I suggested this API is that it follows the recommended pattern for how environment subsetting is supposed to be done across all CEL stacks.

As for EP -- I'm surprised it's actually flagging this (internally, it doesn't). AddOperator enum implements CelStandardOverload, so they should equal. My only guess is that CelStandardOverload is a functional interface, so theoretically it's possible to provide a lambda that's not equals comparable. Though we control the standard overload implementations, so in practice this won't happen. Checking for reference identity should likely get around the issue over == AddOverload.ADD_STRING

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Oh, I see, this is the new setup flow. I didn't look where this FUNCTIONS constant was used. That's fine; I'm less surprised that changed. (And yes, it's good to add it to the doc.)

I'm surprised it's actually flagging this (internally, it doesn't)

I don't think it'd get flagged on master either. It only looked to be a problem because we're still using 0.11.1; in 0.11.1 I agree with ErrorProne that the equals() will always return false.

import javax.annotation.Nullable;

/**
* Interface for extracting values from a match context (e.g. HTTP headers).

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This says explicitly "from a match context", and the only two implementations use MatchContext, so why is T present? Shouldn't this just have an argument that is MatchContext?

return result.actions;
}

public interface MatchContext {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Nothing implements this. Is this still TODO? There's no mention this is missing in the PR description.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

grfc says:

Matcher Context: The input to the Matcher evaluation tree. Provided at runtime by the filter, contains the input data.

MatchContext is the representation of the "Matcher Context" described in gRFC. It is currently an empty shell (no implementations in this PR) because it is designed to be implemented by the specific xDS filters (e.g., RLQS or Composite Filter) that will be the primary consumers of this matching logic, as noted in the gRFC's Implementation section

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

The implementation section saying "as part of" is saying "it will be part of that effort." We aren't saying CEL will be part of RLQS and the Composite Filter will call the RLQS code if RLQS was implemented first.

I think the filter will construct the Matcher Context and provide its contents, but I don't think each filter will have its own implementation, or at least an implementation from scratch. Headers will be Metadata, Method is always POST, Path will be pulled from MethodDescriptor, etc. I could understand if there was a server-side vs client-side implementation, but even that doesn't seem likely; worst-case looks to be different factory methods as convenience.

/**
* Represents a compiled xDS Matcher.
*/
public abstract class UnifiedMatcher {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

How do we have enough information to satisfy:

If set, the return type of the input must match the input type
of the matcher.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I see now. UnifiedMatcher has input+matcher combined together, so there's no need to check types when using it. But I think I got confused because there is not Matcher API. There should be a matcher API; in no way do we want to hard-code each matcher type.

final class OnMatch {
@Nullable private final UnifiedMatcher nestedMatcher;
@Nullable private final TypedExtensionConfig action;
final boolean keepMatching;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Overall, it seems like keepMatching is incomplete (beyond this one instance). But that's not mentioned in the PR description. What is the current status of keepMatching?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

In MatcherList: keep_matching is used to continue the loop and accumulate actions.

In MatcherTree (Prefix): It is also implemented for traversing the trie/list of prefixes. Check line 133 in MatcherTree (if (!onMatch.keepMatching))

In MatcherTree (Exact): If a key matches, it returns immediately without checking if it should "keep matching" because thats the only logical way it seems. Should it fall back to on_no_match?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

keepMatching here is literally not used. Clearly that is wrong. Note that I'm most bothered that there's no TODO or mention in the PR description. There's nothing that calls out "this didn't make sense" or "this was not possible" for us to work through.

It seems you're missing the fact keep_matching means multiple completely different matchers can contribute to the result. You need to accumulate keep_matching results across matchers.

This is probably more clear after reading my comments at https://github.com/grpc/proposal/pull/520/changes#r2683391713 . Basically, the most important thing to understand about keep_matching is that it is a semantically different result. You shouldn't semantically mix the results between a terminal result with those of keep_matching; they aren't interchangeable (if C++ wants to and have an encoding for them to determine which results are what, they are free to, but I don't want the security vulnerability risk). We should either use a callback or a separate list in the result (MatchResult {TypedExecutionConfig action; List<TypedExecutionConfig> keepMatchingActions; }, where action == null means matched == false, or use Optional<TypedExecutionConfig> to track it)

try {
com.github.xds.type.matcher.v3.CelMatcher celProto = customConfig.getTypedConfig()
.unpack(com.github.xds.type.matcher.v3.CelMatcher.class);
if (celProto.hasExprMatch()) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Invert this condition so that we can more easily see what exception is matched with with if and also can get rid of the else. Ditto elsewhere in this class.

Comment thread xds/src/test/java/io/grpc/xds/internal/matcher/UnifiedMatcherTest.java Outdated
Comment thread xds/src/main/java/io/grpc/xds/internal/matcher/PredicateEvaluator.java Outdated
Comment thread xds/src/main/java/io/grpc/xds/internal/matcher/PredicateEvaluator.java Outdated
* Returns the type of value extracted by this input.
*/
default Class<?> outputType() {
return Object.class;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This disables the check by default and it seems extremely doubtful any implementation would legitimately use Object. Delete the default implementation?

}

if (!input.outputType().isAssignableFrom(matcher.inputType())
&& !matcher.inputType().isAssignableFrom(input.outputType())) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

The only way for the input to be assignable from the output and the output to be assignable from the input is for it to be the same class. This is just a verbose equals() check.

And just using equals() sounds perfect. I don't think we need any complex object hierarchy stuff going on. We just need to make sure they match. Equals() is what I'd hope we use, as it is unlikely to be broken.

this.matcher = new Matcher() {
@Override
public boolean match(Object value) {
if (value instanceof String) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

If the input isn't compatible, this should throw. That is a programmer error, as the class said which type it can handle and that wasn't provided. That lets us find bugs. Note that silently ignoring a failure like that can be a security vulnerability. We need to be just as precise with match and non-match; we can't favor one way or the other, as we have no knowledge of what this matching implies.

}

@Override
public Object apply(MatchContext context) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

You can have this method return String even when the interface returns Object. That would help guarantee we don't accidentally return any other type.

@asheshvidyut asheshvidyut left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Reviewing for learning purposes.

Comment thread xds/src/main/java/io/grpc/xds/internal/matcher/CelCommon.java Outdated
Comment thread xds/src/main/java/io/grpc/xds/internal/matcher/CelMatcher.java Outdated
Comment thread xds/src/main/java/io/grpc/xds/internal/matcher/CelCommon.java
Comment thread xds/src/main/java/io/grpc/xds/internal/matcher/CelCommon.java
Comment thread xds/src/main/java/io/grpc/xds/internal/matcher/CelStateMatcher.java Outdated
Comment thread xds/src/main/java/io/grpc/xds/internal/matcher/MatchInputRegistry.java Outdated
Comment thread xds/src/main/java/io/grpc/xds/internal/matcher/OnMatch.java Outdated
Comment thread xds/src/main/java/io/grpc/xds/internal/matcher/OnMatch.java
Comment thread xds/src/main/java/io/grpc/xds/internal/matcher/PredicateEvaluator.java Outdated
@shivaspeaks shivaspeaks force-pushed the xds-unified-matcher-and-cel branch from 8515729 to f312c9c Compare June 8, 2026 09:35
@shivaspeaks shivaspeaks changed the title xds: Implementation of Unified Matcher and CEL Integration xds: Implementation of Unified Matcher Jun 11, 2026

/** Translate StringMatcher xDS proto to internal StringMatcher. */
public static Matchers.StringMatcher parseStringMatcher(
com.github.xds.type.matcher.v3.StringMatcher proto) {

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.

Do we need fully qualified names ?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I kept it intentionally because we have internal form of StringMatcher and this is the proto definition. Having different names didn't made sense, so we need to keep it like that. The other way could be to define a assign a variable with different name during import, but I chose to keep it as is because it's only three usages in the class in function definition and its fairly readable.

return Matchers.StringMatcher.forExact(proto.getExact(), proto.getIgnoreCase());
case PREFIX:
return Matchers.StringMatcher.forPrefix(
checkNonEmpty(proto.getPrefix(), "prefix"), proto.getIgnoreCase());

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.

Is this behaviour same in envoy(as in does it check for emptiness) ??

@shivaspeaks shivaspeaks Jun 19, 2026

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

same as xds*
Yes, check this https://github.com/cncf/xds/blob/main/xds/type/matcher/v3/string.proto

Envoy behavior is right above this function, already existing which has an argument io.envoyproxy.envoy.type.matcher.v3.StringMatcher.

@Override
public CelStateMatcher getMatcher(TypedExtensionConfig config) {
try {
com.github.xds.type.matcher.v3.CelMatcher celProto = config.getTypedConfig()

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.

Do we need fully qualified names here and elsewhere ??

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Same reason as above.

sb.append(",");
}
first = false;
sb.append(com.google.common.io.BaseEncoding.base64().encode(value));

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.

Can we cache this ??

}
try {
if (headerName.endsWith(Metadata.BINARY_HEADER_SUFFIX)) {
Metadata.Key.of(headerName, Metadata.BINARY_BYTE_MARSHALLER);

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.

cache Metadata.Key.of(headerName, Metadata.BINARY_BYTE_MARSHALLER) during construction ?

Comment on lines +260 to +263
// HeadersWrapper has 3 pseudo headers by default, so size is 3.
// We match size to force entrySet check.
CelMatcher celMatcher = createCelMatcher(
"request.headers == {'a':'1','b':'2','c':'3'}");

@AgraVator AgraVator Jun 15, 2026

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.

We have

@Override
  public int size() {
    int count = 0;
    for (String key : context.getMetadata().keys()) {
      String lowerKey = key.toLowerCase(java.util.Locale.ROOT);
      if (!lowerKey.equals("te") 
          && !lowerKey.equals("host") 
          && !PSEUDO_HEADERS.contains(lowerKey)
          && isMetadataKeyResolvable(lowerKey)) {
        count++;
      }
    }
    return count + PSEUDO_HEADERS.size() + 1; // +1 for "host" alias
  }

is 3 correct ??

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Should be 4. The test was passing because 4 != 3, CEL instantly evaluates the expression to false and because the expression is false, the matcher fall back to the no-match action.

@kannanjgithub kannanjgithub left a comment

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.

Reviewed source code, yet to review tests.

return MatchResult.create(result.action, accumulated);
}
} else {
if (!matcher.onMatch.keepMatching) {

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.

keepMatching is only meant to be used for successful match case, not for failed match case. In matcher list it should just move on to the next matcher in the list.

static final int MAX_RECURSION_DEPTH = 16;

@Nullable
public abstract MatchResult match(MatchContext context, int depth);

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.

All concrete subclasses of UnifiedMatcher (MatcherList, MatcherTree, and NoOpMatcher) are package-private, which prevents them from being constructed from outside the package, and checkRecursionDepth check already exists in UnifiedMatcher.fromProto. The depth argument here is redundant and the error condition during match evaluation is unreachable code.

Comment thread xds/src/main/java/io/grpc/xds/internal/matcher/MatcherTree.java
Comment on lines +83 to +84
this.exactMatchMap = null;
this.prefixTrie = null;

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.

Redundant assignments.

accumulated.add(result.action);
}
} else {
if (!match.keepMatching) {

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.

As mentioned in MatcherList, keepWatching should not be used for match fail case.
Same for the usage below in matchPrefix also.

Comment on lines +32 to +33
public final TypedExtensionConfig action;
public final List<TypedExtensionConfig> keepMatchingActions;

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.

Maintaining a separate field for action from keepMatchingActions is entirely redundant since when executing the actions it is going to execute them all. In all places we can just keep appending action to the front of the keepMatchingActions returned for the nested matchers in onMatch. We can also rename keepMatchingActions to just actions.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I don't remember exactly but there was a comment/line where it was mentioned that these should be segregated from a normal match with keep_matching=false.

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.

For matches with keep_matching=true the actions are collected, that is done in MatcherList and MatcherTree. Once collected, keep_matching has no relevance anymore. Nor is there any reason to keep the action separate from keepMatchingActions.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

This was the reason to keep these segregated: https://github.com/grpc/proposal/pull/520/changes#r2696490278

C core is doing like this as mentioned by Mark: https://github.com/grpc/proposal/pull/520/changes#r2696499658

@kannanjgithub kannanjgithub Jun 26, 2026

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.

In the discussion it goes against the segregation idea:

When we get a matching action, we append it to the list of matching actions to return. 

If the matcher returns true, then we know that the last entry in the list of returned actions is the one we should actually take, and any earlier entries in the list are the ones that matched but had keep_matching set to true. If the match returns false, then all actions in the list are the ones that matched but had keep_matching set to true.

This is the code implementing a single array for all actions in c-core.

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.

Also refer what MatcherRunner.java is doing. It is anyway merging the actions and returning it.

Comment on lines +113 to +116
case CONTAINS:
return Matchers.StringMatcher.forContains(
checkNonEmpty(proto.getContains(), "contains"), proto.getIgnoreCase());
case SAFE_REGEX:

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.

nit: Maintain same order as in the above method.

case SAFE_REGEX:
String regex = checkNonEmpty(proto.getSafeRegex().getRegex(), "regex");
return Matchers.StringMatcher.forSafeRegEx(Pattern.compile(regex));
default:

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.

Add case MATCHPATTERN_NOT_SET:

return matcher.match(input.apply(context));
}

private static Matchers.StringMatcher fromStringMatcherProto(

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.

Do we need a separate method for this?

*/

package io.grpc.xds.internal.matcher;

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.

It looks like this version of the file is from before we made all fields non-nullable.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Yes. Seems like, during merge conflicts it was left behind.

Comment on lines +32 to +33
public final TypedExtensionConfig action;
public final List<TypedExtensionConfig> keepMatchingActions;

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.

For matches with keep_matching=true the actions are collected, that is done in MatcherList and MatcherTree. Once collected, keep_matching has no relevance anymore. Nor is there any reason to keep the action separate from keepMatchingActions.

Comment on lines +173 to +175
// If we fall through, we only evaluate onNoMatch if there was at least one successful match
// with keepMatching=true. If no prefixes matched successfully, we return noMatch.
if (anySuccessfulMatch && onNoMatch != null) {

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 is the not the correct behavior to implement. For a successful match with keepMatching true only its action is accumulated, but the match should be considered false.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants