xref: /aosp_15_r20/external/grpc-grpc/src/proto/grpc/testing/xds/v3/route.proto (revision cc02d7e222339f7a4f6ba5f422e6413f4bd931f2)
1// Copyright 2020 The gRPC Authors
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15// Local copy of Envoy xDS proto file, used for testing only.
16
17syntax = "proto3";
18
19package envoy.config.route.v3;
20
21import "src/proto/grpc/testing/xds/v3/base.proto";
22import "src/proto/grpc/testing/xds/v3/extension.proto";
23import "src/proto/grpc/testing/xds/v3/regex.proto";
24import "src/proto/grpc/testing/xds/v3/string.proto";
25import "src/proto/grpc/testing/xds/v3/percent.proto";
26import "src/proto/grpc/testing/xds/v3/range.proto";
27
28import "google/protobuf/any.proto";
29import "google/protobuf/duration.proto";
30import "google/protobuf/wrappers.proto";
31
32// [#protodoc-title: HTTP route components]
33// * Routing :ref:`architecture overview <arch_overview_http_routing>`
34// * HTTP :ref:`router filter <config_http_filters_router>`
35
36message RetryPolicy {
37  string retry_on = 1;
38  google.protobuf.UInt32Value num_retries = 2;
39
40  message RetryBackOff {
41    google.protobuf.Duration base_interval = 1;
42    google.protobuf.Duration max_interval = 2;
43  }
44
45  RetryBackOff retry_back_off = 8;
46}
47
48// The top level element in the routing configuration is a virtual host. Each virtual host has
49// a logical name as well as a set of domains that get routed to it based on the incoming request's
50// host header. This allows a single listener to service multiple top level domain path trees. Once
51// a virtual host is selected based on the domain, the routes are processed in order to see which
52// upstream cluster to route to or whether to perform a redirect.
53// [#next-free-field: 21]
54message VirtualHost {
55  // The logical name of the virtual host. This is used when emitting certain
56  // statistics but is not relevant for routing.
57  string name = 1;
58
59  // A list of domains (host/authority header) that will be matched to this
60  // virtual host. Wildcard hosts are supported in the suffix or prefix form.
61  //
62  // Domain search order:
63  //  1. Exact domain names: ``www.foo.com``.
64  //  2. Suffix domain wildcards: ``*.foo.com`` or ``*-bar.foo.com``.
65  //  3. Prefix domain wildcards: ``foo.*`` or ``foo-*``.
66  //  4. Special wildcard ``*`` matching any domain.
67  //
68  // .. note::
69  //
70  //   The wildcard will not match the empty string.
71  //   e.g. ``*-bar.foo.com`` will match ``baz-bar.foo.com`` but not ``-bar.foo.com``.
72  //   The longest wildcards match first.
73  //   Only a single virtual host in the entire route configuration can match on ``*``. A domain
74  //   must be unique across all virtual hosts or the config will fail to load.
75  //
76  // Domains cannot contain control characters. This is validated by the well_known_regex HTTP_HEADER_VALUE.
77  repeated string domains = 2;
78
79  // The list of routes that will be matched, in order, for incoming requests.
80  // The first route that matches will be used.
81  repeated Route routes = 3;
82
83  // The per_filter_config field can be used to provide virtual host-specific
84  // configurations for filters. The key should match the filter name, such as
85  // *envoy.filters.http.buffer* for the HTTP buffer filter. Use of this field is filter
86  // specific; see the :ref:`HTTP filter documentation <config_http_filters>`
87  // for if and how it is utilized.
88  map<string, google.protobuf.Any> typed_per_filter_config = 15;
89
90  RetryPolicy retry_policy = 16;
91}
92
93// A route is both a specification of how to match a request as well as an indication of what to do
94// next (e.g., redirect, forward, rewrite, etc.).
95//
96// .. attention::
97//
98//   Envoy supports routing on HTTP method via :ref:`header matching
99//   <envoy_api_msg_config.route.v3.HeaderMatcher>`.
100// [#next-free-field: 18]
101message Route {
102  // Name for the route.
103  string name = 14;
104
105  // Route matching parameters.
106  RouteMatch match = 1;
107
108  message NonForwardingAction {
109  }
110
111  oneof action {
112    // Route request to some upstream cluster.
113    RouteAction route = 2;
114
115    // Return a redirect.
116    RedirectAction redirect = 3;
117
118    // An action used when the route will generate a response directly,
119    // without forwarding to an upstream host. This will be used in non-proxy
120    // xDS clients like the gRPC server. It could also be used in the future
121    // in Envoy for a filter that directly generates responses for requests.
122    NonForwardingAction non_forwarding_action = 18;
123  }
124
125  // The typed_per_filter_config field can be used to provide route-specific
126  // configurations for filters. The key should match the filter name, such as
127  // *envoy.filters.http.buffer* for the HTTP buffer filter. Use of this field is filter
128  // specific; see the :ref:`HTTP filter documentation <config_http_filters>` for
129  // if and how it is utilized.
130  map<string, google.protobuf.Any> typed_per_filter_config = 13;
131}
132
133// Compared to the :ref:`cluster <envoy_api_field_config.route.v3.RouteAction.cluster>` field that specifies a
134// single upstream cluster as the target of a request, the :ref:`weighted_clusters
135// <envoy_api_field_config.route.v3.RouteAction.weighted_clusters>` option allows for specification of
136// multiple upstream clusters along with weights that indicate the percentage of
137// traffic to be forwarded to each cluster. The router selects an upstream cluster based on the
138// weights.
139message WeightedCluster {
140  // [#next-free-field: 11]
141  message ClusterWeight {
142    // Name of the upstream cluster. The cluster must exist in the
143    // :ref:`cluster manager configuration <config_cluster_manager>`.
144    string name = 1;
145
146    // An integer between 0 and :ref:`total_weight
147    // <envoy_api_field_config.route.v3.WeightedCluster.total_weight>`. When a request matches the route,
148    // the choice of an upstream cluster is determined by its weight. The sum of weights across all
149    // entries in the clusters array must add up to the total_weight, which defaults to 100.
150    google.protobuf.UInt32Value weight = 2;
151
152    // The per_filter_config field can be used to provide weighted cluster-specific
153    // configurations for filters. The key should match the filter name, such as
154    // *envoy.filters.http.buffer* for the HTTP buffer filter. Use of this field is filter
155    // specific; see the :ref:`HTTP filter documentation <config_http_filters>`
156    // for if and how it is utilized.
157    map<string, google.protobuf.Any> typed_per_filter_config = 10;
158  }
159
160  // Specifies one or more upstream clusters associated with the route.
161  repeated ClusterWeight clusters = 1;
162
163  // Specifies the total weight across all clusters. The sum of all cluster weights must equal this
164  // value, which must be greater than 0. Defaults to 100.
165  google.protobuf.UInt32Value total_weight = 3;
166}
167
168// [#next-free-field: 13]
169message RouteMatch {
170  oneof path_specifier {
171    // If specified, the route is a prefix rule meaning that the prefix must
172    // match the beginning of the *:path* header.
173    string prefix = 1;
174
175    // If specified, the route is an exact path rule meaning that the path must
176    // exactly match the *:path* header once the query string is removed.
177    string path = 2;
178
179    // If specified, the route is a regular expression rule meaning that the
180    // regex must match the *:path* header once the query string is removed. The entire path
181    // (without the query string) must match the regex. The rule will not match if only a
182    // subsequence of the *:path* header matches the regex.
183    //
184    // [#next-major-version: In the v3 API we should redo how path specification works such
185    // that we utilize StringMatcher, and additionally have consistent options around whether we
186    // strip query strings, do a case sensitive match, etc. In the interim it will be too disruptive
187    // to deprecate the existing options. We should even consider whether we want to do away with
188    // path_specifier entirely and just rely on a set of header matchers which can already match
189    // on :path, etc. The issue with that is it is unclear how to generically deal with query string
190    // stripping. This needs more thought.]
191    type.matcher.v3.RegexMatcher safe_regex = 10;
192
193    string path_separated_prefix = 14;
194  }
195
196  // Indicates that prefix/path matching should be case insensitive. The default
197  // is true.
198  google.protobuf.BoolValue case_sensitive = 4;
199
200  // Indicates that the route should additionally match on a runtime key. Every time the route
201  // is considered for a match, it must also fall under the percentage of matches indicated by
202  // this field. For some fraction N/D, a random number in the range [0,D) is selected. If the
203  // number is <= the value of the numerator N, or if the key is not present, the default
204  // value, the router continues to evaluate the remaining match criteria. A runtime_fraction
205  // route configuration can be used to roll out route changes in a gradual manner without full
206  // code/config deploys. Refer to the :ref:`traffic shifting
207  // <config_http_conn_man_route_table_traffic_splitting_shift>` docs for additional documentation.
208  //
209  // .. note::
210  //
211  //    Parsing this field is implemented such that the runtime key's data may be represented
212  //    as a FractionalPercent proto represented as JSON/YAML and may also be represented as an
213  //    integer with the assumption that the value is an integral percentage out of 100. For
214  //    instance, a runtime key lookup returning the value "42" would parse as a FractionalPercent
215  //    whose numerator is 42 and denominator is HUNDRED. This preserves legacy semantics.
216  core.v3.RuntimeFractionalPercent runtime_fraction = 9;
217
218  // Specifies a set of headers that the route should match on. The router will
219  // check the request’s headers against all the specified headers in the route
220  // config. A match will happen if all the headers in the route are present in
221  // the request with the same values (or based on presence if the value field
222  // is not in the config).
223  repeated HeaderMatcher headers = 6;
224
225  // Specifies a set of URL query parameters on which the route should
226  // match. The router will check the query string from the *path* header
227  // against all the specified query parameters. If the number of specified
228  // query parameters is nonzero, they all must match the *path* header's
229  // query string for a match to occur.
230  repeated QueryParameterMatcher query_parameters = 7;
231}
232
233message MaxStreamDuration {
234  // Specifies the maximum duration allowed for streams on the route. If not specified, the value
235  // from the :ref:`max_stream_duration
236  // <envoy_api_field_config.core.v3.HttpProtocolOptions.max_stream_duration>` field in
237  // :ref:`HttpConnectionManager.common_http_protocol_options
238  // <envoy_api_field_extensions.filters.network.http_connection_manager.v3.HttpConnectionManager.common_http_protocol_options>`
239  // is used. If this field is set explicitly to zero, any
240  // HttpConnectionManager max_stream_duration timeout will be disabled for
241  // this route.
242  google.protobuf.Duration max_stream_duration = 1;
243
244  // If present, and the request contains a `grpc-timeout header
245  // <https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-HTTP2.md>`_, use that value as the
246  // *max_stream_duration*, but limit the applied timeout to the maximum value specified here.
247  // If set to 0, the `grpc-timeout` header is used without modification.
248  google.protobuf.Duration grpc_timeout_header_max = 2;
249}
250
251// [#next-free-field: 37]
252message RouteAction {
253  oneof cluster_specifier {
254    // Indicates the upstream cluster to which the request should be routed
255    // to.
256    string cluster = 1;
257
258    // Envoy will determine the cluster to route to by reading the value of the
259    // HTTP header named by cluster_header from the request headers. If the
260    // header is not found or the referenced cluster does not exist, Envoy will
261    // return a 404 response.
262    //
263    // .. attention::
264    //
265    //   Internally, Envoy always uses the HTTP/2 *:authority* header to represent the HTTP/1
266    //   *Host* header. Thus, if attempting to match on *Host*, match on *:authority* instead.
267    string cluster_header = 2;
268
269    // Multiple upstream clusters can be specified for a given route. The
270    // request is routed to one of the upstream clusters based on weights
271    // assigned to each cluster. See
272    // :ref:`traffic splitting <config_http_conn_man_route_table_traffic_splitting_split>`
273    // for additional documentation.
274    WeightedCluster weighted_clusters = 3;
275
276    // Name of the cluster specifier plugin to use to determine the cluster for
277    // requests on this route. The plugin name must be defined in the associated
278    // :ref:`envoy_v3_api_field_config.route.v3.RouteConfiguration.cluster_specifier_plugins`
279    // in the
280    // :ref:`envoy_v3_api_field_config.core.v3.TypedExtensionConfig.name` field.
281    string cluster_specifier_plugin = 37;
282  }
283
284  message HashPolicy {
285    message Header {
286      // The name of the request header that will be used to obtain the hash
287      // key. If the request header is not present, no hash will be produced.
288      string header_name = 1;
289
290      // If specified, the request header value will be rewritten and used
291      // to produce the hash key.
292      type.matcher.v3.RegexMatchAndSubstitute regex_rewrite = 2;
293    }
294
295    message Cookie {
296      string name = 1;
297    }
298
299    message ConnectionProperties {
300      bool source_ip = 1;
301    }
302
303    message QueryParameter {
304      string name = 1;
305    }
306
307    message FilterState {
308      // The name of the Object in the per-request filterState, which is an
309      // Envoy::Http::Hashable object. If there is no data associated with the key,
310      // or the stored object is not Envoy::Http::Hashable, no hash will be produced.
311      string key = 1;
312    }
313
314    oneof policy_specifier {
315      // Header hash policy.
316      Header header = 1;
317
318      // Cookie hash policy.
319      Cookie cookie = 2;
320
321      // Connection properties hash policy.
322      ConnectionProperties connection_properties = 3;
323
324      // Query parameter hash policy.
325      QueryParameter query_parameter = 5;
326
327      // Filter state hash policy.
328      FilterState filter_state = 6;
329    }
330
331    // The flag that short-circuits the hash computing. This field provides a
332    // 'fallback' style of configuration: "if a terminal policy doesn't work,
333    // fallback to rest of the policy list", it saves time when the terminal
334    // policy works.
335    //
336    // If true, and there is already a hash computed, ignore rest of the
337    // list of hash polices.
338    // For example, if the following hash methods are configured:
339    //
340    //  ========= ========
341    //  specifier terminal
342    //  ========= ========
343    //  Header A  true
344    //  Header B  false
345    //  Header C  false
346    //  ========= ========
347    //
348    // The generateHash process ends if policy "header A" generates a hash, as
349    // it's a terminal policy.
350    bool terminal = 4;
351  }
352
353  repeated HashPolicy hash_policy = 15;
354
355  RetryPolicy retry_policy = 9;
356
357  // Specifies the maximum stream duration for this route.
358  MaxStreamDuration max_stream_duration = 36;
359}
360
361// .. attention::
362//
363//   Internally, Envoy always uses the HTTP/2 *:authority* header to represent the HTTP/1 *Host*
364//   header. Thus, if attempting to match on *Host*, match on *:authority* instead.
365//
366// .. attention::
367//
368//   To route on HTTP method, use the special HTTP/2 *:method* header. This works for both
369//   HTTP/1 and HTTP/2 as Envoy normalizes headers. E.g.,
370//
371//   .. code-block:: json
372//
373//     {
374//       "name": ":method",
375//       "exact_match": "POST"
376//     }
377//
378// .. attention::
379//   In the absence of any header match specifier, match will default to :ref:`present_match
380//   <envoy_api_field_config.route.v3.HeaderMatcher.present_match>`. i.e, a request that has the :ref:`name
381//   <envoy_api_field_config.route.v3.HeaderMatcher.name>` header will match, regardless of the header's
382//   value.
383//
384//  [#next-major-version: HeaderMatcher should be refactored to use StringMatcher.]
385// [#next-free-field: 12]
386message HeaderMatcher {
387  // Specifies the name of the header in the request.
388  string name = 1;
389
390  // Specifies how the header match will be performed to route the request.
391  oneof header_match_specifier {
392    // If specified, header match will be performed based on the value of the header.
393    string exact_match = 4;
394
395    // If specified, this regex string is a regular expression rule which implies the entire request
396    // header value must match the regex. The rule will not match if only a subsequence of the
397    // request header value matches the regex.
398    type.matcher.v3.RegexMatcher safe_regex_match = 11;
399
400    // If specified, header match will be performed based on range.
401    // The rule will match if the request header value is within this range.
402    // The entire request header value must represent an integer in base 10 notation: consisting of
403    // an optional plus or minus sign followed by a sequence of digits. The rule will not match if
404    // the header value does not represent an integer. Match will fail for empty values, floating
405    // point numbers or if only a subsequence of the header value is an integer.
406    //
407    // Examples:
408    //
409    // * For range [-10,0), route will match for header value -1, but not for 0, "somestring", 10.9,
410    //   "-1somestring"
411    type.v3.Int64Range range_match = 6;
412
413    // If specified, header match will be performed based on whether the header is in the
414    // request.
415    bool present_match = 7;
416
417    // If specified, header match will be performed based on the prefix of the header value.
418    // Note: empty prefix is not allowed, please use present_match instead.
419    //
420    // Examples:
421    //
422    // * The prefix *abcd* matches the value *abcdxyz*, but not for *abcxyz*.
423    string prefix_match = 9;
424
425    // If specified, header match will be performed based on the suffix of the header value.
426    // Note: empty suffix is not allowed, please use present_match instead.
427    //
428    // Examples:
429    //
430    // * The suffix *abcd* matches the value *xyzabcd*, but not for *xyzbcd*.
431    string suffix_match = 10;
432
433    string contains_match = 12;
434
435    type.matcher.v3.StringMatcher string_match = 13;
436  }
437
438  // If specified, the match result will be inverted before checking. Defaults to false.
439  //
440  // Examples:
441  //
442  // * The regex ``\d{3}`` does not match the value *1234*, so it will match when inverted.
443  // * The range [-10,0) will match the value -1, so it will not match when inverted.
444  bool invert_match = 8;
445}
446
447// Query parameter matching treats the query string of a request's :path header
448// as an ampersand-separated list of keys and/or key=value elements.
449// [#next-free-field: 7]
450message QueryParameterMatcher {
451}
452
453// Configuration for a cluster specifier plugin.
454message ClusterSpecifierPlugin {
455  // The name of the plugin and its opaque configuration.
456  core.v3.TypedExtensionConfig extension = 1;
457
458  // If is_optional is not set and the plugin defined by this message is not
459  // a supported type, the containing resource is NACKed. If is_optional is
460  // set, the resource would not be NACKed for this reason. In this case,
461  // routes referencing this plugin's name would not be treated as an illegal
462  // configuration, but would result in a failure if the route is selected.
463  bool is_optional = 2;
464}
465
466// [#protodoc-title: HTTP route configuration]
467// * Routing :ref:`architecture overview <arch_overview_http_routing>`
468// * HTTP :ref:`router filter <config_http_filters_router>`
469
470// [#next-free-field: 11]
471message RouteConfiguration {
472  // The name of the route configuration. For example, it might match
473  // :ref:`route_config_name
474  // <envoy_api_field_extensions.filters.network.http_connection_manager.v3.Rds.route_config_name>` in
475  // :ref:`envoy_api_msg_extensions.filters.network.http_connection_manager.v3.Rds`.
476  string name = 1;
477
478  // An array of virtual hosts that make up the route table.
479  repeated VirtualHost virtual_hosts = 2;
480
481  // A list of plugins and their configurations which may be used by a
482  // :ref:`envoy_v3_api_field_config.route.v3.RouteAction.cluster_specifier_plugin`
483  // within the route. All *extension.name* fields in this list must be unique.
484  repeated ClusterSpecifierPlugin cluster_specifier_plugins = 12;
485}
486
487message RedirectAction {
488}
489
490message FilterConfig {
491  // The filter config.
492  google.protobuf.Any config = 1;
493
494  // If true, the filter is optional, meaning that if the client does
495  // not support the specified filter, it may ignore the map entry rather
496  // than rejecting the config.
497  bool is_optional = 2;
498}
499