Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

router: integrate matching API #17633

Merged
merged 55 commits into from
Oct 13, 2021
Merged
Show file tree
Hide file tree
Changes from 44 commits
Commits
Show all changes
55 commits
Select commit Hold shift + click to select a range
12ea8c9
alpha matching: support generic action factory context
snowp Jun 17, 2021
44e162b
fix build
snowp Jun 18, 2021
7c35634
fix more tests
snowp Jun 18, 2021
0586cb1
router: poc of integration match api
snowp Jun 18, 2021
50fe3e8
api: move generic matcher proto to its own package
snowp Jun 23, 2021
81aa2bc
deprecation note
snowp Jun 23, 2021
7ff4d44
Merge remote-tracking branch 'envoy/main' into move-generic-matcher
snowp Jul 7, 2021
7acbde0
add new file, make factory generic, add test
snowp Jul 7, 2021
98100c7
fix docs
snowp Jul 7, 2021
fd00924
add alpha exception
snowp Jul 7, 2021
28bf418
fix examples
snowp Jul 9, 2021
f4a6292
Merge branch 'main' of github.com:envoyproxy/envoy into move-generic-…
snowp Jul 9, 2021
a4b752b
use udpa version
snowp Jul 9, 2021
41f07e4
fix examples
snowp Jul 9, 2021
ba371e8
update versioning
snowp Jul 9, 2021
0fb80ba
format
snowp Jul 14, 2021
9d24e1f
update to use xds namespaced protos
snowp Jul 14, 2021
f6d9af7
fix docs
snowp Jul 14, 2021
da0454b
Merge branch 'main' of github.com:envoyproxy/envoy into move-generic-…
snowp Jul 14, 2021
02dc3f0
use xds latest main
snowp Jul 26, 2021
853a1bd
use xds main
snowp Jul 26, 2021
54079e5
Merge remote-tracking branch 'envoy/main' into move-generic-matcher
snowp Jul 26, 2021
7863b17
fix release date
snowp Jul 26, 2021
4ebb008
fix more stringmatcherimpl ctors
snowp Jul 27, 2021
09c782e
Merge remote-tracking branch 'envoy/main' into move-generic-matcher
snowp Jul 27, 2021
199a8b1
more fixes
snowp Jul 30, 2021
73e1848
more build fixes
snowp Aug 5, 2021
4c9f5e6
cleanups, fix composite example
snowp Aug 5, 2021
aae8d46
Merge branch 'move-generic-matcher' into router-matcher-poc
snowp Aug 5, 2021
2381d38
Merge remote-tracking branch 'envoy/main' into router-matcher-poc
snowp Aug 9, 2021
6e5177e
fix merges, start docs
snowp Aug 9, 2021
0071dc8
clean up
snowp Aug 9, 2021
2de2fa8
comments
snowp Aug 9, 2021
fe81ce1
update comments
snowp Aug 9, 2021
90d687f
doc updates
snowp Aug 9, 2021
90e2332
revert stuff from bad merge
snowp Aug 9, 2021
921dcdd
wip
snowp Aug 23, 2021
6863442
evaluate matched route in order to support path rewriting
snowp Aug 29, 2021
0704e32
Merge remote-tracking branch 'envoy/main' into router-matcher-poc
snowp Aug 31, 2021
f75e539
fix docs
snowp Aug 31, 2021
9eedbd5
remove trailing whitespace
snowp Aug 31, 2021
b31ef7a
remove merge marker
snowp Sep 1, 2021
2c2be12
integration test, runtime flag
snowp Sep 2, 2021
082376d
remove trailing whitespace
snowp Sep 2, 2021
c3149c4
wip
snowp Sep 22, 2021
82a5fdd
validate data input
snowp Sep 29, 2021
269954c
format
snowp Sep 29, 2021
8083421
Merge remote-tracking branch 'envoy/main' into router-matcher-poc
snowp Sep 29, 2021
418a270
use wip instead of alpha
snowp Sep 29, 2021
9d72842
Merge remote-tracking branch 'envoy/main' into router-matcher-poc
snowp Oct 4, 2021
694d945
Merge remote-tracking branch 'origin/main' into router-matcher-poc
snowp Oct 8, 2021
50080bd
improve coverage
snowp Oct 9, 2021
a95c67c
format
snowp Oct 9, 2021
1d16eba
improve coverage
snowp Oct 11, 2021
71c4c5a
remove runtime flag
snowp Oct 12, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions api/envoy/config/route/v3/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,6 @@ api_proto_package(
"//envoy/type/tracing/v3:pkg",
"//envoy/type/v3:pkg",
"@com_github_cncf_udpa//udpa/annotations:pkg",
"@com_github_cncf_udpa//xds/type/matcher/v3:pkg",
],
)
14 changes: 13 additions & 1 deletion api/envoy/config/route/v3/route_components.proto
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ import "google/protobuf/any.proto";
import "google/protobuf/duration.proto";
import "google/protobuf/wrappers.proto";

import "xds/type/matcher/v3/matcher.proto";

import "envoy/annotations/deprecation.proto";
import "udpa/annotations/migrate.proto";
import "udpa/annotations/status.proto";
Expand All @@ -37,7 +39,7 @@ option (udpa.annotations.file_status).package_version_status = ACTIVE;
// host header. This allows a single listener to service multiple top level domain path trees. Once
// a virtual host is selected based on the domain, the routes are processed in order to see which
// upstream cluster to route to or whether to perform a redirect.
// [#next-free-field: 21]
// [#next-free-field: 22]
message VirtualHost {
option (udpa.annotations.versioning).previous_message_type = "envoy.api.v2.route.VirtualHost";

Expand Down Expand Up @@ -87,8 +89,18 @@ message VirtualHost {

// The list of routes that will be matched, in order, for incoming requests.
// The first route that matches will be used.
// Only one of this and `matcher` can be specified.
repeated Route routes = 3;

// [#next-major-version: This should be included in a oneof with routes wrapped in a message.]
// The match tree to use when resolving route actions for incoming requests. Only one of this and `routes`
// can be specified.
//
// Note that this API is experimental and must be explicitly enabled by setting the runtime
// "envoy.reloadable_features.experimental_matching_api" to "true".
// [#alpha:]
xds.type.matcher.v3.Matcher matcher = 21;

// Specifies the type of TLS enforcement the virtual host expects. If this option is not
// specified, there is no TLS requirement for the virtual host.
TlsRequirementType require_tls = 4 [(validate.rules).enum = {defined_only: true}];
Expand Down
18 changes: 14 additions & 4 deletions docs/root/intro/arch_overview/advanced/matching/matching_api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ better performance than the linear list matching as seen in Envoy's HTTP routing
use of extension points to make it easy to extend to different inputs based on protocol or
environment data as well as custom sublinear matchers and direct matchers.

Filter Integration
##################

Within supported environments (currently only HTTP filters), a wrapper proto can be used to
instantiate a matching filter associated with the wrapped structure:

Expand All @@ -28,7 +31,7 @@ The above example wraps a HTTP filter (the
allowing us to define a match tree to be evaluated in conjunction with evaluation of the wrapped
filter. Prior to data being made available to the filter, it will be provided to the match tree,
which will then attempt to evaluate the matching rules with the provided data, triggering an
action if match evaluation completes in an action.
action if match evaluation results in an action.

In the above example, we are specifying that we want to match on the incoming request header
``some-header`` by setting the ``input`` to
Expand All @@ -54,7 +57,7 @@ the filter if ``some-header: skip_filter`` is present and ``second-header`` is s
.. _arch_overview_matching_api_iteration_impact:

HTTP Filter Iteration Impact
============================
****************************

The above example only demonstrates matching on request headers, which ends up being the simplest
case due to it happening before the associated filter receives any data. Matching on other HTTP
Expand All @@ -80,8 +83,15 @@ client will receive an invalid response back from Envoy. If the skip action was
trailers, the same gRPC-Web filter would consume all the data but never write it back out (as this
happens when it sees the trailers), resulting in a gRPC-Web response with an empty body.

HTTP Routing Integration
########################

The matching API can be used with HTTP routing, by specifying a match tree as part of the virtual host
and specifying a Route as the resulting action. See examples in the above sections for how the match
tree can be configured.

Match Tree Validation
=====================
#####################

As the match tree structure is very flexible, some filters might need to impose additional restrictions
on what kind of match trees can be used. This system is somewhat inflexible at the moment, only supporting
Expand All @@ -91,7 +101,7 @@ will fail during configuration load, reporting back which data input was invalid

This is done for example to limit the issues talked about in
:ref:`the above section <arch_overview_matching_api_iteration_impact>` or to help users understand in what
context a match tree can be used for a specific filter. Due to the limitations of the validations framework
context a match tree can be used for a specific filter. Due to the limitations of the validation framework
at the current time, it is not used for all filters.

For HTTP filters, the restrictions are specified by the filter implementation, so consult the individual
Expand Down
60 changes: 60 additions & 0 deletions docs/root/intro/arch_overview/http/http_routing.rst
Original file line number Diff line number Diff line change
Expand Up @@ -192,3 +192,63 @@ upon configuration load and cache the contents.

If **response_headers_to_add** has been set for the Route or the enclosing Virtual Host,
Envoy will include the specified headers in the direct HTTP response.

Routing Via Generic Matching
----------------------------

Envoy recently added support for utilzing a :ref:`generic match tree <arch_overview_matching_api>` to
specify the route table. This is a more expressive matching engine than the original one, allowing
for sublinear matching on arbitrary headers (unlike the original matching engine which could only
do this for :authority in some cases).

To use the generic matching tree, specify a matcher on a virtual host with a RouteAction action:

.. code-block:: yaml

matcher:
"@type": type.googleapis.com/xds.type.matcher.v3.Matcher
matcher_tree:
input:
name: request-headers
typed_config:
"@type": type.googleapis.com/envoy.type.matcher.v3.HttpRequestHeaderMatchInput
header_name: :path
exact_match_map:
map:
"/new_endpoint/foo":
action:
name: route
typed_config:
"@type": type.googleapis.com/envoy.config.route.v3.Route
Copy link
Member

Choose a reason for hiding this comment

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

Broadly agree this structure looks great. One observation I have is that making Route the action, rather than RouteAction the action is a bit unfortunate, since we have a RouteMatcher inside of this Route. Ideally it would just be RouteAction, but these days we have a bunch of stuff such as per-route filter config, response headers to add etc. at this level (since shared with other actions). The idea of splitting match-action has kind of fallen apart (we were shooting for that in the v2 xDS RDS structure).

So, what is here is fine. Maybe you could actually run the RouteMatcher on the Route you resolve to after the Matcher match, to be able to support things like path rewrite. It's a bit redundant, but it also is O(1) and might only need to be done when you need the match criteria.

Copy link
Contributor

Choose a reason for hiding this comment

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

I agree that using Route here seems a little counter-intuitive, but I also agree that it's totally workable.

Another option would be to copy the common route fields into a CommonRouteConfig message, and then have each of the action types (RouteAction, RedirectAction, et al) include a field of type CommonRouteConfig. That might be a little more in the spirit of the generic matching API, where the matching action really ought to be the route action.

match:
prefix: /
route:
cluster: cluster_foo
request_headers_to_add:
- header:
key: x-route-header
value: new-value
"/new_endpoint/bar":
action:
name: route
typed_config:
"@type": type.googleapis.com/envoy.config.route.v3.Route
match:
prefix: /
route:
cluster: cluster_bar
request_headers_to_add:
- header:
key: x-route-header
value: new-value

This allows resolving the same Route proto message used for the `routes`-based routing using the additional
matching flexibility provided by the generic matching framework.

Note that the resulting Route also specifies a match criteria. This must be satisfied in addition to resolving
the route in order to achieve a route match. When path rewrites are used, the matched path will only depend on
the match criteria of the resolved Route. Path matching done during the match tree traversal does not contribute
to path rewrites.

The only inputs supported are request headers (via `envoy.type.matcher.v3.HttpRequestHeaderMatchInput`). See
Copy link
Member

Choose a reason for hiding this comment

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

Where is this validated and what error message does the user get if they configure something else accidentally?

Same question about the action config which I guess will only currently work for route proto lookup?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Seems like this was not validated, now we are with the following error message:

requirement violation while creating route match tree: INVALID_ARGUMENT: Route table can only match on request headers, saw type.googleapis.com/envoy.type.matcher.v3.HttpResponseHeaderMatchInput

For action configs the only registered factory for ActionFactory<RouteActionContext> is RouteMatchActionFactory, so all others would result in the typical "no factory found"

the docs for the :ref:`matching API <arch_overview_matching_api>` for more information about the API as a whole.
1 change: 1 addition & 0 deletions generated_api_shadow/envoy/config/route/v3/BUILD

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions source/common/matcher/matcher.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,9 +72,9 @@ template <class DataType> using DataInputFactoryCb = std::function<DataInputPtr<
template <class DataType, class ActionFactoryContext> class MatchTreeFactory {
public:
MatchTreeFactory(ActionFactoryContext& context,
Server::Configuration::ServerFactoryContext& server_factory_context,
Server::Configuration::ServerFactoryContext& factory_context,
MatchTreeValidationVisitor<DataType>& validation_visitor)
: action_factory_context_(context), server_factory_context_(server_factory_context),
: action_factory_context_(context), server_factory_context_(factory_context),
validation_visitor_(validation_visitor) {}

// TODO(snowp): Remove this type parameter once we only have one Matcher proto.
Expand Down
3 changes: 3 additions & 0 deletions source/common/router/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -61,9 +61,12 @@ envoy_cc_library(
"//source/common/http:headers_lib",
"//source/common/http:path_utility_lib",
"//source/common/http:utility_lib",
"//source/common/http/matching:data_impl_lib",
"//source/common/matcher:matcher_lib",
"//source/common/protobuf:utility_lib",
"//source/common/tracing:http_tracer_lib",
"//source/extensions/filters/http/common:utility_lib",
"@envoy_api//envoy/config/common/matcher/v3:pkg_cc_proto",
"@envoy_api//envoy/config/core/v3:pkg_cc_proto",
"@envoy_api//envoy/config/route/v3:pkg_cc_proto",
"@envoy_api//envoy/type/matcher/v3:pkg_cc_proto",
Expand Down
Loading