syntax = "proto3";

package envoy.extensions.filters.network.http_connection_manager.v3;

import "envoy/config/accesslog/v3/accesslog.proto";
import "envoy/config/core/v3/address.proto";
import "envoy/config/core/v3/base.proto";
import "envoy/config/core/v3/config_source.proto";
import "envoy/config/core/v3/extension.proto";
import "envoy/config/core/v3/protocol.proto";
import "envoy/config/core/v3/substitution_format_string.proto";
import "envoy/config/route/v3/route.proto";
import "envoy/config/route/v3/scoped_route.proto";
import "envoy/config/trace/v3/http_tracer.proto";
import "envoy/type/http/v3/path_transformation.proto";
import "envoy/type/tracing/v3/custom_tag.proto";
import "envoy/type/v3/percent.proto";

import "google/protobuf/any.proto";
import "google/protobuf/duration.proto";
import "google/protobuf/wrappers.proto";

import "envoy/annotations/deprecation.proto";
import "udpa/annotations/migrate.proto";
import "udpa/annotations/security.proto";
import "udpa/annotations/status.proto";
import "udpa/annotations/versioning.proto";
import "validate/validate.proto";

option java_package = "io.envoyproxy.envoy.extensions.filters.network.http_connection_manager.v3";
option java_outer_classname = "HttpConnectionManagerProto";
option java_multiple_files = true;
option go_package = "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/network/http_connection_manager/v3;http_connection_managerv3";
option (udpa.annotations.file_status).package_version_status = ACTIVE;

// [#protodoc-title: HTTP connection manager]
// HTTP connection manager :ref:`configuration overview <config_http_conn_man>`.
// [#extension: envoy.filters.network.http_connection_manager]

// [#next-free-field: 59]
message HttpConnectionManager {
  option (udpa.annotations.versioning).previous_message_type =
      "envoy.config.filter.network.http_connection_manager.v2.HttpConnectionManager";

  enum 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;

    // The connection manager will assume that the client is speaking HTTP/3.
    // This needs to be consistent with listener and transport socket config.
    HTTP3 = 3;
  }

  enum 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;
  }

  // How to handle the :ref:`config_http_conn_man_headers_x-forwarded-client-cert` (XFCC) HTTP
  // header.
  enum 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;
  }

  // Determines the action for request that contain ``%2F``, ``%2f``, ``%5C`` or ``%5c`` sequences in the URI path.
  // This operation occurs before URL normalization and the merge slashes transformations if they were enabled.
  enum PathWithEscapedSlashesAction {
    // Default behavior specific to implementation (i.e. Envoy) of this configuration option.
    // Envoy, by default, takes the KEEP_UNCHANGED action.
    //
    // .. note::
    //
    //   The implementation may change the default behavior at-will.
    IMPLEMENTATION_SPECIFIC_DEFAULT = 0;

    // Keep escaped slashes.
    KEEP_UNCHANGED = 1;

    // Reject client request with the 400 status. gRPC requests will be rejected with the INTERNAL (13) error code.
    // The ``httpN.downstream_rq_failed_path_normalization`` counter is incremented for each rejected request.
    REJECT_REQUEST = 2;

    // Unescape ``%2F`` and ``%5C`` sequences and redirect request to the new path if these sequences were present.
    // Redirect occurs after path normalization and merge slashes transformations if they were configured.
    //
    // .. note::
    //
    //   gRPC requests will be rejected with the INTERNAL (13) error code. This option minimizes possibility of path
    //   confusion exploits by forcing request with unescaped slashes to traverse all parties: downstream client,
    //   intermediate proxies, Envoy and upstream server. The ``httpN.downstream_rq_redirected_with_normalized_path``
    //   counter is incremented for each redirected request.
    //
    UNESCAPE_AND_REDIRECT = 3;

    // Unescape ``%2F`` and ``%5C`` sequences.
    //
    // .. note::
    //
    //   This option should not be enabled if intermediaries perform path based access control as it may lead to path
    //   confusion vulnerabilities.
    //
    UNESCAPE_AND_FORWARD = 4;
  }

  // [#next-free-field: 11]
  message Tracing {
    option (udpa.annotations.versioning).previous_message_type =
        "envoy.config.filter.network.http_connection_manager.v2.HttpConnectionManager.Tracing";

    enum OperationName {
      // The HTTP listener is used for ingress/incoming requests.
      INGRESS = 0;

      // The HTTP listener is used for egress/outgoing requests.
      EGRESS = 1;
    }

    reserved 1, 2;

    reserved "operation_name", "request_headers_for_tags";

    // Target percentage of requests managed by this HTTP connection manager that will be force
    // traced if the :ref:`x-client-trace-id <config_http_conn_man_headers_x-client-trace-id>`
    // header is set. This field is a direct analog for the runtime variable
    // 'tracing.client_enabled' in the :ref:`HTTP Connection Manager
    // <config_http_conn_man_runtime>`.
    // Default: 100%
    type.v3.Percent client_sampling = 3;

    // 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 <config_http_conn_man_runtime>`.
    // Default: 100%
    type.v3.Percent random_sampling = 4;

    // 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 <config_http_conn_man_runtime>`.
    // Default: 100%
    type.v3.Percent overall_sampling = 5;

    // Whether to annotate spans with additional data. If true, spans will include logs for stream
    // events.
    bool verbose = 6;

    // 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
    google.protobuf.UInt32Value max_path_tag_length = 7;

    // A list of custom tags with unique tag name to create tags for the active span.
    repeated type.tracing.v3.CustomTag custom_tags = 8;

    // Configuration for an external tracing provider.
    // If not specified, no tracing will be performed.
    config.trace.v3.Tracing.Http provider = 9;

    // Create separate tracing span for each upstream request if true. And if this flag is set to true,
    // the tracing provider will assume that Envoy will be independent hop in the trace chain and may
    // set span type to client or server based on this flag.
    // This will deprecate the
    // :ref:`start_child_span <envoy_v3_api_field_extensions.filters.http.router.v3.Router.start_child_span>`
    // in the router.
    //
    // Users should set appropriate value based on their tracing provider and actual scenario:
    //
    // * If Envoy is used as sidecar and users want to make the sidecar and its application as only one
    //   hop in the trace chain, this flag should be set to false. And please also make sure the
    //   :ref:`start_child_span <envoy_v3_api_field_extensions.filters.http.router.v3.Router.start_child_span>`
    //   in the router is not set to true.
    // * If Envoy is used as gateway or independent proxy, or users want to make the sidecar and its
    //   application as different hops in the trace chain, this flag should be set to true.
    // * If tracing provider that has explicit requirements on span creation (like SkyWalking),
    //   this flag should be set to true.
    //
    // The default value is false for now for backward compatibility.
    google.protobuf.BoolValue spawn_upstream_span = 10;
  }

  message InternalAddressConfig {
    option (udpa.annotations.versioning).previous_message_type =
        "envoy.config.filter.network.http_connection_manager.v2.HttpConnectionManager."
        "InternalAddressConfig";

    // Whether unix socket addresses should be considered internal.
    bool unix_sockets = 1;

    // List of CIDR ranges that are treated as internal. If unset, then RFC1918 / RFC4193
    // IP addresses will be considered internal.
    repeated config.core.v3.CidrRange cidr_ranges = 2;
  }

  // [#next-free-field: 7]
  message SetCurrentClientCertDetails {
    option (udpa.annotations.versioning).previous_message_type =
        "envoy.config.filter.network.http_connection_manager.v2.HttpConnectionManager."
        "SetCurrentClientCertDetails";

    reserved 2;

    // Whether to forward the subject of the client cert. Defaults to false.
    google.protobuf.BoolValue subject = 1;

    // 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.
    bool cert = 3;

    // 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.
    bool chain = 6;

    // Whether to forward the DNS type Subject Alternative Names of the client cert.
    // Defaults to false.
    bool dns = 4;

    // Whether to forward the URI type Subject Alternative Name of the client cert. Defaults to
    // false.
    bool uri = 5;
  }

  // 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.
  //
  message UpgradeConfig {
    option (udpa.annotations.versioning).previous_message_type =
        "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.
    string upgrade_type = 1;

    // 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.
    repeated HttpFilter filters = 2;

    // Determines if upgrades are enabled or disabled by default. Defaults to true.
    // This can be overridden on a per-route basis with :ref:`cluster
    // <envoy_v3_api_field_config.route.v3.RouteAction.upgrade_configs>` as documented in the
    // :ref:`upgrade documentation <arch_overview_upgrades>`.
    google.protobuf.BoolValue enabled = 3;
  }

  // [#not-implemented-hide:] Transformations that apply to path headers. Transformations are applied
  // before any processing of requests by HTTP filters, routing, and matching. Only the normalized
  // path will be visible internally if a transformation is enabled. Any path rewrites that the
  // router performs (e.g. :ref:`regex_rewrite
  // <envoy_v3_api_field_config.route.v3.RouteAction.regex_rewrite>` or :ref:`prefix_rewrite
  // <envoy_v3_api_field_config.route.v3.RouteAction.prefix_rewrite>`) will apply to the ``:path`` header
  // destined for the upstream.
  //
  // .. note::
  //
  //   Access logging and tracing will show the original ``:path`` header.
  //
  message PathNormalizationOptions {
    // [#not-implemented-hide:] Normalization applies internally before any processing of requests by
    // HTTP filters, routing, and matching *and* will affect the forwarded ``:path`` header. Defaults
    // to :ref:`NormalizePathRFC3986
    // <envoy_v3_api_msg_type.http.v3.PathTransformation.Operation.NormalizePathRFC3986>`. When not
    // specified, this value may be overridden by the runtime variable
    // :ref:`http_connection_manager.normalize_path<config_http_conn_man_runtime_normalize_path>`.
    // Envoy will respond with 400 to paths that are malformed (e.g. for paths that fail RFC 3986
    // normalization due to disallowed characters.)
    type.http.v3.PathTransformation forwarding_transformation = 1;

    // [#not-implemented-hide:] Normalization only applies internally before any processing of
    // requests by HTTP filters, routing, and matching. These will be applied after full
    // transformation is applied. The ``:path`` header before this transformation will be restored in
    // the router filter and sent upstream unless it was mutated by a filter. Defaults to no
    // transformations.
    // Multiple actions can be applied in the same Transformation, forming a sequential
    // pipeline. The transformations will be performed in the order that they appear. Envoy will
    // respond with 400 to paths that are malformed (e.g. for paths that fail RFC 3986
    // normalization due to disallowed characters.)
    type.http.v3.PathTransformation http_filter_transformation = 2;
  }

  // Configures the manner in which the Proxy-Status HTTP response header is
  // populated.
  //
  // See the [Proxy-Status
  // RFC](https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-proxy-status-08).
  // [#comment:TODO: Update this with the non-draft URL when finalized.]
  //
  // The Proxy-Status header is a string of the form:
  //
  //   "<server_name>; error=<error_type>; details=<details>"
  // [#next-free-field: 7]
  message ProxyStatusConfig {
    // If true, the details field of the Proxy-Status header is not populated with stream_info.response_code_details.
    // This value defaults to ``false``, i.e. the ``details`` field is populated by default.
    bool remove_details = 1;

    // If true, the details field of the Proxy-Status header will not contain
    // connection termination details. This value defaults to ``false``, i.e. the
    // ``details`` field will contain connection termination details by default.
    bool remove_connection_termination_details = 2;

    // If true, the details field of the Proxy-Status header will not contain an
    // enumeration of the Envoy ResponseFlags. This value defaults to ``false``,
    // i.e. the ``details`` field will contain a list of ResponseFlags by default.
    bool remove_response_flags = 3;

    // If true, overwrites the existing Status header with the response code
    // recommended by the Proxy-Status spec.
    // This value defaults to ``false``, i.e. the HTTP response code is not
    // overwritten.
    bool set_recommended_response_code = 4;

    // The name of the proxy as it appears at the start of the Proxy-Status
    // header.
    //
    // If neither of these values are set, this value defaults to ``server_name``,
    // which itself defaults to "envoy".
    oneof proxy_name {
      // If ``use_node_id`` is set, Proxy-Status headers will use the Envoy's node
      // ID as the name of the proxy.
      bool use_node_id = 5;

      // If ``literal_proxy_name`` is set, Proxy-Status headers will use this
      // value as the name of the proxy.
      string literal_proxy_name = 6;
    }
  }

  message HcmAccessLogOptions {
    // The interval to flush the above access logs. By default, the HCM will flush exactly one access log
    // on stream close, when the HTTP request is complete. If this field is set, the HCM will flush access
    // logs periodically at the specified interval. This is especially useful in the case of long-lived
    // requests, such as CONNECT and Websockets. Final access logs can be detected via the
    // ``requestComplete()`` method of ``StreamInfo`` in access log filters, or through the ``%DURATION%`` substitution
    // string.
    // The interval must be at least 1 millisecond.
    google.protobuf.Duration access_log_flush_interval = 1
        [(validate.rules).duration = {gte {nanos: 1000000}}];

    // If set to true, HCM will flush an access log when a new HTTP request is received, after request
    // headers have been evaluated, before iterating through the HTTP filter chain.
    // This log record, if enabled, does not depend on periodic log records or request completion log.
    // Details related to upstream cluster, such as upstream host, will not be available for this log.
    bool flush_access_log_on_new_request = 2;

    // If true, the HCM will flush an access log when a tunnel is successfully established. For example,
    // this could be when an upstream has successfully returned 101 Switching Protocols, or when the proxy
    // has returned 200 to a CONNECT request.
    bool flush_log_on_tunnel_successfully_established = 3;
  }

  reserved 27, 11;

  reserved "idle_timeout";

  // Supplies the type of codec that the connection manager should use.
  CodecType codec_type = 1 [(validate.rules).enum = {defined_only: true}];

  // The human readable prefix to use when emitting statistics for the
  // connection manager. See the :ref:`statistics documentation <config_http_conn_man_stats>` for
  // more information.
  string stat_prefix = 2 [(validate.rules).string = {min_len: 1}];

  oneof route_specifier {
    option (validate.required) = true;

    // The connection manager’s route table will be dynamically loaded via the RDS API.
    Rds rds = 3;

    // The route table for the connection manager is static and is specified in this property.
    config.route.v3.RouteConfiguration route_config = 4;

    // 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.
    ScopedRoutes scoped_routes = 31;
  }

  // A list of individual HTTP filters that make up the filter chain for
  // requests made to the connection manager. :ref:`Order matters <arch_overview_http_filters_ordering>`
  // as the filters are processed sequentially as request events happen.
  repeated HttpFilter http_filters = 5;

  // 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.
  google.protobuf.BoolValue add_user_agent = 6;

  // Presence of the object defines whether the connection manager
  // emits :ref:`tracing <arch_overview_tracing>` data to the :ref:`configured tracing provider
  // <envoy_v3_api_msg_config.trace.v3.Tracing>`.
  Tracing tracing = 7;

  // Additional settings for HTTP requests handled by the connection manager. These will be
  // applicable to both HTTP/1.1 and HTTP/2 requests.
  config.core.v3.HttpProtocolOptions common_http_protocol_options = 35
      [(udpa.annotations.security).configure_for_untrusted_downstream = true];

  // If set to ``true``, Envoy will not initiate an immediate drain timer for downstream HTTP/1 connections
  // once :ref:`common_http_protocol_options.max_connection_duration
  // <envoy_v3_api_field_config.core.v3.HttpProtocolOptions.max_connection_duration>` is exceeded.
  // Instead, Envoy will wait until the next downstream request arrives, add a ``connection: close`` header
  // to the response, and then gracefully close the connection once the stream has completed.
  //
  // This behavior adheres to `RFC 9112, Section 9.6 <https://www.rfc-editor.org/rfc/rfc9112#name-tear-down>`_.
  //
  // If set to ``false``, exceeding ``max_connection_duration`` triggers Envoy's default drain behavior for HTTP/1,
  // where the connection is eventually closed after all active streams finish.
  //
  // This option has no effect if ``max_connection_duration`` is not configured.
  // Defaults to ``false``.
  bool http1_safe_max_connection_duration = 58;

  // Additional HTTP/1 settings that are passed to the HTTP/1 codec.
  // [#comment:TODO: The following fields are ignored when the
  // :ref:`header validation configuration <envoy_v3_api_field_extensions.filters.network.http_connection_manager.v3.HttpConnectionManager.typed_header_validation_config>`
  // is present:
  // 1. :ref:`allow_chunked_length <envoy_v3_api_field_config.core.v3.Http1ProtocolOptions.allow_chunked_length>`]
  config.core.v3.Http1ProtocolOptions http_protocol_options = 8;

  // Additional HTTP/2 settings that are passed directly to the HTTP/2 codec.
  config.core.v3.Http2ProtocolOptions http2_protocol_options = 9
      [(udpa.annotations.security).configure_for_untrusted_downstream = true];

  // Additional HTTP/3 settings that are passed directly to the HTTP/3 codec.
  config.core.v3.Http3ProtocolOptions http3_protocol_options = 44;

  // An optional override that the connection manager will write to the server
  // header in responses. If not set, the default is ``envoy``.
  string server_name = 10
      [(validate.rules).string = {well_known_regex: HTTP_HEADER_VALUE strict: false}];

  // 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.
  ServerHeaderTransformation server_header_transformation = 34
      [(validate.rules).enum = {defined_only: true}];

  // Allows for explicit transformation of the :scheme header on the request path.
  // If not set, Envoy's default :ref:`scheme  <config_http_conn_man_headers_scheme>`
  // handling applies.
  config.core.v3.SchemeHeaderTransformation scheme_header_transformation = 48;

  // The maximum request headers size for incoming connections.
  // If unconfigured, the default max request headers allowed is 60 KiB.
  // The default value can be overridden by setting runtime key ``envoy.reloadable_features.max_request_headers_size_kb``.
  // Requests that exceed this limit will receive a 431 response.
  //
  // .. note::
  //
  //   Currently some protocol codecs impose limits on the maximum size of a single header.
  //
  //   * HTTP/2 (when using nghttp2) limits a single header to around 100kb.
  //   * HTTP/3 limits a single header to around 1024kb.
  //
  google.protobuf.UInt32Value max_request_headers_kb = 29
      [(validate.rules).uint32 = {lte: 8192 gt: 0}];

  // 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
  // <envoy_v3_api_field_config.route.v3.RouteAction.idle_timeout>`. Even on a stream in
  // which the override applies, prior to receipt of the initial request
  // headers, the :ref:`stream_idle_timeout
  // <envoy_v3_api_field_extensions.filters.network.http_connection_manager.v3.HttpConnectionManager.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.
  //
  // This timeout also specifies the amount of time that Envoy will wait for the peer to open enough
  // window to write any remaining stream data once the entirety of stream data (local end stream is
  // true) has been buffered pending available window. In other words, this timeout defends against
  // a peer that does not release enough window to completely write the stream, even though all
  // data has been proxied within available flow control windows. If the timeout is hit in this
  // case, the :ref:`tx_flush_timeout <config_http_conn_man_stats_per_codec>` counter will be
  // incremented. Note that :ref:`max_stream_duration
  // <envoy_v3_api_field_config.core.v3.HttpProtocolOptions.max_stream_duration>` does not apply to
  // this corner case.
  //
  // If the :ref:`overload action <config_overload_manager_overload_actions>` "envoy.overload_actions.reduce_timeouts"
  // is configured, this timeout is scaled according to the value for
  // :ref:`HTTP_DOWNSTREAM_STREAM_IDLE <envoy_v3_api_enum_value_config.overload.v3.ScaleTimersOverloadActionConfig.TimerType.HTTP_DOWNSTREAM_STREAM_IDLE>`.
  //
  // 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.
  google.protobuf.Duration stream_idle_timeout = 24
      [(udpa.annotations.security).configure_for_untrusted_downstream = true];

  // 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.
  google.protobuf.Duration request_timeout = 28
      [(udpa.annotations.security).configure_for_untrusted_downstream = true];

  // The amount of time that Envoy will wait for the request headers to be received. The timer is
  // activated when the first byte of the headers is received, and is disarmed when the last byte of
  // the headers has been received. If not specified or set to 0, this timeout is disabled.
  google.protobuf.Duration request_headers_timeout = 41 [
    (validate.rules).duration = {gte {}},
    (udpa.annotations.security).configure_for_untrusted_downstream = true
  ];

  // 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
  // either when a connection hits the idle timeout, when :ref:`max_connection_duration
  // <envoy_v3_api_field_config.core.v3.HttpProtocolOptions.max_connection_duration>`
  // is reached, or during general server draining. The default grace period is
  // 5000 milliseconds (5 seconds) if this option is not specified.
  google.protobuf.Duration drain_timeout = 12;

  // 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
  //   <total_time_waiting_for_write_buffer_flushes>+<delayed_close_timeout>.
  //
  // 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* <max round trip time expected between clients and Envoy>+<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.
  //
  google.protobuf.Duration delayed_close_timeout = 26;

  // Configuration for :ref:`HTTP access logs <arch_overview_access_logs>`
  // emitted by the connection manager.
  repeated config.accesslog.v3.AccessLog access_log = 13;

  // The interval to flush the above access logs.
  //
  // .. attention::
  //
  //   This field is deprecated in favor of
  //   :ref:`access_log_flush_interval
  //   <envoy_v3_api_field_extensions.filters.network.http_connection_manager.v3.HttpConnectionManager.HcmAccessLogOptions.access_log_flush_interval>`.
  //   Note that if both this field and :ref:`access_log_flush_interval
  //   <envoy_v3_api_field_extensions.filters.network.http_connection_manager.v3.HttpConnectionManager.HcmAccessLogOptions.access_log_flush_interval>`
  //   are specified, the former (deprecated field) is ignored.
  google.protobuf.Duration access_log_flush_interval = 54 [
    deprecated = true,
    (validate.rules).duration = {gte {nanos: 1000000}},
    (envoy.annotations.deprecated_at_minor_version) = "3.0"
  ];

  // If set to true, HCM will flush an access log once when a new HTTP request is received, after the request
  // headers have been evaluated, and before iterating through the HTTP filter chain.
  //
  // .. attention::
  //
  //   This field is deprecated in favor of
  //   :ref:`flush_access_log_on_new_request
  //   <envoy_v3_api_field_extensions.filters.network.http_connection_manager.v3.HttpConnectionManager.HcmAccessLogOptions.flush_access_log_on_new_request>`.
  //   Note that if both this field and :ref:`flush_access_log_on_new_request
  //   <envoy_v3_api_field_extensions.filters.network.http_connection_manager.v3.HttpConnectionManager.HcmAccessLogOptions.flush_access_log_on_new_request>`
  //   are specified, the former (deprecated field) is ignored.
  bool flush_access_log_on_new_request = 55
      [deprecated = true, (envoy.annotations.deprecated_at_minor_version) = "3.0"];

  // Additional access log options for HTTP connection manager.
  HcmAccessLogOptions access_log_options = 56;

  // 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.
  google.protobuf.BoolValue use_remote_address = 14
      [(udpa.annotations.security).configure_for_untrusted_downstream = true];

  // 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.
  uint32 xff_num_trusted_hops = 19;

  // Configuration for original IP detection extensions.
  //
  // When these extensions are configured, Envoy will invoke them with the incoming request headers and
  // details about the downstream connection, including the directly connected address. Each extension uses
  // this information to determine the effective remote IP address for the request. If an extension cannot
  // identify the original IP address and isn't set to reject the request, Envoy will sequentially attempt
  // the remaining extensions until one successfully determines the IP or explicitly rejects the request.
  // If all extensions fail without rejection, Envoy defaults to using the directly connected remote address.
  //
  // .. warning::
  //    These extensions cannot be configured simultaneously with :ref:`use_remote_address
  //    <envoy_v3_api_field_extensions.filters.network.http_connection_manager.v3.HttpConnectionManager.use_remote_address>`
  //    or :ref:`xff_num_trusted_hops
  //    <envoy_v3_api_field_extensions.filters.network.http_connection_manager.v3.HttpConnectionManager.xff_num_trusted_hops>`.
  //
  // [#extension-category: envoy.http.original_ip_detection]
  repeated config.core.v3.TypedExtensionConfig original_ip_detection_extensions = 46;

  // The configuration for the early header mutation extensions.
  //
  // When configured the extensions will be called before any routing, tracing, or any filter processing.
  // Each extension will be applied in the order they are configured.
  // If the same header is mutated by multiple extensions, then the last extension will win.
  //
  // [#extension-category: envoy.http.early_header_mutation]
  repeated config.core.v3.TypedExtensionConfig early_header_mutation_extensions = 52;

  // 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.
  //
  // .. warning::
  //     As of Envoy 1.33.0 no IP addresses will be considered trusted. If you have tooling such as probes
  //     on your private network which need to be treated as trusted (e.g. changing arbitrary x-envoy headers)
  //     you will have to manually include those addresses or CIDR ranges like:
  //
  // .. validated-code-block:: yaml
  //   :type-name: envoy.extensions.filters.network.http_connection_manager.v3.InternalAddressConfig
  //
  //   cidr_ranges:
  //       address_prefix: 10.0.0.0
  //       prefix_len: 8
  //   cidr_ranges:
  //       address_prefix: 192.168.0.0
  //       prefix_len: 16
  //   cidr_ranges:
  //       address_prefix: 172.16.0.0
  //       prefix_len: 12
  //   cidr_ranges:
  //       address_prefix: 127.0.0.1
  //       prefix_len: 32
  //   cidr_ranges:
  //       address_prefix: fd00::
  //       prefix_len: 8
  //   cidr_ranges:
  //       address_prefix: ::1
  //       prefix_len: 128
  //
  InternalAddressConfig internal_address_config = 25;

  // 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
  // <envoy_v3_api_field_extensions.filters.network.http_connection_manager.v3.HttpConnectionManager.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.
  bool skip_xff_append = 21;

  // Via header value to append to request and response headers. If this is
  // empty, no via header will be appended.
  string via = 22 [(validate.rules).string = {well_known_regex: HTTP_HEADER_VALUE strict: false}];

  // Whether the connection manager will generate the :ref:`x-request-id
  // <config_http_conn_man_headers_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.
  google.protobuf.BoolValue generate_request_id = 15;

  // Whether the connection manager will keep the :ref:`x-request-id
  // <config_http_conn_man_headers_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.
  bool preserve_external_request_id = 32;

  // If set, Envoy will always set :ref:`x-request-id <config_http_conn_man_headers_x-request-id>` header in response.
  // If this is false or not set, the request ID is returned in responses only if tracing is forced using
  // :ref:`x-envoy-force-trace <config_http_conn_man_headers_x-envoy-force-trace>` header.
  bool always_set_request_id_in_response = 37;

  // How to handle the :ref:`config_http_conn_man_headers_x-forwarded-client-cert` (XFCC) HTTP
  // header.
  ForwardClientCertDetails forward_client_cert_details = 16
      [(validate.rules).enum = {defined_only: true}];

  // This field is valid only when :ref:`forward_client_cert_details
  // <envoy_v3_api_field_extensions.filters.network.http_connection_manager.v3.HttpConnectionManager.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.
  SetCurrentClientCertDetails set_current_client_cert_details = 17;

  // 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.
  bool proxy_100_continue = 18;

  // If
  // :ref:`use_remote_address
  // <envoy_v3_api_field_extensions.filters.network.http_connection_manager.v3.HttpConnectionManager.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
  // <https://tools.ietf.org/html/rfc4291#section-2.5.5.2>`_ 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
  // <config_http_conn_man_runtime_represent_ipv4_remote_address_as_ipv4_mapped_ipv6>` for runtime
  // control.
  // [#not-implemented-hide:]
  bool represent_ipv4_remote_address_as_ipv4_mapped_ipv6 = 20;

  repeated UpgradeConfig upgrade_configs = 23;

  // 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<config_http_conn_man_runtime_normalize_path>`.
  // See `Normalization and Comparison <https://tools.ietf.org/html/rfc3986#section-6>`_
  // for details of normalization.
  // Note that Envoy does not perform
  // `case normalization <https://tools.ietf.org/html/rfc3986#section-6.2.2.1>`_
  // [#comment:TODO: This field is ignored when the
  // :ref:`header validation configuration <envoy_v3_api_field_extensions.filters.network.http_connection_manager.v3.HttpConnectionManager.typed_header_validation_config>`
  // is present.]
  google.protobuf.BoolValue normalize_path = 30;

  // 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 <https://tools.ietf.org/html/rfc3986>`_ and is provided for convenience.
  // [#comment:TODO: This field is ignored when the
  // :ref:`header validation configuration <envoy_v3_api_field_extensions.filters.network.http_connection_manager.v3.HttpConnectionManager.typed_header_validation_config>`
  // is present.]
  bool merge_slashes = 33;

  // Action to take when request URL path contains escaped slash sequences (%2F, %2f, %5C and %5c).
  // The default value can be overridden by the :ref:`http_connection_manager.path_with_escaped_slashes_action<config_http_conn_man_runtime_path_with_escaped_slashes_action>`
  // runtime variable.
  // The :ref:`http_connection_manager.path_with_escaped_slashes_action_sampling<config_http_conn_man_runtime_path_with_escaped_slashes_action_enabled>` runtime
  // variable can be used to apply the action to a portion of all requests.
  // [#comment:TODO: This field is ignored when the
  // :ref:`header validation configuration <envoy_v3_api_field_extensions.filters.network.http_connection_manager.v3.HttpConnectionManager.typed_header_validation_config>`
  // is present.]
  PathWithEscapedSlashesAction path_with_escaped_slashes_action = 45;

  // The configuration of the request ID extension. This includes operations such as
  // generation, validation, and associated tracing operations. If empty, the
  // :ref:`UuidRequestIdConfig <envoy_v3_api_msg_extensions.request_id.uuid.v3.UuidRequestIdConfig>`
  // default extension is used with default parameters. See the documentation for that extension
  // for details on what it does. Customizing the configuration for the default extension can be
  // achieved by configuring it explicitly here. For example, to disable trace reason packing,
  // the following configuration can be used:
  //
  // .. validated-code-block:: yaml
  //   :type-name: envoy.extensions.filters.network.http_connection_manager.v3.RequestIDExtension
  //
  //   typed_config:
  //     "@type": type.googleapis.com/envoy.extensions.request_id.uuid.v3.UuidRequestIdConfig
  //     pack_trace_reason: false
  //
  // [#extension-category: envoy.request_id]
  RequestIDExtension request_id_extension = 36;

  // The configuration to customize local reply returned by Envoy. It can customize status code,
  // body text and response content type. If not specified, status code and text body are hard
  // coded in Envoy, the response content type is plain text.
  LocalReplyConfig local_reply_config = 38;

  // Determines if the port part should be removed from host/authority header before any processing
  // of request by HTTP filters or routing. The port would be removed only if it is equal to the :ref:`listener's<envoy_v3_api_field_config.listener.v3.Listener.address>`
  // local port. This affects the upstream host header unless the method is
  // CONNECT in which case if no filter adds a port the original port will be restored before headers are
  // sent upstream.
  // Without setting this option, incoming requests with host ``example:443`` will not match against
  // route with :ref:`domains<envoy_v3_api_field_config.route.v3.VirtualHost.domains>` match set to ``example``. Defaults to ``false``. Note that port removal is not part
  // of `HTTP spec <https://tools.ietf.org/html/rfc3986>`_ and is provided for convenience.
  // Only one of ``strip_matching_host_port`` or ``strip_any_host_port`` can be set.
  bool strip_matching_host_port = 39
      [(udpa.annotations.field_migrate).oneof_promotion = "strip_port_mode"];

  oneof strip_port_mode {
    // Determines if the port part should be removed from host/authority header before any processing
    // of request by HTTP filters or routing.
    // This affects the upstream host header unless the method is CONNECT in
    // which case if no filter adds a port the original port will be restored before headers are sent upstream.
    // Without setting this option, incoming requests with host ``example:443`` will not match against
    // route with :ref:`domains<envoy_v3_api_field_config.route.v3.VirtualHost.domains>` match set to ``example``. Defaults to ``false``. Note that port removal is not part
    // of `HTTP spec <https://tools.ietf.org/html/rfc3986>`_ and is provided for convenience.
    // Only one of ``strip_matching_host_port`` or ``strip_any_host_port`` can be set.
    bool strip_any_host_port = 42;
  }

  // Governs Envoy's behavior when receiving invalid HTTP from downstream.
  // If this option is false (default), Envoy will err on the conservative side handling HTTP
  // errors, terminating both HTTP/1.1 and HTTP/2 connections when receiving an invalid request.
  // If this option is set to true, Envoy will be more permissive, only resetting the invalid
  // stream in the case of HTTP/2 and leaving the connection open where possible (if the entire
  // request is read for HTTP/1.1)
  // In general this should be true for deployments receiving trusted traffic (L2 Envoys,
  // company-internal mesh) and false when receiving untrusted traffic (edge deployments).
  //
  // If different behaviors for invalid_http_message for HTTP/1 and HTTP/2 are
  // desired, one should use the new HTTP/1 option :ref:`override_stream_error_on_invalid_http_message
  // <envoy_v3_api_field_config.core.v3.Http1ProtocolOptions.override_stream_error_on_invalid_http_message>` or the new HTTP/2 option
  // :ref:`override_stream_error_on_invalid_http_message
  // <envoy_v3_api_field_config.core.v3.Http2ProtocolOptions.override_stream_error_on_invalid_http_message>`
  // ``not`` the deprecated but similarly named :ref:`stream_error_on_invalid_http_messaging
  // <envoy_v3_api_field_config.core.v3.Http2ProtocolOptions.stream_error_on_invalid_http_messaging>`
  google.protobuf.BoolValue stream_error_on_invalid_http_message = 40;

  // [#not-implemented-hide:] Path normalization configuration. This includes
  // configurations for transformations (e.g. RFC 3986 normalization or merge
  // adjacent slashes) and the policy to apply them. The policy determines
  // whether transformations affect the forwarded ``:path`` header. RFC 3986 path
  // normalization is enabled by default and the default policy is that the
  // normalized header will be forwarded. See :ref:`PathNormalizationOptions
  // <envoy_v3_api_msg_extensions.filters.network.http_connection_manager.v3.PathNormalizationOptions>`
  // for details.
  PathNormalizationOptions path_normalization_options = 43;

  // Determines if trailing dot of the host should be removed from host/authority header before any
  // processing of request by HTTP filters or routing.
  // This affects the upstream host header.
  // Without setting this option, incoming requests with host ``example.com.`` will not match against
  // route with :ref:`domains<envoy_v3_api_field_config.route.v3.VirtualHost.domains>` match set to ``example.com``. Defaults to ``false``.
  // When the incoming request contains a host/authority header that includes a port number,
  // setting this option will strip a trailing dot, if present, from the host section,
  // leaving the port as is (e.g. host value ``example.com.:443`` will be updated to ``example.com:443``).
  bool strip_trailing_host_dot = 47;

  // Proxy-Status HTTP response header configuration.
  // If this config is set, the Proxy-Status HTTP response header field is
  // populated. By default, it is not.
  ProxyStatusConfig proxy_status_config = 49;

  // Configuration options for Header Validation (UHV).
  // UHV is an extensible mechanism for checking validity of HTTP requests as well as providing
  // normalization for request attributes, such as URI path.
  // If the typed_header_validation_config is present it overrides the following options:
  // ``normalize_path``, ``merge_slashes``, ``path_with_escaped_slashes_action``
  // ``http_protocol_options.allow_chunked_length``, ``common_http_protocol_options.headers_with_underscores_action``.
  //
  // The default UHV checks the following:
  //
  // #. HTTP/1 header map validity according to `RFC 7230 section 3.2<https://datatracker.ietf.org/doc/html/rfc7230#section-3.2>`_
  // #. Syntax of HTTP/1 request target URI and response status
  // #. HTTP/2 header map validity according to `RFC 7540 section 8.1.2<https://datatracker.ietf.org/doc/html/rfc7540#section-8.1.2`_
  // #. Syntax of HTTP/2 pseudo headers
  // #. HTTP/3 header map validity according to `RFC 9114 section 4.3 <https://www.rfc-editor.org/rfc/rfc9114.html>`_
  // #. Syntax of HTTP/3 pseudo headers
  // #. Syntax of ``Content-Length`` and ``Transfer-Encoding``
  // #. Validation of HTTP/1 requests with both ``Content-Length`` and ``Transfer-Encoding`` headers
  // #. Normalization of the URI path according to `Normalization and Comparison <https://datatracker.ietf.org/doc/html/rfc3986#section-6>`_
  //    without `case normalization <https://datatracker.ietf.org/doc/html/rfc3986#section-6.2.2.1>`_
  //
  // [#not-implemented-hide:]
  // [#extension-category: envoy.http.header_validators]
  config.core.v3.TypedExtensionConfig typed_header_validation_config = 50;

  // Append the ``x-forwarded-port`` header with the port value client used to connect to Envoy. It
  // will be ignored if the ``x-forwarded-port`` header has been set by any trusted proxy in front of Envoy.
  bool append_x_forwarded_port = 51;

  // Append the :ref:`config_http_conn_man_headers_x-envoy-local-overloaded` HTTP header in the scenario where
  // the Overload Manager has been triggered.
  bool append_local_overload = 57;

  // Whether the HCM will add ProxyProtocolFilterState to the Connection lifetime filter state. Defaults to ``true``.
  // This should be set to ``false`` in cases where Envoy's view of the downstream address may not correspond to the
  // actual client address, for example, if there's another proxy in front of the Envoy.
  google.protobuf.BoolValue add_proxy_protocol_connection_state = 53;
}

// The configuration to customize local reply returned by Envoy.
message LocalReplyConfig {
  // Configuration of list of mappers which allows to filter and change local response.
  // The mappers will be checked by the specified order until one is matched.
  repeated ResponseMapper mappers = 1;

  // The configuration to form response body from the :ref:`command operators <config_access_log_command_operators>`
  // and to specify response content type as one of: plain/text or application/json.
  //
  // Example one: "plain/text" ``body_format``.
  //
  // .. validated-code-block:: yaml
  //   :type-name: envoy.config.core.v3.SubstitutionFormatString
  //
  //   text_format: "%LOCAL_REPLY_BODY%:%RESPONSE_CODE%:path=%REQ(:path)%\n"
  //
  // The following response body in "plain/text" format will be generated for a request with
  // local reply body of "upstream connection error", response_code=503 and path=/foo.
  //
  // .. code-block:: text
  //
  //   upstream connect error:503:path=/foo
  //
  // Example two: "application/json" ``body_format``.
  //
  // .. validated-code-block:: yaml
  //   :type-name: envoy.config.core.v3.SubstitutionFormatString
  //
  //   json_format:
  //     status: "%RESPONSE_CODE%"
  //     message: "%LOCAL_REPLY_BODY%"
  //     path: "%REQ(:path)%"
  //
  // The following response body in "application/json" format would be generated for a request with
  // local reply body of "upstream connection error", response_code=503 and path=/foo.
  //
  // .. code-block:: json
  //
  //  {
  //    "status": 503,
  //    "message": "upstream connection error",
  //    "path": "/foo"
  //  }
  //
  config.core.v3.SubstitutionFormatString body_format = 2;
}

// The configuration to filter and change local response.
// [#next-free-field: 6]
message ResponseMapper {
  // Filter to determine if this mapper should apply.
  config.accesslog.v3.AccessLogFilter filter = 1 [(validate.rules).message = {required: true}];

  // The new response status code if specified.
  google.protobuf.UInt32Value status_code = 2 [(validate.rules).uint32 = {lt: 600 gte: 200}];

  // The new local reply body text if specified. It will be used in the ``%LOCAL_REPLY_BODY%``
  // command operator in the ``body_format``.
  config.core.v3.DataSource body = 3;

  // A per mapper ``body_format`` to override the :ref:`body_format <envoy_v3_api_field_extensions.filters.network.http_connection_manager.v3.LocalReplyConfig.body_format>`.
  // It will be used when this mapper is matched.
  config.core.v3.SubstitutionFormatString body_format_override = 4;

  // HTTP headers to add to a local reply. This allows the response mapper to append, to add
  // or to override headers of any local reply before it is sent to a downstream client.
  repeated config.core.v3.HeaderValueOption headers_to_add = 5
      [(validate.rules).repeated = {max_items: 1000}];
}

message Rds {
  option (udpa.annotations.versioning).previous_message_type =
      "envoy.config.filter.network.http_connection_manager.v2.Rds";

  // Configuration source specifier for RDS.
  config.core.v3.ConfigSource config_source = 1 [(validate.rules).message = {required: true}];

  // 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.
  string route_config_name = 2;
}

// This message is used to work around the limitations with 'oneof' and repeated fields.
message ScopedRouteConfigurationsList {
  option (udpa.annotations.versioning).previous_message_type =
      "envoy.config.filter.network.http_connection_manager.v2.ScopedRouteConfigurationsList";

  repeated config.route.v3.ScopedRouteConfiguration scoped_route_configurations = 1
      [(validate.rules).repeated = {min_items: 1}];
}

// [#next-free-field: 6]
message ScopedRoutes {
  option (udpa.annotations.versioning).previous_message_type =
      "envoy.config.filter.network.http_connection_manager.v2.ScopedRoutes";

  // Specifies the mechanism for constructing "scope keys" based on HTTP request attributes. These
  // keys are matched against a set of :ref:`Key<envoy_v3_api_msg_config.route.v3.ScopedRouteConfiguration.Key>`
  // objects assembled from :ref:`ScopedRouteConfiguration<envoy_v3_api_msg_config.route.v3.ScopedRouteConfiguration>`
  // messages distributed via SRDS (the Scoped Route Discovery Service) or assigned statically via
  // :ref:`scoped_route_configurations_list<envoy_v3_api_field_extensions.filters.network.http_connection_manager.v3.ScopedRoutes.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<envoy_v3_api_msg_config.route.v3.RouteConfiguration>`) to use for the request.
  message ScopeKeyBuilder {
    option (udpa.annotations.versioning).previous_message_type =
        "envoy.config.filter.network.http_connection_manager.v2.ScopedRoutes.ScopeKeyBuilder";

    // Specifies the mechanism for constructing key fragments which are composed into scope keys.
    message FragmentBuilder {
      option (udpa.annotations.versioning).previous_message_type =
          "envoy.config.filter.network.http_connection_manager.v2.ScopedRoutes.ScopeKeyBuilder."
          "FragmentBuilder";

      // 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
      //    |         || |
      //    |         || \----> <element_separator>
      //    |         ||
      //    |         |\----> <element.separator>
      //    |         |
      //    |         \----> <element.key>
      //    |
      //    \----> <name>
      //
      //    Each 'a=b' key-value pair constitutes an 'element' of the header field.
      message HeaderValueExtractor {
        option (udpa.annotations.versioning).previous_message_type =
            "envoy.config.filter.network.http_connection_manager.v2.ScopedRoutes.ScopeKeyBuilder."
            "FragmentBuilder.HeaderValueExtractor";

        // Specifies a header field's key value pair to match on.
        message KvElement {
          option (udpa.annotations.versioning).previous_message_type =
              "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.
          string separator = 1 [(validate.rules).string = {min_len: 1}];

          // The key to match on.
          string key = 2 [(validate.rules).string = {min_len: 1}];
        }

        // The name of the header field to extract the value from.
        //
        // .. note::
        //
        //   If the header appears multiple times only the first value is used.
        string name = 1 [
          (validate.rules).string = {min_len: 1 well_known_regex: HTTP_HEADER_NAME strict: false}
        ];

        // 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.
        string element_separator = 2;

        oneof extract_type {
          // 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.
          uint32 index = 3;

          // Specifies the key value pair to extract the value from.
          KvElement element = 4;
        }
      }

      oneof type {
        option (validate.required) = true;

        // Specifies how a header field's value should be extracted.
        HeaderValueExtractor header_value_extractor = 1;
      }
    }

    // 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<envoy_v3_api_msg_config.route.v3.ScopedRouteConfiguration>`.
    // A missing fragment during comparison will make the key invalid, i.e., the computed key doesn't match any key.
    repeated FragmentBuilder fragments = 1 [(validate.rules).repeated = {min_items: 1}];
  }

  // The name assigned to the scoped routing configuration.
  string name = 1 [(validate.rules).string = {min_len: 1}];

  // The algorithm to use for constructing a scope key for each request.
  ScopeKeyBuilder scope_key_builder = 2 [(validate.rules).message = {required: true}];

  // Configuration source specifier for RDS.
  // This config source is used to subscribe to RouteConfiguration resources specified in
  // ScopedRouteConfiguration messages.
  config.core.v3.ConfigSource rds_config_source = 3;

  oneof config_specifier {
    option (validate.required) = true;

    // 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<envoy_v3_api_msg_extensions.filters.network.http_connection_manager.v3.ScopedRoutes.ScopeKeyBuilder>`
    // in this message.
    ScopedRouteConfigurationsList scoped_route_configurations_list = 4;

    // 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<envoy_v3_api_msg_extensions.filters.network.http_connection_manager.v3.ScopedRoutes.ScopeKeyBuilder>`
    // in this message.
    ScopedRds scoped_rds = 5;
  }
}

message ScopedRds {
  option (udpa.annotations.versioning).previous_message_type =
      "envoy.config.filter.network.http_connection_manager.v2.ScopedRds";

  // Configuration source specifier for scoped RDS.
  config.core.v3.ConfigSource scoped_rds_config_source = 1
      [(validate.rules).message = {required: true}];

  // xdstp:// resource locator for scoped RDS collection.
  // [#not-implemented-hide:]
  string srds_resources_locator = 2;
}

// [#next-free-field: 8]
message HttpFilter {
  option (udpa.annotations.versioning).previous_message_type =
      "envoy.config.filter.network.http_connection_manager.v2.HttpFilter";

  reserved 3, 2;

  reserved "config";

  // The name of the filter configuration. It also serves as a resource name in ExtensionConfigDS.
  string name = 1 [(validate.rules).string = {min_len: 1}];

  oneof config_type {
    // Filter specific configuration which depends on the filter being instantiated. See the supported
    // filters for further documentation.
    //
    // To support configuring a :ref:`match tree <arch_overview_matching_api>`, use an
    // :ref:`ExtensionWithMatcher <envoy_v3_api_msg_extensions.common.matching.v3.ExtensionWithMatcher>`
    // with the desired HTTP filter.
    // [#extension-category: envoy.filters.http]
    google.protobuf.Any typed_config = 4;

    // Configuration source specifier for an extension configuration discovery service.
    // In case of a failure and without the default configuration, the HTTP listener responds with code 500.
    // Extension configs delivered through this mechanism are not expected to require warming (see https://github.com/envoyproxy/envoy/issues/12061).
    //
    // To support configuring a :ref:`match tree <arch_overview_matching_api>`, use an
    // :ref:`ExtensionWithMatcher <envoy_v3_api_msg_extensions.common.matching.v3.ExtensionWithMatcher>`
    // with the desired HTTP filter. This works for both the default filter configuration as well
    // as for filters provided via the API.
    config.core.v3.ExtensionConfigSource config_discovery = 5;
  }

  // If true, clients that do not support this filter may ignore the
  // filter but otherwise accept the config.
  // Otherwise, clients that do not support this filter must reject the config.
  bool is_optional = 6;

  // If true, the filter is disabled by default and must be explicitly enabled by setting
  // per filter configuration in the route configuration.
  // See :ref:`route based filter chain <arch_overview_http_filters_route_based_filter_chain>`
  // for more details.
  //
  // Terminal filters (e.g. ``envoy.filters.http.router``) cannot be marked as disabled.
  bool disabled = 7;
}

message RequestIDExtension {
  option (udpa.annotations.versioning).previous_message_type =
      "envoy.config.filter.network.http_connection_manager.v2.RequestIDExtension";

  // Request ID extension specific configuration.
  google.protobuf.Any typed_config = 1;
}

// [#protodoc-title: Envoy Mobile HTTP connection manager]
// HTTP connection manager for use in Envoy mobile.
// [#extension: envoy.filters.network.envoy_mobile_http_connection_manager]
message EnvoyMobileHttpConnectionManager {
  // The configuration for the underlying HttpConnectionManager which will be
  // instantiated for Envoy mobile.
  HttpConnectionManager config = 1;
}
