Composite Filter

  • This filter should be configured with the type URL type.googleapis.com/envoy.extensions.filters.http.composite.v3.Composite.

  • v3 API reference

The composite filter allows delegating filter actions to a filter specified by a match result. The purpose of this is to allow different filters or filter configurations to be selected based on the incoming request, allowing for more dynamic configuration that could become prohibitive when making use of per route configurations (e.g. because the cardinality would cause a route table explosion).

The filter does not do any kind of buffering, and as a result it will only delegate callbacks received during or after the phase which instantiates the delegated filter. In order to delegate all the data to the specified filter, the decision must be made based on just the request headers.

Delegation can fail if the filter factory attempted to use a callback not supported by the composite filter. In either case, the <stat_prefix>.composite.delegation_error stat will be incremented.

This filter adds a map of the delegated filter name (of the action that is matched) and the root config filter name to the filter state with key envoy.extensions.filters.http.composite.matched_actions. This filter state is not emitted when the filter is configured in the upstream filter chain.

Contains a map of pairs FILTER_CONFIG_NAME:ACTION_NAME:

  • FILTER_CONFIG_NAME: root filter config name.

  • ACTION_NAME: delegated filter name of the action that is matched.

Configuration Examples

Single Filter Delegation

Here’s a sample Envoy configuration that makes use of the composite filter to inject a different latency via the fault filter. It uses the header x-fault-category to determine which fault configuration to use: if the header is equal to the string huge fault, a 10s latency is injected while if the header contains tiny fault a 1s latency is injected. If the header is absent or contains a different value, no filter is instantiated.

admin:
  address:
    socket_address: {address: 0.0.0.0, port_value: 9901}

static_resources:
  listeners:
  - name: listener1
    address:
      socket_address: {address: 0.0.0.0, port_value: 51051}
    filter_chains:
    - filters:
      - name: envoy.filters.network.http_connection_manager
        typed_config:
          "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
          stat_prefix: grpc_json
          codec_type: AUTO
          route_config:
            name: local_route
            virtual_hosts:
            - name: local_service
              domains: ["*"]
              routes:
              # NOTE: by default, matching happens based on the gRPC route, and not on the incoming request path.
              # Reference:
              # https://envoyproxy.io/docs/envoy/latest/configuration/http/http_filters/grpc_json_transcoder_filter#route-configs-for-transcoded-requests
              - match: {prefix: "/helloworld.Greeter"}
                route: {cluster: grpc, timeout: 60s}
          http_filters:
          - name: composite
            typed_config:
              "@type": type.googleapis.com/envoy.extensions.common.matching.v3.ExtensionWithMatcher
              extension_config:
                name: composite
                typed_config:
                  "@type": type.googleapis.com/envoy.extensions.filters.http.composite.v3.Composite
              xds_matcher:
                matcher_tree:
                  input:
                    name: request-headers
                    typed_config:
                      "@type": type.googleapis.com/envoy.type.matcher.v3.HttpRequestHeaderMatchInput
                      header_name: x-fault-category
                  exact_match_map:
                    map:
                      "huge fault":  # inject 10s latency into all requests
                        action:
                          name: composite-action
                          typed_config:
                            "@type": type.googleapis.com/envoy.extensions.filters.http.composite.v3.ExecuteFilterAction
                            typed_config:
                              name: http-fault
                              typed_config:
                                "@type": type.googleapis.com/envoy.extensions.filters.http.fault.v3.HTTPFault
                                delay:
                                  fixed_delay: 10s
                                  percentage:
                                    numerator: 100
                                    denominator: HUNDRED
                      "tiny fault":  # inject 1s latency into all requests
                        action:
                          name: composite-action
                          typed_config:
                            "@type": type.googleapis.com/envoy.extensions.filters.http.composite.v3.ExecuteFilterAction
                            typed_config:
                              name: http-fault
                              typed_config:
                                "@type": type.googleapis.com/envoy.extensions.filters.http.fault.v3.HTTPFault
                                delay:
                                  fixed_delay: 1s
                                  percentage:
                                    numerator: 100
                                    denominator: HUNDRED
          - name: envoy.filters.http.router
            typed_config:
              "@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router

  clusters:
  - name: grpc
    type: LOGICAL_DNS
    lb_policy: ROUND_ROBIN
    dns_lookup_family: V4_ONLY
    typed_extension_protocol_options:
      envoy.extensions.upstreams.http.v3.HttpProtocolOptions:
        "@type": type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions
        explicit_http_config:
          http2_protocol_options: {}
    load_assignment:
      cluster_name: grpc
      endpoints:
      - lb_endpoints:
        - endpoint:
            address:
              socket_address:
                address: 127.0.0.1
                port_value: 50051

Filter Chain Delegation

The composite filter can also delegate to a chain of filters rather than a single filter. When using filter_chain, multiple HTTP filters are executed in sequence for request processing (decoding) and in reverse order for response processing (encoding), similar to how the main HTTP filter chain operates.

This is useful when you need to apply multiple filter operations as a group based on request matching criteria. For example, you might want to apply header manipulation, rate limiting, and authentication together for certain routes.

The following example shows a composite filter configured with a filter chain that includes both header manipulation and fault injection filters:

http_filters:
- name: composite
  typed_config:
    "@type": type.googleapis.com/envoy.extensions.common.matching.v3.ExtensionWithMatcher
    extension_config:
      name: composite
      typed_config:
        "@type": type.googleapis.com/envoy.extensions.filters.http.composite.v3.Composite
    xds_matcher:
      matcher_tree:
        input:
          name: request-headers
          typed_config:
            "@type": type.googleapis.com/envoy.type.matcher.v3.HttpRequestHeaderMatchInput
            header_name: x-api-version
        exact_match_map:
          map:
            "v2":
              action:
                name: composite-action
                typed_config:
                  "@type": type.googleapis.com/envoy.extensions.filters.http.composite.v3.ExecuteFilterAction
                  filter_chain:
                    typed_config:
                    - name: envoy.filters.http.header_to_metadata
                      typed_config:
                        "@type": type.googleapis.com/envoy.extensions.filters.http.header_to_metadata.v3.Config
                        request_rules:
                        - header: x-user-id
                          on_header_present:
                            metadata_namespace: envoy.lb
                            key: user
                            type: STRING
                    - name: envoy.filters.http.fault
                      typed_config:
                        "@type": type.googleapis.com/envoy.extensions.filters.http.fault.v3.HTTPFault
                        delay:
                          fixed_delay: 1s
                          percentage:
                            numerator: 50
                            denominator: HUNDRED
- name: envoy.filters.http.router
  typed_config:
    "@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router

Note

When filter_chain is set in ExecuteFilterAction, it takes precedence over both typed_config and dynamic_config fields.

Statistics

The composite filter outputs statistics in the <stat_prefix>.composite.* namespace.

Name

Type

Description

delegation_success

Counter

Number of requests that successfully created a delegated filter or filter chain

delegation_error

Counter

Number of requests that attempted to create a delegated filter or filter chain but failed