1 /* 2 * Copyright 2021 The gRPC Authors 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package io.grpc.xds.internal; 18 19 import com.google.re2j.Pattern; 20 import com.google.re2j.PatternSyntaxException; 21 22 // TODO(zivy@): may reuse common matchers parsers. 23 public final class MatcherParser { 24 /** Translates envoy proto HeaderMatcher to internal HeaderMatcher.*/ parseHeaderMatcher( io.envoyproxy.envoy.config.route.v3.HeaderMatcher proto)25 public static Matchers.HeaderMatcher parseHeaderMatcher( 26 io.envoyproxy.envoy.config.route.v3.HeaderMatcher proto) { 27 switch (proto.getHeaderMatchSpecifierCase()) { 28 case EXACT_MATCH: 29 return Matchers.HeaderMatcher.forExactValue( 30 proto.getName(), proto.getExactMatch(), proto.getInvertMatch()); 31 case SAFE_REGEX_MATCH: 32 String rawPattern = proto.getSafeRegexMatch().getRegex(); 33 Pattern safeRegExMatch; 34 try { 35 safeRegExMatch = Pattern.compile(rawPattern); 36 } catch (PatternSyntaxException e) { 37 throw new IllegalArgumentException( 38 "HeaderMatcher [" + proto.getName() + "] contains malformed safe regex pattern: " 39 + e.getMessage()); 40 } 41 return Matchers.HeaderMatcher.forSafeRegEx( 42 proto.getName(), safeRegExMatch, proto.getInvertMatch()); 43 case RANGE_MATCH: 44 Matchers.HeaderMatcher.Range rangeMatch = Matchers.HeaderMatcher.Range.create( 45 proto.getRangeMatch().getStart(), proto.getRangeMatch().getEnd()); 46 return Matchers.HeaderMatcher.forRange( 47 proto.getName(), rangeMatch, proto.getInvertMatch()); 48 case PRESENT_MATCH: 49 return Matchers.HeaderMatcher.forPresent( 50 proto.getName(), proto.getPresentMatch(), proto.getInvertMatch()); 51 case PREFIX_MATCH: 52 return Matchers.HeaderMatcher.forPrefix( 53 proto.getName(), proto.getPrefixMatch(), proto.getInvertMatch()); 54 case SUFFIX_MATCH: 55 return Matchers.HeaderMatcher.forSuffix( 56 proto.getName(), proto.getSuffixMatch(), proto.getInvertMatch()); 57 case CONTAINS_MATCH: 58 return Matchers.HeaderMatcher.forContains( 59 proto.getName(), proto.getContainsMatch(), proto.getInvertMatch()); 60 case STRING_MATCH: 61 return Matchers.HeaderMatcher.forString( 62 proto.getName(), parseStringMatcher(proto.getStringMatch()), proto.getInvertMatch()); 63 case HEADERMATCHSPECIFIER_NOT_SET: 64 default: 65 throw new IllegalArgumentException( 66 "Unknown header matcher type: " + proto.getHeaderMatchSpecifierCase()); 67 } 68 } 69 70 /** Translate StringMatcher envoy proto to internal StringMatcher. */ parseStringMatcher( io.envoyproxy.envoy.type.matcher.v3.StringMatcher proto)71 public static Matchers.StringMatcher parseStringMatcher( 72 io.envoyproxy.envoy.type.matcher.v3.StringMatcher proto) { 73 switch (proto.getMatchPatternCase()) { 74 case EXACT: 75 return Matchers.StringMatcher.forExact(proto.getExact(), proto.getIgnoreCase()); 76 case PREFIX: 77 return Matchers.StringMatcher.forPrefix(proto.getPrefix(), proto.getIgnoreCase()); 78 case SUFFIX: 79 return Matchers.StringMatcher.forSuffix(proto.getSuffix(), proto.getIgnoreCase()); 80 case SAFE_REGEX: 81 return Matchers.StringMatcher.forSafeRegEx( 82 Pattern.compile(proto.getSafeRegex().getRegex())); 83 case CONTAINS: 84 return Matchers.StringMatcher.forContains(proto.getContains()); 85 case MATCHPATTERN_NOT_SET: 86 default: 87 throw new IllegalArgumentException( 88 "Unknown StringMatcher match pattern: " + proto.getMatchPatternCase()); 89 } 90 } 91 } 92