/proc/self/cwd/source/common/common/matchers.h
Line | Count | Source (jump to first uncovered line) |
1 | | #pragma once |
2 | | |
3 | | #include <string> |
4 | | |
5 | | #include "envoy/common/exception.h" |
6 | | #include "envoy/common/matchers.h" |
7 | | #include "envoy/common/regex.h" |
8 | | #include "envoy/config/core/v3/base.pb.h" |
9 | | #include "envoy/type/matcher/v3/filter_state.pb.h" |
10 | | #include "envoy/type/matcher/v3/metadata.pb.h" |
11 | | #include "envoy/type/matcher/v3/number.pb.h" |
12 | | #include "envoy/type/matcher/v3/path.pb.h" |
13 | | #include "envoy/type/matcher/v3/string.pb.h" |
14 | | #include "envoy/type/matcher/v3/value.pb.h" |
15 | | |
16 | | #include "source/common/common/regex.h" |
17 | | #include "source/common/common/utility.h" |
18 | | #include "source/common/protobuf/protobuf.h" |
19 | | |
20 | | #include "absl/strings/match.h" |
21 | | |
22 | | namespace Envoy { |
23 | | namespace Matchers { |
24 | | |
25 | | class ValueMatcher; |
26 | | using ValueMatcherConstSharedPtr = std::shared_ptr<const ValueMatcher>; |
27 | | |
28 | | class PathMatcher; |
29 | | using PathMatcherConstSharedPtr = std::shared_ptr<const PathMatcher>; |
30 | | |
31 | | class ValueMatcher { |
32 | | public: |
33 | 262k | virtual ~ValueMatcher() = default; |
34 | | |
35 | | /** |
36 | | * Check whether the value is matched to the matcher. |
37 | | */ |
38 | | virtual bool match(const ProtobufWkt::Value& value) const PURE; |
39 | | |
40 | | /** |
41 | | * Create the matcher object. |
42 | | */ |
43 | | static ValueMatcherConstSharedPtr create(const envoy::type::matcher::v3::ValueMatcher& value, |
44 | | Server::Configuration::CommonFactoryContext& context); |
45 | | }; |
46 | | |
47 | | class NullMatcher : public ValueMatcher { |
48 | | public: |
49 | | /** |
50 | | * Check whether the value is NULL. |
51 | | */ |
52 | | bool match(const ProtobufWkt::Value& value) const override; |
53 | | }; |
54 | | |
55 | | class BoolMatcher : public ValueMatcher { |
56 | | public: |
57 | 14.3k | BoolMatcher(bool matcher) : matcher_(matcher) {} |
58 | | |
59 | | bool match(const ProtobufWkt::Value& value) const override; |
60 | | |
61 | | private: |
62 | | const bool matcher_; |
63 | | }; |
64 | | |
65 | | class PresentMatcher : public ValueMatcher { |
66 | | public: |
67 | 19.5k | PresentMatcher(bool matcher) : matcher_(matcher) {} |
68 | | |
69 | | bool match(const ProtobufWkt::Value& value) const override; |
70 | | |
71 | | private: |
72 | | const bool matcher_; |
73 | | }; |
74 | | |
75 | | class DoubleMatcher : public ValueMatcher { |
76 | | public: |
77 | 3.62k | DoubleMatcher(const envoy::type::matcher::v3::DoubleMatcher& matcher) : matcher_(matcher) {} |
78 | | |
79 | | bool match(const ProtobufWkt::Value& value) const override; |
80 | | |
81 | | private: |
82 | | const envoy::type::matcher::v3::DoubleMatcher matcher_; |
83 | | }; |
84 | | |
85 | | class UniversalStringMatcher : public StringMatcher { |
86 | | public: |
87 | 66 | bool match(absl::string_view) const override { return true; } |
88 | | }; |
89 | | |
90 | | StringMatcherPtr getExtensionStringMatcher(const ::xds::core::v3::TypedExtensionConfig& config, |
91 | | Server::Configuration::CommonFactoryContext& context); |
92 | | |
93 | | template <class StringMatcherType = envoy::type::matcher::v3::StringMatcher> |
94 | | class StringMatcherImpl : public ValueMatcher, public StringMatcher { |
95 | | public: |
96 | | explicit StringMatcherImpl(const StringMatcherType& matcher, |
97 | | Server::Configuration::CommonFactoryContext& context) |
98 | 171k | : matcher_(matcher) { |
99 | 171k | if (matcher.match_pattern_case() == StringMatcherType::MatchPatternCase::kSafeRegex) { |
100 | 21.0k | if (matcher.ignore_case()) { |
101 | 89 | ExceptionUtil::throwEnvoyException("ignore_case has no effect for safe_regex."); |
102 | 89 | } |
103 | 21.0k | regex_ = Regex::Utility::parseRegex(matcher_.safe_regex(), context.regexEngine()); |
104 | 150k | } else if (matcher.match_pattern_case() == StringMatcherType::MatchPatternCase::kContains) { |
105 | 17.6k | if (matcher_.ignore_case()) { |
106 | | // Cache the lowercase conversion of the Contains matcher for future use |
107 | 6.00k | lowercase_contains_match_ = absl::AsciiStrToLower(matcher_.contains()); |
108 | 6.00k | } |
109 | 132k | } else if (matcher.has_custom()) { |
110 | 682 | custom_ = getExtensionStringMatcher(matcher.custom(), context); |
111 | 682 | } |
112 | 171k | } Envoy::Matchers::StringMatcherImpl<envoy::type::matcher::v3::StringMatcher>::StringMatcherImpl(envoy::type::matcher::v3::StringMatcher const&, Envoy::Server::Configuration::CommonFactoryContext&) Line | Count | Source | 98 | 159k | : matcher_(matcher) { | 99 | 159k | if (matcher.match_pattern_case() == StringMatcherType::MatchPatternCase::kSafeRegex) { | 100 | 20.8k | if (matcher.ignore_case()) { | 101 | 85 | ExceptionUtil::throwEnvoyException("ignore_case has no effect for safe_regex."); | 102 | 85 | } | 103 | 20.8k | regex_ = Regex::Utility::parseRegex(matcher_.safe_regex(), context.regexEngine()); | 104 | 138k | } else if (matcher.match_pattern_case() == StringMatcherType::MatchPatternCase::kContains) { | 105 | 15.3k | if (matcher_.ignore_case()) { | 106 | | // Cache the lowercase conversion of the Contains matcher for future use | 107 | 5.29k | lowercase_contains_match_ = absl::AsciiStrToLower(matcher_.contains()); | 108 | 5.29k | } | 109 | 123k | } else if (matcher.has_custom()) { | 110 | 650 | custom_ = getExtensionStringMatcher(matcher.custom(), context); | 111 | 650 | } | 112 | 159k | } |
Envoy::Matchers::StringMatcherImpl<xds::type::matcher::v3::StringMatcher>::StringMatcherImpl(xds::type::matcher::v3::StringMatcher const&, Envoy::Server::Configuration::CommonFactoryContext&) Line | Count | Source | 98 | 11.8k | : matcher_(matcher) { | 99 | 11.8k | if (matcher.match_pattern_case() == StringMatcherType::MatchPatternCase::kSafeRegex) { | 100 | 169 | if (matcher.ignore_case()) { | 101 | 4 | ExceptionUtil::throwEnvoyException("ignore_case has no effect for safe_regex."); | 102 | 4 | } | 103 | 169 | regex_ = Regex::Utility::parseRegex(matcher_.safe_regex(), context.regexEngine()); | 104 | 11.6k | } else if (matcher.match_pattern_case() == StringMatcherType::MatchPatternCase::kContains) { | 105 | 2.35k | if (matcher_.ignore_case()) { | 106 | | // Cache the lowercase conversion of the Contains matcher for future use | 107 | 708 | lowercase_contains_match_ = absl::AsciiStrToLower(matcher_.contains()); | 108 | 708 | } | 109 | 9.32k | } else if (matcher.has_custom()) { | 110 | 32 | custom_ = getExtensionStringMatcher(matcher.custom(), context); | 111 | 32 | } | 112 | 11.8k | } |
|
113 | | |
114 | | // StringMatcher |
115 | 128k | bool match(const absl::string_view value) const override { |
116 | 128k | switch (matcher_.match_pattern_case()) { |
117 | 60.8k | case StringMatcherType::MatchPatternCase::kExact: |
118 | 60.8k | return matcher_.ignore_case() ? absl::EqualsIgnoreCase(value, matcher_.exact()) |
119 | 60.8k | : value == matcher_.exact(); |
120 | 32.6k | case StringMatcherType::MatchPatternCase::kPrefix: |
121 | 32.6k | return matcher_.ignore_case() ? absl::StartsWithIgnoreCase(value, matcher_.prefix()) |
122 | 32.6k | : absl::StartsWith(value, matcher_.prefix()); |
123 | 8.64k | case StringMatcherType::MatchPatternCase::kSuffix: |
124 | 8.64k | return matcher_.ignore_case() ? absl::EndsWithIgnoreCase(value, matcher_.suffix()) |
125 | 8.64k | : absl::EndsWith(value, matcher_.suffix()); |
126 | 18.3k | case StringMatcherType::MatchPatternCase::kContains: |
127 | 18.3k | return matcher_.ignore_case() |
128 | 18.3k | ? absl::StrContains(absl::AsciiStrToLower(value), lowercase_contains_match_) |
129 | 18.3k | : absl::StrContains(value, matcher_.contains()); |
130 | 7.97k | case StringMatcherType::MatchPatternCase::kSafeRegex: |
131 | 7.97k | return regex_->match(value); |
132 | 0 | case StringMatcherType::MatchPatternCase::kCustom: |
133 | 0 | return custom_->match(value); |
134 | 0 | default: |
135 | 0 | PANIC("unexpected"); |
136 | 128k | } |
137 | 128k | } Envoy::Matchers::StringMatcherImpl<envoy::type::matcher::v3::StringMatcher>::match(std::__1::basic_string_view<char, std::__1::char_traits<char> >) const Line | Count | Source | 115 | 123k | bool match(const absl::string_view value) const override { | 116 | 123k | switch (matcher_.match_pattern_case()) { | 117 | 58.5k | case StringMatcherType::MatchPatternCase::kExact: | 118 | 58.5k | return matcher_.ignore_case() ? absl::EqualsIgnoreCase(value, matcher_.exact()) | 119 | 58.5k | : value == matcher_.exact(); | 120 | 31.8k | case StringMatcherType::MatchPatternCase::kPrefix: | 121 | 31.8k | return matcher_.ignore_case() ? absl::StartsWithIgnoreCase(value, matcher_.prefix()) | 122 | 31.8k | : absl::StartsWith(value, matcher_.prefix()); | 123 | 7.87k | case StringMatcherType::MatchPatternCase::kSuffix: | 124 | 7.87k | return matcher_.ignore_case() ? absl::EndsWithIgnoreCase(value, matcher_.suffix()) | 125 | 7.87k | : absl::EndsWith(value, matcher_.suffix()); | 126 | 17.0k | case StringMatcherType::MatchPatternCase::kContains: | 127 | 17.0k | return matcher_.ignore_case() | 128 | 17.0k | ? absl::StrContains(absl::AsciiStrToLower(value), lowercase_contains_match_) | 129 | 17.0k | : absl::StrContains(value, matcher_.contains()); | 130 | 7.94k | case StringMatcherType::MatchPatternCase::kSafeRegex: | 131 | 7.94k | return regex_->match(value); | 132 | 0 | case StringMatcherType::MatchPatternCase::kCustom: | 133 | 0 | return custom_->match(value); | 134 | 0 | default: | 135 | 0 | PANIC("unexpected"); | 136 | 123k | } | 137 | 123k | } |
Envoy::Matchers::StringMatcherImpl<xds::type::matcher::v3::StringMatcher>::match(std::__1::basic_string_view<char, std::__1::char_traits<char> >) const Line | Count | Source | 115 | 5.25k | bool match(const absl::string_view value) const override { | 116 | 5.25k | switch (matcher_.match_pattern_case()) { | 117 | 2.29k | case StringMatcherType::MatchPatternCase::kExact: | 118 | 2.29k | return matcher_.ignore_case() ? absl::EqualsIgnoreCase(value, matcher_.exact()) | 119 | 2.29k | : value == matcher_.exact(); | 120 | 891 | case StringMatcherType::MatchPatternCase::kPrefix: | 121 | 891 | return matcher_.ignore_case() ? absl::StartsWithIgnoreCase(value, matcher_.prefix()) | 122 | 891 | : absl::StartsWith(value, matcher_.prefix()); | 123 | 766 | case StringMatcherType::MatchPatternCase::kSuffix: | 124 | 766 | return matcher_.ignore_case() ? absl::EndsWithIgnoreCase(value, matcher_.suffix()) | 125 | 766 | : absl::EndsWith(value, matcher_.suffix()); | 126 | 1.27k | case StringMatcherType::MatchPatternCase::kContains: | 127 | 1.27k | return matcher_.ignore_case() | 128 | 1.27k | ? absl::StrContains(absl::AsciiStrToLower(value), lowercase_contains_match_) | 129 | 1.27k | : absl::StrContains(value, matcher_.contains()); | 130 | 30 | case StringMatcherType::MatchPatternCase::kSafeRegex: | 131 | 30 | return regex_->match(value); | 132 | 0 | case StringMatcherType::MatchPatternCase::kCustom: | 133 | 0 | return custom_->match(value); | 134 | 0 | default: | 135 | 0 | PANIC("unexpected"); | 136 | 5.25k | } | 137 | 5.25k | } |
|
138 | | |
139 | 7.38k | bool match(const ProtobufWkt::Value& value) const override { |
140 | | |
141 | 7.38k | if (value.kind_case() != ProtobufWkt::Value::kStringValue) { |
142 | 6.21k | return false; |
143 | 6.21k | } |
144 | | |
145 | 1.17k | return match(value.string_value()); |
146 | 7.38k | } Envoy::Matchers::StringMatcherImpl<envoy::type::matcher::v3::StringMatcher>::match(google::protobuf::Value const&) const Line | Count | Source | 139 | 7.38k | bool match(const ProtobufWkt::Value& value) const override { | 140 | | | 141 | 7.38k | if (value.kind_case() != ProtobufWkt::Value::kStringValue) { | 142 | 6.21k | return false; | 143 | 6.21k | } | 144 | | | 145 | 1.17k | return match(value.string_value()); | 146 | 7.38k | } |
Unexecuted instantiation: Envoy::Matchers::StringMatcherImpl<xds::type::matcher::v3::StringMatcher>::match(google::protobuf::Value const&) const |
147 | | |
148 | 1.17k | const StringMatcherType& matcher() const { return matcher_; } |
149 | | |
150 | | /** |
151 | | * Helps applications optimize the case where a matcher is a case-sensitive |
152 | | * prefix-match. |
153 | | * |
154 | | * @param prefix the returned prefix string |
155 | | * @return true if the matcher is a case-sensitive prefix-match. |
156 | | */ |
157 | 8.83k | bool getCaseSensitivePrefixMatch(std::string& prefix) const { |
158 | 8.83k | if (matcher_.match_pattern_case() == |
159 | 8.83k | envoy::type::matcher::v3::StringMatcher::MatchPatternCase::kPrefix && |
160 | 8.83k | !matcher_.ignore_case()) { |
161 | 4.65k | prefix = matcher_.prefix(); |
162 | 4.65k | return true; |
163 | 4.65k | } |
164 | 4.18k | return false; |
165 | 8.83k | } |
166 | | |
167 | | private: |
168 | | const StringMatcherType matcher_; |
169 | | Regex::CompiledMatcherPtr regex_; |
170 | | std::string lowercase_contains_match_; |
171 | | StringMatcherPtr custom_; |
172 | | }; |
173 | | |
174 | | class StringMatcherExtensionFactory : public Config::TypedFactory { |
175 | | public: |
176 | | virtual StringMatcherPtr |
177 | | createStringMatcher(const Protobuf::Message& config, |
178 | | Server::Configuration::CommonFactoryContext& context) PURE; |
179 | | |
180 | 8 | std::string category() const override { return "envoy.string_matcher"; } |
181 | | }; |
182 | | |
183 | | class ListMatcher : public ValueMatcher { |
184 | | public: |
185 | | ListMatcher(const envoy::type::matcher::v3::ListMatcher& matcher, |
186 | | Server::Configuration::CommonFactoryContext& context); |
187 | | |
188 | | bool match(const ProtobufWkt::Value& value) const override; |
189 | | |
190 | | private: |
191 | | const envoy::type::matcher::v3::ListMatcher matcher_; |
192 | | |
193 | | ValueMatcherConstSharedPtr oneof_value_matcher_; |
194 | | }; |
195 | | |
196 | | class OrMatcher : public ValueMatcher { |
197 | | public: |
198 | | OrMatcher(const envoy::type::matcher::v3::OrMatcher& matcher, |
199 | | Server::Configuration::CommonFactoryContext& context); |
200 | | |
201 | | bool match(const ProtobufWkt::Value& value) const override; |
202 | | |
203 | | private: |
204 | | std::vector<ValueMatcherConstSharedPtr> or_matchers_; |
205 | | }; |
206 | | |
207 | | class MetadataMatcher { |
208 | | public: |
209 | | MetadataMatcher(const envoy::type::matcher::v3::MetadataMatcher& matcher, |
210 | | Server::Configuration::CommonFactoryContext& context); |
211 | | |
212 | | /** |
213 | | * Check whether the metadata is matched to the matcher. |
214 | | * @param metadata the metadata to check. |
215 | | * @return true if it's matched otherwise false. |
216 | | */ |
217 | | bool match(const envoy::config::core::v3::Metadata& metadata) const; |
218 | | |
219 | | private: |
220 | | const envoy::type::matcher::v3::MetadataMatcher matcher_; |
221 | | std::vector<std::string> path_; |
222 | | |
223 | | ValueMatcherConstSharedPtr value_matcher_; |
224 | | }; |
225 | | |
226 | | class FilterStateMatcher { |
227 | | public: |
228 | | FilterStateMatcher(const envoy::type::matcher::v3::FilterStateMatcher& matcher, |
229 | | Server::Configuration::CommonFactoryContext& context); |
230 | | |
231 | | /** |
232 | | * Check whether the filter state object is matched to the matcher. |
233 | | * @param filter state to check. |
234 | | * @return true if it's matched otherwise false. |
235 | | */ |
236 | | bool match(const StreamInfo::FilterState& filter_state) const; |
237 | | |
238 | | private: |
239 | | const std::string key_; |
240 | | const StringMatcherPtr value_matcher_; |
241 | | }; |
242 | | |
243 | | class PathMatcher : public StringMatcher { |
244 | | public: |
245 | | PathMatcher(const envoy::type::matcher::v3::PathMatcher& path, |
246 | | Server::Configuration::CommonFactoryContext& context) |
247 | 7.00k | : matcher_(path.path(), context) {} |
248 | | PathMatcher(const envoy::type::matcher::v3::StringMatcher& matcher, |
249 | | Server::Configuration::CommonFactoryContext& context) |
250 | 53.7k | : matcher_(matcher, context) {} |
251 | | |
252 | | static PathMatcherConstSharedPtr |
253 | | createExact(const std::string& exact, bool ignore_case, |
254 | | Server::Configuration::CommonFactoryContext& context); |
255 | | static PathMatcherConstSharedPtr |
256 | | createPrefix(const std::string& prefix, bool ignore_case, |
257 | | Server::Configuration::CommonFactoryContext& context); |
258 | | static PathMatcherConstSharedPtr |
259 | | createPattern(const std::string& pattern, bool ignore_case, |
260 | | Server::Configuration::CommonFactoryContext& context); |
261 | | static PathMatcherConstSharedPtr |
262 | | createSafeRegex(const envoy::type::matcher::v3::RegexMatcher& regex_matcher, |
263 | | Server::Configuration::CommonFactoryContext& context); |
264 | | |
265 | | bool match(const absl::string_view path) const override; |
266 | 1.17k | const StringMatcherImpl<envoy::type::matcher::v3::StringMatcher>& matcher() const { |
267 | 1.17k | return matcher_; |
268 | 1.17k | } |
269 | | |
270 | | private: |
271 | | const StringMatcherImpl<envoy::type::matcher::v3::StringMatcher> matcher_; |
272 | | }; |
273 | | |
274 | | } // namespace Matchers |
275 | | } // namespace Envoy |