Compressor

Compressor is an HTTP filter which enables Envoy to compress dispatched data from an upstream service upon client request. Compression is useful in situations when bandwidth is scarce and large payloads can be effectively compressed at the expense of higher CPU load or offloading it to a compression accelerator.

Configuration

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

  • v3 API reference

How it works

When compressor filter is enabled, request and response headers are inspected to determine whether or not the content should be compressed. The content is compressed and then sent to the client with the appropriate headers, if response and request allow.

Currently the filter supports gzip, brotli and zstd compression only. Other compression libraries can be supported as extensions.

An example configuration of the filter may look like the following:

 1          http_filters:
 2          - name: envoy.filters.http.compressor
 3            typed_config:
 4              "@type": type.googleapis.com/envoy.extensions.filters.http.compressor.v3.Compressor
 5              response_direction_config:
 6                common_config:
 7                  min_content_length: 100
 8                  content_type:
 9                    - text/html
10                    - application/json
11                disable_on_etag_header: true
12              request_direction_config:
13                common_config:
14                  enabled:
15                    default_value: false
16                    runtime_key: request_compressor_enabled
17              compressor_library:
18                name: text_optimized
19                typed_config:
20                  "@type": type.googleapis.com/envoy.extensions.compression.gzip.compressor.v3.Gzip
21                  memory_level: 3
22                  window_bits: 10
23                  compression_level: BEST_COMPRESSION
24                  compression_strategy: DEFAULT_STRATEGY

By default request compression is disabled, but when enabled it will be skipped if:

  • A request does not contain a content-type value that matches one of the selected mime-types, which default to the following:

    • application/javascript

    • application/json

    • application/xhtml+xml

    • image/svg+xml

    • text/css

    • text/html

    • text/plain

    • text/xml

  • A request does not contain a content-length header.

  • A request contains a content-encoding header.

  • A request contains a transfer-encoding header whose value includes a known compression name.

By default response compression is enabled, but it will be skipped when:

  • A request does not contain accept-encoding header.

  • A request contains an accept-encoding header, but it does not contain gzip or \*.

  • A request contains an accept-encoding header with gzip or \*`` with the weight q=0. Note that the gzip will have a higher weight than \*. For example, if accept-encoding is gzip;q=0,\*;q=1, the filter will not compress. But if the header is set to \*;q=0,gzip;q=1, the filter will compress.

  • A request whose accept-encoding header includes any encoding type with a higher weight than gzip’s given the corresponding compression filter is present in the chain.

  • A response contains a content-encoding header.

  • A response contains a cache-control`` header whose value includes no-transform.

  • A response contains a transfer-encoding`` header whose value includes a known compression name.

  • A response does not contain a content-type value that matches one of the selected mime-types, which default to:

    • application/javascript

    • application/json

    • application/xhtml+xml

    • image/svg+xml

    • text/css

    • text/html

    • text/plain

    • text/xml

  • A response does not contain a content-length or transfer-encoding headers.

  • Response size is smaller than 30 bytes (only applicable when transfer-encoding is not chunked).

Please note that in case the filter is configured to use a compression library extension other than gzip it looks for content encoding in the accept-encoding header provided by the extension.

When response compression is applied:

  • The content-length is removed from response headers.

  • Response headers contain transfer-encoding: chunked, and content-encoding with the compression scheme used (e.g., gzip).

  • The vary: accept-encoding header is inserted on every response.

Also the vary: accept-encoding header may be inserted even if compression is not applied due to incompatible accept-encoding header in a request. This happens when the requested resource can still be compressed given compatible accept-encoding. Otherwise, if an uncompressed response is cached by a caching proxy in front of Envoy, the proxy won’t know to fetch a new incoming request with compatible accept-encoding from upstream.

When request compression is applied:

  • content-length is removed from request headers.

  • content-encoding with the compression scheme used (e.g., gzip) is added to request headers.

Per-Route Configuration

Response compression can be enabled and disabled on individual virtual hosts and routes. For example, to disable response compression for a particular virtual host, but enable response compression for its /static route:

 1          route_config:
 2            name: local_route
 3            virtual_hosts:
 4            - name: local_service
 5              domains: ["*"]
 6              typed_per_filter_config:
 7                envoy.filters.http.compression:
 8                  "@type": type.googleapis.com/envoy.extensions.filters.http.compressor.v3.CompressorPerRoute
 9                  disabled: true
10              routes:
11              - match: { prefix: "/static" }
12                route: { cluster: service }
13                typed_per_filter_config:
14                  envoy.filters.http.compression:
15                    "@type": type.googleapis.com/envoy.extensions.filters.http.compressor.v3.CompressorPerRoute
16                    overrides:
17                      response_direction_config:
18              - match: { prefix: "/" }
19                route: { cluster: service }

Using different compressors for requests and responses

If different compression libraries are desired for requests and responses, it is possible to install multiple compressor filters enabled only for requests or responses. For instance:

 1          http_filters:
 2          # This filter is only enabled for responses.
 3          - name: envoy.filters.http.compressor
 4            typed_config:
 5              "@type": type.googleapis.com/envoy.extensions.filters.http.compressor.v3.Compressor
 6              request_direction_config:
 7                common_config:
 8                  enabled:
 9                    default_value: false
10                    runtime_key: request_compressor_enabled
11              compressor_library:
12                name: for_response
13                typed_config:
14                  "@type": type.googleapis.com/envoy.extensions.compression.gzip.compressor.v3.Gzip
15                  memory_level: 3
16                  window_bits: 10
17                  compression_level: BEST_COMPRESSION
18                  compression_strategy: DEFAULT_STRATEGY
19          # This filter is only enabled for requests.
20          - name: envoy.filters.http.compressor
21            typed_config:
22              "@type": type.googleapis.com/envoy.extensions.filters.http.compressor.v3.Compressor
23              response_direction_config:
24                common_config:
25                  enabled:
26                    default_value: false
27                    runtime_key: response_compressor_enabled
28              request_direction_config:
29                common_config:
30                  enabled:
31                    default_value: true
32                    runtime_key: request_compressor_enabled
33              compressor_library:
34                name: for_request
35                typed_config:
36                  "@type": type.googleapis.com/envoy.extensions.compression.gzip.compressor.v3.Gzip
37                  memory_level: 9
38                  window_bits: 15
39                  compression_level: BEST_SPEED
40                  compression_strategy: DEFAULT_STRATEGY

Statistics

Every configured Compressor filter has statistics rooted at <stat_prefix>.compressor.<compressor_library.name>.<compressor_library_stat_prefix>.<direction_prefix>.* with the following:

Name

Type

Description

compressed

Counter

Number of requests compressed.

not_compressed

Counter

Number of requests not compressed.

total_uncompressed_bytes

Counter

The total uncompressed bytes of all the requests that were marked for compression.

total_compressed_bytes

Counter

The total compressed bytes of all the requests that were marked for compression.

content_length_too_small

Counter

Number of requests that accepted the compressor encoding but did not compress because the payload was too small.

In addition to the statics common for requests and responses there are statistics specific to responses only:

Name

Type

Description

no_accept_header

Counter

Number of requests with no accept header sent.

header_identity

Counter

Number of requests sent with “identity” set as the accept-encoding.

header_compressor_used

Counter

Number of requests sent with filter’s configured encoding set as the accept-encoding.

header_compressor_overshadowed

Counter

Number of requests skipped by this filter instance because they were handled by another filter in the same filter chain.

header_wildcard

Counter

Number of requests sent with \* set as the accept-encoding.

header_not_valid

Counter

Number of requests sent with a not valid accept-encoding header (aka q=0 or an unsupported encoding type).

not_compressed_etag

Counter

Number of requests that were not compressed due to the etag header. disable_on_etag_header must be turned on for this to happen.