Skip to content

Commit a6a7d0c

Browse files
committed
initial impl of grpc decompressor filter
Signed-off-by: William Zhang <[email protected]>
1 parent b18b993 commit a6a7d0c

File tree

13 files changed

+645
-0
lines changed

13 files changed

+645
-0
lines changed

api/BUILD

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,7 @@ proto_library(
195195
"//envoy/extensions/filters/http/file_system_buffer/v3:pkg",
196196
"//envoy/extensions/filters/http/gcp_authn/v3:pkg",
197197
"//envoy/extensions/filters/http/geoip/v3:pkg",
198+
"//envoy/extensions/filters/http/grpc_decompressor/v3:pkg",
198199
"//envoy/extensions/filters/http/grpc_field_extraction/v3:pkg",
199200
"//envoy/extensions/filters/http/grpc_http1_bridge/v3:pkg",
200201
"//envoy/extensions/filters/http/grpc_http1_reverse_bridge/v3:pkg",
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# DO NOT EDIT. This file is generated by tools/proto_format/proto_sync.py.
2+
3+
load("@envoy_api//bazel:api_build_system.bzl", "api_proto_package")
4+
5+
licenses(["notice"]) # Apache 2
6+
7+
api_proto_package(
8+
deps = [
9+
"//envoy/config/core/v3:pkg",
10+
"@com_github_cncf_xds//udpa/annotations:pkg",
11+
],
12+
)
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
syntax = "proto3";
2+
3+
package envoy.extensions.filters.http.grpc_decompressor.v3;
4+
5+
import "envoy/config/core/v3/base.proto";
6+
import "envoy/config/core/v3/extension.proto";
7+
8+
import "google/protobuf/wrappers.proto";
9+
10+
import "udpa/annotations/status.proto";
11+
import "validate/validate.proto";
12+
13+
option java_package = "io.envoyproxy.envoy.extensions.filters.http.grpc_decompressor.v3";
14+
option java_outer_classname = "DecompressorProto";
15+
option java_multiple_files = true;
16+
option go_package = "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/http/grpc_decompressor/v3;grpc_decompressorv3";
17+
option (udpa.annotations.file_status).package_version_status = ACTIVE;
18+
19+
// [#protodoc-title: gRPC Decompressor]
20+
// [#extension: envoy.filters.http.grpc_decompressor]
21+
22+
message Decompressor {
23+
// Common configuration for filter behavior on both the request and response direction.
24+
message CommonDirectionConfig {
25+
// Runtime flag that controls whether the filter is enabled for decompression or not. If set to false, the
26+
// filter will operate as a pass-through filter. If the message is unspecified, the filter will be enabled.
27+
config.core.v3.RuntimeFeatureFlag enabled = 1;
28+
29+
// If set to true, and decompression is enabled for the opposite direction, the filter modifies the
30+
// grpc-accept-encoding header by appending the decompressor_library's encoding. Defaults to true.
31+
google.protobuf.BoolValue advertise_grpc_accept_encoding = 2;
32+
33+
// The maximum message size in bytes that the filter will decompress. If the message size is greater than this value,
34+
// the filter will abort the stream with a gRPC status code of ResourceExhausted. This is to avoid unbounded caching
35+
// of large messages within the proxy. If not set, there is no limit.
36+
google.protobuf.UInt32Value max_message_length = 3;
37+
}
38+
39+
// Configuration for filter behavior on the request direction.
40+
message RequestDirectionConfig {
41+
CommonDirectionConfig common_config = 1;
42+
}
43+
44+
// Configuration for filter behavior on the response direction.
45+
message ResponseDirectionConfig {
46+
CommonDirectionConfig common_config = 1;
47+
}
48+
49+
// A decompressor library to use for both request and response decompression. Currently only
50+
// :ref:`envoy.compression.gzip.compressor<envoy_v3_api_msg_extensions.compression.gzip.decompressor.v3.Gzip>`
51+
// is included in Envoy.
52+
// [#extension-category: envoy.compression.decompressor]
53+
config.core.v3.TypedExtensionConfig decompressor_library = 1
54+
[(validate.rules).message = {required: true}];
55+
56+
// Configuration for request decompression. Decompression is enabled by default if left empty.
57+
RequestDirectionConfig request_direction_config = 2;
58+
59+
// Configuration for response decompression. Decompression is enabled by default if left empty.
60+
ResponseDirectionConfig response_direction_config = 3;
61+
}

api/versioning/BUILD

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,7 @@ proto_library(
134134
"//envoy/extensions/filters/http/file_system_buffer/v3:pkg",
135135
"//envoy/extensions/filters/http/gcp_authn/v3:pkg",
136136
"//envoy/extensions/filters/http/geoip/v3:pkg",
137+
"//envoy/extensions/filters/http/grpc_decompressor/v3:pkg",
137138
"//envoy/extensions/filters/http/grpc_field_extraction/v3:pkg",
138139
"//envoy/extensions/filters/http/grpc_http1_bridge/v3:pkg",
139140
"//envoy/extensions/filters/http/grpc_http1_reverse_bridge/v3:pkg",
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
.. _config_http_filters_grpc_decompression:
2+
3+
gRPC Decompression
4+
================
5+
6+
* gRPC :ref:`architecture overview <arch_overview_grpc>`
7+
* This filter should be configured with the type URL ``type.googleapis.com/envoy.extensions.filters.http.grpc_decompressor.v3.Decompressor``.
8+
* :ref:`v3 API reference <envoy_v3_api_msg_extensions.filters.http.grpc_decompressor.v3.Decompressor>`
9+
10+
The gRPC decompression filter enables decompression of messages following the `gRPC over HTTP/2 specification
11+
<https://github.com/grpc/grpc/blob/345f048b5bebda1e03eb1c520ee0e18d7a694d11/doc/PROTOCOL-HTTP2.md#introduction>`_.

envoy/compression/decompressor/factory.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ class DecompressorFactory {
1010
public:
1111
virtual ~DecompressorFactory() = default;
1212

13+
// Creates a new decompressor instance. This should be thread-safe.
1314
virtual DecompressorPtr createDecompressor(const std::string& stats_prefix) PURE;
1415
virtual const std::string& statsPrefix() const PURE;
1516
// TODO(junr03): this method assumes that decompressors are used on http messages.

source/extensions/extensions_build_config.bzl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,7 @@ EXTENSIONS = {
176176
"envoy.filters.http.file_system_buffer": "//source/extensions/filters/http/file_system_buffer:config",
177177
"envoy.filters.http.gcp_authn": "//source/extensions/filters/http/gcp_authn:config",
178178
"envoy.filters.http.geoip": "//source/extensions/filters/http/geoip:config",
179+
"envoy.filters.http.grpc_decompressor": "//source/extensions/filters/http/grpc_decompressor:config",
179180
"envoy.filters.http.grpc_field_extraction": "//source/extensions/filters/http/grpc_field_extraction:config",
180181
"envoy.filters.http.grpc_http1_bridge": "//source/extensions/filters/http/grpc_http1_bridge:config",
181182
"envoy.filters.http.grpc_http1_reverse_bridge": "//source/extensions/filters/http/grpc_http1_reverse_bridge:config",

source/extensions/extensions_metadata.yaml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -454,6 +454,13 @@ envoy.filters.http.gcp_authn:
454454
status: alpha
455455
type_urls:
456456
- envoy.extensions.filters.http.gcp_authn.v3.GcpAuthnFilterConfig
457+
envoy.filters.http.grpc_decompressor:
458+
categories:
459+
- envoy.filters.http
460+
security_posture: unknown
461+
status: alpha
462+
type_urls:
463+
- envoy.extensions.filters.http.grpc_decompressor.v3.Decompressor
457464
envoy.filters.http.grpc_field_extraction:
458465
categories:
459466
- envoy.filters.http
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
load(
2+
"//bazel:envoy_build_system.bzl",
3+
"envoy_cc_extension",
4+
"envoy_cc_library",
5+
"envoy_extension_package",
6+
)
7+
8+
licenses(["notice"]) # Apache 2
9+
10+
# HTTP L7 filter that performs decompression with configurable decompression libraries
11+
# Public docs: https://envoyproxy.io/docs/envoy/latest/configuration/http/http_filters/decompressor_filter
12+
13+
envoy_extension_package()
14+
15+
envoy_cc_library(
16+
name = "decompressor_filter_lib",
17+
srcs = ["decompressor_filter.cc"],
18+
hdrs = ["decompressor_filter.h"],
19+
deps = [
20+
"//envoy/compression/decompressor:decompressor_config_interface",
21+
"//envoy/compression/decompressor:decompressor_interface",
22+
"//envoy/http:filter_interface",
23+
"//source/common/buffer:buffer_lib",
24+
"//source/common/common:macros",
25+
"//source/common/grpc:codec_lib",
26+
"//source/common/http:headers_lib",
27+
"//source/common/runtime:runtime_lib",
28+
"//source/extensions/filters/http/common:pass_through_filter_lib",
29+
"@envoy_api//envoy/extensions/filters/http/grpc_decompressor/v3:pkg_cc_proto",
30+
],
31+
)
32+
33+
envoy_cc_extension(
34+
name = "config",
35+
srcs = ["config.cc"],
36+
hdrs = ["config.h"],
37+
deps = [
38+
":decompressor_filter_lib",
39+
"//envoy/compression/decompressor:decompressor_config_interface",
40+
"//source/common/config:utility_lib",
41+
"//source/extensions/filters/http/common:factory_base_lib",
42+
"@envoy_api//envoy/extensions/filters/http/grpc_decompressor/v3:pkg_cc_proto",
43+
],
44+
)
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
#include "source/extensions/filters/http/grpc_decompressor/config.h"
2+
3+
#include "envoy/compression/decompressor/config.h"
4+
5+
#include "source/common/config/utility.h"
6+
#include "source/extensions/filters/http/grpc_decompressor/decompressor_filter.h"
7+
8+
namespace Envoy {
9+
namespace Extensions {
10+
namespace HttpFilters {
11+
namespace GrpcDecompressor {
12+
13+
absl::StatusOr<Http::FilterFactoryCb> DecompressorFilterFactory::createFilterFactoryFromProtoTyped(
14+
const envoy::extensions::filters::http::grpc_decompressor::v3::Decompressor& proto_config,
15+
const std::string& stats_prefix, Server::Configuration::FactoryContext& context) {
16+
const std::string decompressor_library_type{TypeUtil::typeUrlToDescriptorFullName(
17+
proto_config.decompressor_library().typed_config().type_url())};
18+
Compression::Decompressor::NamedDecompressorLibraryConfigFactory* const
19+
decompressor_library_factory = Registry::FactoryRegistry<
20+
Compression::Decompressor::NamedDecompressorLibraryConfigFactory>::
21+
getFactoryByType(decompressor_library_type);
22+
if (decompressor_library_factory == nullptr) {
23+
return absl::InvalidArgumentError(fmt::format(
24+
"Didn't find a registered implementation for type: '{}'", decompressor_library_type));
25+
}
26+
ProtobufTypes::MessagePtr message = Config::Utility::translateAnyToFactoryConfig(
27+
proto_config.decompressor_library().typed_config(), context.messageValidationVisitor(),
28+
*decompressor_library_factory);
29+
Compression::Decompressor::DecompressorFactoryPtr decompressor_factory =
30+
decompressor_library_factory->createDecompressorFactoryFromProto(*message, context);
31+
DecompressorFilterConfigSharedPtr filter_config = std::make_shared<DecompressorFilterConfig>(
32+
proto_config, stats_prefix, context.scope(), context.serverFactoryContext().runtime(),
33+
std::move(decompressor_factory));
34+
return [filter_config](Http::FilterChainFactoryCallbacks& callbacks) -> void {
35+
callbacks.addStreamFilter(std::make_shared<DecompressorFilter>(filter_config));
36+
};
37+
}
38+
39+
/**
40+
* Static registration for the decompressor filter. @see NamedHttpFilterConfigFactory.
41+
*/
42+
REGISTER_FACTORY(DecompressorFilterFactory, Server::Configuration::NamedHttpFilterConfigFactory);
43+
44+
} // namespace GrpcDecompressor
45+
} // namespace HttpFilters
46+
} // namespace Extensions
47+
} // namespace Envoy

0 commit comments

Comments
 (0)