diff --git a/packages/grpc-js/package.json b/packages/grpc-js/package.json index 4c4e59f0..ee910cfb 100644 --- a/packages/grpc-js/package.json +++ b/packages/grpc-js/package.json @@ -48,7 +48,7 @@ "clean": "node -e 'require(\"rimraf\")(\"./build\", () => {})'", "compile": "tsc -p .", "format": "clang-format -i -style=\"{Language: JavaScript, BasedOnStyle: Google, ColumnLimit: 80}\" src/*.ts test/*.ts", - "generate-types": "proto-loader-gen-types --keepCase --longs String --enums String --defaults --oneofs --json --includeComments --includeDirs deps/envoy-api/ deps/udpa/ deps/googleapis/ deps/protoc-gen-validate/ -O src/generated/ --grpcLib ../index envoy/service/discovery/v2/ads.proto envoy/service/load_stats/v2/lrs.proto envoy/api/v2/listener.proto envoy/api/v2/route.proto envoy/api/v2/cluster.proto envoy/api/v2/endpoint.proto", + "generate-types": "proto-loader-gen-types --keepCase --longs String --enums String --defaults --oneofs --json --includeComments --includeDirs deps/envoy-api/ deps/udpa/ deps/googleapis/ deps/protoc-gen-validate/ -O src/generated/ --grpcLib ../index envoy/service/discovery/v2/ads.proto envoy/service/load_stats/v2/lrs.proto envoy/api/v2/listener.proto envoy/api/v2/route.proto envoy/api/v2/cluster.proto envoy/api/v2/endpoint.proto envoy/config/filter/network/http_connection_manager/v2/http_connection_manager.proto", "lint": "npm run check", "prepare": "npm run compile", "test": "gulp test", diff --git a/packages/grpc-js/src/channel.ts b/packages/grpc-js/src/channel.ts index f2ad181a..8c369192 100644 --- a/packages/grpc-js/src/channel.ts +++ b/packages/grpc-js/src/channel.ts @@ -34,7 +34,6 @@ import { CallCredentialsFilterFactory } from './call-credentials-filter'; import { DeadlineFilterFactory } from './deadline-filter'; import { CompressionFilterFactory } from './compression-filter'; import { getDefaultAuthority, mapUriDefaultScheme } from './resolver'; -import { ServiceConfig, validateServiceConfig } from './service-config'; import { trace, log } from './logging'; import { SubchannelAddress } from './subchannel'; import { MaxMessageSizeFilterFactory } from './max-message-size-filter'; @@ -220,20 +219,10 @@ export class ChannelImplementation implements Channel { ); }, }; - // TODO(murgatroid99): check channel arg for default service config - let defaultServiceConfig: ServiceConfig = { - loadBalancingConfig: [], - methodConfig: [], - }; - if (options['grpc.service_config']) { - defaultServiceConfig = validateServiceConfig( - JSON.parse(options['grpc.service_config']!) - ); - } this.resolvingLoadBalancer = new ResolvingLoadBalancer( this.target, channelControlHelper, - defaultServiceConfig + options ); this.filterStackFactory = new FilterStackFactory([ new CallCredentialsFilterFactory(this), diff --git a/packages/grpc-js/src/generated/envoy/api/v2/ScopedRouteConfiguration.ts b/packages/grpc-js/src/generated/envoy/api/v2/ScopedRouteConfiguration.ts new file mode 100644 index 00000000..02810bf0 --- /dev/null +++ b/packages/grpc-js/src/generated/envoy/api/v2/ScopedRouteConfiguration.ts @@ -0,0 +1,204 @@ +// Original file: deps/envoy-api/envoy/api/v2/scoped_route.proto + + +export interface _envoy_api_v2_ScopedRouteConfiguration_Key_Fragment { + /** + * A string to match against. + */ + 'string_key'?: (string); + 'type'?: "string_key"; +} + +export interface _envoy_api_v2_ScopedRouteConfiguration_Key_Fragment__Output { + /** + * A string to match against. + */ + 'string_key'?: (string); + 'type': "string_key"; +} + +/** + * Specifies a key which is matched against the output of the + * :ref:`scope_key_builder` + * specified in the HttpConnectionManager. The matching is done per HTTP + * request and is dependent on the order of the fragments contained in the + * Key. + */ +export interface _envoy_api_v2_ScopedRouteConfiguration_Key { + /** + * The ordered set of fragments to match against. The order must match the + * fragments in the corresponding + * :ref:`scope_key_builder`. + */ + 'fragments'?: (_envoy_api_v2_ScopedRouteConfiguration_Key_Fragment)[]; +} + +/** + * Specifies a key which is matched against the output of the + * :ref:`scope_key_builder` + * specified in the HttpConnectionManager. The matching is done per HTTP + * request and is dependent on the order of the fragments contained in the + * Key. + */ +export interface _envoy_api_v2_ScopedRouteConfiguration_Key__Output { + /** + * The ordered set of fragments to match against. The order must match the + * fragments in the corresponding + * :ref:`scope_key_builder`. + */ + 'fragments': (_envoy_api_v2_ScopedRouteConfiguration_Key_Fragment__Output)[]; +} + +/** + * Specifies a routing scope, which associates a + * :ref:`Key` to a + * :ref:`envoy_api_msg_RouteConfiguration` (identified by its resource name). + * + * The HTTP connection manager builds up a table consisting of these Key to + * RouteConfiguration mappings, and looks up the RouteConfiguration to use per + * request according to the algorithm specified in the + * :ref:`scope_key_builder` + * assigned to the HttpConnectionManager. + * + * For example, with the following configurations (in YAML): + * + * HttpConnectionManager config: + * + * .. code:: + * + * ... + * scoped_routes: + * name: foo-scoped-routes + * scope_key_builder: + * fragments: + * - header_value_extractor: + * name: X-Route-Selector + * element_separator: , + * element: + * separator: = + * key: vip + * + * ScopedRouteConfiguration resources (specified statically via + * :ref:`scoped_route_configurations_list` + * or obtained dynamically via SRDS): + * + * .. code:: + * + * (1) + * name: route-scope1 + * route_configuration_name: route-config1 + * key: + * fragments: + * - string_key: 172.10.10.20 + * + * (2) + * name: route-scope2 + * route_configuration_name: route-config2 + * key: + * fragments: + * - string_key: 172.20.20.30 + * + * A request from a client such as: + * + * .. code:: + * + * GET / HTTP/1.1 + * Host: foo.com + * X-Route-Selector: vip=172.10.10.20 + * + * would result in the routing table defined by the `route-config1` + * RouteConfiguration being assigned to the HTTP request/stream. + */ +export interface ScopedRouteConfiguration { + /** + * The name assigned to the routing scope. + */ + 'name'?: (string); + /** + * The resource name to use for a :ref:`envoy_api_msg_DiscoveryRequest` to an + * RDS server to fetch the :ref:`envoy_api_msg_RouteConfiguration` associated + * with this scope. + */ + 'route_configuration_name'?: (string); + /** + * The key to match against. + */ + 'key'?: (_envoy_api_v2_ScopedRouteConfiguration_Key); +} + +/** + * Specifies a routing scope, which associates a + * :ref:`Key` to a + * :ref:`envoy_api_msg_RouteConfiguration` (identified by its resource name). + * + * The HTTP connection manager builds up a table consisting of these Key to + * RouteConfiguration mappings, and looks up the RouteConfiguration to use per + * request according to the algorithm specified in the + * :ref:`scope_key_builder` + * assigned to the HttpConnectionManager. + * + * For example, with the following configurations (in YAML): + * + * HttpConnectionManager config: + * + * .. code:: + * + * ... + * scoped_routes: + * name: foo-scoped-routes + * scope_key_builder: + * fragments: + * - header_value_extractor: + * name: X-Route-Selector + * element_separator: , + * element: + * separator: = + * key: vip + * + * ScopedRouteConfiguration resources (specified statically via + * :ref:`scoped_route_configurations_list` + * or obtained dynamically via SRDS): + * + * .. code:: + * + * (1) + * name: route-scope1 + * route_configuration_name: route-config1 + * key: + * fragments: + * - string_key: 172.10.10.20 + * + * (2) + * name: route-scope2 + * route_configuration_name: route-config2 + * key: + * fragments: + * - string_key: 172.20.20.30 + * + * A request from a client such as: + * + * .. code:: + * + * GET / HTTP/1.1 + * Host: foo.com + * X-Route-Selector: vip=172.10.10.20 + * + * would result in the routing table defined by the `route-config1` + * RouteConfiguration being assigned to the HTTP request/stream. + */ +export interface ScopedRouteConfiguration__Output { + /** + * The name assigned to the routing scope. + */ + 'name': (string); + /** + * The resource name to use for a :ref:`envoy_api_msg_DiscoveryRequest` to an + * RDS server to fetch the :ref:`envoy_api_msg_RouteConfiguration` associated + * with this scope. + */ + 'route_configuration_name': (string); + /** + * The key to match against. + */ + 'key'?: (_envoy_api_v2_ScopedRouteConfiguration_Key__Output); +} diff --git a/packages/grpc-js/src/generated/envoy/config/filter/network/http_connection_manager/v2/HttpConnectionManager.ts b/packages/grpc-js/src/generated/envoy/config/filter/network/http_connection_manager/v2/HttpConnectionManager.ts new file mode 100644 index 00000000..9aa2b2d2 --- /dev/null +++ b/packages/grpc-js/src/generated/envoy/config/filter/network/http_connection_manager/v2/HttpConnectionManager.ts @@ -0,0 +1,1039 @@ +// Original file: deps/envoy-api/envoy/config/filter/network/http_connection_manager/v2/http_connection_manager.proto + +import { Rds as _envoy_config_filter_network_http_connection_manager_v2_Rds, Rds__Output as _envoy_config_filter_network_http_connection_manager_v2_Rds__Output } from '../../../../../../envoy/config/filter/network/http_connection_manager/v2/Rds'; +import { RouteConfiguration as _envoy_api_v2_RouteConfiguration, RouteConfiguration__Output as _envoy_api_v2_RouteConfiguration__Output } from '../../../../../../envoy/api/v2/RouteConfiguration'; +import { HttpFilter as _envoy_config_filter_network_http_connection_manager_v2_HttpFilter, HttpFilter__Output as _envoy_config_filter_network_http_connection_manager_v2_HttpFilter__Output } from '../../../../../../envoy/config/filter/network/http_connection_manager/v2/HttpFilter'; +import { BoolValue as _google_protobuf_BoolValue, BoolValue__Output as _google_protobuf_BoolValue__Output } from '../../../../../../google/protobuf/BoolValue'; +import { Http1ProtocolOptions as _envoy_api_v2_core_Http1ProtocolOptions, Http1ProtocolOptions__Output as _envoy_api_v2_core_Http1ProtocolOptions__Output } from '../../../../../../envoy/api/v2/core/Http1ProtocolOptions'; +import { Http2ProtocolOptions as _envoy_api_v2_core_Http2ProtocolOptions, Http2ProtocolOptions__Output as _envoy_api_v2_core_Http2ProtocolOptions__Output } from '../../../../../../envoy/api/v2/core/Http2ProtocolOptions'; +import { Duration as _google_protobuf_Duration, Duration__Output as _google_protobuf_Duration__Output } from '../../../../../../google/protobuf/Duration'; +import { AccessLog as _envoy_config_filter_accesslog_v2_AccessLog, AccessLog__Output as _envoy_config_filter_accesslog_v2_AccessLog__Output } from '../../../../../../envoy/config/filter/accesslog/v2/AccessLog'; +import { UInt32Value as _google_protobuf_UInt32Value, UInt32Value__Output as _google_protobuf_UInt32Value__Output } from '../../../../../../google/protobuf/UInt32Value'; +import { ScopedRoutes as _envoy_config_filter_network_http_connection_manager_v2_ScopedRoutes, ScopedRoutes__Output as _envoy_config_filter_network_http_connection_manager_v2_ScopedRoutes__Output } from '../../../../../../envoy/config/filter/network/http_connection_manager/v2/ScopedRoutes'; +import { HttpProtocolOptions as _envoy_api_v2_core_HttpProtocolOptions, HttpProtocolOptions__Output as _envoy_api_v2_core_HttpProtocolOptions__Output } from '../../../../../../envoy/api/v2/core/HttpProtocolOptions'; +import { RequestIDExtension as _envoy_config_filter_network_http_connection_manager_v2_RequestIDExtension, RequestIDExtension__Output as _envoy_config_filter_network_http_connection_manager_v2_RequestIDExtension__Output } from '../../../../../../envoy/config/filter/network/http_connection_manager/v2/RequestIDExtension'; +import { Percent as _envoy_type_Percent, Percent__Output as _envoy_type_Percent__Output } from '../../../../../../envoy/type/Percent'; +import { CustomTag as _envoy_type_tracing_v2_CustomTag, CustomTag__Output as _envoy_type_tracing_v2_CustomTag__Output } from '../../../../../../envoy/type/tracing/v2/CustomTag'; +import { _envoy_config_trace_v2_Tracing_Http, _envoy_config_trace_v2_Tracing_Http__Output } from '../../../../../../envoy/config/trace/v2/Tracing'; + +// Original file: deps/envoy-api/envoy/config/filter/network/http_connection_manager/v2/http_connection_manager.proto + +export enum _envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_CodecType { + /** + * For every new connection, the connection manager will determine which + * codec to use. This mode supports both ALPN for TLS listeners as well as + * protocol inference for plaintext listeners. If ALPN data is available, it + * is preferred, otherwise protocol inference is used. In almost all cases, + * this is the right option to choose for this setting. + */ + AUTO = 0, + /** + * The connection manager will assume that the client is speaking HTTP/1.1. + */ + HTTP1 = 1, + /** + * The connection manager will assume that the client is speaking HTTP/2 + * (Envoy does not require HTTP/2 to take place over TLS or to use ALPN. + * Prior knowledge is allowed). + */ + HTTP2 = 2, + /** + * [#not-implemented-hide:] QUIC implementation is not production ready yet. Use this enum with + * caution to prevent accidental execution of QUIC code. I.e. `!= HTTP2` is no longer sufficient + * to distinguish HTTP1 and HTTP2 traffic. + */ + HTTP3 = 3, +} + +// Original file: deps/envoy-api/envoy/config/filter/network/http_connection_manager/v2/http_connection_manager.proto + +/** + * How to handle the :ref:`config_http_conn_man_headers_x-forwarded-client-cert` (XFCC) HTTP + * header. + */ +export enum _envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_ForwardClientCertDetails { + /** + * Do not send the XFCC header to the next hop. This is the default value. + */ + SANITIZE = 0, + /** + * When the client connection is mTLS (Mutual TLS), forward the XFCC header + * in the request. + */ + FORWARD_ONLY = 1, + /** + * When the client connection is mTLS, append the client certificate + * information to the request’s XFCC header and forward it. + */ + APPEND_FORWARD = 2, + /** + * When the client connection is mTLS, reset the XFCC header with the client + * certificate information and send it to the next hop. + */ + SANITIZE_SET = 3, + /** + * Always forward the XFCC header in the request, regardless of whether the + * client connection is mTLS. + */ + ALWAYS_FORWARD_ONLY = 4, +} + +export interface _envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_InternalAddressConfig { + /** + * Whether unix socket addresses should be considered internal. + */ + 'unix_sockets'?: (boolean); +} + +export interface _envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_InternalAddressConfig__Output { + /** + * Whether unix socket addresses should be considered internal. + */ + 'unix_sockets': (boolean); +} + +// Original file: deps/envoy-api/envoy/config/filter/network/http_connection_manager/v2/http_connection_manager.proto + +export enum _envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_Tracing_OperationName { + /** + * The HTTP listener is used for ingress/incoming requests. + */ + INGRESS = 0, + /** + * The HTTP listener is used for egress/outgoing requests. + */ + EGRESS = 1, +} + +// Original file: deps/envoy-api/envoy/config/filter/network/http_connection_manager/v2/http_connection_manager.proto + +export enum _envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_ServerHeaderTransformation { + /** + * Overwrite any Server header with the contents of server_name. + */ + OVERWRITE = 0, + /** + * If no Server header is present, append Server server_name + * If a Server header is present, pass it through. + */ + APPEND_IF_ABSENT = 1, + /** + * Pass through the value of the server header, and do not append a header + * if none is present. + */ + PASS_THROUGH = 2, +} + +/** + * [#next-free-field: 7] + */ +export interface _envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_SetCurrentClientCertDetails { + /** + * Whether to forward the subject of the client cert. Defaults to false. + */ + 'subject'?: (_google_protobuf_BoolValue); + /** + * Whether to forward the entire client cert in URL encoded PEM format. This will appear in the + * XFCC header comma separated from other values with the value Cert="PEM". + * Defaults to false. + */ + 'cert'?: (boolean); + /** + * Whether to forward the entire client cert chain (including the leaf cert) in URL encoded PEM + * format. This will appear in the XFCC header comma separated from other values with the value + * Chain="PEM". + * Defaults to false. + */ + 'chain'?: (boolean); + /** + * Whether to forward the DNS type Subject Alternative Names of the client cert. + * Defaults to false. + */ + 'dns'?: (boolean); + /** + * Whether to forward the URI type Subject Alternative Name of the client cert. Defaults to + * false. + */ + 'uri'?: (boolean); +} + +/** + * [#next-free-field: 7] + */ +export interface _envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_SetCurrentClientCertDetails__Output { + /** + * Whether to forward the subject of the client cert. Defaults to false. + */ + 'subject'?: (_google_protobuf_BoolValue__Output); + /** + * Whether to forward the entire client cert in URL encoded PEM format. This will appear in the + * XFCC header comma separated from other values with the value Cert="PEM". + * Defaults to false. + */ + 'cert': (boolean); + /** + * Whether to forward the entire client cert chain (including the leaf cert) in URL encoded PEM + * format. This will appear in the XFCC header comma separated from other values with the value + * Chain="PEM". + * Defaults to false. + */ + 'chain': (boolean); + /** + * Whether to forward the DNS type Subject Alternative Names of the client cert. + * Defaults to false. + */ + 'dns': (boolean); + /** + * Whether to forward the URI type Subject Alternative Name of the client cert. Defaults to + * false. + */ + 'uri': (boolean); +} + +/** + * [#next-free-field: 10] + */ +export interface _envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_Tracing { + /** + * The span name will be derived from this field. If + * :ref:`traffic_direction ` is + * specified on the parent listener, then it is used instead of this field. + * + * .. attention:: + * This field has been deprecated in favor of `traffic_direction`. + */ + 'operation_name'?: (_envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_Tracing_OperationName | keyof typeof _envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_Tracing_OperationName); + /** + * A list of header names used to create tags for the active span. The header name is used to + * populate the tag name, and the header value is used to populate the tag value. The tag is + * created if the specified header name is present in the request's headers. + * + * .. attention:: + * This field has been deprecated in favor of :ref:`custom_tags + * `. + */ + 'request_headers_for_tags'?: (string)[]; + /** + * Target percentage of requests managed by this HTTP connection manager that will be force + * traced if the :ref:`x-client-trace-id ` + * header is set. This field is a direct analog for the runtime variable + * 'tracing.client_sampling' in the :ref:`HTTP Connection Manager + * `. + * Default: 100% + */ + 'client_sampling'?: (_envoy_type_Percent); + /** + * Target percentage of requests managed by this HTTP connection manager that will be randomly + * selected for trace generation, if not requested by the client or not forced. This field is + * a direct analog for the runtime variable 'tracing.random_sampling' in the + * :ref:`HTTP Connection Manager `. + * Default: 100% + */ + 'random_sampling'?: (_envoy_type_Percent); + /** + * Target percentage of requests managed by this HTTP connection manager that will be traced + * after all other sampling checks have been applied (client-directed, force tracing, random + * sampling). This field functions as an upper limit on the total configured sampling rate. For + * instance, setting client_sampling to 100% but overall_sampling to 1% will result in only 1% + * of client requests with the appropriate headers to be force traced. This field is a direct + * analog for the runtime variable 'tracing.global_enabled' in the + * :ref:`HTTP Connection Manager `. + * Default: 100% + */ + 'overall_sampling'?: (_envoy_type_Percent); + /** + * Whether to annotate spans with additional data. If true, spans will include logs for stream + * events. + */ + 'verbose'?: (boolean); + /** + * Maximum length of the request path to extract and include in the HttpUrl tag. Used to + * truncate lengthy request paths to meet the needs of a tracing backend. + * Default: 256 + */ + 'max_path_tag_length'?: (_google_protobuf_UInt32Value); + /** + * A list of custom tags with unique tag name to create tags for the active span. + */ + 'custom_tags'?: (_envoy_type_tracing_v2_CustomTag)[]; + /** + * Configuration for an external tracing provider. + * If not specified, no tracing will be performed. + * + * .. attention:: + * Please be aware that *envoy.tracers.opencensus* provider can only be configured once + * in Envoy lifetime. + * Any attempts to reconfigure it or to use different configurations for different HCM filters + * will be rejected. + * Such a constraint is inherent to OpenCensus itself. It cannot be overcome without changes + * on OpenCensus side. + */ + 'provider'?: (_envoy_config_trace_v2_Tracing_Http); +} + +/** + * [#next-free-field: 10] + */ +export interface _envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_Tracing__Output { + /** + * The span name will be derived from this field. If + * :ref:`traffic_direction ` is + * specified on the parent listener, then it is used instead of this field. + * + * .. attention:: + * This field has been deprecated in favor of `traffic_direction`. + */ + 'operation_name': (keyof typeof _envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_Tracing_OperationName); + /** + * A list of header names used to create tags for the active span. The header name is used to + * populate the tag name, and the header value is used to populate the tag value. The tag is + * created if the specified header name is present in the request's headers. + * + * .. attention:: + * This field has been deprecated in favor of :ref:`custom_tags + * `. + */ + 'request_headers_for_tags': (string)[]; + /** + * Target percentage of requests managed by this HTTP connection manager that will be force + * traced if the :ref:`x-client-trace-id ` + * header is set. This field is a direct analog for the runtime variable + * 'tracing.client_sampling' in the :ref:`HTTP Connection Manager + * `. + * Default: 100% + */ + 'client_sampling'?: (_envoy_type_Percent__Output); + /** + * Target percentage of requests managed by this HTTP connection manager that will be randomly + * selected for trace generation, if not requested by the client or not forced. This field is + * a direct analog for the runtime variable 'tracing.random_sampling' in the + * :ref:`HTTP Connection Manager `. + * Default: 100% + */ + 'random_sampling'?: (_envoy_type_Percent__Output); + /** + * Target percentage of requests managed by this HTTP connection manager that will be traced + * after all other sampling checks have been applied (client-directed, force tracing, random + * sampling). This field functions as an upper limit on the total configured sampling rate. For + * instance, setting client_sampling to 100% but overall_sampling to 1% will result in only 1% + * of client requests with the appropriate headers to be force traced. This field is a direct + * analog for the runtime variable 'tracing.global_enabled' in the + * :ref:`HTTP Connection Manager `. + * Default: 100% + */ + 'overall_sampling'?: (_envoy_type_Percent__Output); + /** + * Whether to annotate spans with additional data. If true, spans will include logs for stream + * events. + */ + 'verbose': (boolean); + /** + * Maximum length of the request path to extract and include in the HttpUrl tag. Used to + * truncate lengthy request paths to meet the needs of a tracing backend. + * Default: 256 + */ + 'max_path_tag_length'?: (_google_protobuf_UInt32Value__Output); + /** + * A list of custom tags with unique tag name to create tags for the active span. + */ + 'custom_tags': (_envoy_type_tracing_v2_CustomTag__Output)[]; + /** + * Configuration for an external tracing provider. + * If not specified, no tracing will be performed. + * + * .. attention:: + * Please be aware that *envoy.tracers.opencensus* provider can only be configured once + * in Envoy lifetime. + * Any attempts to reconfigure it or to use different configurations for different HCM filters + * will be rejected. + * Such a constraint is inherent to OpenCensus itself. It cannot be overcome without changes + * on OpenCensus side. + */ + 'provider'?: (_envoy_config_trace_v2_Tracing_Http__Output); +} + +/** + * The configuration for HTTP upgrades. + * For each upgrade type desired, an UpgradeConfig must be added. + * + * .. warning:: + * + * The current implementation of upgrade headers does not handle + * multi-valued upgrade headers. Support for multi-valued headers may be + * added in the future if needed. + * + * .. warning:: + * The current implementation of upgrade headers does not work with HTTP/2 + * upstreams. + */ +export interface _envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_UpgradeConfig { + /** + * The case-insensitive name of this upgrade, e.g. "websocket". + * For each upgrade type present in upgrade_configs, requests with + * Upgrade: [upgrade_type] + * will be proxied upstream. + */ + 'upgrade_type'?: (string); + /** + * If present, this represents the filter chain which will be created for + * this type of upgrade. If no filters are present, the filter chain for + * HTTP connections will be used for this upgrade type. + */ + 'filters'?: (_envoy_config_filter_network_http_connection_manager_v2_HttpFilter)[]; + /** + * Determines if upgrades are enabled or disabled by default. Defaults to true. + * This can be overridden on a per-route basis with :ref:`cluster + * ` as documented in the + * :ref:`upgrade documentation `. + */ + 'enabled'?: (_google_protobuf_BoolValue); +} + +/** + * The configuration for HTTP upgrades. + * For each upgrade type desired, an UpgradeConfig must be added. + * + * .. warning:: + * + * The current implementation of upgrade headers does not handle + * multi-valued upgrade headers. Support for multi-valued headers may be + * added in the future if needed. + * + * .. warning:: + * The current implementation of upgrade headers does not work with HTTP/2 + * upstreams. + */ +export interface _envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_UpgradeConfig__Output { + /** + * The case-insensitive name of this upgrade, e.g. "websocket". + * For each upgrade type present in upgrade_configs, requests with + * Upgrade: [upgrade_type] + * will be proxied upstream. + */ + 'upgrade_type': (string); + /** + * If present, this represents the filter chain which will be created for + * this type of upgrade. If no filters are present, the filter chain for + * HTTP connections will be used for this upgrade type. + */ + 'filters': (_envoy_config_filter_network_http_connection_manager_v2_HttpFilter__Output)[]; + /** + * Determines if upgrades are enabled or disabled by default. Defaults to true. + * This can be overridden on a per-route basis with :ref:`cluster + * ` as documented in the + * :ref:`upgrade documentation `. + */ + 'enabled'?: (_google_protobuf_BoolValue__Output); +} + +/** + * [#next-free-field: 37] + */ +export interface HttpConnectionManager { + /** + * Supplies the type of codec that the connection manager should use. + */ + 'codec_type'?: (_envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_CodecType | keyof typeof _envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_CodecType); + /** + * The human readable prefix to use when emitting statistics for the + * connection manager. See the :ref:`statistics documentation ` for + * more information. + */ + 'stat_prefix'?: (string); + /** + * The connection manager’s route table will be dynamically loaded via the RDS API. + */ + 'rds'?: (_envoy_config_filter_network_http_connection_manager_v2_Rds); + /** + * The route table for the connection manager is static and is specified in this property. + */ + 'route_config'?: (_envoy_api_v2_RouteConfiguration); + /** + * A list of individual HTTP filters that make up the filter chain for + * requests made to the connection manager. :ref:`Order matters ` + * as the filters are processed sequentially as request events happen. + */ + 'http_filters'?: (_envoy_config_filter_network_http_connection_manager_v2_HttpFilter)[]; + /** + * Whether the connection manager manipulates the :ref:`config_http_conn_man_headers_user-agent` + * and :ref:`config_http_conn_man_headers_downstream-service-cluster` headers. See the linked + * documentation for more information. Defaults to false. + */ + 'add_user_agent'?: (_google_protobuf_BoolValue); + /** + * Presence of the object defines whether the connection manager + * emits :ref:`tracing ` data to the :ref:`configured tracing provider + * `. + */ + 'tracing'?: (_envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_Tracing); + /** + * Additional HTTP/1 settings that are passed to the HTTP/1 codec. + */ + 'http_protocol_options'?: (_envoy_api_v2_core_Http1ProtocolOptions); + /** + * Additional HTTP/2 settings that are passed directly to the HTTP/2 codec. + */ + 'http2_protocol_options'?: (_envoy_api_v2_core_Http2ProtocolOptions); + /** + * An optional override that the connection manager will write to the server + * header in responses. If not set, the default is *envoy*. + */ + 'server_name'?: (string); + /** + * The idle timeout for connections managed by the connection manager. The + * idle timeout is defined as the period in which there are no active + * requests. If not set, there is no idle timeout. When the idle timeout is + * reached the connection will be closed. If the connection is an HTTP/2 + * connection a drain sequence will occur prior to closing the connection. + * This field is deprecated. Use :ref:`idle_timeout + * ` + * instead. + */ + 'idle_timeout'?: (_google_protobuf_Duration); + /** + * The time that Envoy will wait between sending an HTTP/2 “shutdown + * notification” (GOAWAY frame with max stream ID) and a final GOAWAY frame. + * This is used so that Envoy provides a grace period for new streams that + * race with the final GOAWAY frame. During this grace period, Envoy will + * continue to accept new streams. After the grace period, a final GOAWAY + * frame is sent and Envoy will start refusing new streams. Draining occurs + * both when a connection hits the idle timeout or during general server + * draining. The default grace period is 5000 milliseconds (5 seconds) if this + * option is not specified. + */ + 'drain_timeout'?: (_google_protobuf_Duration); + /** + * Configuration for :ref:`HTTP access logs ` + * emitted by the connection manager. + */ + 'access_log'?: (_envoy_config_filter_accesslog_v2_AccessLog)[]; + /** + * If set to true, the connection manager will use the real remote address + * of the client connection when determining internal versus external origin and manipulating + * various headers. If set to false or absent, the connection manager will use the + * :ref:`config_http_conn_man_headers_x-forwarded-for` HTTP header. See the documentation for + * :ref:`config_http_conn_man_headers_x-forwarded-for`, + * :ref:`config_http_conn_man_headers_x-envoy-internal`, and + * :ref:`config_http_conn_man_headers_x-envoy-external-address` for more information. + */ + 'use_remote_address'?: (_google_protobuf_BoolValue); + /** + * Whether the connection manager will generate the :ref:`x-request-id + * ` header if it does not exist. This defaults to + * true. Generating a random UUID4 is expensive so in high throughput scenarios where this feature + * is not desired it can be disabled. + */ + 'generate_request_id'?: (_google_protobuf_BoolValue); + /** + * How to handle the :ref:`config_http_conn_man_headers_x-forwarded-client-cert` (XFCC) HTTP + * header. + */ + 'forward_client_cert_details'?: (_envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_ForwardClientCertDetails | keyof typeof _envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_ForwardClientCertDetails); + /** + * This field is valid only when :ref:`forward_client_cert_details + * ` + * is APPEND_FORWARD or SANITIZE_SET and the client connection is mTLS. It specifies the fields in + * the client certificate to be forwarded. Note that in the + * :ref:`config_http_conn_man_headers_x-forwarded-client-cert` header, *Hash* is always set, and + * *By* is always set when the client certificate presents the URI type Subject Alternative Name + * value. + */ + 'set_current_client_cert_details'?: (_envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_SetCurrentClientCertDetails); + /** + * If proxy_100_continue is true, Envoy will proxy incoming "Expect: + * 100-continue" headers upstream, and forward "100 Continue" responses + * downstream. If this is false or not set, Envoy will instead strip the + * "Expect: 100-continue" header, and send a "100 Continue" response itself. + */ + 'proxy_100_continue'?: (boolean); + /** + * The number of additional ingress proxy hops from the right side of the + * :ref:`config_http_conn_man_headers_x-forwarded-for` HTTP header to trust when + * determining the origin client's IP address. The default is zero if this option + * is not specified. See the documentation for + * :ref:`config_http_conn_man_headers_x-forwarded-for` for more information. + */ + 'xff_num_trusted_hops'?: (number); + /** + * If + * :ref:`use_remote_address + * ` + * is true and represent_ipv4_remote_address_as_ipv4_mapped_ipv6 is true and the remote address is + * an IPv4 address, the address will be mapped to IPv6 before it is appended to *x-forwarded-for*. + * This is useful for testing compatibility of upstream services that parse the header value. For + * example, 50.0.0.1 is represented as ::FFFF:50.0.0.1. See `IPv4-Mapped IPv6 Addresses + * `_ for details. This will also affect the + * :ref:`config_http_conn_man_headers_x-envoy-external-address` header. See + * :ref:`http_connection_manager.represent_ipv4_remote_address_as_ipv4_mapped_ipv6 + * ` for runtime + * control. + * [#not-implemented-hide:] + */ + 'represent_ipv4_remote_address_as_ipv4_mapped_ipv6'?: (boolean); + /** + * If set, Envoy will not append the remote address to the + * :ref:`config_http_conn_man_headers_x-forwarded-for` HTTP header. This may be used in + * conjunction with HTTP filters that explicitly manipulate XFF after the HTTP connection manager + * has mutated the request headers. While :ref:`use_remote_address + * ` + * will also suppress XFF addition, it has consequences for logging and other + * Envoy uses of the remote address, so *skip_xff_append* should be used + * when only an elision of XFF addition is intended. + */ + 'skip_xff_append'?: (boolean); + /** + * Via header value to append to request and response headers. If this is + * empty, no via header will be appended. + */ + 'via'?: (string); + 'upgrade_configs'?: (_envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_UpgradeConfig)[]; + /** + * The stream idle timeout for connections managed by the connection manager. + * If not specified, this defaults to 5 minutes. The default value was selected + * so as not to interfere with any smaller configured timeouts that may have + * existed in configurations prior to the introduction of this feature, while + * introducing robustness to TCP connections that terminate without a FIN. + * + * This idle timeout applies to new streams and is overridable by the + * :ref:`route-level idle_timeout + * `. Even on a stream in + * which the override applies, prior to receipt of the initial request + * headers, the :ref:`stream_idle_timeout + * ` + * applies. Each time an encode/decode event for headers or data is processed + * for the stream, the timer will be reset. If the timeout fires, the stream + * is terminated with a 408 Request Timeout error code if no upstream response + * header has been received, otherwise a stream reset occurs. + * + * Note that it is possible to idle timeout even if the wire traffic for a stream is non-idle, due + * to the granularity of events presented to the connection manager. For example, while receiving + * very large request headers, it may be the case that there is traffic regularly arriving on the + * wire while the connection manage is only able to observe the end-of-headers event, hence the + * stream may still idle timeout. + * + * A value of 0 will completely disable the connection manager stream idle + * timeout, although per-route idle timeout overrides will continue to apply. + */ + 'stream_idle_timeout'?: (_google_protobuf_Duration); + /** + * Configures what network addresses are considered internal for stats and header sanitation + * purposes. If unspecified, only RFC1918 IP addresses will be considered internal. + * See the documentation for :ref:`config_http_conn_man_headers_x-envoy-internal` for more + * information about internal/external addresses. + */ + 'internal_address_config'?: (_envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_InternalAddressConfig); + /** + * The delayed close timeout is for downstream connections managed by the HTTP connection manager. + * It is defined as a grace period after connection close processing has been locally initiated + * during which Envoy will wait for the peer to close (i.e., a TCP FIN/RST is received by Envoy + * from the downstream connection) prior to Envoy closing the socket associated with that + * connection. + * NOTE: This timeout is enforced even when the socket associated with the downstream connection + * is pending a flush of the write buffer. However, any progress made writing data to the socket + * will restart the timer associated with this timeout. This means that the total grace period for + * a socket in this state will be + * +. + * + * Delaying Envoy's connection close and giving the peer the opportunity to initiate the close + * sequence mitigates a race condition that exists when downstream clients do not drain/process + * data in a connection's receive buffer after a remote close has been detected via a socket + * write(). This race leads to such clients failing to process the response code sent by Envoy, + * which could result in erroneous downstream processing. + * + * If the timeout triggers, Envoy will close the connection's socket. + * + * The default timeout is 1000 ms if this option is not specified. + * + * .. NOTE:: + * To be useful in avoiding the race condition described above, this timeout must be set + * to *at least* +<100ms to account for + * a reasonable "worst" case processing time for a full iteration of Envoy's event loop>. + * + * .. WARNING:: + * A value of 0 will completely disable delayed close processing. When disabled, the downstream + * connection's socket will be closed immediately after the write flush is completed or will + * never close if the write flush does not complete. + */ + 'delayed_close_timeout'?: (_google_protobuf_Duration); + /** + * The amount of time that Envoy will wait for the entire request to be received. + * The timer is activated when the request is initiated, and is disarmed when the last byte of the + * request is sent upstream (i.e. all decoding filters have processed the request), OR when the + * response is initiated. If not specified or set to 0, this timeout is disabled. + */ + 'request_timeout'?: (_google_protobuf_Duration); + /** + * The maximum request headers size for incoming connections. + * If unconfigured, the default max request headers allowed is 60 KiB. + * Requests that exceed this limit will receive a 431 response. + * The max configurable limit is 96 KiB, based on current implementation + * constraints. + */ + 'max_request_headers_kb'?: (_google_protobuf_UInt32Value); + /** + * Should paths be normalized according to RFC 3986 before any processing of + * requests by HTTP filters or routing? This affects the upstream *:path* header + * as well. For paths that fail this check, Envoy will respond with 400 to + * paths that are malformed. This defaults to false currently but will default + * true in the future. When not specified, this value may be overridden by the + * runtime variable + * :ref:`http_connection_manager.normalize_path`. + * See `Normalization and Comparison ` + * for details of normalization. + * Note that Envoy does not perform + * `case normalization ` + */ + 'normalize_path'?: (_google_protobuf_BoolValue); + /** + * A route table will be dynamically assigned to each request based on request attributes + * (e.g., the value of a header). The "routing scopes" (i.e., route tables) and "scope keys" are + * specified in this message. + */ + 'scoped_routes'?: (_envoy_config_filter_network_http_connection_manager_v2_ScopedRoutes); + /** + * Whether the connection manager will keep the :ref:`x-request-id + * ` header if passed for a request that is edge + * (Edge request is the request from external clients to front Envoy) and not reset it, which + * is the current Envoy behaviour. This defaults to false. + */ + 'preserve_external_request_id'?: (boolean); + /** + * Determines if adjacent slashes in the path are merged into one before any processing of + * requests by HTTP filters or routing. This affects the upstream *:path* header as well. Without + * setting this option, incoming requests with path `//dir///file` will not match against route + * with `prefix` match set to `/dir`. Defaults to `false`. Note that slash merging is not part of + * `HTTP spec ` and is provided for convenience. + */ + 'merge_slashes'?: (boolean); + /** + * Defines the action to be applied to the Server header on the response path. + * By default, Envoy will overwrite the header with the value specified in + * server_name. + */ + 'server_header_transformation'?: (_envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_ServerHeaderTransformation | keyof typeof _envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_ServerHeaderTransformation); + /** + * Additional settings for HTTP requests handled by the connection manager. These will be + * applicable to both HTTP1 and HTTP2 requests. + */ + 'common_http_protocol_options'?: (_envoy_api_v2_core_HttpProtocolOptions); + /** + * The configuration of the request ID extension. This includes operations such as + * generation, validation, and associated tracing operations. + * + * If not set, Envoy uses the default UUID-based behavior: + * + * 1. Request ID is propagated using *x-request-id* header. + * + * 2. Request ID is a universally unique identifier (UUID). + * + * 3. Tracing decision (sampled, forced, etc) is set in 14th byte of the UUID. + */ + 'request_id_extension'?: (_envoy_config_filter_network_http_connection_manager_v2_RequestIDExtension); + 'route_specifier'?: "rds"|"route_config"|"scoped_routes"; +} + +/** + * [#next-free-field: 37] + */ +export interface HttpConnectionManager__Output { + /** + * Supplies the type of codec that the connection manager should use. + */ + 'codec_type': (keyof typeof _envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_CodecType); + /** + * The human readable prefix to use when emitting statistics for the + * connection manager. See the :ref:`statistics documentation ` for + * more information. + */ + 'stat_prefix': (string); + /** + * The connection manager’s route table will be dynamically loaded via the RDS API. + */ + 'rds'?: (_envoy_config_filter_network_http_connection_manager_v2_Rds__Output); + /** + * The route table for the connection manager is static and is specified in this property. + */ + 'route_config'?: (_envoy_api_v2_RouteConfiguration__Output); + /** + * A list of individual HTTP filters that make up the filter chain for + * requests made to the connection manager. :ref:`Order matters ` + * as the filters are processed sequentially as request events happen. + */ + 'http_filters': (_envoy_config_filter_network_http_connection_manager_v2_HttpFilter__Output)[]; + /** + * Whether the connection manager manipulates the :ref:`config_http_conn_man_headers_user-agent` + * and :ref:`config_http_conn_man_headers_downstream-service-cluster` headers. See the linked + * documentation for more information. Defaults to false. + */ + 'add_user_agent'?: (_google_protobuf_BoolValue__Output); + /** + * Presence of the object defines whether the connection manager + * emits :ref:`tracing ` data to the :ref:`configured tracing provider + * `. + */ + 'tracing'?: (_envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_Tracing__Output); + /** + * Additional HTTP/1 settings that are passed to the HTTP/1 codec. + */ + 'http_protocol_options'?: (_envoy_api_v2_core_Http1ProtocolOptions__Output); + /** + * Additional HTTP/2 settings that are passed directly to the HTTP/2 codec. + */ + 'http2_protocol_options'?: (_envoy_api_v2_core_Http2ProtocolOptions__Output); + /** + * An optional override that the connection manager will write to the server + * header in responses. If not set, the default is *envoy*. + */ + 'server_name': (string); + /** + * The idle timeout for connections managed by the connection manager. The + * idle timeout is defined as the period in which there are no active + * requests. If not set, there is no idle timeout. When the idle timeout is + * reached the connection will be closed. If the connection is an HTTP/2 + * connection a drain sequence will occur prior to closing the connection. + * This field is deprecated. Use :ref:`idle_timeout + * ` + * instead. + */ + 'idle_timeout'?: (_google_protobuf_Duration__Output); + /** + * The time that Envoy will wait between sending an HTTP/2 “shutdown + * notification” (GOAWAY frame with max stream ID) and a final GOAWAY frame. + * This is used so that Envoy provides a grace period for new streams that + * race with the final GOAWAY frame. During this grace period, Envoy will + * continue to accept new streams. After the grace period, a final GOAWAY + * frame is sent and Envoy will start refusing new streams. Draining occurs + * both when a connection hits the idle timeout or during general server + * draining. The default grace period is 5000 milliseconds (5 seconds) if this + * option is not specified. + */ + 'drain_timeout'?: (_google_protobuf_Duration__Output); + /** + * Configuration for :ref:`HTTP access logs ` + * emitted by the connection manager. + */ + 'access_log': (_envoy_config_filter_accesslog_v2_AccessLog__Output)[]; + /** + * If set to true, the connection manager will use the real remote address + * of the client connection when determining internal versus external origin and manipulating + * various headers. If set to false or absent, the connection manager will use the + * :ref:`config_http_conn_man_headers_x-forwarded-for` HTTP header. See the documentation for + * :ref:`config_http_conn_man_headers_x-forwarded-for`, + * :ref:`config_http_conn_man_headers_x-envoy-internal`, and + * :ref:`config_http_conn_man_headers_x-envoy-external-address` for more information. + */ + 'use_remote_address'?: (_google_protobuf_BoolValue__Output); + /** + * Whether the connection manager will generate the :ref:`x-request-id + * ` header if it does not exist. This defaults to + * true. Generating a random UUID4 is expensive so in high throughput scenarios where this feature + * is not desired it can be disabled. + */ + 'generate_request_id'?: (_google_protobuf_BoolValue__Output); + /** + * How to handle the :ref:`config_http_conn_man_headers_x-forwarded-client-cert` (XFCC) HTTP + * header. + */ + 'forward_client_cert_details': (keyof typeof _envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_ForwardClientCertDetails); + /** + * This field is valid only when :ref:`forward_client_cert_details + * ` + * is APPEND_FORWARD or SANITIZE_SET and the client connection is mTLS. It specifies the fields in + * the client certificate to be forwarded. Note that in the + * :ref:`config_http_conn_man_headers_x-forwarded-client-cert` header, *Hash* is always set, and + * *By* is always set when the client certificate presents the URI type Subject Alternative Name + * value. + */ + 'set_current_client_cert_details'?: (_envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_SetCurrentClientCertDetails__Output); + /** + * If proxy_100_continue is true, Envoy will proxy incoming "Expect: + * 100-continue" headers upstream, and forward "100 Continue" responses + * downstream. If this is false or not set, Envoy will instead strip the + * "Expect: 100-continue" header, and send a "100 Continue" response itself. + */ + 'proxy_100_continue': (boolean); + /** + * The number of additional ingress proxy hops from the right side of the + * :ref:`config_http_conn_man_headers_x-forwarded-for` HTTP header to trust when + * determining the origin client's IP address. The default is zero if this option + * is not specified. See the documentation for + * :ref:`config_http_conn_man_headers_x-forwarded-for` for more information. + */ + 'xff_num_trusted_hops': (number); + /** + * If + * :ref:`use_remote_address + * ` + * is true and represent_ipv4_remote_address_as_ipv4_mapped_ipv6 is true and the remote address is + * an IPv4 address, the address will be mapped to IPv6 before it is appended to *x-forwarded-for*. + * This is useful for testing compatibility of upstream services that parse the header value. For + * example, 50.0.0.1 is represented as ::FFFF:50.0.0.1. See `IPv4-Mapped IPv6 Addresses + * `_ for details. This will also affect the + * :ref:`config_http_conn_man_headers_x-envoy-external-address` header. See + * :ref:`http_connection_manager.represent_ipv4_remote_address_as_ipv4_mapped_ipv6 + * ` for runtime + * control. + * [#not-implemented-hide:] + */ + 'represent_ipv4_remote_address_as_ipv4_mapped_ipv6': (boolean); + /** + * If set, Envoy will not append the remote address to the + * :ref:`config_http_conn_man_headers_x-forwarded-for` HTTP header. This may be used in + * conjunction with HTTP filters that explicitly manipulate XFF after the HTTP connection manager + * has mutated the request headers. While :ref:`use_remote_address + * ` + * will also suppress XFF addition, it has consequences for logging and other + * Envoy uses of the remote address, so *skip_xff_append* should be used + * when only an elision of XFF addition is intended. + */ + 'skip_xff_append': (boolean); + /** + * Via header value to append to request and response headers. If this is + * empty, no via header will be appended. + */ + 'via': (string); + 'upgrade_configs': (_envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_UpgradeConfig__Output)[]; + /** + * The stream idle timeout for connections managed by the connection manager. + * If not specified, this defaults to 5 minutes. The default value was selected + * so as not to interfere with any smaller configured timeouts that may have + * existed in configurations prior to the introduction of this feature, while + * introducing robustness to TCP connections that terminate without a FIN. + * + * This idle timeout applies to new streams and is overridable by the + * :ref:`route-level idle_timeout + * `. Even on a stream in + * which the override applies, prior to receipt of the initial request + * headers, the :ref:`stream_idle_timeout + * ` + * applies. Each time an encode/decode event for headers or data is processed + * for the stream, the timer will be reset. If the timeout fires, the stream + * is terminated with a 408 Request Timeout error code if no upstream response + * header has been received, otherwise a stream reset occurs. + * + * Note that it is possible to idle timeout even if the wire traffic for a stream is non-idle, due + * to the granularity of events presented to the connection manager. For example, while receiving + * very large request headers, it may be the case that there is traffic regularly arriving on the + * wire while the connection manage is only able to observe the end-of-headers event, hence the + * stream may still idle timeout. + * + * A value of 0 will completely disable the connection manager stream idle + * timeout, although per-route idle timeout overrides will continue to apply. + */ + 'stream_idle_timeout'?: (_google_protobuf_Duration__Output); + /** + * Configures what network addresses are considered internal for stats and header sanitation + * purposes. If unspecified, only RFC1918 IP addresses will be considered internal. + * See the documentation for :ref:`config_http_conn_man_headers_x-envoy-internal` for more + * information about internal/external addresses. + */ + 'internal_address_config'?: (_envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_InternalAddressConfig__Output); + /** + * The delayed close timeout is for downstream connections managed by the HTTP connection manager. + * It is defined as a grace period after connection close processing has been locally initiated + * during which Envoy will wait for the peer to close (i.e., a TCP FIN/RST is received by Envoy + * from the downstream connection) prior to Envoy closing the socket associated with that + * connection. + * NOTE: This timeout is enforced even when the socket associated with the downstream connection + * is pending a flush of the write buffer. However, any progress made writing data to the socket + * will restart the timer associated with this timeout. This means that the total grace period for + * a socket in this state will be + * +. + * + * Delaying Envoy's connection close and giving the peer the opportunity to initiate the close + * sequence mitigates a race condition that exists when downstream clients do not drain/process + * data in a connection's receive buffer after a remote close has been detected via a socket + * write(). This race leads to such clients failing to process the response code sent by Envoy, + * which could result in erroneous downstream processing. + * + * If the timeout triggers, Envoy will close the connection's socket. + * + * The default timeout is 1000 ms if this option is not specified. + * + * .. NOTE:: + * To be useful in avoiding the race condition described above, this timeout must be set + * to *at least* +<100ms to account for + * a reasonable "worst" case processing time for a full iteration of Envoy's event loop>. + * + * .. WARNING:: + * A value of 0 will completely disable delayed close processing. When disabled, the downstream + * connection's socket will be closed immediately after the write flush is completed or will + * never close if the write flush does not complete. + */ + 'delayed_close_timeout'?: (_google_protobuf_Duration__Output); + /** + * The amount of time that Envoy will wait for the entire request to be received. + * The timer is activated when the request is initiated, and is disarmed when the last byte of the + * request is sent upstream (i.e. all decoding filters have processed the request), OR when the + * response is initiated. If not specified or set to 0, this timeout is disabled. + */ + 'request_timeout'?: (_google_protobuf_Duration__Output); + /** + * The maximum request headers size for incoming connections. + * If unconfigured, the default max request headers allowed is 60 KiB. + * Requests that exceed this limit will receive a 431 response. + * The max configurable limit is 96 KiB, based on current implementation + * constraints. + */ + 'max_request_headers_kb'?: (_google_protobuf_UInt32Value__Output); + /** + * Should paths be normalized according to RFC 3986 before any processing of + * requests by HTTP filters or routing? This affects the upstream *:path* header + * as well. For paths that fail this check, Envoy will respond with 400 to + * paths that are malformed. This defaults to false currently but will default + * true in the future. When not specified, this value may be overridden by the + * runtime variable + * :ref:`http_connection_manager.normalize_path`. + * See `Normalization and Comparison ` + * for details of normalization. + * Note that Envoy does not perform + * `case normalization ` + */ + 'normalize_path'?: (_google_protobuf_BoolValue__Output); + /** + * A route table will be dynamically assigned to each request based on request attributes + * (e.g., the value of a header). The "routing scopes" (i.e., route tables) and "scope keys" are + * specified in this message. + */ + 'scoped_routes'?: (_envoy_config_filter_network_http_connection_manager_v2_ScopedRoutes__Output); + /** + * Whether the connection manager will keep the :ref:`x-request-id + * ` header if passed for a request that is edge + * (Edge request is the request from external clients to front Envoy) and not reset it, which + * is the current Envoy behaviour. This defaults to false. + */ + 'preserve_external_request_id': (boolean); + /** + * Determines if adjacent slashes in the path are merged into one before any processing of + * requests by HTTP filters or routing. This affects the upstream *:path* header as well. Without + * setting this option, incoming requests with path `//dir///file` will not match against route + * with `prefix` match set to `/dir`. Defaults to `false`. Note that slash merging is not part of + * `HTTP spec ` and is provided for convenience. + */ + 'merge_slashes': (boolean); + /** + * Defines the action to be applied to the Server header on the response path. + * By default, Envoy will overwrite the header with the value specified in + * server_name. + */ + 'server_header_transformation': (keyof typeof _envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_ServerHeaderTransformation); + /** + * Additional settings for HTTP requests handled by the connection manager. These will be + * applicable to both HTTP1 and HTTP2 requests. + */ + 'common_http_protocol_options'?: (_envoy_api_v2_core_HttpProtocolOptions__Output); + /** + * The configuration of the request ID extension. This includes operations such as + * generation, validation, and associated tracing operations. + * + * If not set, Envoy uses the default UUID-based behavior: + * + * 1. Request ID is propagated using *x-request-id* header. + * + * 2. Request ID is a universally unique identifier (UUID). + * + * 3. Tracing decision (sampled, forced, etc) is set in 14th byte of the UUID. + */ + 'request_id_extension'?: (_envoy_config_filter_network_http_connection_manager_v2_RequestIDExtension__Output); + 'route_specifier': "rds"|"route_config"|"scoped_routes"; +} diff --git a/packages/grpc-js/src/generated/envoy/config/filter/network/http_connection_manager/v2/HttpFilter.ts b/packages/grpc-js/src/generated/envoy/config/filter/network/http_connection_manager/v2/HttpFilter.ts new file mode 100644 index 00000000..cf68dd98 --- /dev/null +++ b/packages/grpc-js/src/generated/envoy/config/filter/network/http_connection_manager/v2/HttpFilter.ts @@ -0,0 +1,34 @@ +// Original file: deps/envoy-api/envoy/config/filter/network/http_connection_manager/v2/http_connection_manager.proto + +import { Struct as _google_protobuf_Struct, Struct__Output as _google_protobuf_Struct__Output } from '../../../../../../google/protobuf/Struct'; +import { Any as _google_protobuf_Any, Any__Output as _google_protobuf_Any__Output } from '../../../../../../google/protobuf/Any'; + +export interface HttpFilter { + /** + * The name of the filter to instantiate. The name must match a + * :ref:`supported filter `. + */ + 'name'?: (string); + 'config'?: (_google_protobuf_Struct); + 'typed_config'?: (_google_protobuf_Any); + /** + * Filter specific configuration which depends on the filter being instantiated. See the supported + * filters for further documentation. + */ + 'config_type'?: "config"|"typed_config"; +} + +export interface HttpFilter__Output { + /** + * The name of the filter to instantiate. The name must match a + * :ref:`supported filter `. + */ + 'name': (string); + 'config'?: (_google_protobuf_Struct__Output); + 'typed_config'?: (_google_protobuf_Any__Output); + /** + * Filter specific configuration which depends on the filter being instantiated. See the supported + * filters for further documentation. + */ + 'config_type': "config"|"typed_config"; +} diff --git a/packages/grpc-js/src/generated/envoy/config/filter/network/http_connection_manager/v2/Rds.ts b/packages/grpc-js/src/generated/envoy/config/filter/network/http_connection_manager/v2/Rds.ts new file mode 100644 index 00000000..306cc0dd --- /dev/null +++ b/packages/grpc-js/src/generated/envoy/config/filter/network/http_connection_manager/v2/Rds.ts @@ -0,0 +1,31 @@ +// Original file: deps/envoy-api/envoy/config/filter/network/http_connection_manager/v2/http_connection_manager.proto + +import { ConfigSource as _envoy_api_v2_core_ConfigSource, ConfigSource__Output as _envoy_api_v2_core_ConfigSource__Output } from '../../../../../../envoy/api/v2/core/ConfigSource'; + +export interface Rds { + /** + * Configuration source specifier for RDS. + */ + 'config_source'?: (_envoy_api_v2_core_ConfigSource); + /** + * The name of the route configuration. This name will be passed to the RDS + * API. This allows an Envoy configuration with multiple HTTP listeners (and + * associated HTTP connection manager filters) to use different route + * configurations. + */ + 'route_config_name'?: (string); +} + +export interface Rds__Output { + /** + * Configuration source specifier for RDS. + */ + 'config_source'?: (_envoy_api_v2_core_ConfigSource__Output); + /** + * The name of the route configuration. This name will be passed to the RDS + * API. This allows an Envoy configuration with multiple HTTP listeners (and + * associated HTTP connection manager filters) to use different route + * configurations. + */ + 'route_config_name': (string); +} diff --git a/packages/grpc-js/src/generated/envoy/config/filter/network/http_connection_manager/v2/RequestIDExtension.ts b/packages/grpc-js/src/generated/envoy/config/filter/network/http_connection_manager/v2/RequestIDExtension.ts new file mode 100644 index 00000000..4688b09c --- /dev/null +++ b/packages/grpc-js/src/generated/envoy/config/filter/network/http_connection_manager/v2/RequestIDExtension.ts @@ -0,0 +1,17 @@ +// Original file: deps/envoy-api/envoy/config/filter/network/http_connection_manager/v2/http_connection_manager.proto + +import { Any as _google_protobuf_Any, Any__Output as _google_protobuf_Any__Output } from '../../../../../../google/protobuf/Any'; + +export interface RequestIDExtension { + /** + * Request ID extension specific configuration. + */ + 'typed_config'?: (_google_protobuf_Any); +} + +export interface RequestIDExtension__Output { + /** + * Request ID extension specific configuration. + */ + 'typed_config'?: (_google_protobuf_Any__Output); +} diff --git a/packages/grpc-js/src/generated/envoy/config/filter/network/http_connection_manager/v2/ScopedRds.ts b/packages/grpc-js/src/generated/envoy/config/filter/network/http_connection_manager/v2/ScopedRds.ts new file mode 100644 index 00000000..989aee15 --- /dev/null +++ b/packages/grpc-js/src/generated/envoy/config/filter/network/http_connection_manager/v2/ScopedRds.ts @@ -0,0 +1,17 @@ +// Original file: deps/envoy-api/envoy/config/filter/network/http_connection_manager/v2/http_connection_manager.proto + +import { ConfigSource as _envoy_api_v2_core_ConfigSource, ConfigSource__Output as _envoy_api_v2_core_ConfigSource__Output } from '../../../../../../envoy/api/v2/core/ConfigSource'; + +export interface ScopedRds { + /** + * Configuration source specifier for scoped RDS. + */ + 'scoped_rds_config_source'?: (_envoy_api_v2_core_ConfigSource); +} + +export interface ScopedRds__Output { + /** + * Configuration source specifier for scoped RDS. + */ + 'scoped_rds_config_source'?: (_envoy_api_v2_core_ConfigSource__Output); +} diff --git a/packages/grpc-js/src/generated/envoy/config/filter/network/http_connection_manager/v2/ScopedRouteConfigurationsList.ts b/packages/grpc-js/src/generated/envoy/config/filter/network/http_connection_manager/v2/ScopedRouteConfigurationsList.ts new file mode 100644 index 00000000..81de7333 --- /dev/null +++ b/packages/grpc-js/src/generated/envoy/config/filter/network/http_connection_manager/v2/ScopedRouteConfigurationsList.ts @@ -0,0 +1,17 @@ +// Original file: deps/envoy-api/envoy/config/filter/network/http_connection_manager/v2/http_connection_manager.proto + +import { ScopedRouteConfiguration as _envoy_api_v2_ScopedRouteConfiguration, ScopedRouteConfiguration__Output as _envoy_api_v2_ScopedRouteConfiguration__Output } from '../../../../../../envoy/api/v2/ScopedRouteConfiguration'; + +/** + * This message is used to work around the limitations with 'oneof' and repeated fields. + */ +export interface ScopedRouteConfigurationsList { + 'scoped_route_configurations'?: (_envoy_api_v2_ScopedRouteConfiguration)[]; +} + +/** + * This message is used to work around the limitations with 'oneof' and repeated fields. + */ +export interface ScopedRouteConfigurationsList__Output { + 'scoped_route_configurations': (_envoy_api_v2_ScopedRouteConfiguration__Output)[]; +} diff --git a/packages/grpc-js/src/generated/envoy/config/filter/network/http_connection_manager/v2/ScopedRoutes.ts b/packages/grpc-js/src/generated/envoy/config/filter/network/http_connection_manager/v2/ScopedRoutes.ts new file mode 100644 index 00000000..1409cb89 --- /dev/null +++ b/packages/grpc-js/src/generated/envoy/config/filter/network/http_connection_manager/v2/ScopedRoutes.ts @@ -0,0 +1,265 @@ +// Original file: deps/envoy-api/envoy/config/filter/network/http_connection_manager/v2/http_connection_manager.proto + +import { ConfigSource as _envoy_api_v2_core_ConfigSource, ConfigSource__Output as _envoy_api_v2_core_ConfigSource__Output } from '../../../../../../envoy/api/v2/core/ConfigSource'; +import { ScopedRouteConfigurationsList as _envoy_config_filter_network_http_connection_manager_v2_ScopedRouteConfigurationsList, ScopedRouteConfigurationsList__Output as _envoy_config_filter_network_http_connection_manager_v2_ScopedRouteConfigurationsList__Output } from '../../../../../../envoy/config/filter/network/http_connection_manager/v2/ScopedRouteConfigurationsList'; +import { ScopedRds as _envoy_config_filter_network_http_connection_manager_v2_ScopedRds, ScopedRds__Output as _envoy_config_filter_network_http_connection_manager_v2_ScopedRds__Output } from '../../../../../../envoy/config/filter/network/http_connection_manager/v2/ScopedRds'; + +/** + * Specifies the mechanism for constructing key fragments which are composed into scope keys. + */ +export interface _envoy_config_filter_network_http_connection_manager_v2_ScopedRoutes_ScopeKeyBuilder_FragmentBuilder { + /** + * Specifies how a header field's value should be extracted. + */ + 'header_value_extractor'?: (_envoy_config_filter_network_http_connection_manager_v2_ScopedRoutes_ScopeKeyBuilder_FragmentBuilder_HeaderValueExtractor); + 'type'?: "header_value_extractor"; +} + +/** + * Specifies the mechanism for constructing key fragments which are composed into scope keys. + */ +export interface _envoy_config_filter_network_http_connection_manager_v2_ScopedRoutes_ScopeKeyBuilder_FragmentBuilder__Output { + /** + * Specifies how a header field's value should be extracted. + */ + 'header_value_extractor'?: (_envoy_config_filter_network_http_connection_manager_v2_ScopedRoutes_ScopeKeyBuilder_FragmentBuilder_HeaderValueExtractor__Output); + 'type': "header_value_extractor"; +} + +/** + * Specifies how the value of a header should be extracted. + * The following example maps the structure of a header to the fields in this message. + * + * .. code:: + * + * <0> <1> <-- index + * X-Header: a=b;c=d + * | || | + * | || \----> + * | || + * | |\----> + * | | + * | \----> + * | + * \----> + * + * Each 'a=b' key-value pair constitutes an 'element' of the header field. + */ +export interface _envoy_config_filter_network_http_connection_manager_v2_ScopedRoutes_ScopeKeyBuilder_FragmentBuilder_HeaderValueExtractor { + /** + * The name of the header field to extract the value from. + */ + 'name'?: (string); + /** + * The element separator (e.g., ';' separates 'a;b;c;d'). + * Default: empty string. This causes the entirety of the header field to be extracted. + * If this field is set to an empty string and 'index' is used in the oneof below, 'index' + * must be set to 0. + */ + 'element_separator'?: (string); + /** + * Specifies the zero based index of the element to extract. + * Note Envoy concatenates multiple values of the same header key into a comma separated + * string, the splitting always happens after the concatenation. + */ + 'index'?: (number); + /** + * Specifies the key value pair to extract the value from. + */ + 'element'?: (_envoy_config_filter_network_http_connection_manager_v2_ScopedRoutes_ScopeKeyBuilder_FragmentBuilder_HeaderValueExtractor_KvElement); + 'extract_type'?: "index"|"element"; +} + +/** + * Specifies how the value of a header should be extracted. + * The following example maps the structure of a header to the fields in this message. + * + * .. code:: + * + * <0> <1> <-- index + * X-Header: a=b;c=d + * | || | + * | || \----> + * | || + * | |\----> + * | | + * | \----> + * | + * \----> + * + * Each 'a=b' key-value pair constitutes an 'element' of the header field. + */ +export interface _envoy_config_filter_network_http_connection_manager_v2_ScopedRoutes_ScopeKeyBuilder_FragmentBuilder_HeaderValueExtractor__Output { + /** + * The name of the header field to extract the value from. + */ + 'name': (string); + /** + * The element separator (e.g., ';' separates 'a;b;c;d'). + * Default: empty string. This causes the entirety of the header field to be extracted. + * If this field is set to an empty string and 'index' is used in the oneof below, 'index' + * must be set to 0. + */ + 'element_separator': (string); + /** + * Specifies the zero based index of the element to extract. + * Note Envoy concatenates multiple values of the same header key into a comma separated + * string, the splitting always happens after the concatenation. + */ + 'index'?: (number); + /** + * Specifies the key value pair to extract the value from. + */ + 'element'?: (_envoy_config_filter_network_http_connection_manager_v2_ScopedRoutes_ScopeKeyBuilder_FragmentBuilder_HeaderValueExtractor_KvElement__Output); + 'extract_type': "index"|"element"; +} + +/** + * Specifies a header field's key value pair to match on. + */ +export interface _envoy_config_filter_network_http_connection_manager_v2_ScopedRoutes_ScopeKeyBuilder_FragmentBuilder_HeaderValueExtractor_KvElement { + /** + * The separator between key and value (e.g., '=' separates 'k=v;...'). + * If an element is an empty string, the element is ignored. + * If an element contains no separator, the whole element is parsed as key and the + * fragment value is an empty string. + * If there are multiple values for a matched key, the first value is returned. + */ + 'separator'?: (string); + /** + * The key to match on. + */ + 'key'?: (string); +} + +/** + * Specifies a header field's key value pair to match on. + */ +export interface _envoy_config_filter_network_http_connection_manager_v2_ScopedRoutes_ScopeKeyBuilder_FragmentBuilder_HeaderValueExtractor_KvElement__Output { + /** + * The separator between key and value (e.g., '=' separates 'k=v;...'). + * If an element is an empty string, the element is ignored. + * If an element contains no separator, the whole element is parsed as key and the + * fragment value is an empty string. + * If there are multiple values for a matched key, the first value is returned. + */ + 'separator': (string); + /** + * The key to match on. + */ + 'key': (string); +} + +/** + * Specifies the mechanism for constructing "scope keys" based on HTTP request attributes. These + * keys are matched against a set of :ref:`Key` + * objects assembled from :ref:`ScopedRouteConfiguration` + * messages distributed via SRDS (the Scoped Route Discovery Service) or assigned statically via + * :ref:`scoped_route_configurations_list`. + * + * Upon receiving a request's headers, the Router will build a key using the algorithm specified + * by this message. This key will be used to look up the routing table (i.e., the + * :ref:`RouteConfiguration`) to use for the request. + */ +export interface _envoy_config_filter_network_http_connection_manager_v2_ScopedRoutes_ScopeKeyBuilder { + /** + * The final(built) scope key consists of the ordered union of these fragments, which are compared in order with the + * fragments of a :ref:`ScopedRouteConfiguration`. + * A missing fragment during comparison will make the key invalid, i.e., the computed key doesn't match any key. + */ + 'fragments'?: (_envoy_config_filter_network_http_connection_manager_v2_ScopedRoutes_ScopeKeyBuilder_FragmentBuilder)[]; +} + +/** + * Specifies the mechanism for constructing "scope keys" based on HTTP request attributes. These + * keys are matched against a set of :ref:`Key` + * objects assembled from :ref:`ScopedRouteConfiguration` + * messages distributed via SRDS (the Scoped Route Discovery Service) or assigned statically via + * :ref:`scoped_route_configurations_list`. + * + * Upon receiving a request's headers, the Router will build a key using the algorithm specified + * by this message. This key will be used to look up the routing table (i.e., the + * :ref:`RouteConfiguration`) to use for the request. + */ +export interface _envoy_config_filter_network_http_connection_manager_v2_ScopedRoutes_ScopeKeyBuilder__Output { + /** + * The final(built) scope key consists of the ordered union of these fragments, which are compared in order with the + * fragments of a :ref:`ScopedRouteConfiguration`. + * A missing fragment during comparison will make the key invalid, i.e., the computed key doesn't match any key. + */ + 'fragments': (_envoy_config_filter_network_http_connection_manager_v2_ScopedRoutes_ScopeKeyBuilder_FragmentBuilder__Output)[]; +} + +/** + * [#next-free-field: 6] + */ +export interface ScopedRoutes { + /** + * The name assigned to the scoped routing configuration. + */ + 'name'?: (string); + /** + * The algorithm to use for constructing a scope key for each request. + */ + 'scope_key_builder'?: (_envoy_config_filter_network_http_connection_manager_v2_ScopedRoutes_ScopeKeyBuilder); + /** + * Configuration source specifier for RDS. + * This config source is used to subscribe to RouteConfiguration resources specified in + * ScopedRouteConfiguration messages. + */ + 'rds_config_source'?: (_envoy_api_v2_core_ConfigSource); + /** + * The set of routing scopes corresponding to the HCM. A scope is assigned to a request by + * matching a key constructed from the request's attributes according to the algorithm specified + * by the + * :ref:`ScopeKeyBuilder` + * in this message. + */ + 'scoped_route_configurations_list'?: (_envoy_config_filter_network_http_connection_manager_v2_ScopedRouteConfigurationsList); + /** + * The set of routing scopes associated with the HCM will be dynamically loaded via the SRDS + * API. A scope is assigned to a request by matching a key constructed from the request's + * attributes according to the algorithm specified by the + * :ref:`ScopeKeyBuilder` + * in this message. + */ + 'scoped_rds'?: (_envoy_config_filter_network_http_connection_manager_v2_ScopedRds); + 'config_specifier'?: "scoped_route_configurations_list"|"scoped_rds"; +} + +/** + * [#next-free-field: 6] + */ +export interface ScopedRoutes__Output { + /** + * The name assigned to the scoped routing configuration. + */ + 'name': (string); + /** + * The algorithm to use for constructing a scope key for each request. + */ + 'scope_key_builder'?: (_envoy_config_filter_network_http_connection_manager_v2_ScopedRoutes_ScopeKeyBuilder__Output); + /** + * Configuration source specifier for RDS. + * This config source is used to subscribe to RouteConfiguration resources specified in + * ScopedRouteConfiguration messages. + */ + 'rds_config_source'?: (_envoy_api_v2_core_ConfigSource__Output); + /** + * The set of routing scopes corresponding to the HCM. A scope is assigned to a request by + * matching a key constructed from the request's attributes according to the algorithm specified + * by the + * :ref:`ScopeKeyBuilder` + * in this message. + */ + 'scoped_route_configurations_list'?: (_envoy_config_filter_network_http_connection_manager_v2_ScopedRouteConfigurationsList__Output); + /** + * The set of routing scopes associated with the HCM will be dynamically loaded via the SRDS + * API. A scope is assigned to a request by matching a key constructed from the request's + * attributes according to the algorithm specified by the + * :ref:`ScopeKeyBuilder` + * in this message. + */ + 'scoped_rds'?: (_envoy_config_filter_network_http_connection_manager_v2_ScopedRds__Output); + 'config_specifier': "scoped_route_configurations_list"|"scoped_rds"; +} diff --git a/packages/grpc-js/src/generated/envoy/config/trace/v2/Tracing.ts b/packages/grpc-js/src/generated/envoy/config/trace/v2/Tracing.ts new file mode 100644 index 00000000..b7ee1c3a --- /dev/null +++ b/packages/grpc-js/src/generated/envoy/config/trace/v2/Tracing.ts @@ -0,0 +1,114 @@ +// Original file: deps/envoy-api/envoy/config/trace/v2/http_tracer.proto + +import { Struct as _google_protobuf_Struct, Struct__Output as _google_protobuf_Struct__Output } from '../../../../google/protobuf/Struct'; +import { Any as _google_protobuf_Any, Any__Output as _google_protobuf_Any__Output } from '../../../../google/protobuf/Any'; + +/** + * Configuration for an HTTP tracer provider used by Envoy. + * + * The configuration is defined by the + * :ref:`HttpConnectionManager.Tracing ` + * :ref:`provider ` + * field. + */ +export interface _envoy_config_trace_v2_Tracing_Http { + /** + * The name of the HTTP trace driver to instantiate. The name must match a + * supported HTTP trace driver. Built-in trace drivers: + * + * - *envoy.tracers.lightstep* + * - *envoy.tracers.zipkin* + * - *envoy.tracers.dynamic_ot* + * - *envoy.tracers.datadog* + * - *envoy.tracers.opencensus* + * - *envoy.tracers.xray* + */ + 'name'?: (string); + 'config'?: (_google_protobuf_Struct); + 'typed_config'?: (_google_protobuf_Any); + /** + * Trace driver specific configuration which depends on the driver being instantiated. + * See the trace drivers for examples: + * + * - :ref:`LightstepConfig ` + * - :ref:`ZipkinConfig ` + * - :ref:`DynamicOtConfig ` + * - :ref:`DatadogConfig ` + * - :ref:`OpenCensusConfig ` + * - :ref:`AWS X-Ray ` + */ + 'config_type'?: "config"|"typed_config"; +} + +/** + * Configuration for an HTTP tracer provider used by Envoy. + * + * The configuration is defined by the + * :ref:`HttpConnectionManager.Tracing ` + * :ref:`provider ` + * field. + */ +export interface _envoy_config_trace_v2_Tracing_Http__Output { + /** + * The name of the HTTP trace driver to instantiate. The name must match a + * supported HTTP trace driver. Built-in trace drivers: + * + * - *envoy.tracers.lightstep* + * - *envoy.tracers.zipkin* + * - *envoy.tracers.dynamic_ot* + * - *envoy.tracers.datadog* + * - *envoy.tracers.opencensus* + * - *envoy.tracers.xray* + */ + 'name': (string); + 'config'?: (_google_protobuf_Struct__Output); + 'typed_config'?: (_google_protobuf_Any__Output); + /** + * Trace driver specific configuration which depends on the driver being instantiated. + * See the trace drivers for examples: + * + * - :ref:`LightstepConfig ` + * - :ref:`ZipkinConfig ` + * - :ref:`DynamicOtConfig ` + * - :ref:`DatadogConfig ` + * - :ref:`OpenCensusConfig ` + * - :ref:`AWS X-Ray ` + */ + 'config_type': "config"|"typed_config"; +} + +/** + * The tracing configuration specifies settings for an HTTP tracer provider used by Envoy. + * + * Envoy may support other tracers in the future, but right now the HTTP tracer is the only one + * supported. + * + * .. attention:: + * + * Use of this message type has been deprecated in favor of direct use of + * :ref:`Tracing.Http `. + */ +export interface Tracing { + /** + * Provides configuration for the HTTP tracer. + */ + 'http'?: (_envoy_config_trace_v2_Tracing_Http); +} + +/** + * The tracing configuration specifies settings for an HTTP tracer provider used by Envoy. + * + * Envoy may support other tracers in the future, but right now the HTTP tracer is the only one + * supported. + * + * .. attention:: + * + * Use of this message type has been deprecated in favor of direct use of + * :ref:`Tracing.Http `. + */ +export interface Tracing__Output { + /** + * Provides configuration for the HTTP tracer. + */ + 'http'?: (_envoy_config_trace_v2_Tracing_Http__Output); +} diff --git a/packages/grpc-js/src/generated/google/protobuf/MethodOptions.ts b/packages/grpc-js/src/generated/google/protobuf/MethodOptions.ts index a5edbd8b..982c7d5d 100644 --- a/packages/grpc-js/src/generated/google/protobuf/MethodOptions.ts +++ b/packages/grpc-js/src/generated/google/protobuf/MethodOptions.ts @@ -1,16 +1,13 @@ // Original file: null import { UninterpretedOption as _google_protobuf_UninterpretedOption, UninterpretedOption__Output as _google_protobuf_UninterpretedOption__Output } from '../../google/protobuf/UninterpretedOption'; -import { HttpRule as _google_api_HttpRule, HttpRule__Output as _google_api_HttpRule__Output } from '../../google/api/HttpRule'; export interface MethodOptions { 'deprecated'?: (boolean); 'uninterpretedOption'?: (_google_protobuf_UninterpretedOption)[]; - '.google.api.http'?: (_google_api_HttpRule); } export interface MethodOptions__Output { 'deprecated': (boolean); 'uninterpretedOption': (_google_protobuf_UninterpretedOption__Output)[]; - '.google.api.http'?: (_google_api_HttpRule__Output); } diff --git a/packages/grpc-js/src/generated/http_connection_manager.ts b/packages/grpc-js/src/generated/http_connection_manager.ts new file mode 100644 index 00000000..37fe303b --- /dev/null +++ b/packages/grpc-js/src/generated/http_connection_manager.ts @@ -0,0 +1,228 @@ +import * as grpc from '../index'; +import { ServiceDefinition, EnumTypeDefinition, MessageTypeDefinition } from '@grpc/proto-loader'; + + +type ConstructorArguments = Constructor extends new (...args: infer Args) => any ? Args: never; +type SubtypeConstructor = { + new(...args: ConstructorArguments): Subtype; +} + +export interface ProtoGrpcType { + envoy: { + annotations: { + } + api: { + v2: { + RouteConfiguration: MessageTypeDefinition + ScopedRouteConfiguration: MessageTypeDefinition + Vhds: MessageTypeDefinition + core: { + Address: MessageTypeDefinition + AggregatedConfigSource: MessageTypeDefinition + ApiConfigSource: MessageTypeDefinition + ApiVersion: EnumTypeDefinition + AsyncDataSource: MessageTypeDefinition + BackoffStrategy: MessageTypeDefinition + BindConfig: MessageTypeDefinition + BuildVersion: MessageTypeDefinition + CidrRange: MessageTypeDefinition + ConfigSource: MessageTypeDefinition + ControlPlane: MessageTypeDefinition + DataSource: MessageTypeDefinition + Extension: MessageTypeDefinition + GrpcProtocolOptions: MessageTypeDefinition + GrpcService: MessageTypeDefinition + HeaderMap: MessageTypeDefinition + HeaderValue: MessageTypeDefinition + HeaderValueOption: MessageTypeDefinition + Http1ProtocolOptions: MessageTypeDefinition + Http2ProtocolOptions: MessageTypeDefinition + HttpProtocolOptions: MessageTypeDefinition + HttpUri: MessageTypeDefinition + Locality: MessageTypeDefinition + Metadata: MessageTypeDefinition + Node: MessageTypeDefinition + Pipe: MessageTypeDefinition + RateLimitSettings: MessageTypeDefinition + RemoteDataSource: MessageTypeDefinition + RequestMethod: EnumTypeDefinition + RetryPolicy: MessageTypeDefinition + RoutingPriority: EnumTypeDefinition + RuntimeDouble: MessageTypeDefinition + RuntimeFeatureFlag: MessageTypeDefinition + RuntimeFractionalPercent: MessageTypeDefinition + RuntimeUInt32: MessageTypeDefinition + SelfConfigSource: MessageTypeDefinition + SocketAddress: MessageTypeDefinition + SocketOption: MessageTypeDefinition + TcpKeepalive: MessageTypeDefinition + TcpProtocolOptions: MessageTypeDefinition + TrafficDirection: EnumTypeDefinition + TransportSocket: MessageTypeDefinition + UpstreamHttpProtocolOptions: MessageTypeDefinition + } + route: { + CorsPolicy: MessageTypeDefinition + Decorator: MessageTypeDefinition + DirectResponseAction: MessageTypeDefinition + FilterAction: MessageTypeDefinition + HeaderMatcher: MessageTypeDefinition + HedgePolicy: MessageTypeDefinition + QueryParameterMatcher: MessageTypeDefinition + RateLimit: MessageTypeDefinition + RedirectAction: MessageTypeDefinition + RetryPolicy: MessageTypeDefinition + Route: MessageTypeDefinition + RouteAction: MessageTypeDefinition + RouteMatch: MessageTypeDefinition + Tracing: MessageTypeDefinition + VirtualCluster: MessageTypeDefinition + VirtualHost: MessageTypeDefinition + WeightedCluster: MessageTypeDefinition + } + } + } + config: { + filter: { + accesslog: { + v2: { + AccessLog: MessageTypeDefinition + AccessLogFilter: MessageTypeDefinition + AndFilter: MessageTypeDefinition + ComparisonFilter: MessageTypeDefinition + DurationFilter: MessageTypeDefinition + ExtensionFilter: MessageTypeDefinition + GrpcStatusFilter: MessageTypeDefinition + HeaderFilter: MessageTypeDefinition + NotHealthCheckFilter: MessageTypeDefinition + OrFilter: MessageTypeDefinition + ResponseFlagFilter: MessageTypeDefinition + RuntimeFilter: MessageTypeDefinition + StatusCodeFilter: MessageTypeDefinition + TraceableFilter: MessageTypeDefinition + } + } + network: { + http_connection_manager: { + v2: { + HttpConnectionManager: MessageTypeDefinition + HttpFilter: MessageTypeDefinition + Rds: MessageTypeDefinition + RequestIDExtension: MessageTypeDefinition + ScopedRds: MessageTypeDefinition + ScopedRouteConfigurationsList: MessageTypeDefinition + ScopedRoutes: MessageTypeDefinition + } + } + } + } + trace: { + v2: { + Tracing: MessageTypeDefinition + } + } + } + type: { + DoubleRange: MessageTypeDefinition + FractionalPercent: MessageTypeDefinition + Int32Range: MessageTypeDefinition + Int64Range: MessageTypeDefinition + Percent: MessageTypeDefinition + SemanticVersion: MessageTypeDefinition + matcher: { + ListStringMatcher: MessageTypeDefinition + RegexMatchAndSubstitute: MessageTypeDefinition + RegexMatcher: MessageTypeDefinition + StringMatcher: MessageTypeDefinition + } + metadata: { + v2: { + MetadataKey: MessageTypeDefinition + MetadataKind: MessageTypeDefinition + } + } + tracing: { + v2: { + CustomTag: MessageTypeDefinition + } + } + } + } + google: { + protobuf: { + Any: MessageTypeDefinition + BoolValue: MessageTypeDefinition + BytesValue: MessageTypeDefinition + DescriptorProto: MessageTypeDefinition + DoubleValue: MessageTypeDefinition + Duration: MessageTypeDefinition + Empty: MessageTypeDefinition + EnumDescriptorProto: MessageTypeDefinition + EnumOptions: MessageTypeDefinition + EnumValueDescriptorProto: MessageTypeDefinition + EnumValueOptions: MessageTypeDefinition + FieldDescriptorProto: MessageTypeDefinition + FieldOptions: MessageTypeDefinition + FileDescriptorProto: MessageTypeDefinition + FileDescriptorSet: MessageTypeDefinition + FileOptions: MessageTypeDefinition + FloatValue: MessageTypeDefinition + GeneratedCodeInfo: MessageTypeDefinition + Int32Value: MessageTypeDefinition + Int64Value: MessageTypeDefinition + ListValue: MessageTypeDefinition + MessageOptions: MessageTypeDefinition + MethodDescriptorProto: MessageTypeDefinition + MethodOptions: MessageTypeDefinition + NullValue: EnumTypeDefinition + OneofDescriptorProto: MessageTypeDefinition + OneofOptions: MessageTypeDefinition + ServiceDescriptorProto: MessageTypeDefinition + ServiceOptions: MessageTypeDefinition + SourceCodeInfo: MessageTypeDefinition + StringValue: MessageTypeDefinition + Struct: MessageTypeDefinition + Timestamp: MessageTypeDefinition + UInt32Value: MessageTypeDefinition + UInt64Value: MessageTypeDefinition + UninterpretedOption: MessageTypeDefinition + Value: MessageTypeDefinition + } + } + udpa: { + annotations: { + FieldMigrateAnnotation: MessageTypeDefinition + FileMigrateAnnotation: MessageTypeDefinition + MigrateAnnotation: MessageTypeDefinition + PackageVersionStatus: EnumTypeDefinition + StatusAnnotation: MessageTypeDefinition + } + } + validate: { + AnyRules: MessageTypeDefinition + BoolRules: MessageTypeDefinition + BytesRules: MessageTypeDefinition + DoubleRules: MessageTypeDefinition + DurationRules: MessageTypeDefinition + EnumRules: MessageTypeDefinition + FieldRules: MessageTypeDefinition + Fixed32Rules: MessageTypeDefinition + Fixed64Rules: MessageTypeDefinition + FloatRules: MessageTypeDefinition + Int32Rules: MessageTypeDefinition + Int64Rules: MessageTypeDefinition + KnownRegex: EnumTypeDefinition + MapRules: MessageTypeDefinition + MessageRules: MessageTypeDefinition + RepeatedRules: MessageTypeDefinition + SFixed32Rules: MessageTypeDefinition + SFixed64Rules: MessageTypeDefinition + SInt32Rules: MessageTypeDefinition + SInt64Rules: MessageTypeDefinition + StringRules: MessageTypeDefinition + TimestampRules: MessageTypeDefinition + UInt32Rules: MessageTypeDefinition + UInt64Rules: MessageTypeDefinition + } +} + diff --git a/packages/grpc-js/src/resolver-dns.ts b/packages/grpc-js/src/resolver-dns.ts index 74e43ca0..2db8a5e4 100644 --- a/packages/grpc-js/src/resolver-dns.ts +++ b/packages/grpc-js/src/resolver-dns.ts @@ -31,6 +31,7 @@ import { LogVerbosity } from './constants'; import { SubchannelAddress, TcpSubchannelAddress } from './subchannel'; import { GrpcUri, uriToString, splitHostPort } from './uri-parser'; import { isIPv6, isIPv4 } from 'net'; +import { ChannelOptions } from './channel-options'; const TRACER_NAME = 'dns_resolver'; @@ -84,7 +85,11 @@ class DnsResolver implements Resolver { private latestServiceConfigError: StatusObject | null = null; private percentage: number; private defaultResolutionError: StatusObject; - constructor(private target: GrpcUri, private listener: ResolverListener) { + constructor( + private target: GrpcUri, + private listener: ResolverListener, + channelOptions: ChannelOptions + ) { trace('Resolver constructed for target ' + uriToString(target)); const hostPort = splitHostPort(target.path); if (hostPort === null) { diff --git a/packages/grpc-js/src/resolver-uds.ts b/packages/grpc-js/src/resolver-uds.ts index 25856913..14bc0176 100644 --- a/packages/grpc-js/src/resolver-uds.ts +++ b/packages/grpc-js/src/resolver-uds.ts @@ -17,10 +17,15 @@ import { Resolver, ResolverListener, registerResolver } from './resolver'; import { SubchannelAddress } from './subchannel'; import { GrpcUri } from './uri-parser'; +import { ChannelOptions } from './channel-options'; class UdsResolver implements Resolver { private addresses: SubchannelAddress[] = []; - constructor(target: GrpcUri, private listener: ResolverListener) { + constructor( + target: GrpcUri, + private listener: ResolverListener, + channelOptions: ChannelOptions + ) { let path: string; if (target.authority === '') { path = '/' + target.path; diff --git a/packages/grpc-js/src/resolver-xds.ts b/packages/grpc-js/src/resolver-xds.ts new file mode 100644 index 00000000..e92fddff --- /dev/null +++ b/packages/grpc-js/src/resolver-xds.ts @@ -0,0 +1,82 @@ +/* + * Copyright 2019 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Resolver, ResolverListener, registerResolver } from './resolver'; +import { GrpcUri, uriToString } from './uri-parser'; +import { XdsClient } from './xds-client'; +import { ServiceConfig } from './service-config'; +import { StatusObject } from './call-stream'; +import { Status } from './constants'; +import { Metadata } from './metadata'; +import { ChannelOptions } from './channel-options'; + +class XdsResolver implements Resolver { + private resolutionStarted = false; + private hasReportedSuccess = false; + + constructor( + private target: GrpcUri, + private listener: ResolverListener, + private channelOptions: ChannelOptions + ) {} + + private reportResolutionError() { + this.listener.onError({ + code: Status.UNAVAILABLE, + details: `xDS name resolution failed for target ${uriToString( + this.target + )}`, + metadata: new Metadata(), + }); + } + + updateResolution(): void { + // Wait until updateResolution is called once to start the xDS requests + if (!this.resolutionStarted) { + this.resolutionStarted = true; + const xdsClient = new XdsClient( + this.target.path, + { + onValidUpdate: (update: ServiceConfig) => { + this.hasReportedSuccess = true; + this.listener.onSuccessfulResolution([], update, null, { + xdsClient: xdsClient, + }); + }, + onTransientError: (error: StatusObject) => { + /* A transient error only needs to bubble up as a failure if we have + * not already provided a ServiceConfig for the upper layer to use */ + if (!this.hasReportedSuccess) { + this.reportResolutionError(); + } + }, + onResourceDoesNotExist: () => { + this.reportResolutionError(); + }, + }, + this.channelOptions + ); + } + } + + static getDefaultAuthority(target: GrpcUri) { + return target.path; + } +} + +export function setup() { + registerResolver('xds', XdsResolver); +} diff --git a/packages/grpc-js/src/resolver.ts b/packages/grpc-js/src/resolver.ts index 16c84351..57c750ae 100644 --- a/packages/grpc-js/src/resolver.ts +++ b/packages/grpc-js/src/resolver.ts @@ -21,6 +21,7 @@ import * as resolver_uds from './resolver-uds'; import { StatusObject } from './call-stream'; import { SubchannelAddress } from './subchannel'; import { GrpcUri, uriToString } from './uri-parser'; +import { ChannelOptions } from './channel-options'; /** * A listener object passed to the resolver's constructor that provides name @@ -64,7 +65,11 @@ export interface Resolver { } export interface ResolverConstructor { - new (target: GrpcUri, listener: ResolverListener): Resolver; + new ( + target: GrpcUri, + listener: ResolverListener, + channelOptions: ChannelOptions + ): Resolver; /** * Get the default authority for a target. This loosely corresponds to that * target's hostname. Throws an error if this resolver class cannot parse the @@ -108,10 +113,11 @@ export function registerDefaultScheme(scheme: string) { */ export function createResolver( target: GrpcUri, - listener: ResolverListener + listener: ResolverListener, + options: ChannelOptions ): Resolver { if (target.scheme !== undefined && target.scheme in registeredResolvers) { - return new registeredResolvers[target.scheme](target, listener); + return new registeredResolvers[target.scheme](target, listener, options); } else { throw new Error( `No resolver could be created for target ${uriToString(target)}` diff --git a/packages/grpc-js/src/resolving-load-balancer.ts b/packages/grpc-js/src/resolving-load-balancer.ts index b467a767..452d3c28 100644 --- a/packages/grpc-js/src/resolving-load-balancer.ts +++ b/packages/grpc-js/src/resolving-load-balancer.ts @@ -20,7 +20,7 @@ import { LoadBalancer, getFirstUsableConfig, } from './load-balancer'; -import { ServiceConfig } from './service-config'; +import { ServiceConfig, validateServiceConfig } from './service-config'; import { ConnectivityState } from './channel'; import { createResolver, Resolver } from './resolver'; import { ServiceError } from './call'; @@ -35,6 +35,7 @@ import { LogVerbosity } from './constants'; import { SubchannelAddress } from './subchannel'; import { GrpcUri, uriToString } from './uri-parser'; import { ChildLoadBalancerHandler } from './load-balancer-child-handler'; +import { ChannelOptions } from './channel-options'; const TRACER_NAME = 'resolving_load_balancer'; @@ -57,6 +58,7 @@ export class ResolvingLoadBalancer implements LoadBalancer { * This resolving load balancer's current connectivity state. */ private currentState: ConnectivityState = ConnectivityState.IDLE; + private readonly defaultServiceConfig: ServiceConfig; /** * The service config object from the last successful resolution, if * available. A value of null indicates that we have not yet received a valid @@ -90,8 +92,18 @@ export class ResolvingLoadBalancer implements LoadBalancer { constructor( private readonly target: GrpcUri, private readonly channelControlHelper: ChannelControlHelper, - private readonly defaultServiceConfig: ServiceConfig | null + private readonly channelOptions: ChannelOptions ) { + if (channelOptions['grpc.service_config']) { + this.defaultServiceConfig = validateServiceConfig( + JSON.parse(channelOptions['grpc.service_config']!) + ); + } else { + this.defaultServiceConfig = { + loadBalancingConfig: [], + methodConfig: [], + }; + } this.updateState(ConnectivityState.IDLE, new QueuePicker(this)); this.childLoadBalancer = new ChildLoadBalancerHandler({ createSubchannel: channelControlHelper.createSubchannel.bind( @@ -114,68 +126,72 @@ export class ResolvingLoadBalancer implements LoadBalancer { this.updateState(newState, picker); }, }); - this.innerResolver = createResolver(target, { - onSuccessfulResolution: ( - addressList: SubchannelAddress[], - serviceConfig: ServiceConfig | null, - serviceConfigError: ServiceError | null, - attributes: { [key: string]: unknown } - ) => { - let workingServiceConfig: ServiceConfig | null = null; - /* This first group of conditionals implements the algorithm described - * in https://github.com/grpc/proposal/blob/master/A21-service-config-error-handling.md - * in the section called "Behavior on receiving a new gRPC Config". - */ - if (serviceConfig === null) { - // Step 4 and 5 - if (serviceConfigError === null) { - // Step 5 - this.previousServiceConfig = null; - workingServiceConfig = this.defaultServiceConfig; - } else { - // Step 4 - if (this.previousServiceConfig === null) { - // Step 4.ii - this.handleResolutionFailure(serviceConfigError); + this.innerResolver = createResolver( + target, + { + onSuccessfulResolution: ( + addressList: SubchannelAddress[], + serviceConfig: ServiceConfig | null, + serviceConfigError: ServiceError | null, + attributes: { [key: string]: unknown } + ) => { + let workingServiceConfig: ServiceConfig | null = null; + /* This first group of conditionals implements the algorithm described + * in https://github.com/grpc/proposal/blob/master/A21-service-config-error-handling.md + * in the section called "Behavior on receiving a new gRPC Config". + */ + if (serviceConfig === null) { + // Step 4 and 5 + if (serviceConfigError === null) { + // Step 5 + this.previousServiceConfig = null; + workingServiceConfig = this.defaultServiceConfig; } else { - // Step 4.i - workingServiceConfig = this.previousServiceConfig; + // Step 4 + if (this.previousServiceConfig === null) { + // Step 4.ii + this.handleResolutionFailure(serviceConfigError); + } else { + // Step 4.i + workingServiceConfig = this.previousServiceConfig; + } } + } else { + // Step 3 + workingServiceConfig = serviceConfig; + this.previousServiceConfig = serviceConfig; } - } else { - // Step 3 - workingServiceConfig = serviceConfig; - this.previousServiceConfig = serviceConfig; - } - const workingConfigList = - workingServiceConfig?.loadBalancingConfig ?? []; - if (workingConfigList.length === 0) { - workingConfigList.push({ - name: 'pick_first', - pick_first: {}, - }); - } - const loadBalancingConfig = getFirstUsableConfig(workingConfigList); - if (loadBalancingConfig === null) { - // There were load balancing configs but none are supported. This counts as a resolution failure - this.handleResolutionFailure({ - code: Status.UNAVAILABLE, - details: - 'All load balancer options in service config are not compatible', - metadata: new Metadata(), - }); - return; - } - this.childLoadBalancer.updateAddressList( - addressList, - loadBalancingConfig, - attributes - ); + const workingConfigList = + workingServiceConfig?.loadBalancingConfig ?? []; + if (workingConfigList.length === 0) { + workingConfigList.push({ + name: 'pick_first', + pick_first: {}, + }); + } + const loadBalancingConfig = getFirstUsableConfig(workingConfigList); + if (loadBalancingConfig === null) { + // There were load balancing configs but none are supported. This counts as a resolution failure + this.handleResolutionFailure({ + code: Status.UNAVAILABLE, + details: + 'All load balancer options in service config are not compatible', + metadata: new Metadata(), + }); + return; + } + this.childLoadBalancer.updateAddressList( + addressList, + loadBalancingConfig, + attributes + ); + }, + onError: (error: StatusObject) => { + this.handleResolutionFailure(error); + }, }, - onError: (error: StatusObject) => { - this.handleResolutionFailure(error); - }, - }); + channelOptions + ); this.backoffTimeout = new BackoffTimeout(() => { if (this.continueResolving) { diff --git a/packages/grpc-js/src/server.ts b/packages/grpc-js/src/server.ts index ebd4504d..683198c5 100644 --- a/packages/grpc-js/src/server.ts +++ b/packages/grpc-js/src/server.ts @@ -415,7 +415,7 @@ export class Server { }, }; - const resolver = createResolver(portUri, resolverListener); + const resolver = createResolver(portUri, resolverListener, this.options); resolver.updateResolution(); } diff --git a/packages/grpc-js/src/xds-client.ts b/packages/grpc-js/src/xds-client.ts index fc2aa17f..f5725d78 100644 --- a/packages/grpc-js/src/xds-client.ts +++ b/packages/grpc-js/src/xds-client.ts @@ -47,6 +47,9 @@ import { _envoy_api_v2_endpoint_ClusterStats_DroppedRequests, } from './generated/envoy/api/v2/endpoint/ClusterStats'; import { UpstreamLocalityStats } from './generated/envoy/api/v2/endpoint/UpstreamLocalityStats'; +import { Listener__Output } from './generated/envoy/api/v2/Listener'; +import { HttpConnectionManager__Output } from './generated/envoy/config/filter/network/http_connection_manager/v2/HttpConnectionManager'; +import { RouteConfiguration__Output } from './generated/envoy/api/v2/RouteConfiguration'; const TRACER_NAME = 'xds_client'; @@ -58,6 +61,11 @@ const clientVersion = require('../../package.json').version; const EDS_TYPE_URL = 'type.googleapis.com/envoy.api.v2.ClusterLoadAssignment'; const CDS_TYPE_URL = 'type.googleapis.com/envoy.api.v2.Cluster'; +const LDS_TYPE_URL = 'type.googleapis.com/envoy.api.v2.Listener'; +const RDS_TYPE_URL = 'type.googleapis.com/envoy.api.v2.RouteConfiguration'; + +const HTTP_CONNECTION_MANGER_TYPE_URL = + 'type.googleapis.com/envoy.config.filter.network.http_connection_manager.v2.HttpConnectionManager'; let loadedProtos: Promise< adsTypes.ProtoGrpcType & lrsTypes.ProtoGrpcType @@ -73,10 +81,12 @@ function loadAdsProtos(): Promise< .load( [ 'envoy/service/discovery/v2/ads.proto', + 'envoy/service/load_stats/v2/lrs.proto', 'envoy/api/v2/listener.proto', 'envoy/api/v2/route.proto', 'envoy/api/v2/cluster.proto', 'envoy/api/v2/endpoint.proto', + 'envoy/config/filter/network/http_connection_manager/v2/http_connection_manager.proto', ], { keepCase: true, @@ -238,6 +248,15 @@ export class XdsClient { private lastCdsNonce = ''; private latestCdsResponses: Cluster__Output[] = []; + private lastLdsVersionInfo = ''; + private lastLdsNonce = ''; + private latestLdsResponse: Listener__Output | null = null; + + private routeConfigName: string | null = null; + private lastRdsVersionInfo = ''; + private lastRdsNonce = ''; + private latestRdsResponse: RouteConfiguration__Output | null = null; + constructor( private targetName: string, private serviceConfigWatcher: Watcher, @@ -308,6 +327,155 @@ export class XdsClient { clearInterval(this.statsTimer); } + private handleAdsResponse(message: DiscoveryResponse__Output) { + switch (message.type_url) { + case EDS_TYPE_URL: { + const edsResponses: ClusterLoadAssignment__Output[] = []; + for (const resource of message.resources) { + if ( + protoLoader.isAnyExtension(resource) && + resource['@type'] === EDS_TYPE_URL + ) { + const resp = resource as protoLoader.AnyExtension & + ClusterLoadAssignment__Output; + if (!this.validateEdsResponse(resp)) { + this.nackEds('ClusterLoadAssignment validation failed'); + return; + } + edsResponses.push(resp); + } else { + this.nackEds( + `Invalid resource type ${ + protoLoader.isAnyExtension(resource) + ? resource['@type'] + : resource.type_url + }` + ); + return; + } + } + for (const message of edsResponses) { + this.handleEdsResponse(message); + } + this.lastEdsVersionInfo = message.version_info; + this.lastEdsNonce = message.nonce; + this.latestEdsResponses = edsResponses; + this.ackEds(); + break; + } + case CDS_TYPE_URL: { + const cdsResponses: Cluster__Output[] = []; + for (const resource of message.resources) { + if ( + protoLoader.isAnyExtension(resource) && + resource['@type'] === CDS_TYPE_URL + ) { + const resp = resource as protoLoader.AnyExtension & Cluster__Output; + if (!this.validateCdsResponse(resp)) { + this.nackCds('Cluster validation failed'); + return; + } + } else { + this.nackCds( + `Invalid resource type ${ + protoLoader.isAnyExtension(resource) + ? resource['@type'] + : resource.type_url + }` + ); + return; + } + } + for (const message of cdsResponses) { + this.handleCdsResponse(message); + } + this.lastCdsVersionInfo = message.version_info; + this.lastCdsNonce = message.nonce; + this.latestCdsResponses = cdsResponses; + this.ackCds(); + break; + } + case LDS_TYPE_URL: { + let nackError: string | null = null; + for (const resource of message.resources) { + if ( + protoLoader.isAnyExtension(resource) && + resource['@type'] === LDS_TYPE_URL + ) { + const resp = resource as protoLoader.AnyExtension & + Listener__Output; + if (resp.name === this.targetName) { + if (this.validateLdsResponse(resp)) { + this.handleLdsResponse(resp); + this.lastLdsVersionInfo = message.version_info; + this.lastLdsNonce = message.nonce; + this.latestLdsResponse = resp; + } else { + nackError = 'Listener validation failed'; + } + break; + } + } else { + nackError = `Invalid resource type ${ + protoLoader.isAnyExtension(resource) + ? resource['@type'] + : resource.type_url + }`; + break; + } + } + if (nackError) { + this.nackLds(nackError); + } else { + this.ackLds(); + } + break; + } + case RDS_TYPE_URL: { + let nackError: string | null = null; + if (this.routeConfigName === null) { + nackError = 'Unexpected RouteConfiguration response'; + } else { + for (const resource of message.resources) { + if ( + protoLoader.isAnyExtension(resource) && + resource['@type'] === RDS_TYPE_URL + ) { + const resp = resource as protoLoader.AnyExtension & + RouteConfiguration__Output; + if (resp.name === this.routeConfigName) { + if (this.validateRdsResponse(resp)) { + this.handleRdsResponse(resp); + this.lastRdsVersionInfo = message.version_info; + this.lastRdsNonce = message.nonce; + this.latestRdsResponse = resp; + } else { + nackError = 'RouteConfiguration validation failed'; + } + break; + } + } else { + nackError = `Invalid resource type ${ + protoLoader.isAnyExtension(resource) + ? resource['@type'] + : resource.type_url + }`; + break; + } + } + } + if (nackError) { + this.nackRds(nackError); + } else { + this.ackRds(); + } + break; + } + default: + this.nackUnknown(message.type_url, message.version_info, message.nonce); + } + } + /** * Start the ADS stream if the client exists and there is not already an * existing stream, and there @@ -324,81 +492,7 @@ export class XdsClient { } this.adsCall = this.adsClient.StreamAggregatedResources(); this.adsCall.on('data', (message: DiscoveryResponse__Output) => { - switch (message.type_url) { - case EDS_TYPE_URL: { - const edsResponses: ClusterLoadAssignment__Output[] = []; - for (const resource of message.resources) { - if ( - protoLoader.isAnyExtension(resource) && - resource['@type'] === EDS_TYPE_URL - ) { - const resp = resource as protoLoader.AnyExtension & - ClusterLoadAssignment__Output; - if (!this.validateEdsResponse(resp)) { - this.nackEds('ClusterLoadAssignment validation failed'); - return; - } - edsResponses.push(resp); - } else { - this.nackEds( - `Invalid resource type ${ - protoLoader.isAnyExtension(resource) - ? resource['@type'] - : resource.type_url - }` - ); - return; - } - } - for (const message of edsResponses) { - this.handleEdsResponse(message); - } - this.lastEdsVersionInfo = message.version_info; - this.lastEdsNonce = message.nonce; - this.latestEdsResponses = edsResponses; - this.ackEds(); - break; - } - case CDS_TYPE_URL: { - const cdsResponses: Cluster__Output[] = []; - for (const resource of message.resources) { - if ( - protoLoader.isAnyExtension(resource) && - resource['@type'] === CDS_TYPE_URL - ) { - const resp = resource as protoLoader.AnyExtension & - Cluster__Output; - if (!this.validateCdsResponse(resp)) { - this.nackCds('Cluster validation failed'); - return; - } - } else { - this.nackEds( - `Invalid resource type ${ - protoLoader.isAnyExtension(resource) - ? resource['@type'] - : resource.type_url - }` - ); - return; - } - } - for (const message of cdsResponses) { - this.handleCdsResponse(message); - } - this.lastCdsVersionInfo = message.version_info; - this.lastCdsNonce = message.nonce; - this.latestCdsResponses = cdsResponses; - this.ackCds(); - break; - } - default: - this.nackUnknown( - message.type_url, - message.version_info, - message.nonce - ); - } + this.handleAdsResponse(message); }); this.adsCall.on('error', (error: ServiceError) => { trace( @@ -411,6 +505,30 @@ export class XdsClient { * reconnect */ this.maybeStartAdsStream(); }); + + this.adsCall.write({ + node: this.adsNode!, + type_url: LDS_TYPE_URL, + resource_names: [this.targetName], + }); + + if (this.routeConfigName) { + this.adsCall.write({ + node: this.adsNode!, + type_url: RDS_TYPE_URL, + resource_names: [this.routeConfigName], + }); + } + + const clusterNames = Array.from(this.clusterWatchers.keys()); + if (clusterNames.length > 0) { + this.adsCall.write({ + node: this.adsNode!, + type_url: CDS_TYPE_URL, + resource_names: clusterNames, + }); + } + const endpointWatcherNames = Array.from(this.endpointWatchers.keys()); if (endpointWatcherNames.length > 0) { this.adsCall.write({ @@ -466,6 +584,26 @@ export class XdsClient { }); } + private ackLds() { + this.adsCall?.write({ + node: this.adsNode!, + type_url: LDS_TYPE_URL, + resource_names: [this.targetName], + response_nonce: this.lastLdsNonce, + version_info: this.lastLdsVersionInfo, + }); + } + + private ackRds() { + this.adsCall?.write({ + node: this.adsNode!, + type_url: RDS_TYPE_URL, + resource_names: [this.routeConfigName!], + response_nonce: this.lastRdsNonce, + version_info: this.lastRdsVersionInfo, + }); + } + /** * Reject an EDS update. This should be called without updating the local * nonce and version info. @@ -502,6 +640,32 @@ export class XdsClient { }); } + private nackLds(message: string) { + this.adsCall?.write({ + node: this.adsNode!, + type_url: LDS_TYPE_URL, + resource_names: [this.targetName], + response_nonce: this.lastLdsNonce, + version_info: this.lastLdsVersionInfo, + error_detail: { + message, + }, + }); + } + + private nackRds(message: string) { + this.adsCall?.write({ + node: this.adsNode!, + type_url: RDS_TYPE_URL, + resource_names: this.routeConfigName ? [this.routeConfigName] : [], + response_nonce: this.lastRdsNonce, + version_info: this.lastRdsVersionInfo, + error_detail: { + message, + }, + }); + } + /** * Validate the ClusterLoadAssignment object by these rules: * https://github.com/grpc/proposal/blob/master/A27-xds-global-load-balancing.md#clusterloadassignment-proto @@ -543,6 +707,36 @@ export class XdsClient { return true; } + private validateLdsResponse(message: Listener__Output): boolean { + if ( + !( + message.api_listener?.api_listener && + protoLoader.isAnyExtension(message.api_listener.api_listener) && + message.api_listener?.api_listener['@type'] === + HTTP_CONNECTION_MANGER_TYPE_URL + ) + ) { + return false; + } + const httpConnectionManager = message.api_listener + ?.api_listener as protoLoader.AnyExtension & + HttpConnectionManager__Output; + switch (httpConnectionManager.route_specifier) { + case 'rds': + if (!httpConnectionManager.rds?.config_source?.ads) { + return false; + } + break; + case 'route_config': + return this.validateRdsResponse(httpConnectionManager.route_config!); + } + return false; + } + + private validateRdsResponse(message: RouteConfiguration__Output): boolean { + return true; + } + private handleEdsResponse(message: ClusterLoadAssignment__Output) { const watchers = this.endpointWatchers.get(message.cluster_name) ?? []; for (const watcher of watchers) { @@ -557,6 +751,52 @@ export class XdsClient { } } + private handleLdsResponse(message: Listener__Output) { + // The validation step ensures that this is correct + const httpConnectionManager = message.api_listener! + .api_listener as protoLoader.AnyExtension & HttpConnectionManager__Output; + switch (httpConnectionManager.route_specifier) { + case 'rds': + this.routeConfigName = httpConnectionManager.rds!.route_config_name; + this.updateRdsNames(); + break; + case 'route_config': + this.handleRdsResponse(httpConnectionManager.route_config!); + if (this.routeConfigName) { + this.routeConfigName = null; + this.updateRdsNames(); + } + break; + default: + // The validation rules should prevent this + } + } + + private handleRdsResponse(message: RouteConfiguration__Output) { + for (const virtualHost of message.virtual_hosts) { + if (virtualHost.domains.indexOf(this.routeConfigName!) >= 0) { + const route = virtualHost.routes[virtualHost.routes.length - 1]; + if (route.match?.prefix === '' && route.route?.cluster) { + this.serviceConfigWatcher.onValidUpdate({ + methodConfig: [], + loadBalancingConfig: [ + { + name: 'cds', + cds: { + cluster: route.route.cluster, + }, + }, + ], + }); + break; + } + } + } + /* If none of the routes match the one we are looking for, bubble up an + * error. */ + this.serviceConfigWatcher.onResourceDoesNotExist(); + } + private updateEdsNames() { if (this.adsCall) { this.adsCall.write({ @@ -581,16 +821,26 @@ export class XdsClient { } } + private updateRdsNames() { + this.adsCall?.write({ + node: this.adsNode!, + type_url: RDS_TYPE_URL, + resource_names: this.routeConfigName ? [this.routeConfigName] : [], + response_nonce: this.lastRdsNonce, + version_info: this.lastRdsVersionInfo, + }); + } + private reportStreamError(status: StatusObject) { for (const watcherList of [ ...this.endpointWatchers.values(), ...this.clusterWatchers.values(), + [this.serviceConfigWatcher], ]) { for (const watcher of watcherList) { watcher.onTransientError(status); } } - // Also do the same for other types of watchers when those are implemented } private maybeStartLrsStream() { diff --git a/packages/grpc-js/test/test-resolver.ts b/packages/grpc-js/test/test-resolver.ts index d2a85fc4..42ca64d4 100644 --- a/packages/grpc-js/test/test-resolver.ts +++ b/packages/grpc-js/test/test-resolver.ts @@ -63,7 +63,7 @@ describe('Name Resolver', () => { done(new Error(`Failed with status ${error.details}`)); }, }; - const resolver = resolverManager.createResolver(target, listener); + const resolver = resolverManager.createResolver(target, listener, {}); resolver.updateResolution(); }); it('Should default to port 443', done => { @@ -98,7 +98,7 @@ describe('Name Resolver', () => { done(new Error(`Failed with status ${error.details}`)); }, }; - const resolver = resolverManager.createResolver(target, listener); + const resolver = resolverManager.createResolver(target, listener, {}); resolver.updateResolution(); }); it('Should correctly represent an ipv4 address', done => { @@ -125,7 +125,7 @@ describe('Name Resolver', () => { done(new Error(`Failed with status ${error.details}`)); }, }; - const resolver = resolverManager.createResolver(target, listener); + const resolver = resolverManager.createResolver(target, listener, {}); resolver.updateResolution(); }); it('Should correctly represent an ipv6 address', done => { @@ -152,7 +152,7 @@ describe('Name Resolver', () => { done(new Error(`Failed with status ${error.details}`)); }, }; - const resolver = resolverManager.createResolver(target, listener); + const resolver = resolverManager.createResolver(target, listener, {}); resolver.updateResolution(); }); it('Should correctly represent a bracketed ipv6 address', done => { @@ -179,7 +179,7 @@ describe('Name Resolver', () => { done(new Error(`Failed with status ${error.details}`)); }, }; - const resolver = resolverManager.createResolver(target, listener); + const resolver = resolverManager.createResolver(target, listener, {}); resolver.updateResolution(); }); it('Should resolve a public address', done => { @@ -199,7 +199,7 @@ describe('Name Resolver', () => { done(new Error(`Failed with status ${error.details}`)); }, }; - const resolver = resolverManager.createResolver(target, listener); + const resolver = resolverManager.createResolver(target, listener, {}); resolver.updateResolution(); }); it('Should resolve a name with multiple dots', done => { @@ -226,7 +226,7 @@ describe('Name Resolver', () => { done(new Error(`Failed with status ${error.details}`)); }, }; - const resolver = resolverManager.createResolver(target, listener); + const resolver = resolverManager.createResolver(target, listener, {}); resolver.updateResolution(); }); /* TODO(murgatroid99): re-enable this test, once we can get the IPv6 result @@ -255,7 +255,7 @@ describe('Name Resolver', () => { done(new Error(`Failed with status ${error.details}`)); }, }; - const resolver = resolverManager.createResolver(target, listener); + const resolver = resolverManager.createResolver(target, listener, {}); resolver.updateResolution(); }); it('Should resolve a DNS name to IPv4 and IPv6 addresses', done => { @@ -284,7 +284,7 @@ describe('Name Resolver', () => { done(new Error(`Failed with status ${error.details}`)); }, }; - const resolver = resolverManager.createResolver(target, listener); + const resolver = resolverManager.createResolver(target, listener, {}); resolver.updateResolution(); }); it('Should resolve a name with a hyphen', done => { @@ -306,7 +306,7 @@ describe('Name Resolver', () => { done(new Error(`Failed with status ${error.details}`)); }, }; - const resolver = resolverManager.createResolver(target, listener); + const resolver = resolverManager.createResolver(target, listener, {}); resolver.updateResolution(); }); it('Should resolve gRPC interop servers', done => { @@ -331,9 +331,9 @@ describe('Name Resolver', () => { done(new Error(`Failed with status ${error.details}`)); }, }; - const resolver1 = resolverManager.createResolver(target1, listener); + const resolver1 = resolverManager.createResolver(target1, listener, {}); resolver1.updateResolution(); - const resolver2 = resolverManager.createResolver(target2, listener); + const resolver2 = resolverManager.createResolver(target2, listener, {}); resolver2.updateResolution(); }); }); @@ -359,7 +359,7 @@ describe('Name Resolver', () => { done(new Error(`Failed with status ${error.details}`)); }, }; - const resolver = resolverManager.createResolver(target, listener); + const resolver = resolverManager.createResolver(target, listener, {}); resolver.updateResolution(); }); it('Should handle an absolute Unix Domain Socket name', done => { @@ -384,7 +384,7 @@ describe('Name Resolver', () => { done(new Error(`Failed with status ${error.details}`)); }, }; - const resolver = resolverManager.createResolver(target, listener); + const resolver = resolverManager.createResolver(target, listener, {}); resolver.updateResolution(); }); });