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

bneradt 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 1796051ca3 Fix s-maxage not respected with Authorization headers 
(#12668)
1796051ca3 is described below

commit 1796051ca30386eccd676009209ac88ec9ebc498
Author: Brian Neradt <[email protected]>
AuthorDate: Mon Feb 2 12:16:58 2026 -0600

    Fix s-maxage not respected with Authorization headers (#12668)
    
    According to RFC 7234 section 3.2, a shared cache can serve cached
    responses to requests with Authorization headers if the response contains
    one of the following Cache-Control directives: must-revalidate,
    proxy-revalidate, public, or s-maxage. The implementation was missing the
    check for s-maxage, causing requests with Authorization headers to always
    bypass the cache even when s-maxage was present in the cached response.
    
    This commit adds the missing check for s-maxage in the 
AuthenticationNeeded()
    function and includes comprehensive tests to verify the fix and prevent
    regression.
    
    Fixes #7227
---
 src/proxy/http/HttpTransact.cc                     |  12 +-
 tests/gold_tests/cache/cache-auth.test.py          |   4 +
 .../cache/replay/auth-s-maxage.replay.yaml         | 204 +++++++++++++++++++++
 3 files changed, 215 insertions(+), 5 deletions(-)

diff --git a/src/proxy/http/HttpTransact.cc b/src/proxy/http/HttpTransact.cc
index 4c2e67cd9d..0f5e689222 100644
--- a/src/proxy/http/HttpTransact.cc
+++ b/src/proxy/http/HttpTransact.cc
@@ -7512,11 +7512,11 @@ HttpTransact::what_is_document_freshness(State *s, 
HTTPHdr *client_request, HTTP
 HttpTransact::Authentication_t
 HttpTransact::AuthenticationNeeded(const OverridableHttpConfigParams *p, 
HTTPHdr *client_request, HTTPHdr *obj_response)
 {
-  ///////////////////////////////////////////////////////////////////////
-  // from RFC2068, sec 14.8, if a client request has the Authorization //
-  // header set, we can't serve it unless the response is public, or   //
-  // if it has a Cache-Control revalidate flag, and we do revalidate.  //
-  ///////////////////////////////////////////////////////////////////////
+  
///////////////////////////////////////////////////////////////////////////////
+  // Per RFC 7234 section 3.2, if a client request has the Authorization      
//
+  // header set, we can't serve a cached response unless the response has one 
//
+  // of: must-revalidate, proxy-revalidate, public, or s-maxage directives.   
//
+  
///////////////////////////////////////////////////////////////////////////////
 
   if ((p->cache_ignore_auth == 0) && 
client_request->presence(MIME_PRESENCE_AUTHORIZATION)) {
     if (obj_response->is_cache_control_set(HTTP_VALUE_MUST_REVALIDATE.c_str()) 
||
@@ -7526,6 +7526,8 @@ HttpTransact::AuthenticationNeeded(const 
OverridableHttpConfigParams *p, HTTPHdr
       return Authentication_t::MUST_REVALIDATE;
     } else if (obj_response->is_cache_control_set(HTTP_VALUE_PUBLIC.c_str())) {
       return Authentication_t::SUCCESS;
+    } else if 
(obj_response->is_cache_control_set(HTTP_VALUE_S_MAXAGE.c_str())) {
+      return Authentication_t::SUCCESS;
     } else {
       if (obj_response->field_find("@WWW-Auth"sv) && 
client_request->method_get_wksidx() == HTTP_WKSIDX_GET) {
         return Authentication_t::CACHE_AUTH;
diff --git a/tests/gold_tests/cache/cache-auth.test.py 
b/tests/gold_tests/cache/cache-auth.test.py
index 0861355464..e60064c3a4 100644
--- a/tests/gold_tests/cache/cache-auth.test.py
+++ b/tests/gold_tests/cache/cache-auth.test.py
@@ -23,3 +23,7 @@ Test authorization-related caching behaviors
 
 # Verify proxy.config.http.cache.ignore_authentication behavior.
 Test.ATSReplayTest(replay_file="replay/ignore_authentication.replay.yaml")
+
+# Verify that s-maxage allows serving cached responses to requests with
+# Authorization headers per RFC 7234 section 3.2
+Test.ATSReplayTest(replay_file="replay/auth-s-maxage.replay.yaml")
diff --git a/tests/gold_tests/cache/replay/auth-s-maxage.replay.yaml 
b/tests/gold_tests/cache/replay/auth-s-maxage.replay.yaml
new file mode 100644
index 0000000000..2cf1d36431
--- /dev/null
+++ b/tests/gold_tests/cache/replay/auth-s-maxage.replay.yaml
@@ -0,0 +1,204 @@
+#  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.
+
+#
+# This replay file tests RFC 7234 section 3.2:
+# A shared cache can serve cached responses to requests with Authorization
+# headers if the response has s-maxage directive (along with must-revalidate
+# and public).
+#
+# This replay file assumes that caching is enabled and
+# proxy.config.http.cache.ignore_authentication is set to 0 (current default).
+#
+meta:
+  version: "1.0"
+
+# Configuration section for autest integration
+autest:
+  description: 'Test s-maxage allows serving cached responses to requests with 
Authorization headers per RFC 7234 section 3.2'
+
+  # Server configuration
+  server:
+    name: 'server-s-maxage'
+
+  # Client configuration
+  client:
+    name: 'client-s-maxage'
+
+  # ATS configuration
+  ats:
+    name: 'ts-auth-s-maxage'
+
+    # ATS process configuration
+    process_config:
+      enable_cache: true
+
+    # ATS records.config settings
+    records_config:
+      proxy.config.diags.debug.enabled: 1
+      proxy.config.diags.debug.tags: 'http'
+
+    # Remap configuration
+    remap_config:
+      - from: "/"
+        to: "http://127.0.0.1:{SERVER_HTTP_PORT}/";
+
+sessions:
+  - transactions:
+      # First request: Cache a 200 response with s-maxage.
+      - client-request:
+          method: "GET"
+          version: "1.1"
+          url: /auth/s-maxage-test
+          headers:
+            fields:
+              - [uuid, s-maxage-cache-fill]
+              - [Host, example.com]
+
+        server-response:
+          status: 200
+          reason: OK
+          headers:
+            fields:
+              - [Content-Length, 16]
+              - [Cache-Control, "s-maxage=300"]
+
+        proxy-response:
+          status: 200
+
+      # Second request: Request with Authorization header should be served 
from cache
+      # because response has s-maxage per RFC 7234 section 3.2.
+      - client-request:
+          # Add a delay so ATS has time to finish any caching IO for the
+          # previous transaction.
+          delay: 100ms
+          method: "GET"
+          version: "1.1"
+          url: /auth/s-maxage-test
+          headers:
+            fields:
+              - [uuid, s-maxage-with-auth]
+              - [Host, example.com]
+              - [Authorization, "Basic ZGVtbzphdHNAc3Ryb25ncHc="]
+
+        # The server should NOT be reached because the cached response
+        # with s-maxage should be served. Return 400 to verify caching.
+        server-response:
+          status: 400
+          reason: "Bad Request"
+          headers:
+            fields:
+              - [Content-Length, 0]
+
+        # Expect the cached 200 response per RFC 7234 section 3.2
+        proxy-response:
+          status: 200
+
+  - transactions:
+      # Test 2: Verify that public also works.
+      - client-request:
+          method: "GET"
+          version: "1.1"
+          url: /auth/public-test
+          headers:
+            fields:
+              - [uuid, public-cache-fill]
+              - [Host, example.com]
+
+        server-response:
+          status: 200
+          reason: OK
+          headers:
+            fields:
+              - [Content-Length, 16]
+              - [Cache-Control, "public, max-age=300"]
+
+        proxy-response:
+          status: 200
+
+      # Request with Authorization header should be served from cache with 
public
+      - client-request:
+          delay: 100ms
+          method: "GET"
+          version: "1.1"
+          url: /auth/public-test
+          headers:
+            fields:
+              - [uuid, public-with-auth]
+              - [Host, example.com]
+              - [Authorization, "Basic ZGVtbzphdHNAc3Ryb25ncHc="]
+
+        # The server should NOT be reached because the cached response
+        # with public should be served. Return 400 to verify caching.
+        server-response:
+          status: 400
+          reason: "Bad Request"
+          headers:
+            fields:
+              - [Content-Length, 0]
+
+        # Expect cached 200 response
+        proxy-response:
+          status: 200
+
+  - transactions:
+      # Test 3: Without s-maxage or public, Authorization should require 
revalidation
+      - client-request:
+          method: "GET"
+          version: "1.1"
+          url: /auth/no-directive-test
+          headers:
+            fields:
+              - [uuid, no-directive-cache-fill]
+              - [Host, example.com]
+
+        server-response:
+          status: 200
+          reason: OK
+          headers:
+            fields:
+              - [Content-Length, 16]
+              - [Cache-Control, "max-age=300"]
+
+        proxy-response:
+          status: 200
+
+      # Request with Authorization header should NOT be served from cache
+      - client-request:
+          delay: 100ms
+          method: "GET"
+          version: "1.1"
+          url: /auth/no-directive-test
+          headers:
+            fields:
+              - [uuid, no-directive-with-auth]
+              - [Host, example.com]
+              - [Authorization, "Basic ZGVtbzphdHNAc3Ryb25ncHc="]
+
+        # The request should be forwarded to the server and a 404 response
+        # should be returned.
+        server-response:
+          status: 404
+          reason: "Not Found"
+          headers:
+            fields:
+              - [Content-Length, 20]
+
+        # Expect the new 404 response from server rather than the previous 200
+        # response.
+        proxy-response:
+          status: 404
+

Reply via email to