This is an automated email from the ASF dual-hosted git repository. cmcfarlen pushed a commit to branch 10.0.x in repository https://gitbox.apache.org/repos/asf/trafficserver.git
commit 8f16f2dc7e283a5144f4f812f0eef9d906a4c8f4 Author: Jasmine Emanouel <[email protected]> AuthorDate: Thu Oct 31 10:15:42 2024 +1100 Content-type lost when sent after duplicate headers (#11821) * Fix for #11784 * Just specify content-type not be altered * Update HttpTransact.cc (cherry picked from commit 8671ddb311793d7586c42c6dd90e71a632213066) --- src/proxy/http/HttpTransact.cc | 11 + .../headers/cachedDuplicateHeaders.test.py | 60 +++++ .../headers/replays/cache-test.replay.yaml | 257 +++++++++++++++++++++ 3 files changed, 328 insertions(+) diff --git a/src/proxy/http/HttpTransact.cc b/src/proxy/http/HttpTransact.cc index cb49e0d481..d844bf5229 100644 --- a/src/proxy/http/HttpTransact.cc +++ b/src/proxy/http/HttpTransact.cc @@ -5022,6 +5022,17 @@ HttpTransact::merge_response_header_with_cached_header(HTTPHdr *cached_header, H MIMEField &field2{*spot2}; name2 = field2.name_get(&name_len2); + // It is specified above that content type should not + // be altered here however when a duplicate header + // is present, all headers following are delete and + // re-added back. This includes content type if it follows + // any duplicate header. This leads to the loss of + // content type in the client response. + // This ensures that it is not altered when duplicate + // headers are present. + if (name2 == MIME_FIELD_CONTENT_TYPE) { + continue; + } cached_header->field_delete(name2, name_len2); } dups_seen = true; diff --git a/tests/gold_tests/headers/cachedDuplicateHeaders.test.py b/tests/gold_tests/headers/cachedDuplicateHeaders.test.py new file mode 100644 index 0000000000..c3c6be98d7 --- /dev/null +++ b/tests/gold_tests/headers/cachedDuplicateHeaders.test.py @@ -0,0 +1,60 @@ +''' +Test cached responses and requests with bodies +''' +# 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. + +Test.Summary = ''' +Test revalidating cached objects +''' +testName = "RevalidateCacheObject" +Test.ContinueOnFail = True + + +class CachedHeaderValidationTest: + replay_file = "replays/cache-test.replay.yaml" + + def __init__(self): + self.setupOriginServer() + self.setupTS() + + def setupOriginServer(self): + self.server = Test.MakeVerifierServerProcess("cached-header-verifier-server", self.replay_file) + + def setupTS(self): + self.ts = Test.MakeATSProcess("ts", enable_tls=True) + self.ts.Disk.plugin_config.AddLine('xdebug.so --enable=x-cache,x-cache-key,via') + self.ts.Disk.records_config.update( + { + 'proxy.config.diags.debug.enabled': 1, + 'proxy.config.diags.debug.tags': 'http', + 'proxy.config.http.response_via_str': 3, + }) + self.ts.Disk.remap_config.AddLine('map / http://127.0.0.1:{0}'.format(self.server.Variables.http_port)) + + def runTraffic(self): + tr = Test.AddTestRun() + tr.AddVerifierClientProcess("cached-header-verifier-client", self.replay_file, http_ports=[self.ts.Variables.port]) + tr.Processes.Default.StartBefore(self.server) + tr.Processes.Default.StartBefore(self.ts) + tr.StillRunningAfter = self.ts + tr.StillRunningAfter = self.server + + def run(self): + self.runTraffic() + + +CachedHeaderValidationTest().run() diff --git a/tests/gold_tests/headers/replays/cache-test.replay.yaml b/tests/gold_tests/headers/replays/cache-test.replay.yaml new file mode 100644 index 0000000000..df88226200 --- /dev/null +++ b/tests/gold_tests/headers/replays/cache-test.replay.yaml @@ -0,0 +1,257 @@ +# 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. + +meta: + version: "1.0" + +# Note 1: +# When testing duplicate headers here, replay files cannot +# handle two seperate values. So make sure that duplicate headers +# have the same value in testing. + +sessions: + - transactions: + # Test 0: Cache fill with content-type after duplicate headers + - client-request: + method: "GET" + version: "1.1" + url: /1 + headers: + fields: + - [Host, example.com] + - [uuid, fill_1] + - [x-debug, "x-cache,x-cache-key,via"] + + server-response: + status: 200 + reason: OK + headers: + fields: + - [Date, "Mon, 23 Sep 2024 14:22:14 GMT"] + - [X-Reveal-Duplicate, same] + - [Cache-Control, "max-age=1, stale-if-error=1, stale-while-revalidate=1, public"] + - [Content-Length, 3] + - [Content-Type, application/javascript] + - [Expires, "Mon, 23 Sep 2024 14:22:44 GMT"] + - [Last-Modified, "Mon, 23 Sep 2024 14:22:14 GMT"] + - [X-Reveal-Duplicate, same] + + proxy-response: + status: 200 + reason: OK + headers: + fields: + - [Date, { value: "Mon, 23 Sep 2024 14:22:14 GMT", as: equal }] + - [X-Reveal-Duplicate, { value: same, as: equal }] + - [Cache-Control, { value: "max-age=1, stale-if-error=1, stale-while-revalidate=1, public", as: equal }] + - [Content-Length, { value: 3, as: equal }] + - [Content-Type, { value: application/javascript, as: equal }] + - [Expires, { value: "Mon, 23 Sep 2024 14:22:44 GMT", as: equal }] + - [Last-Modified, { value: "Mon, 23 Sep 2024 14:22:14 GMT", as: equal }] + - [X-Cache, { value: miss, as: equal }] + - [X-Reveal-Duplicate, { value: same, as: equal }] + + # Test 1: Cache hit stale with content-type after duplicate headers + - client-request: + method: "GET" + version: "1.1" + url: /1 + headers: + fields: + - [Host, example.com] + - [uuid, stale_1] + - [x-debug, "x-cache,x-cache-key,via"] + + server-response: + status: 304 + reason: Not Modified + headers: + fields: + - [Date, "Mon, 23 Sep 2024 14:22:14 GMT"] + - [X-Reveal-Duplicate, same] + - [Cache-Control, "max-age=1, stale-if-error=1, stale-while-revalidate=1, public"] + - [Content-Length, 3] + - [Content-Type, application/javascript] + - [Expires, "Mon, 23 Sep 2024 14:22:44 GMT"] + - [Last-Modified, "Mon, 23 Sep 2024 14:22:14 GMT"] + - [X-Reveal-Duplicate, same] + + proxy-response: + status: 200 + reason: OK + headers: + fields: + - [Date, { value: "Mon, 23 Sep 2024 14:22:14 GMT", as: equal }] + - [X-Reveal-Duplicate, { value: same, as: equal }] + - [Cache-Control, { value: "max-age=1, stale-if-error=1, stale-while-revalidate=1, public", as: equal }] + - [Content-Length, { value: 3, as: equal }] + - [Content-Type, { value: application/javascript, as: equal }] + - [Expires, { value: "Mon, 23 Sep 2024 14:22:44 GMT", as: equal }] + - [Last-Modified, { value: "Mon, 23 Sep 2024 14:22:14 GMT", as: equal }] + - [X-Cache, { value: hit-stale, as: equal }] + - [X-Reveal-Duplicate, { value: same, as: equal }] + + # Test 2: Cache fill with content-type before duplicate headers + - client-request: + method: "GET" + version: "1.1" + url: /2 + headers: + fields: + - [Host, example.com] + - [uuid, fill_2] + - [x-debug, "x-cache,x-cache-key,via"] + + server-response: + status: 200 + reason: OK + headers: + fields: + - [Date, "Mon, 23 Sep 2024 14:22:14 GMT"] + - [Content-Type, application/javascript] + - [X-Reveal-Duplicate, same] + - [Cache-Control, "max-age=1, stale-if-error=1, stale-while-revalidate=1, public"] + - [Content-Length, 3] + - [Expires, "Mon, 23 Sep 2024 14:22:44 GMT"] + - [Last-Modified, "Mon, 23 Sep 2024 14:22:14 GMT"] + - [X-Reveal-Duplicate, same] + + proxy-response: + status: 200 + reason: OK + headers: + fields: + - [Date, { value: "Mon, 23 Sep 2024 14:22:14 GMT", as: equal }] + - [X-Reveal-Duplicate, { value: same, as: equal }] + - [Cache-Control, { value: "max-age=1, stale-if-error=1, stale-while-revalidate=1, public", as: equal }] + - [Content-Length, { value: 3, as: equal }] + - [Content-Type, { value: application/javascript, as: equal }] + - [Expires, { value: "Mon, 23 Sep 2024 14:22:44 GMT", as: equal }] + - [Last-Modified, { value: "Mon, 23 Sep 2024 14:22:14 GMT", as: equal }] + - [X-Cache, { value: miss, as: equal }] + - [X-Reveal-Duplicate, { value: same, as: equal }] + + # Test 3: Cache hit stale with content-type before duplicate headers + - client-request: + method: "GET" + version: "1.1" + url: /2 + headers: + fields: + - [Host, example.com] + - [uuid, stale_2] + - [x-debug, "x-cache,x-cache-key,via"] + + server-response: + status: 304 + reason: Not Modified + headers: + fields: + - [Date, "Mon, 23 Sep 2024 14:22:14 GMT"] + - [Content-Type, application/javascript] + - [X-Reveal-Duplicate, same] + - [X-Reveal-Duplicate, same] + - [Cache-Control, "max-age=1, stale-if-error=1, stale-while-revalidate=1, public"] + - [Content-Length, 3] + - [Expires, "Mon, 23 Sep 2024 14:22:44 GMT"] + - [Last-Modified, "Mon, 23 Sep 2024 14:22:14 GMT"] + + proxy-response: + status: 200 + reason: OK + headers: + fields: + - [Date, { value: "Mon, 23 Sep 2024 14:22:14 GMT", as: equal }] + - [X-Reveal-Duplicate, { value: same, as: equal }] + - [X-Reveal-Duplicate, { value: same, as: equal }] + - [Cache-Control, { value: "max-age=1, stale-if-error=1, stale-while-revalidate=1, public", as: equal }] + - [Content-Length, { value: 3, as: equal }] + - [Content-Type, { value: application/javascript, as: equal }] + - [Expires, { value: "Mon, 23 Sep 2024 14:22:44 GMT", as: equal }] + - [Last-Modified, { value: "Mon, 23 Sep 2024 14:22:14 GMT", as: equal }] + - [X-Cache, { value: hit-stale, as: equal }] + + # Test 4: Cache fill with no duplicate headers + - client-request: + method: "GET" + version: "1.1" + url: /3 + headers: + fields: + - [Host, example.com] + - [uuid, fill_3] + - [x-debug, "x-cache,x-cache-key,via"] + + server-response: + status: 200 + reason: OK + headers: + fields: + - [Date, "Mon, 23 Sep 2024 14:22:14 GMT"] + - [Content-Type, application/javascript] + - [Cache-Control, "max-age=1, stale-if-error=1, stale-while-revalidate=1, public"] + - [Content-Length, 3] + - [Expires, "Mon, 23 Sep 2024 14:22:44 GMT"] + - [Last-Modified, "Mon, 23 Sep 2024 14:22:14 GMT"] + + proxy-response: + status: 200 + reason: OK + headers: + fields: + - [Date, { value: "Mon, 23 Sep 2024 14:22:14 GMT", as: equal }] + - [Cache-Control, { value: "max-age=1, stale-if-error=1, stale-while-revalidate=1, public", as: equal }] + - [Content-Length, { value: 3, as: equal }] + - [Content-Type, { value: application/javascript, as: equal }] + - [Expires, { value: "Mon, 23 Sep 2024 14:22:44 GMT", as: equal }] + - [Last-Modified, { value: "Mon, 23 Sep 2024 14:22:14 GMT", as: equal }] + - [X-Cache, { value: miss, as: equal }] + + # Test 5: Cache hit stale no duplicate headers + - client-request: + method: "GET" + version: "1.1" + url: /3 + headers: + fields: + - [Host, example.com] + - [uuid, stale_3] + - [x-debug, "x-cache,x-cache-key,via"] + + server-response: + status: 304 + reason: Not Modified + headers: + fields: + - [Date, "Mon, 23 Sep 2024 14:22:14 GMT"] + - [Content-Type, application/javascript] + - [Cache-Control, "max-age=1, stale-if-error=1, stale-while-revalidate=1, public"] + - [Content-Length, 3] + - [Expires, "Mon, 23 Sep 2024 14:22:44 GMT"] + - [Last-Modified, "Mon, 23 Sep 2024 14:22:14 GMT"] + + proxy-response: + status: 200 + reason: OK + headers: + fields: + - [Date, { value: "Mon, 23 Sep 2024 14:22:14 GMT", as: equal }] + - [Cache-Control, { value: "max-age=1, stale-if-error=1, stale-while-revalidate=1, public", as: equal }] + - [Content-Length, { value: 3, as: equal }] + - [Content-Type, { value: application/javascript, as: equal }] + - [Expires, { value: "Mon, 23 Sep 2024 14:22:44 GMT", as: equal }] + - [Last-Modified, { value: "Mon, 23 Sep 2024 14:22:14 GMT", as: equal }] + - [X-Cache, { value: hit-stale, as: equal }]
