This is an automated email from the ASF dual-hosted git repository.

masaori 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 678d786c86 [compress] Add an option to do not compress partial object 
(#12121)
678d786c86 is described below

commit 678d786c86d6e7625f97cc85c447a55aeee065be
Author: Masaori Koshiba <masa...@apache.org>
AuthorDate: Sun May 25 17:21:58 2025 -0500

    [compress] Add an option to do not compress partial object (#12121)
---
 doc/admin-guide/plugins/compress.en.rst            | 24 ++++++-----
 plugins/compress/compress.cc                       | 43 +++++++++++++++++---
 plugins/compress/configuration.cc                  | 16 +++++---
 plugins/compress/configuration.h                   |  9 +++--
 .../pluginTest/compress/compress-range.test.py     | 16 ++++++--
 ...ig => cache-true-remove-accept-encoding.config} |  2 +-
 ...range.config => cache-true-remove-range.config} |  2 +-
 .../compress/replay/compress-and-range.replay.yaml | 46 +++++++++++++++++++---
 8 files changed, 123 insertions(+), 35 deletions(-)

diff --git a/doc/admin-guide/plugins/compress.en.rst 
b/doc/admin-guide/plugins/compress.en.rst
index 846212f142..81dec81dc8 100644
--- a/doc/admin-guide/plugins/compress.en.rst
+++ b/doc/admin-guide/plugins/compress.en.rst
@@ -108,20 +108,26 @@ range-request
 
 This config controls behavior of this plugin when a client send ``Range`` 
header and ``Accept-Encoding`` header in the same time.
 
-============== 
=================================================================
-Value          Description
-============== 
=================================================================
-ignore-range   Remove ``Range`` header if the request has both headers 
(Default)
-false          Same as ``ignore-range`` for compatiblity
-no-compression Remove ``Accept-Encoding`` header if the request has both 
headers
-none           Do nothing
-true           Same as ``none`` for compatibility
-============== 
=================================================================
+====================== 
=================================================================
+Value                  Description
+====================== 
=================================================================
+none                   Do nothing
+true                   Same as ``none`` for compatibility
+remove-range           Remove ``Range`` header if the request has both headers
+remove-accept-encoding Remove ``Accept-Encoding`` header if the request has 
both headers
+no-compression         Do NOT compress Partial Content (default)
+false                  Same as ``no-compression`` for compatiblity
+====================== 
=================================================================
 
 .. important::
 
    Do NOT set this to ``none`` (or ``true``) if the cache config is set to 
``false``. This combination will deliver corrupted content.
 
+
+.. important::
+
+   Some plugins (like cache_range_request) remove ``Range`` header. If you set 
``remove-range`` or ``remove-accept-encoding``, be careful with the order of 
plugins.
+
 compressible-content-type
 -------------------------
 
diff --git a/plugins/compress/compress.cc b/plugins/compress/compress.cc
index 72556c586a..44e8235a0d 100644
--- a/plugins/compress/compress.cc
+++ b/plugins/compress/compress.cc
@@ -103,8 +103,8 @@ handle_range_request(TSMBuffer req_buf, TSMLoc req_loc, 
HostConfiguration *hc)
   debug("Both of Accept-Encoding and Range header are found in the request");
 
   switch (hc->range_request_ctl()) {
-  case RangeRequestCtrl::IGNORE_RANGE: {
-    debug("Remove the Range header by ignore-range config");
+  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);
@@ -113,8 +113,8 @@ handle_range_request(TSMBuffer req_buf, TSMLoc req_loc, 
HostConfiguration *hc)
     }
     break;
   }
-  case RangeRequestCtrl::NO_COMPRESSION: {
-    debug("Remove the Accept-Encoding header by no-compression config");
+  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);
@@ -123,6 +123,10 @@ handle_range_request(TSMBuffer req_buf, TSMLoc req_loc, 
HostConfiguration *hc)
     }
     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:
@@ -733,6 +737,33 @@ transformable(TSHttpTxn txnp, bool server, 
HostConfiguration *host_configuration
     return 0;
   }
 
+  // check Partial Object is transformable
+  if (host_configuration->range_request_ctl() == 
RangeRequestCtrl::NO_COMPRESSION) {
+    // check Range header in client request
+    // CAVETE: some plugin (- e.g. cache_range_request) tweaks client headers
+    TSMLoc range_hdr_field = TSMimeHdrFieldFind(cbuf, chdr, 
TS_MIME_FIELD_RANGE, TS_MIME_LEN_RANGE);
+    if (range_hdr_field != TS_NULL_MLOC) {
+      debug("Range header found in the request and range_request is configured 
as no_compression");
+      TSHandleMLocRelease(bufp, TS_NULL_MLOC, hdr_loc);
+      TSHandleMLocRelease(cbuf, chdr, range_hdr_field);
+      TSHandleMLocRelease(cbuf, TS_NULL_MLOC, chdr);
+      return 0;
+    }
+
+    // check Content-Range header in (cached) server response
+    TSMLoc content_range_hdr_field = TSMimeHdrFieldFind(bufp, hdr_loc, 
TS_MIME_FIELD_CONTENT_RANGE, TS_MIME_LEN_CONTENT_RANGE);
+    if (content_range_hdr_field != TS_NULL_MLOC) {
+      debug("Content-Range header found in the response and range_request is 
configured as no_compression");
+      TSHandleMLocRelease(bufp, hdr_loc, content_range_hdr_field);
+      TSHandleMLocRelease(bufp, TS_NULL_MLOC, hdr_loc);
+      TSHandleMLocRelease(cbuf, TS_NULL_MLOC, chdr);
+      return 0;
+    }
+
+    TSHandleMLocRelease(bufp, hdr_loc, content_range_hdr_field);
+    TSHandleMLocRelease(cbuf, chdr, range_hdr_field);
+  }
+
   // the only compressible method is currently GET.
   int         method_length;
   const char *method = TSHttpHdrMethodGet(cbuf, chdr, &method_length);
@@ -966,8 +997,8 @@ transform_plugin(TSCont contp, TSEvent event, void *edata)
  * 1. Reads the client request header
  * 2. For global plugin, get host configuration from global config
  *    For remap plugin, get host configuration from configs populated through 
remap
- * 3. Check for Accept encoding
- * 4. Remove Range header
+ * 3. Check for Accept-Encoding header
+ * 4. Check for Range header
  * 5. Schedules TS_HTTP_CACHE_LOOKUP_COMPLETE_HOOK and TS_HTTP_TXN_CLOSE_HOOK 
for
  *    further processing
  */
diff --git a/plugins/compress/configuration.cc 
b/plugins/compress/configuration.cc
index 9447bd6a3c..dd95952f97 100644
--- a/plugins/compress/configuration.cc
+++ b/plugins/compress/configuration.cc
@@ -272,16 +272,22 @@ HostConfiguration::compression_algorithms()
   return compression_algorithms_;
 }
 
+/**
+  "true" and "false" are compatibility with old version, will be removed
+ */
 void
 HostConfiguration::set_range_request(const std::string &token)
 {
-  // "true" and "false" are compatibility with old version, will be removed
-  if (token == "false" || token == "ignore-range") {
-    range_request_ctl_ = RangeRequestCtrl::IGNORE_RANGE;
-  } else if (token == "true" || token == "none") {
+  if (token == "true" || token == "none") {
     range_request_ctl_ = RangeRequestCtrl::NONE;
-  } else if (token == "no-compression") {
+  } else if (token == "false" || token == "no-compression") {
     range_request_ctl_ = RangeRequestCtrl::NO_COMPRESSION;
+  } else if (token == "remove-range") {
+    range_request_ctl_ = RangeRequestCtrl::REMOVE_RANGE;
+  } else if (token == "remove-accept-encoding") {
+    range_request_ctl_ = RangeRequestCtrl::REMOVE_ACCEPT_ENCODING;
+  } else {
+    error("invalid token for range_request: %s", token.c_str());
   }
 }
 
diff --git a/plugins/compress/configuration.h b/plugins/compress/configuration.h
index f710375a13..22b2173c59 100644
--- a/plugins/compress/configuration.h
+++ b/plugins/compress/configuration.h
@@ -42,9 +42,10 @@ enum CompressionAlgorithm {
 };
 
 enum class RangeRequestCtrl : int {
-  IGNORE_RANGE   = 0, ///< Ignore Range Header (default)
-  NO_COMPRESSION = 1, ///< Do NOT compress if it's a range request
-  NONE           = 2, ///< Do nothing
+  NONE                   = 0, ///< Do nothing
+  NO_COMPRESSION         = 1, ///< Do NOT compress Partial Content (default)
+  REMOVE_RANGE           = 2, ///< Remove Range Header
+  REMOVE_ACCEPT_ENCODING = 3, ///< Remove Accept-Encoding Header
 };
 
 class HostConfiguration : private atscppapi::noncopyable
@@ -148,7 +149,7 @@ private:
   int          compression_algorithms_;
   unsigned int minimum_content_length_;
 
-  RangeRequestCtrl range_request_ctl_{RangeRequestCtrl::IGNORE_RANGE};
+  RangeRequestCtrl range_request_ctl_ = RangeRequestCtrl::NO_COMPRESSION;
   StringContainer  compressible_content_types_;
   StringContainer  allows_;
   // maintain backwards compatibility/usability out of the box
diff --git a/tests/gold_tests/pluginTest/compress/compress-range.test.py 
b/tests/gold_tests/pluginTest/compress/compress-range.test.py
index 42c1e19e8b..0b4b874758 100644
--- a/tests/gold_tests/pluginTest/compress/compress-range.test.py
+++ b/tests/gold_tests/pluginTest/compress/compress-range.test.py
@@ -42,13 +42,23 @@ class CompressPluginTest:
                 "proxy.config.http.insert_response_via_str": 2,
             })
 
-        self.ts.Setup.Copy("etc/cache-true-ignore-range.config")
+        self.ts.Setup.Copy("etc/cache-true-remove-range.config")
+        self.ts.Setup.Copy("etc/cache-true-remove-accept-encoding.config")
         self.ts.Setup.Copy("etc/cache-true-no-compression.config")
 
         self.ts.Disk.remap_config.AddLines(
             {
-                f"map /cache-true-ignore-range/ 
http://127.0.0.1:{self.server.Variables.http_port}/ @plugin=compress.so 
@pparam={Test.RunDirectory}/cache-true-ignore-range.config",
-                f"map /cache-true-no-compression/ 
http://127.0.0.1:{self.server.Variables.http_port}/ @plugin=compress.so 
@pparam={Test.RunDirectory}/cache-true-no-compression.config",
+                f"""
+map /cache-true-remove-range/ 
http://127.0.0.1:{self.server.Variables.http_port}/ \
+    @plugin=compress.so \
+    @pparam={Test.RunDirectory}/cache-true-remove-range.config
+map /cache-true-remove-accept-encoding/ 
http://127.0.0.1:{self.server.Variables.http_port}/ \
+    @plugin=compress.so \
+    @pparam={Test.RunDirectory}/cache-true-remove-accept-encoding.config
+map /cache-true-no-compression/ 
http://127.0.0.1:{self.server.Variables.http_port}/ \
+    @plugin=compress.so \
+    @pparam={Test.RunDirectory}/cache-true-no-compression.config
+"""
             })
 
     def run(self):
diff --git 
a/tests/gold_tests/pluginTest/compress/etc/cache-true-ignore-range.config 
b/tests/gold_tests/pluginTest/compress/etc/cache-true-remove-accept-encoding.config
similarity index 73%
copy from 
tests/gold_tests/pluginTest/compress/etc/cache-true-ignore-range.config
copy to 
tests/gold_tests/pluginTest/compress/etc/cache-true-remove-accept-encoding.config
index c961699cc0..5fd5911ce5 100644
--- a/tests/gold_tests/pluginTest/compress/etc/cache-true-ignore-range.config
+++ 
b/tests/gold_tests/pluginTest/compress/etc/cache-true-remove-accept-encoding.config
@@ -1,5 +1,5 @@
 cache true
-range-request ignore-range
+range-request remove-accept-encoding
 compressible-content-type application/json
 supported-algorithms gzip
 minimum-content-length 0
diff --git 
a/tests/gold_tests/pluginTest/compress/etc/cache-true-ignore-range.config 
b/tests/gold_tests/pluginTest/compress/etc/cache-true-remove-range.config
similarity index 79%
rename from 
tests/gold_tests/pluginTest/compress/etc/cache-true-ignore-range.config
rename to 
tests/gold_tests/pluginTest/compress/etc/cache-true-remove-range.config
index c961699cc0..a1bbadc146 100644
--- a/tests/gold_tests/pluginTest/compress/etc/cache-true-ignore-range.config
+++ b/tests/gold_tests/pluginTest/compress/etc/cache-true-remove-range.config
@@ -1,5 +1,5 @@
 cache true
-range-request ignore-range
+range-request remove-range
 compressible-content-type application/json
 supported-algorithms gzip
 minimum-content-length 0
diff --git 
a/tests/gold_tests/pluginTest/compress/replay/compress-and-range.replay.yaml 
b/tests/gold_tests/pluginTest/compress/replay/compress-and-range.replay.yaml
index 8582997504..071446448d 100644
--- a/tests/gold_tests/pluginTest/compress/replay/compress-and-range.replay.yaml
+++ b/tests/gold_tests/pluginTest/compress/replay/compress-and-range.replay.yaml
@@ -45,14 +45,14 @@ sessions:
   #
   # ```
   # cache true
-  # range-request ignore-range
+  # range-request remove-range
   #```
   #
   # 1-1: Accept-Encoding only
   - client-request:
       method: "GET"
       version: "1.1"
-      url: /cache-true-ignore-range/
+      url: /cache-true-remove-range/
       headers:
         fields:
           - [ uuid, 1-1]
@@ -73,7 +73,7 @@ sessions:
   - client-request:
       method: "GET"
       version: "1.1"
-      url: /cache-true-ignore-range/
+      url: /cache-true-remove-range/
       headers:
         fields:
           - [ uuid, 1-2]
@@ -98,7 +98,7 @@ sessions:
   - client-request:
       method: "GET"
       version: "1.1"
-      url: /cache-true-ignore-range/
+      url: /cache-true-remove-range/
       headers:
         fields:
           - [ uuid, 1-3]
@@ -125,14 +125,14 @@ sessions:
   #
   # ```
   # cache true
-  # range-request no-compression
+  # range-request remove-accept-encoding
   #```
   #
   # 2-1: Range and Accept-Encoding
   - client-request:
       method: "GET"
       version: "1.1"
-      url: /cache-true-no-compression/
+      url: /cache-true-remove-accept-encoding/
       headers:
         fields:
           - [ uuid, 2-1]
@@ -154,3 +154,37 @@ sessions:
         fields:
           - [ Content-Length, { value: 10, as: equal } ]
 
+  # Test Case 3
+  #
+  # ```
+  # cache true
+  # range-request no-compression
+  #```
+  #
+  # 3-1: Range and Accept-Encoding
+  - client-request:
+      method: "GET"
+      version: "1.1"
+      url: /cache-true-no-compression/
+      headers:
+        fields:
+          - [ uuid, 3-1]
+          - [ Host, example.com ]
+          - [ Range, 0-9 ]
+          - [ Accept-Encoding, gzip ]
+
+    proxy-request:
+      headers:
+        fields:
+          - [ Range, { as: present } ]
+          - [ Accept-Encoding, { as: present } ]
+
+    server-response:
+      <<: *origin-server-response-206
+
+    proxy-response:
+      status: 206
+      headers:
+        fields:
+          - [ Content-Length, { value: 10, as: equal } ]
+

Reply via email to