This is an automated email from the ASF dual-hosted git repository.
bcall pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/trafficserver.git
The following commit(s) were added to refs/heads/master by this push:
new ea8ad983e4 compress plugin: refactor compression algorithms into their
own files (#12590)
ea8ad983e4 is described below
commit ea8ad983e48aafd346aa42ea647b465ec9e77c28
Author: Jake Champion <[email protected]>
AuthorDate: Mon Oct 27 22:20:15 2025 +0000
compress plugin: refactor compression algorithms into their own files
(#12590)
this separates gzip/deflate and brotli compression implementations into
dedicated modules with their own namespaces
the intention behind this is to make is simpler to contribute new
compression algorithms to the compress plugin and to try and keep the main
plugin file contents centered around the compressing feature and not the
implementation of each compression algorithm option
---
plugins/compress/CMakeLists.txt | 5 +-
plugins/compress/brotli_compress.cc | 148 ++++++++++++++
plugins/compress/brotli_compress.h | 46 +++++
plugins/compress/compress.cc | 386 +++++++++---------------------------
plugins/compress/compress_common.cc | 37 ++++
plugins/compress/compress_common.h | 76 +++++++
plugins/compress/configuration.cc | 4 +-
plugins/compress/configuration.h | 4 +-
plugins/compress/gzip_compress.cc | 169 ++++++++++++++++
plugins/compress/gzip_compress.h | 51 +++++
plugins/compress/misc.cc | 22 --
plugins/compress/misc.h | 64 ------
12 files changed, 624 insertions(+), 388 deletions(-)
diff --git a/plugins/compress/CMakeLists.txt b/plugins/compress/CMakeLists.txt
index f630bf0d1c..6744d69d47 100644
--- a/plugins/compress/CMakeLists.txt
+++ b/plugins/compress/CMakeLists.txt
@@ -15,10 +15,13 @@
#
#######################
-add_atsplugin(compress compress.cc configuration.cc misc.cc)
+add_atsplugin(compress compress.cc configuration.cc misc.cc compress_common.cc
gzip_compress.cc)
target_link_libraries(compress PRIVATE libswoc::libswoc)
+
if(HAVE_BROTLI_ENCODE_H)
+ target_sources(compress PRIVATE brotli_compress.cc)
target_link_libraries(compress PRIVATE brotli::brotlienc)
+ target_compile_definitions(compress PRIVATE HAVE_BROTLI_ENCODE_H=1)
endif()
verify_global_plugin(compress)
verify_remap_plugin(compress)
diff --git a/plugins/compress/brotli_compress.cc
b/plugins/compress/brotli_compress.cc
new file mode 100644
index 0000000000..da0eb29997
--- /dev/null
+++ b/plugins/compress/brotli_compress.cc
@@ -0,0 +1,148 @@
+/** @file
+
+ Brotli compression implementation
+
+ @section license License
+
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#include "brotli_compress.h"
+
+#if HAVE_BROTLI_ENCODE_H
+
+#include "debug_macros.h"
+
+#include <brotli/encode.h>
+#include <cinttypes>
+
+namespace Brotli
+{
+const int BROTLI_COMPRESSION_LEVEL = 6;
+const int BROTLI_LGW = 16;
+
+static bool
+compress_operation(Data *data, const char *upstream_buffer, int64_t
upstream_length, BrotliEncoderOperation op)
+{
+ TSIOBufferBlock downstream_blkp;
+ int64_t downstream_length;
+
+ data->bstrm.next_in = (uint8_t *)upstream_buffer;
+ data->bstrm.avail_in = upstream_length;
+
+ bool ok = true;
+ while (ok) {
+ downstream_blkp = TSIOBufferStart(data->downstream_buffer);
+ char *downstream_buffer = TSIOBufferBlockWriteStart(downstream_blkp,
&downstream_length);
+
+ data->bstrm.next_out = reinterpret_cast<unsigned char
*>(downstream_buffer);
+ data->bstrm.avail_out = downstream_length;
+ data->bstrm.total_out = 0;
+
+ ok =
+ !!BrotliEncoderCompressStream(data->bstrm.br, op, &data->bstrm.avail_in,
&const_cast<const uint8_t *&>(data->bstrm.next_in),
+ &data->bstrm.avail_out,
&data->bstrm.next_out, &data->bstrm.total_out);
+
+ if (!ok) {
+ error("BrotliEncoderCompressStream(%d) call failed", op);
+ return false;
+ }
+
+ TSIOBufferProduce(data->downstream_buffer, downstream_length -
data->bstrm.avail_out);
+ data->downstream_length += (downstream_length - data->bstrm.avail_out);
+ if (data->bstrm.avail_in || BrotliEncoderHasMoreOutput(data->bstrm.br)) {
+ continue;
+ }
+
+ break;
+ }
+
+ return ok;
+}
+
+void
+data_alloc(Data *data)
+{
+ debug("brotli compression. Create Brotli Encoder Instance.");
+ data->bstrm.br = BrotliEncoderCreateInstance(nullptr, nullptr, nullptr);
+ if (!data->bstrm.br) {
+ fatal("Brotli Encoder Instance Failed");
+ }
+ BrotliEncoderSetParameter(data->bstrm.br, BROTLI_PARAM_QUALITY,
BROTLI_COMPRESSION_LEVEL);
+ BrotliEncoderSetParameter(data->bstrm.br, BROTLI_PARAM_LGWIN, BROTLI_LGW);
+ data->bstrm.next_in = nullptr;
+ data->bstrm.avail_in = 0;
+ data->bstrm.total_in = 0;
+ data->bstrm.next_out = nullptr;
+ data->bstrm.avail_out = 0;
+ data->bstrm.total_out = 0;
+}
+
+void
+data_destroy(Data *data)
+{
+ BrotliEncoderDestroyInstance(data->bstrm.br);
+}
+
+void
+transform_one(Data *data, const char *upstream_buffer, int64_t upstream_length)
+{
+ bool ok = compress_operation(data, upstream_buffer, upstream_length,
BROTLI_OPERATION_PROCESS);
+ if (!ok) {
+ error("BrotliEncoderCompressStream(PROCESS) call failed");
+ return;
+ }
+
+ data->bstrm.total_in += upstream_length;
+
+ if (!data->hc->flush()) {
+ return;
+ }
+
+ ok = compress_operation(data, nullptr, 0, BROTLI_OPERATION_FLUSH);
+ if (!ok) {
+ error("BrotliEncoderCompressStream(FLUSH) call failed");
+ return;
+ }
+}
+
+void
+transform_finish(Data *data)
+{
+ if (data->state != transform_state_output) {
+ return;
+ }
+
+ data->state = transform_state_finished;
+
+ bool ok = compress_operation(data, nullptr, 0, BROTLI_OPERATION_FINISH);
+ if (!ok) {
+ error("BrotliEncoderCompressStream(PROCESS) call failed");
+ return;
+ }
+
+ if (data->downstream_length != static_cast<int64_t>(data->bstrm.total_out)) {
+ error("brotli-transform: output lengths don't match (%" PRId64 ", %zu)",
data->downstream_length, data->bstrm.total_out);
+ }
+
+ debug("brotli-transform: Finished brotli");
+ log_compression_ratio(data->bstrm.total_in, data->downstream_length);
+}
+
+} // namespace Brotli
+
+#endif // HAVE_BROTLI_ENCODE_H
diff --git a/plugins/compress/brotli_compress.h
b/plugins/compress/brotli_compress.h
new file mode 100644
index 0000000000..40be1b9036
--- /dev/null
+++ b/plugins/compress/brotli_compress.h
@@ -0,0 +1,46 @@
+/** @file
+
+ Brotli compression implementation
+
+ @section license License
+
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#pragma once
+
+#include "compress_common.h"
+
+#if HAVE_BROTLI_ENCODE_H
+
+namespace Brotli
+{
+// Initialize brotli compression context
+void data_alloc(Data *data);
+
+// Destroy brotli compression context
+void data_destroy(Data *data);
+
+// Compress one chunk of data
+void transform_one(Data *data, const char *upstream_buffer, int64_t
upstream_length);
+
+// Finish compression and flush remaining data
+void transform_finish(Data *data);
+
+} // namespace Brotli
+
+#endif // HAVE_BROTLI_ENCODE_H
diff --git a/plugins/compress/compress.cc b/plugins/compress/compress.cc
index 5290d9ec11..319059ea56 100644
--- a/plugins/compress/compress.cc
+++ b/plugins/compress/compress.cc
@@ -23,28 +23,25 @@
#include <cstring>
#include <cinttypes>
-#include <zlib.h>
#include "ts/apidefs.h"
#include "tscore/ink_config.h"
#include <tsutil/PostScript.h>
-#if HAVE_BROTLI_ENCODE_H
-#include <brotli/encode.h>
-#endif
-
#include "ts/ts.h"
#include "tscore/ink_defs.h"
#include "debug_macros.h"
+#include "compress_common.h"
#include "misc.h"
#include "configuration.h"
+#include "gzip_compress.h"
+#include "brotli_compress.h"
#include "ts/remap.h"
#include "ts/remap_version.h"
using namespace std;
-using namespace Gzip;
// FIXME: custom dictionaries would be nice. configurable/content-type?
// a GPRS device might benefit from a higher compression ratio, whereas a
desktop w. high bandwidth
@@ -63,14 +60,10 @@ namespace compress_ns
DbgCtl dbg_ctl{TAG};
}
-const int ZLIB_COMPRESSION_LEVEL = 6;
-const char *dictionary = nullptr;
+namespace Compress
+{
-// brotli compression quality 1-11. Testing proved level '6'
-#if HAVE_BROTLI_ENCODE_H
-const int BROTLI_COMPRESSION_LEVEL = 6;
-const int BROTLI_LGW = 16;
-#endif
+const char *dictionary = nullptr;
static const char *global_hidden_header_name = nullptr;
@@ -82,66 +75,65 @@ Configuration *prev_config = nullptr;
namespace
{
-/**
- If client request has both of Range and Accept-Encoding header, follow
range-request config.
- */
-void
-handle_range_request(TSMBuffer req_buf, TSMLoc req_loc, HostConfiguration *hc)
-{
- TSMLoc accept_encoding_hdr_field =
- TSMimeHdrFieldFind(req_buf, req_loc, TS_MIME_FIELD_ACCEPT_ENCODING,
TS_MIME_LEN_ACCEPT_ENCODING);
- ts::PostScript accept_encoding_defer([&]() -> void {
TSHandleMLocRelease(req_buf, req_loc, accept_encoding_hdr_field); });
- if (accept_encoding_hdr_field == TS_NULL_MLOC) {
- return;
- }
+ /**
+ If client request has both of Range and Accept-Encoding header, follow
range-request config.
+ */
+ void
+ handle_range_request(TSMBuffer req_buf, TSMLoc req_loc, HostConfiguration
*hc)
+ {
+ TSMLoc accept_encoding_hdr_field =
+ TSMimeHdrFieldFind(req_buf, req_loc, TS_MIME_FIELD_ACCEPT_ENCODING,
TS_MIME_LEN_ACCEPT_ENCODING);
+ ts::PostScript accept_encoding_defer([&]() -> void {
TSHandleMLocRelease(req_buf, req_loc, accept_encoding_hdr_field); });
+ if (accept_encoding_hdr_field == TS_NULL_MLOC) {
+ return;
+ }
- TSMLoc range_hdr_field = TSMimeHdrFieldFind(req_buf, req_loc,
TS_MIME_FIELD_RANGE, TS_MIME_LEN_RANGE);
- ts::PostScript range_defer([&]() -> void { TSHandleMLocRelease(req_buf,
req_loc, range_hdr_field); });
- if (range_hdr_field == TS_NULL_MLOC) {
- return;
- }
+ TSMLoc range_hdr_field = TSMimeHdrFieldFind(req_buf, req_loc,
TS_MIME_FIELD_RANGE, TS_MIME_LEN_RANGE);
+ ts::PostScript range_defer([&]() -> void { TSHandleMLocRelease(req_buf,
req_loc, range_hdr_field); });
+ if (range_hdr_field == TS_NULL_MLOC) {
+ return;
+ }
- debug("Both of Accept-Encoding and Range header are found in the request");
+ debug("Both of Accept-Encoding and Range header are found in the request");
- switch (hc->range_request_ctl()) {
- case RangeRequestCtrl::REMOVE_RANGE: {
- debug("Remove the Range header by remove-range config");
- while (range_hdr_field) {
- TSMLoc next_dup = TSMimeHdrFieldNextDup(req_buf, req_loc,
range_hdr_field);
- TSMimeHdrFieldDestroy(req_buf, req_loc, range_hdr_field);
- TSHandleMLocRelease(req_buf, req_loc, range_hdr_field);
- range_hdr_field = next_dup;
+ switch (hc->range_request_ctl()) {
+ case RangeRequestCtrl::REMOVE_RANGE: {
+ debug("Remove the Range header by remove-range config");
+ while (range_hdr_field) {
+ TSMLoc next_dup = TSMimeHdrFieldNextDup(req_buf, req_loc,
range_hdr_field);
+ TSMimeHdrFieldDestroy(req_buf, req_loc, range_hdr_field);
+ TSHandleMLocRelease(req_buf, req_loc, range_hdr_field);
+ range_hdr_field = next_dup;
+ }
+ break;
}
- break;
- }
- case RangeRequestCtrl::REMOVE_ACCEPT_ENCODING: {
- debug("Remove the Accept-Encoding header by remove-accept-encoding
config");
- while (accept_encoding_hdr_field) {
- TSMLoc next_dup = TSMimeHdrFieldNextDup(req_buf, req_loc,
accept_encoding_hdr_field);
- TSMimeHdrFieldDestroy(req_buf, req_loc, accept_encoding_hdr_field);
- TSHandleMLocRelease(req_buf, req_loc, accept_encoding_hdr_field);
- accept_encoding_hdr_field = next_dup;
+ case RangeRequestCtrl::REMOVE_ACCEPT_ENCODING: {
+ debug("Remove the Accept-Encoding header by remove-accept-encoding
config");
+ while (accept_encoding_hdr_field) {
+ TSMLoc next_dup = TSMimeHdrFieldNextDup(req_buf, req_loc,
accept_encoding_hdr_field);
+ TSMimeHdrFieldDestroy(req_buf, req_loc, accept_encoding_hdr_field);
+ TSHandleMLocRelease(req_buf, req_loc, accept_encoding_hdr_field);
+ accept_encoding_hdr_field = next_dup;
+ }
+ break;
+ }
+ case RangeRequestCtrl::NO_COMPRESSION:
+ // Do NOT touch header - this config is referred by `transformable()`
function
+ debug("no header modification by no-compression config");
+ break;
+ case RangeRequestCtrl::NONE:
+ [[fallthrough]];
+ default:
+ debug("Do nothing by none config");
+ break;
}
- break;
- }
- case RangeRequestCtrl::NO_COMPRESSION:
- // Do NOT touch header - this config is referred by `transformable()`
function
- debug("no header modification by no-compression config");
- break;
- case RangeRequestCtrl::NONE:
- [[fallthrough]];
- default:
- debug("Do nothing by none config");
- break;
}
-}
} // namespace
static Data *
-data_alloc(int compression_type, int compression_algorithms)
+data_alloc(int compression_type, int compression_algorithms, HostConfiguration
*hc)
{
Data *data;
- int err;
data = static_cast<Data *>(TSmalloc(sizeof(Data)));
data->downstream_vio = nullptr;
@@ -151,50 +143,17 @@ data_alloc(int compression_type, int
compression_algorithms)
data->state = transform_state_initialized;
data->compression_type = compression_type;
data->compression_algorithms = compression_algorithms;
- data->zstrm.next_in = Z_NULL;
- data->zstrm.avail_in = 0;
- data->zstrm.total_in = 0;
- data->zstrm.next_out = Z_NULL;
- data->zstrm.avail_out = 0;
- data->zstrm.total_out = 0;
- data->zstrm.zalloc = gzip_alloc;
- data->zstrm.zfree = gzip_free;
- data->zstrm.opaque = (voidpf) nullptr;
- data->zstrm.data_type = Z_ASCII;
-
- int window_bits = WINDOW_BITS_GZIP;
- if (compression_type & COMPRESSION_TYPE_DEFLATE) {
- window_bits = WINDOW_BITS_DEFLATE;
- }
+ data->hc = hc;
- err = deflateInit2(&data->zstrm, ZLIB_COMPRESSION_LEVEL, Z_DEFLATED,
window_bits, ZLIB_MEMLEVEL, Z_DEFAULT_STRATEGY);
-
- if (err != Z_OK) {
- fatal("gzip-transform: ERROR: deflateInit (%d)!", err);
+ // Initialize algorithm-specific compression contexts
+ if ((compression_type & (COMPRESSION_TYPE_GZIP | COMPRESSION_TYPE_DEFLATE))
&&
+ (compression_algorithms & (ALGORITHM_GZIP | ALGORITHM_DEFLATE))) {
+ Gzip::data_alloc(data);
}
- if (dictionary) {
- err = deflateSetDictionary(&data->zstrm, reinterpret_cast<const Bytef
*>(dictionary), strlen(dictionary));
- if (err != Z_OK) {
- fatal("gzip-transform: ERROR: deflateSetDictionary (%d)!", err);
- }
- }
#if HAVE_BROTLI_ENCODE_H
- data->bstrm.br = nullptr;
- if (compression_type & COMPRESSION_TYPE_BROTLI) {
- debug("brotli compression. Create Brotli Encoder Instance.");
- data->bstrm.br = BrotliEncoderCreateInstance(nullptr, nullptr, nullptr);
- if (!data->bstrm.br) {
- fatal("Brotli Encoder Instance Failed");
- }
- BrotliEncoderSetParameter(data->bstrm.br, BROTLI_PARAM_QUALITY,
BROTLI_COMPRESSION_LEVEL);
- BrotliEncoderSetParameter(data->bstrm.br, BROTLI_PARAM_LGWIN, BROTLI_LGW);
- data->bstrm.next_in = nullptr;
- data->bstrm.avail_in = 0;
- data->bstrm.total_in = 0;
- data->bstrm.next_out = nullptr;
- data->bstrm.avail_out = 0;
- data->bstrm.total_out = 0;
+ if (compression_type & COMPRESSION_TYPE_BROTLI && compression_algorithms &
ALGORITHM_BROTLI) {
+ Brotli::data_alloc(data);
}
#endif
return data;
@@ -205,17 +164,20 @@ data_destroy(Data *data)
{
TSReleaseAssert(data);
- // deflateEnd return value ignore is intentional
- // it would spew log on every client abort
- deflateEnd(&data->zstrm);
-
if (data->downstream_buffer) {
TSIOBufferDestroy(data->downstream_buffer);
}
-// brotlidestory
+ // Destroy algorithm-specific compression contexts
+ if ((data->compression_type & (COMPRESSION_TYPE_GZIP |
COMPRESSION_TYPE_DEFLATE)) &&
+ (data->compression_algorithms & (ALGORITHM_GZIP | ALGORITHM_DEFLATE))) {
+ Gzip::data_destroy(data);
+ }
+
#if HAVE_BROTLI_ENCODE_H
- BrotliEncoderDestroyInstance(data->bstrm.br);
+ if (data->compression_type & COMPRESSION_TYPE_BROTLI &&
data->compression_algorithms & ALGORITHM_BROTLI) {
+ Brotli::data_destroy(data);
+ }
#endif
TSfree(data);
@@ -241,7 +203,6 @@ content_encoding_header(TSMBuffer bufp, TSMLoc hdr_loc,
const int compression_ty
}
if (value_len == 0) {
- error("no need to add Content-Encoding header");
return TS_SUCCESS;
}
@@ -365,108 +326,6 @@ compress_transform_init(TSCont contp, Data *data)
TSHandleMLocRelease(bufp, TS_NULL_MLOC, hdr_loc);
}
-static void
-gzip_transform_one(Data *data, const char *upstream_buffer, int64_t
upstream_length)
-{
- TSIOBufferBlock downstream_blkp;
- int64_t downstream_length;
- int err;
- data->zstrm.next_in = (unsigned char *)upstream_buffer;
- data->zstrm.avail_in = upstream_length;
-
- while (data->zstrm.avail_in > 0) {
- downstream_blkp = TSIOBufferStart(data->downstream_buffer);
- char *downstream_buffer = TSIOBufferBlockWriteStart(downstream_blkp,
&downstream_length);
-
- data->zstrm.next_out = reinterpret_cast<unsigned char
*>(downstream_buffer);
- data->zstrm.avail_out = downstream_length;
-
- if (!data->hc->flush()) {
- err = deflate(&data->zstrm, Z_NO_FLUSH);
- } else {
- err = deflate(&data->zstrm, Z_SYNC_FLUSH);
- }
-
- if (err != Z_OK) {
- warning("deflate() call failed: %d", err);
- }
-
- if (downstream_length > data->zstrm.avail_out) {
- TSIOBufferProduce(data->downstream_buffer, downstream_length -
data->zstrm.avail_out);
- data->downstream_length += (downstream_length - data->zstrm.avail_out);
- }
-
- if (data->zstrm.avail_out > 0) {
- if (data->zstrm.avail_in != 0) {
- error("gzip-transform: avail_in is (%d): should be 0",
data->zstrm.avail_in);
- }
- }
- }
-}
-
-#if HAVE_BROTLI_ENCODE_H
-static bool
-brotli_compress_operation(Data *data, const char *upstream_buffer, int64_t
upstream_length, BrotliEncoderOperation op)
-{
- TSIOBufferBlock downstream_blkp;
- int64_t downstream_length;
-
- data->bstrm.next_in = (uint8_t *)upstream_buffer;
- data->bstrm.avail_in = upstream_length;
-
- bool ok = true;
- while (ok) {
- downstream_blkp = TSIOBufferStart(data->downstream_buffer);
- char *downstream_buffer = TSIOBufferBlockWriteStart(downstream_blkp,
&downstream_length);
-
- data->bstrm.next_out = reinterpret_cast<unsigned char
*>(downstream_buffer);
- data->bstrm.avail_out = downstream_length;
- data->bstrm.total_out = 0;
-
- ok =
- !!BrotliEncoderCompressStream(data->bstrm.br, op, &data->bstrm.avail_in,
&const_cast<const uint8_t *&>(data->bstrm.next_in),
- &data->bstrm.avail_out,
&data->bstrm.next_out, &data->bstrm.total_out);
-
- if (!ok) {
- error("BrotliEncoderCompressStream(%d) call failed", op);
- return false;
- }
-
- TSIOBufferProduce(data->downstream_buffer, downstream_length -
data->bstrm.avail_out);
- data->downstream_length += (downstream_length - data->bstrm.avail_out);
- if (data->bstrm.avail_in || BrotliEncoderHasMoreOutput(data->bstrm.br)) {
- continue;
- }
-
- break;
- }
-
- return ok;
-}
-
-static void
-brotli_transform_one(Data *data, const char *upstream_buffer, int64_t
upstream_length)
-{
- bool ok = brotli_compress_operation(data, upstream_buffer, upstream_length,
BROTLI_OPERATION_PROCESS);
- if (!ok) {
- error("BrotliEncoderCompressStream(PROCESS) call failed");
- return;
- }
-
- data->bstrm.total_in += upstream_length;
-
- if (!data->hc->flush()) {
- return;
- }
-
- ok = brotli_compress_operation(data, nullptr, 0, BROTLI_OPERATION_FLUSH);
- if (!ok) {
- error("BrotliEncoderCompressStream(FLUSH) call failed");
- return;
- }
-}
-#endif
-
static void
compress_transform_one(Data *data, TSIOBufferReader upstream_reader, int
amount)
{
@@ -491,12 +350,12 @@ compress_transform_one(Data *data, TSIOBufferReader
upstream_reader, int amount)
#if HAVE_BROTLI_ENCODE_H
if (data->compression_type & COMPRESSION_TYPE_BROTLI &&
(data->compression_algorithms & ALGORITHM_BROTLI)) {
- brotli_transform_one(data, upstream_buffer, upstream_length);
+ Brotli::transform_one(data, upstream_buffer, upstream_length);
} else
#endif
if ((data->compression_type & (COMPRESSION_TYPE_GZIP |
COMPRESSION_TYPE_DEFLATE)) &&
(data->compression_algorithms & (ALGORITHM_GZIP |
ALGORITHM_DEFLATE))) {
- gzip_transform_one(data, upstream_buffer, upstream_length);
+ Gzip::transform_one(data, upstream_buffer, upstream_length);
} else {
warning("No compression supported. Shouldn't come here.");
}
@@ -506,85 +365,18 @@ compress_transform_one(Data *data, TSIOBufferReader
upstream_reader, int amount)
}
}
-static void
-gzip_transform_finish(Data *data)
-{
- if (data->state == transform_state_output) {
- TSIOBufferBlock downstream_blkp;
- int64_t downstream_length;
-
- data->state = transform_state_finished;
-
- for (;;) {
- downstream_blkp = TSIOBufferStart(data->downstream_buffer);
-
- char *downstream_buffer = TSIOBufferBlockWriteStart(downstream_blkp,
&downstream_length);
- data->zstrm.next_out = reinterpret_cast<unsigned char
*>(downstream_buffer);
- data->zstrm.avail_out = downstream_length;
-
- int err = deflate(&data->zstrm, Z_FINISH);
-
- if (downstream_length > static_cast<int64_t>(data->zstrm.avail_out)) {
- TSIOBufferProduce(data->downstream_buffer, downstream_length -
data->zstrm.avail_out);
- data->downstream_length += (downstream_length - data->zstrm.avail_out);
- }
-
- if (err == Z_OK) { /* some more data to encode */
- continue;
- }
-
- if (err != Z_STREAM_END) {
- warning("deflate should report Z_STREAM_END");
- }
- break;
- }
-
- if (data->downstream_length !=
static_cast<int64_t>(data->zstrm.total_out)) {
- error("gzip-transform: output lengths don't match (%" PRId64 ", %lu)",
data->downstream_length, data->zstrm.total_out);
- }
-
- debug("gzip-transform: Finished gzip");
- log_compression_ratio(data->zstrm.total_in, data->downstream_length);
- }
-}
-
-#if HAVE_BROTLI_ENCODE_H
-static void
-brotli_transform_finish(Data *data)
-{
- if (data->state != transform_state_output) {
- return;
- }
-
- data->state = transform_state_finished;
-
- bool ok = brotli_compress_operation(data, nullptr, 0,
BROTLI_OPERATION_FINISH);
- if (!ok) {
- error("BrotliEncoderCompressStream(PROCESS) call failed");
- return;
- }
-
- if (data->downstream_length != static_cast<int64_t>(data->bstrm.total_out)) {
- error("brotli-transform: output lengths don't match (%" PRId64 ", %zu)",
data->downstream_length, data->bstrm.total_out);
- }
-
- debug("brotli-transform: Finished brotli");
- log_compression_ratio(data->bstrm.total_in, data->downstream_length);
-}
-#endif
-
static void
compress_transform_finish(Data *data)
{
#if HAVE_BROTLI_ENCODE_H
if (data->compression_type & COMPRESSION_TYPE_BROTLI &&
data->compression_algorithms & ALGORITHM_BROTLI) {
- brotli_transform_finish(data);
+ Brotli::transform_finish(data);
debug("compress_transform_finish: brotli compression finish");
} else
#endif
if ((data->compression_type & (COMPRESSION_TYPE_GZIP |
COMPRESSION_TYPE_DEFLATE)) &&
(data->compression_algorithms & (ALGORITHM_GZIP | ALGORITHM_DEFLATE)))
{
- gzip_transform_finish(data);
+ Gzip::transform_finish(data);
debug("compress_transform_finish: gzip compression finish");
} else {
error("No Compression matched, shouldn't come here");
@@ -888,9 +680,8 @@ compress_transform_add(TSHttpTxn txnp, HostConfiguration
*hc, int compress_type,
}
connp = TSTransformCreate(compress_transform, txnp);
- data = data_alloc(compress_type, algorithms);
+ data = data_alloc(compress_type, algorithms, hc);
data->txn = txnp;
- data->hc = hc;
TSContDataSet(connp, data);
TSHttpTxnHookAdd(txnp, TS_HTTP_RESPONSE_TRANSFORM_HOOK, connp);
@@ -1091,12 +882,13 @@ management_update(TSCont contp, TSEvent event, void * /*
edata ATS_UNUSED */)
return 0;
}
+} // namespace Compress
void
TSPluginInit(int argc, const char *argv[])
{
- const char *config_path = nullptr;
- compress_config_mutex = TSMutexCreate();
+ const char *config_path = nullptr;
+ Compress::compress_config_mutex = TSMutexCreate();
if (argc > 2) {
fatal("the compress plugin does not accept more than 1 plugin argument");
@@ -1110,19 +902,19 @@ TSPluginInit(int argc, const char *argv[])
info("TSPluginInit %s", argv[0]);
- if (!global_hidden_header_name) {
- global_hidden_header_name = init_hidden_header_name();
+ if (!Compress::global_hidden_header_name) {
+ Compress::global_hidden_header_name = init_hidden_header_name();
}
- TSCont management_contp = TSContCreate(management_update, nullptr);
+ TSCont management_contp = TSContCreate(Compress::management_update, nullptr);
// Make sure the global configuration is properly loaded and reloaded on
changes
TSContDataSet(management_contp, (void *)config_path);
TSMgmtUpdateRegister(management_contp, TAG);
- load_global_configuration(management_contp);
+ Compress::load_global_configuration(management_contp);
// Setup the global hook, main entry point for kicking off the plugin
- TSCont transform_global_contp = TSContCreate(transform_global_plugin,
nullptr);
+ TSCont transform_global_contp =
TSContCreate(Compress::transform_global_plugin, nullptr);
TSHttpHookAdd(TS_HTTP_READ_REQUEST_HDR_HOOK, transform_global_contp);
info("loaded");
@@ -1152,12 +944,12 @@ TSRemapNewInstance(int argc, char *argv[], void
**instance, char * /* errbuf ATS
} else {
config_path = TSstrdup(3 == argc ? argv[2] : "");
}
- if (!global_hidden_header_name) {
- global_hidden_header_name = init_hidden_header_name();
+ if (!Compress::global_hidden_header_name) {
+ Compress::global_hidden_header_name = init_hidden_header_name();
}
- Configuration *config = Configuration::Parse(config_path);
- *instance = config;
+ Compress::Configuration *config =
Compress::Configuration::Parse(config_path);
+ *instance = config;
free((void *)config_path);
info("Configuration loaded");
@@ -1168,7 +960,7 @@ void
TSRemapDeleteInstance(void *instance)
{
debug("Cleanup configs read from remap");
- auto c = static_cast<Configuration *>(instance);
+ auto c = static_cast<Compress::Configuration *>(instance);
delete c;
}
@@ -1179,7 +971,7 @@ TSRemapDoRemap(void *instance, TSHttpTxn txnp,
TSRemapRequestInfo * /* rri ATS_U
info("No Rules configured, falling back to default");
} else {
info("Remap Rules configured for compress");
- Configuration *config = static_cast<Configuration *>(instance);
+ Compress::Configuration *config = static_cast<Compress::Configuration
*>(instance);
// Handle compress request and use the configs populated from remap
instance
handle_request(txnp, config);
}
diff --git a/plugins/compress/compress_common.cc
b/plugins/compress/compress_common.cc
new file mode 100644
index 0000000000..f5b3a2d230
--- /dev/null
+++ b/plugins/compress/compress_common.cc
@@ -0,0 +1,37 @@
+/** @file
+
+ Common types and utilities for compression plugin
+
+ @section license License
+
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#include "compress_common.h"
+#include "debug_macros.h"
+
+#include <cinttypes>
+
+void
+log_compression_ratio(int64_t in, int64_t out)
+{
+ if (in) {
+ info("Compressed size %" PRId64 " (bytes), Original size %" PRId64 ",
ratio: %f", out, in, ((float)(in - out) / in));
+ } else {
+ debug("Compressed size %" PRId64 " (bytes), Original size %" PRId64 ",
ratio: %f", out, in, 0.0F);
+ }
+}
diff --git a/plugins/compress/compress_common.h
b/plugins/compress/compress_common.h
new file mode 100644
index 0000000000..1dccd4aa25
--- /dev/null
+++ b/plugins/compress/compress_common.h
@@ -0,0 +1,76 @@
+/** @file
+
+ Common types and structures for compression plugin
+
+ @section license License
+
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#pragma once
+
+#include <zlib.h>
+#include <ts/ts.h>
+
+#if HAVE_BROTLI_ENCODE_H
+#include <brotli/encode.h>
+#endif
+
+#include "configuration.h"
+
+enum CompressionType {
+ COMPRESSION_TYPE_DEFAULT = 0,
+ COMPRESSION_TYPE_DEFLATE = 1,
+ COMPRESSION_TYPE_GZIP = 2,
+ COMPRESSION_TYPE_BROTLI = 4
+};
+
+enum transform_state {
+ transform_state_initialized,
+ transform_state_output,
+ transform_state_finished,
+};
+
+#if HAVE_BROTLI_ENCODE_H
+struct BrotliStream {
+ BrotliEncoderState *br;
+ uint8_t *next_in;
+ size_t avail_in;
+ uint8_t *next_out;
+ size_t avail_out;
+ size_t total_in;
+ size_t total_out;
+};
+#endif
+
+struct Data {
+ TSHttpTxn txn;
+ Compress::HostConfiguration *hc;
+ TSVIO downstream_vio;
+ TSIOBuffer downstream_buffer;
+ TSIOBufferReader downstream_reader;
+ int64_t downstream_length;
+ z_stream zstrm;
+ enum transform_state state;
+ int compression_type;
+ int compression_algorithms;
+#if HAVE_BROTLI_ENCODE_H
+ BrotliStream bstrm;
+#endif
+};
+
+void log_compression_ratio(int64_t in, int64_t out);
diff --git a/plugins/compress/configuration.cc
b/plugins/compress/configuration.cc
index 167ea8da89..9b76ffa619 100644
--- a/plugins/compress/configuration.cc
+++ b/plugins/compress/configuration.cc
@@ -38,7 +38,7 @@
#include <cctype>
-namespace Gzip
+namespace Compress
{
swoc::TextView
extractFirstToken(swoc::TextView &view, int (*fp)(int))
@@ -410,4 +410,4 @@ Configuration::Parse(const char *path)
return c;
} // Configuration::Parse
-} // namespace Gzip
+} // namespace Compress
diff --git a/plugins/compress/configuration.h b/plugins/compress/configuration.h
index 1929130788..3af37b10c0 100644
--- a/plugins/compress/configuration.h
+++ b/plugins/compress/configuration.h
@@ -31,7 +31,7 @@
#include "tscpp/api/noncopyable.h"
#include "swoc/TextView.h"
-namespace Gzip
+namespace Compress
{
using StringContainer = std::vector<std::string>;
@@ -189,4 +189,4 @@ private:
}; // class Configuration
-} // namespace Gzip
+} // namespace Compress
diff --git a/plugins/compress/gzip_compress.cc
b/plugins/compress/gzip_compress.cc
new file mode 100644
index 0000000000..9de74ab072
--- /dev/null
+++ b/plugins/compress/gzip_compress.cc
@@ -0,0 +1,169 @@
+/** @file
+
+ Gzip/Deflate compression implementation
+
+ @section license License
+
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#include "gzip_compress.h"
+#include "debug_macros.h"
+
+#include <zlib.h>
+#include <cinttypes>
+
+const char *dictionary = nullptr;
+
+namespace Gzip
+{
+const int ZLIB_COMPRESSION_LEVEL = 6;
+voidpf
+gzip_alloc(voidpf /* opaque ATS_UNUSED */, uInt items, uInt size)
+{
+ return static_cast<voidpf>(TSmalloc(items * size));
+}
+
+void
+gzip_free(voidpf /* opaque ATS_UNUSED */, voidpf address)
+{
+ TSfree(address);
+}
+
+void
+data_alloc(Data *data)
+{
+ int window_bits = WINDOW_BITS_GZIP;
+ if (data->compression_type & COMPRESSION_TYPE_DEFLATE) {
+ window_bits = WINDOW_BITS_DEFLATE;
+ }
+
+ data->zstrm.next_in = Z_NULL;
+ data->zstrm.avail_in = 0;
+ data->zstrm.total_in = 0;
+ data->zstrm.next_out = Z_NULL;
+ data->zstrm.avail_out = 0;
+ data->zstrm.total_out = 0;
+ data->zstrm.zalloc = Gzip::gzip_alloc;
+ data->zstrm.zfree = Gzip::gzip_free;
+ data->zstrm.opaque = (voidpf) nullptr;
+ data->zstrm.data_type = Z_ASCII;
+
+ int err = deflateInit2(&data->zstrm, ZLIB_COMPRESSION_LEVEL, Z_DEFLATED,
window_bits, ZLIB_MEMLEVEL, Z_DEFAULT_STRATEGY);
+
+ if (err != Z_OK) {
+ fatal("gzip-transform: ERROR: deflateInit (%d)!", err);
+ }
+
+ if (dictionary) {
+ err = deflateSetDictionary(&data->zstrm, reinterpret_cast<const Bytef
*>(dictionary), strlen(dictionary));
+ if (err != Z_OK) {
+ fatal("gzip-transform: ERROR: deflateSetDictionary (%d)!", err);
+ }
+ }
+}
+
+void
+data_destroy(Data *data)
+{
+ // deflateEnd return value ignore is intentional
+ // it would spew log on every client abort
+ deflateEnd(&data->zstrm);
+}
+
+void
+transform_one(Data *data, const char *upstream_buffer, int64_t upstream_length)
+{
+ TSIOBufferBlock downstream_blkp;
+ int64_t downstream_length;
+ int err;
+ data->zstrm.next_in = (unsigned char *)upstream_buffer;
+ data->zstrm.avail_in = upstream_length;
+
+ while (data->zstrm.avail_in > 0) {
+ downstream_blkp = TSIOBufferStart(data->downstream_buffer);
+ char *downstream_buffer = TSIOBufferBlockWriteStart(downstream_blkp,
&downstream_length);
+
+ data->zstrm.next_out = reinterpret_cast<unsigned char
*>(downstream_buffer);
+ data->zstrm.avail_out = downstream_length;
+
+ if (!data->hc->flush()) {
+ err = deflate(&data->zstrm, Z_NO_FLUSH);
+ } else {
+ err = deflate(&data->zstrm, Z_SYNC_FLUSH);
+ }
+
+ if (err != Z_OK) {
+ warning("deflate() call failed: %d", err);
+ }
+
+ if (downstream_length > data->zstrm.avail_out) {
+ TSIOBufferProduce(data->downstream_buffer, downstream_length -
data->zstrm.avail_out);
+ data->downstream_length += (downstream_length - data->zstrm.avail_out);
+ }
+
+ if (data->zstrm.avail_out > 0) {
+ if (data->zstrm.avail_in != 0) {
+ error("gzip-transform: avail_in is (%d): should be 0",
data->zstrm.avail_in);
+ }
+ }
+ }
+}
+
+void
+transform_finish(Data *data)
+{
+ if (data->state == transform_state_output) {
+ TSIOBufferBlock downstream_blkp;
+ int64_t downstream_length;
+
+ data->state = transform_state_finished;
+
+ for (;;) {
+ downstream_blkp = TSIOBufferStart(data->downstream_buffer);
+
+ char *downstream_buffer = TSIOBufferBlockWriteStart(downstream_blkp,
&downstream_length);
+ data->zstrm.next_out = reinterpret_cast<unsigned char
*>(downstream_buffer);
+ data->zstrm.avail_out = downstream_length;
+
+ int err = deflate(&data->zstrm, Z_FINISH);
+
+ if (downstream_length > static_cast<int64_t>(data->zstrm.avail_out)) {
+ TSIOBufferProduce(data->downstream_buffer, downstream_length -
data->zstrm.avail_out);
+ data->downstream_length += (downstream_length - data->zstrm.avail_out);
+ }
+
+ if (err == Z_OK) { /* some more data to encode */
+ continue;
+ }
+
+ if (err != Z_STREAM_END) {
+ warning("deflate should report Z_STREAM_END");
+ }
+ break;
+ }
+
+ if (data->downstream_length !=
static_cast<int64_t>(data->zstrm.total_out)) {
+ error("gzip-transform: output lengths don't match (%" PRId64 ", %lu)",
data->downstream_length, data->zstrm.total_out);
+ }
+
+ debug("gzip-transform: Finished gzip");
+ log_compression_ratio(data->zstrm.total_in, data->downstream_length);
+ }
+}
+
+} // namespace Gzip
diff --git a/plugins/compress/gzip_compress.h b/plugins/compress/gzip_compress.h
new file mode 100644
index 0000000000..5257bb4bb4
--- /dev/null
+++ b/plugins/compress/gzip_compress.h
@@ -0,0 +1,51 @@
+/** @file
+
+ Gzip/Deflate compression implementation
+
+ @section license License
+
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#pragma once
+
+#include "compress_common.h"
+#include <zlib.h>
+
+// zlib stuff, see [deflateInit2] at http://www.zlib.net/manual.html
+static const int ZLIB_MEMLEVEL = 9; // min=1 (optimize for memory),max=9
(optimized for speed)
+static const int WINDOW_BITS_DEFLATE = -15;
+static const int WINDOW_BITS_GZIP = 31;
+
+namespace Gzip
+{
+// Initialize gzip/deflate compression context
+void data_alloc(Data *data);
+
+// Destroy gzip/deflate compression context
+void data_destroy(Data *data);
+
+// Compress one chunk of data
+void transform_one(Data *data, const char *upstream_buffer, int64_t
upstream_length);
+
+// Finish compression and flush remaining data
+void transform_finish(Data *data);
+
+voidpf gzip_alloc(voidpf opaque, uInt items, uInt size);
+void gzip_free(voidpf opaque, voidpf address);
+
+} // namespace Gzip
diff --git a/plugins/compress/misc.cc b/plugins/compress/misc.cc
index a1b33b79cc..9a4b7f6685 100644
--- a/plugins/compress/misc.cc
+++ b/plugins/compress/misc.cc
@@ -30,18 +30,6 @@
#include <cinttypes>
#include "debug_macros.h"
-voidpf
-gzip_alloc(voidpf /* opaque ATS_UNUSED */, uInt items, uInt size)
-{
- return static_cast<voidpf>(TSmalloc(items * size));
-}
-
-void
-gzip_free(voidpf /* opaque ATS_UNUSED */, voidpf address)
-{
- TSfree(address);
-}
-
namespace
{
// Strips parameters from value. Returns cleared TextView if a q=f parameter
present, where f is less than or equal to
@@ -190,13 +178,3 @@ register_plugin()
}
return 1;
}
-
-void
-log_compression_ratio(int64_t in, int64_t out)
-{
- if (in) {
- info("Compressed size %" PRId64 " (bytes), Original size %" PRId64 ",
ratio: %f", out, in, ((float)(in - out) / in));
- } else {
- debug("Compressed size %" PRId64 " (bytes), Original size %" PRId64 ",
ratio: %f", out, in, 0.0F);
- }
-}
diff --git a/plugins/compress/misc.h b/plugins/compress/misc.h
index a18f1dce71..f5d37c1da4 100644
--- a/plugins/compress/misc.h
+++ b/plugins/compress/misc.h
@@ -23,74 +23,10 @@
#pragma once
-#include <zlib.h>
#include <ts/ts.h>
-#include <cstdlib>
-#include <cstdio>
-#if HAVE_BROTLI_ENCODE_H
-#include <brotli/encode.h>
-#endif
-
-#include "configuration.h"
-
-// zlib stuff, see [deflateInit2] at http://www.zlib.net/manual.html
-static const int ZLIB_MEMLEVEL = 9; // min=1 (optimize for memory),max=9
(optimized for speed)
-static const int WINDOW_BITS_DEFLATE = -15;
-static const int WINDOW_BITS_GZIP = 31;
-
-// misc
-enum CompressionType {
- COMPRESSION_TYPE_DEFAULT = 0,
- COMPRESSION_TYPE_DEFLATE = 1,
- COMPRESSION_TYPE_GZIP = 2,
- COMPRESSION_TYPE_BROTLI = 4
-};
-
-// this one is used to rename the accept encoding header
-// it will be restored later on
-// to make it work, the name must be different then downstream proxies though
-// otherwise the downstream will restore the accept encoding header
-
-enum transform_state {
- transform_state_initialized,
- transform_state_output,
- transform_state_finished,
-};
-
-#if HAVE_BROTLI_ENCODE_H
-using b_stream = struct {
- BrotliEncoderState *br;
- uint8_t *next_in;
- size_t avail_in;
- uint8_t *next_out;
- size_t avail_out;
- size_t total_in;
- size_t total_out;
-};
-#endif
-
-using Data = struct {
- TSHttpTxn txn;
- Gzip::HostConfiguration *hc;
- TSVIO downstream_vio;
- TSIOBuffer downstream_buffer;
- TSIOBufferReader downstream_reader;
- int64_t downstream_length;
- z_stream zstrm;
- enum transform_state state;
- int compression_type;
- int compression_algorithms;
-#if HAVE_BROTLI_ENCODE_H
- b_stream bstrm;
-#endif
-};
-
-voidpf gzip_alloc(voidpf opaque, uInt items, uInt size);
-void gzip_free(voidpf opaque, voidpf address);
void normalize_accept_encoding(TSHttpTxn txnp, TSMBuffer reqp, TSMLoc
hdr_loc);
void hide_accept_encoding(TSHttpTxn txnp, TSMBuffer reqp, TSMLoc
hdr_loc, const char *hidden_header_name);
void restore_accept_encoding(TSHttpTxn txnp, TSMBuffer reqp, TSMLoc
hdr_loc, const char *hidden_header_name);
const char *init_hidden_header_name();
int register_plugin();
-void log_compression_ratio(int64_t in, int64_t out);