Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
55 commits
Select commit Hold shift + click to select a range
eb1f837
compression: add brotli compressor and decompressor
Aug 31, 2020
95e0251
run check_spelling_pedantic.py
Sep 7, 2020
6b8c9e4
speed up testing by reducing default compression quality
Sep 8, 2020
7400a45
fix modernize-use-nullptr check
Sep 8, 2020
162eee4
run check_format.py
Sep 8, 2020
f10361b
test Windows build
Sep 8, 2020
0a579d9
add reference to pull request to brotli repo
rojkov Sep 8, 2020
7166d94
remove commented out leftovers
rojkov Sep 8, 2020
9f5d5f3
address review comments
rojkov Sep 10, 2020
b407c3a
free memory as soon as possible
rojkov Sep 14, 2020
d3d47fe
address review comments
rojkov Sep 14, 2020
42ad0e9
drop brotli patch
rojkov Sep 17, 2020
3408206
Avoid needless copying
rojkov Sep 21, 2020
dc8cf74
Add CPE for brotli as specified in NIST database
rojkov Sep 25, 2020
f139336
Merge remote-tracking branch 'upstream/master' into brotli-v2
rojkov Sep 28, 2020
70a25ed
add project_desc to brotli repo location
rojkov Sep 28, 2020
b4bd706
add last_updated field
rojkov Sep 28, 2020
6f7393a
no need for workaround for omitted value
rojkov Sep 30, 2020
fc40f09
add comments
rojkov Sep 30, 2020
d6e47b0
Merge remote-tracking branch 'upstream/master' into brotli-v2
rojkov Sep 30, 2020
4df3311
fix test
rojkov Sep 30, 2020
a26e102
Merge remote-tracking branch 'upstream/master' into brotli-v2
rojkov Oct 7, 2020
8f3168f
move brotli to dataplane_core
rojkov Oct 7, 2020
f6ef155
actually dataplane_ext fits better
rojkov Oct 7, 2020
4c8fcc0
Merge remote-tracking branch 'upstream/master' into brotli-v2
rojkov Oct 8, 2020
aa6512c
fix ASan tests
rojkov Oct 12, 2020
296d81e
Merge remote-tracking branch 'upstream/master' into brotli-v2
rojkov Oct 12, 2020
2b30376
fix up currest.rst
rojkov Oct 12, 2020
53c047f
fix windows build
rojkov Oct 13, 2020
2bd7591
tests: increase coverage for stats_sinks/wasm
rojkov Oct 14, 2020
ea6c21a
Merge remote-tracking branch 'upstream/master' into brotli-v2
rojkov Oct 14, 2020
d378c03
fix repositries.bzl to reflect latest changes
rojkov Oct 14, 2020
3b98400
Kick CI
rojkov Oct 14, 2020
40b204c
Kick CI
rojkov Oct 16, 2020
84f9703
link exmaple_configs_tests with envoy.filters.http.dynamic_forward_proxy
rojkov Oct 16, 2020
5d62287
Merge remote-tracking branch 'upstream/master' into brotli-v2
rojkov Oct 19, 2020
cd04f7c
add more deps to config_test
rojkov Oct 19, 2020
d43d9a0
Merge remote-tracking branch 'upstream/master' into brotli-v2
rojkov Oct 27, 2020
43d0b4a
fix repository_locations.bzl
rojkov Oct 27, 2020
032c9b5
revert //test/config_test tweaks as asan tests pass again
rojkov Oct 27, 2020
9a2aa0e
Merge remote-tracking branch 'upstream/master' into brotli-v2
rojkov Nov 10, 2020
23edfb8
correct release_date for brotli
rojkov Nov 10, 2020
29f4e54
update formatting
rojkov Nov 10, 2020
6e88e7d
fix indenting
rojkov Nov 23, 2020
c7e316d
Change brotli defaults to be friendlier to dynamic content
rojkov Nov 23, 2020
f2b5965
Merge remote-tracking branch 'upstream/master' into brotli-v2
rojkov Nov 23, 2020
43327fa
run proto_format
rojkov Nov 23, 2020
f5e2200
Merge remote-tracking branch 'upstream/master' into brotli-v2
rojkov Dec 30, 2020
2baf168
Merge remote-tracking branch 'upstream/master' into brotli-v2
rojkov Jan 13, 2021
e8494ca
adjust current.rst
rojkov Jan 13, 2021
6e6e207
Merge remote-tracking branch 'upstream/main' into brotli-v2
rojkov Jan 20, 2021
30cec33
update current.rst to have features in alphabetical order
rojkov Jan 20, 2021
4ffacc6
Merge remote-tracking branch 'upstream/main' into brotli-v2
rojkov Feb 2, 2021
e6fb711
fix current.rst after resolving merge conflict
rojkov Feb 2, 2021
2101920
Merge remote-tracking branch 'upstream/main' into brotli-v2
rojkov Feb 5, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CODEOWNERS
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,7 @@ extensions/filters/common/original_src @snowp @klarose
# Compression
/*/extensions/compression/common @junr03 @rojkov
/*/extensions/compression/gzip @junr03 @rojkov
/*/extensions/compression/brotli @junr03 @rojkov
/*/extensions/filters/http/decompressor @rojkov @dio
# Watchdog Extensions
/*/extensions/watchdog/profile_action @kbaichoo @antoniovicente
Expand Down
2 changes: 2 additions & 0 deletions api/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,8 @@ proto_library(
"//envoy/extensions/common/matching/v3:pkg",
"//envoy/extensions/common/ratelimit/v3:pkg",
"//envoy/extensions/common/tap/v3:pkg",
"//envoy/extensions/compression/brotli/compressor/v3:pkg",
"//envoy/extensions/compression/brotli/decompressor/v3:pkg",
"//envoy/extensions/compression/gzip/compressor/v3:pkg",
"//envoy/extensions/compression/gzip/decompressor/v3:pkg",
"//envoy/extensions/filters/common/dependency/v3:pkg",
Expand Down
9 changes: 9 additions & 0 deletions api/envoy/extensions/compression/brotli/compressor/v3/BUILD
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# DO NOT EDIT. This file is generated by tools/proto_format/proto_sync.py.

load("@envoy_api//bazel:api_build_system.bzl", "api_proto_package")

licenses(["notice"]) # Apache 2

api_proto_package(
deps = ["@com_github_cncf_udpa//udpa/annotations:pkg"],
)
54 changes: 54 additions & 0 deletions api/envoy/extensions/compression/brotli/compressor/v3/brotli.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
syntax = "proto3";

package envoy.extensions.compression.brotli.compressor.v3;

import "google/protobuf/wrappers.proto";

import "udpa/annotations/status.proto";
import "validate/validate.proto";

option java_package = "io.envoyproxy.envoy.extensions.compression.brotli.compressor.v3";
option java_outer_classname = "BrotliProto";
option java_multiple_files = true;
option (udpa.annotations.file_status).package_version_status = ACTIVE;

// [#protodoc-title: Brotli Compressor]
// [#extension: envoy.compression.brotli.compressor]

// [#next-free-field: 7]
message Brotli {
enum EncoderMode {
DEFAULT = 0;
GENERIC = 1;
TEXT = 2;
FONT = 3;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where do these come from? How will users decide which to use?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see, you comment below on this.

}

// Value from 0 to 11 that controls the main compression speed-density lever.
// The higher quality, the slower compression. The default value is 3.
google.protobuf.UInt32Value quality = 1 [(validate.rules).uint32 = {lte: 11}];

// A value used to tune encoder for specific input. For more information about modes,
// please refer to brotli manual: https://brotli.org/encode.html#aa6f
// This field will be set to "DEFAULT" if not specified.
EncoderMode encoder_mode = 2 [(validate.rules).enum = {defined_only: true}];

// Value from 10 to 24 that represents the base two logarithmic of the compressor's window size.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These defaults may be a bit too compression-ratio optimized:

  • window size of 22 is 4MB of memory (per request I assume)
  • compression level 11 compresses at speed of ~100-500kb/s (depending on the hardware) which is a bit too slow for most dynamic data (and would block the executing thread I assume)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree. Saner defaults wouldn't harm definitely. What would be the best choices for your use cases?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking at cloudflare they use WSIZE=18 (262128) and compression level somewhere between 3 and 4 (based on brotlidump.py). This seems relatively sane for dynamic content. You may consider cracking down on WSIZE even more to bring it closer to gzip.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! Updated the defaults.

// Larger window results in better compression at the expense of memory usage. The default is 18.
// For more details about this parameter, please refer to brotli manual:
// https://brotli.org/encode.html#a9a8
google.protobuf.UInt32Value window_bits = 3 [(validate.rules).uint32 = {lte: 24 gte: 10}];

// Value from 16 to 24 that represents the base two logarithmic of the compressor's input block
// size. Larger input block results in better compression at the expense of memory usage. The
// default is 24. For more details about this parameter, please refer to brotli manual:
// https://brotli.org/encode.html#a9a8
google.protobuf.UInt32Value input_block_bits = 4 [(validate.rules).uint32 = {lte: 24 gte: 16}];

// Value for compressor's next output buffer. If not set, defaults to 4096.
google.protobuf.UInt32Value chunk_size = 5 [(validate.rules).uint32 = {lte: 65536 gte: 4096}];

// If true, disables "literal context modeling" format feature.
// This flag is a "decoding-speed vs compression ratio" trade-off.
bool disable_literal_context_modeling = 6;
}
9 changes: 9 additions & 0 deletions api/envoy/extensions/compression/brotli/decompressor/v3/BUILD
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# DO NOT EDIT. This file is generated by tools/proto_format/proto_sync.py.

load("@envoy_api//bazel:api_build_system.bzl", "api_proto_package")

licenses(["notice"]) # Apache 2

api_proto_package(
deps = ["@com_github_cncf_udpa//udpa/annotations:pkg"],
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
syntax = "proto3";

package envoy.extensions.compression.brotli.decompressor.v3;

import "google/protobuf/wrappers.proto";

import "udpa/annotations/status.proto";
import "validate/validate.proto";

option java_package = "io.envoyproxy.envoy.extensions.compression.brotli.decompressor.v3";
option java_outer_classname = "BrotliProto";
option java_multiple_files = true;
option (udpa.annotations.file_status).package_version_status = ACTIVE;

// [#protodoc-title: Brotli Decompressor]
// [#extension: envoy.compression.brotli.decompressor]

message Brotli {
// If true, disables "canny" ring buffer allocation strategy.
// Ring buffer is allocated according to window size, despite the real size of the content.
bool disable_ring_buffer_reallocation = 1;

// Value for decompressor's next output buffer. If not set, defaults to 4096.
google.protobuf.UInt32Value chunk_size = 2 [(validate.rules).uint32 = {lte: 65536 gte: 4096}];
}
2 changes: 2 additions & 0 deletions api/versioning/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ proto_library(
"//envoy/extensions/common/matching/v3:pkg",
"//envoy/extensions/common/ratelimit/v3:pkg",
"//envoy/extensions/common/tap/v3:pkg",
"//envoy/extensions/compression/brotli/compressor/v3:pkg",
"//envoy/extensions/compression/brotli/decompressor/v3:pkg",
"//envoy/extensions/compression/gzip/compressor/v3:pkg",
"//envoy/extensions/compression/gzip/decompressor/v3:pkg",
"//envoy/extensions/filters/common/dependency/v3:pkg",
Expand Down
14 changes: 14 additions & 0 deletions bazel/repositories.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,7 @@ def envoy_dependencies(skip_targets = []):
_io_opentracing_cpp()
_net_zlib()
_com_github_zlib_ng_zlib_ng()
_org_brotli()
_upb()
_proxy_wasm_cpp_sdk()
_proxy_wasm_cpp_host()
Expand Down Expand Up @@ -352,6 +353,19 @@ def _com_github_zlib_ng_zlib_ng():
patches = ["@envoy//bazel/foreign_cc:zlib_ng.patch"],
)

def _org_brotli():
external_http_archive(
name = "org_brotli",
)
native.bind(
name = "brotlienc",
actual = "@org_brotli//:brotlienc",
)
native.bind(
name = "brotlidec",
actual = "@org_brotli//:brotlidec",
)

def _com_google_cel_cpp():
external_http_archive("com_google_cel_cpp")
external_http_archive("rules_antlr")
Expand Down
18 changes: 18 additions & 0 deletions bazel/repository_locations.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -406,6 +406,24 @@ REPOSITORY_LOCATIONS_SPEC = dict(
release_date = "2019-04-14",
cpe = "cpe:2.3:a:gnu:zlib:*",
),
org_brotli = dict(
project_name = "brotli",
project_desc = "brotli compression library",
project_url = "https://brotli.org",
# Use the dev branch of brotli to resolve compilation issues.
# TODO(rojkov): Remove when brotli > 1.0.9 is released.
version = "0cd2e3926e95e7e2930f57ae3f4885508d462a25",
sha256 = "93810780e60304b51f2c9645fe313a6e4640711063ed0b860cfa60999dd256c5",
strip_prefix = "brotli-{version}",
urls = ["https://github.com/google/brotli/archive/{version}.tar.gz"],
use_category = ["dataplane_ext"],
extensions = [
"envoy.compression.brotli.compressor",
"envoy.compression.brotli.decompressor",
],
release_date = "2020-09-08",
cpe = "cpe:2.3:a:google:brotli:*",
),
com_github_zlib_ng_zlib_ng = dict(
project_name = "zlib-ng",
project_desc = "zlib fork (higher performance)",
Expand Down
1 change: 1 addition & 0 deletions docs/root/api-v3/config/compression/compression.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@ Compression
:maxdepth: 2

../../extensions/compression/gzip/*/v3/*
../../extensions/compression/brotli/*/v3/*
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,9 @@ 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 :ref:`gzip compression <envoy_v3_api_msg_extensions.compression.gzip.compressor.v3.Gzip>`
only. Other compression libraries can be supported as extensions.
Currently the filter supports :ref:`gzip <envoy_v3_api_msg_extensions.compression.gzip.compressor.v3.Gzip>`
and :ref:`brotli <envoy_v3_api_msg_extensions.compression.brotli.compressor.v3.Brotli>`
compression only. Other compression libraries can be supported as extensions.

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

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,9 @@ determine whether or not the content should be decompressed. The content is
decompressed and passed on to the rest of the filter chain. Note that decompression happens
independently for request and responses based on the rules described below.

Currently the filter supports :ref:`gzip compression <envoy_v3_api_msg_extensions.compression.gzip.decompressor.v3.Gzip>`
only. Other compression libraries can be supported as extensions.
Currently the filter supports :ref:`gzip <envoy_v3_api_msg_extensions.compression.gzip.decompressor.v3.Gzip>`
and :ref:`brotli <envoy_v3_api_msg_extensions.compression.brotli.decompressor.v3.Brotli>`
compression only. Other compression libraries can be supported as extensions.

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

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ Compression Libraries
Underlying implementation
-------------------------

Currently Envoy uses `zlib <http://zlib.net>`_ as a compression library.
Currently Envoy uses `zlib <http://zlib.net>`_ and `brotli <https://brotli.org>`_ as compression
libraries.

.. note::

Expand Down
1 change: 1 addition & 0 deletions docs/root/version_history/current.rst
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ New Features
------------
* access log: added the :ref:`formatters <envoy_v3_api_field_config.core.v3.SubstitutionFormatString.formatters>` extension point for custom formatters (command operators).
* access log: support command operator: %REQUEST_HEADERS_BYTES%, %RESPONSE_HEADERS_BYTES%, and %RESPONSE_TRAILERS_BYTES%.
* compression: add brotli :ref:`compressor <envoy_v3_api_msg_extensions.compression.brotli.compressor.v3.Brotli>` and :ref:`decompressor <envoy_v3_api_msg_extensions.compression.brotli.decompressor.v3.Brotli>`.
* config: add `envoy.features.fail_on_any_deprecated_feature` runtime key, which matches the behaviour of compile-time flag `ENVOY_DISABLE_DEPRECATED_FEATURES`, i.e. use of deprecated fields will cause a crash.
* dispatcher: supports a stack of `Envoy::ScopeTrackedObject` instead of a single tracked object. This will allow Envoy to dump more debug information on crash.
* grpc_json_transcoder: added option :ref:`strict_http_request_validation <envoy_v3_api_field_extensions.filters.http.grpc_json_transcoder.v3.GrpcJsonTranscoder.strict_http_request_validation>` to reject invalid requests early.
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions source/common/http/headers.h
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ class CustomHeaderValues {
} CacheControlValues;

struct {
const std::string Brotli{"br"};
const std::string Gzip{"gzip"};
} ContentEncodingValues;

Expand Down
18 changes: 18 additions & 0 deletions source/extensions/compression/brotli/common/BUILD
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
load(
"//bazel:envoy_build_system.bzl",
"envoy_cc_library",
"envoy_extension_package",
)

licenses(["notice"]) # Apache 2

envoy_extension_package()

envoy_cc_library(
name = "brotli_base_lib",
srcs = ["base.cc"],
hdrs = ["base.h"],
deps = [
"//source/common/buffer:buffer_lib",
],
)
36 changes: 36 additions & 0 deletions source/extensions/compression/brotli/common/base.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
#include "extensions/compression/brotli/common/base.h"

namespace Envoy {
namespace Extensions {
namespace Compression {
namespace Brotli {
namespace Common {

BrotliContext::BrotliContext(const uint32_t chunk_size)
: chunk_size_{chunk_size}, chunk_ptr_{std::make_unique<uint8_t[]>(chunk_size)}, next_in_{},
next_out_{chunk_ptr_.get()}, avail_in_{0}, avail_out_{chunk_size} {}

void BrotliContext::updateOutput(Buffer::Instance& output_buffer) {
if (avail_out_ == 0) {
output_buffer.add(static_cast<void*>(chunk_ptr_.get()), chunk_size_);
resetOut();
}
}

void BrotliContext::finalizeOutput(Buffer::Instance& output_buffer) {
const size_t n_output = chunk_size_ - avail_out_;
if (n_output > 0) {
output_buffer.add(static_cast<void*>(chunk_ptr_.get()), n_output);
}
}

void BrotliContext::resetOut() {
avail_out_ = chunk_size_;
next_out_ = chunk_ptr_.get();
}

} // namespace Common
} // namespace Brotli
} // namespace Compression
} // namespace Extensions
} // namespace Envoy
Loading