From 255ba551a801760be82f3bd680ad3dbd52cc0141 Mon Sep 17 00:00:00 2001 From: Jarkko Hietaniemi Date: Wed, 9 Jun 2021 18:08:16 +0300 Subject: [PATCH 1/4] Adds new X-Effective-URL header to the xdebug plugin By adding "X-Effective-URL" to the request header "X-Debug", the header "X-Effective-URL" header will be inserted to the request headers with the effective URL value. Exposes the TSHttpTxnEffectiveUrlStringGet() result, which is the URL after the remap. Note: the inserted header is intentionally X-prefixed for consistency with the other headers inserted by the xdebug plugin. --- plugins/xdebug/xdebug.cc | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/plugins/xdebug/xdebug.cc b/plugins/xdebug/xdebug.cc index f0b1d307a48..604f7ddf95d 100644 --- a/plugins/xdebug/xdebug.cc +++ b/plugins/xdebug/xdebug.cc @@ -83,6 +83,7 @@ enum { XHEADER_X_PROBE_HEADERS = 1u << 9, XHEADER_X_PSELECT_KEY = 1u << 10, XHEADER_X_CACHE_INFO = 1u << 11, + XHEADER_X_EFFECTIVE_URL = 1u << 12, }; static TSCont XInjectHeadersCont = nullptr; @@ -376,6 +377,34 @@ InjectRemapHeader(TSHttpTxn txn, TSMBuffer buffer, TSMLoc hdr) } } +static void +InjectEffectiveURLHeader(TSHttpTxn txn, TSMBuffer buffer, TSMLoc hdr) +{ + TSMLoc dst = TS_NULL_MLOC; + + struct { + char *ptr; + int len; + } strval = {nullptr, 0}; + + TSDebug("xdebug", "attempting to inject X-Effective-URL header"); + + strval.ptr = TSHttpTxnEffectiveUrlStringGet(txn, &strval.len); + + if (strval.ptr != nullptr && strval.len > 0) { + dst = FindOrMakeHdrField(buffer, hdr, "X-Effective-URL", lengthof("X-Effective-URL")); + if (dst != TS_NULL_MLOC) { + TSReleaseAssert(TSMimeHdrFieldValueStringInsert(buffer, hdr, dst, -1 /* idx */, strval.ptr, strval.len) == TS_SUCCESS); + } + } + + if (dst != TS_NULL_MLOC) { + TSHandleMLocRelease(buffer, hdr, dst); + } + + TSfree(strval.ptr); +} + static void InjectTxnUuidHeader(TSHttpTxn txn, TSMBuffer buffer, TSMLoc hdr) { @@ -484,6 +513,10 @@ XInjectResponseHeaders(TSCont /* contp */, TSEvent event, void *edata) InjectRemapHeader(txn, buffer, hdr); } + if (xheaders & XHEADER_X_EFFECTIVE_URL) { + InjectEffectiveURLHeader(txn, buffer, hdr); + } + // intentionally placed after all injected headers. if (xheaders & XHEADER_X_DUMP_HEADERS) { @@ -649,6 +682,8 @@ XScanRequestHeaders(TSCont /* contp */, TSEvent event, void *edata) snprintf(newVal, sizeof(newVal), "fwd=%" PRIiMAX, fwdCnt - 1); TSMimeHdrFieldValueStringSet(buffer, hdr, field, i, newVal, std::strlen(newVal)); } + } else if (header_field_eq("x-effective-url", value, vsize)) { + xheaders |= XHEADER_X_EFFECTIVE_URL; } else { TSDebug("xdebug", "ignoring unrecognized debug tag '%.*s'", vsize, value); } From f388b7fe38fcd36efc019a6286db40e88e06ea1c Mon Sep 17 00:00:00 2001 From: Jarkko Hietaniemi Date: Wed, 9 Jun 2021 21:05:47 +0300 Subject: [PATCH 2/4] Add Au tests. --- .../pluginTest/xdebug/x_effective_url/none.in | 5 ++ .../pluginTest/xdebug/x_effective_url/one.in | 5 ++ .../xdebug/x_effective_url/out.gold | 61 ++++++++++++++ .../xdebug/x_effective_url/three.in | 5 ++ .../pluginTest/xdebug/x_effective_url/two.in | 5 ++ .../x_effective_url/x_effective_url.test.py | 81 +++++++++++++++++++ 6 files changed, 162 insertions(+) create mode 100644 tests/gold_tests/pluginTest/xdebug/x_effective_url/none.in create mode 100644 tests/gold_tests/pluginTest/xdebug/x_effective_url/one.in create mode 100644 tests/gold_tests/pluginTest/xdebug/x_effective_url/out.gold create mode 100644 tests/gold_tests/pluginTest/xdebug/x_effective_url/three.in create mode 100644 tests/gold_tests/pluginTest/xdebug/x_effective_url/two.in create mode 100644 tests/gold_tests/pluginTest/xdebug/x_effective_url/x_effective_url.test.py diff --git a/tests/gold_tests/pluginTest/xdebug/x_effective_url/none.in b/tests/gold_tests/pluginTest/xdebug/x_effective_url/none.in new file mode 100644 index 00000000000..e07b30662f5 --- /dev/null +++ b/tests/gold_tests/pluginTest/xdebug/x_effective_url/none.in @@ -0,0 +1,5 @@ +GET /argh HTTP/1.1 +Host: none +X-Debug: X-Effective-URL +Connection: close + diff --git a/tests/gold_tests/pluginTest/xdebug/x_effective_url/one.in b/tests/gold_tests/pluginTest/xdebug/x_effective_url/one.in new file mode 100644 index 00000000000..d9223256128 --- /dev/null +++ b/tests/gold_tests/pluginTest/xdebug/x_effective_url/one.in @@ -0,0 +1,5 @@ +GET /argh HTTP/1.1 +Host: one +X-Debug: x-effective-url +Connection: close + diff --git a/tests/gold_tests/pluginTest/xdebug/x_effective_url/out.gold b/tests/gold_tests/pluginTest/xdebug/x_effective_url/out.gold new file mode 100644 index 00000000000..2c14aa13de0 --- /dev/null +++ b/tests/gold_tests/pluginTest/xdebug/x_effective_url/out.gold @@ -0,0 +1,61 @@ +HTTP/1.1 502 Cannot find server. +Date: `` +Connection: close +Server: ATS/`` +Cache-Control: no-store +Content-Type: text/html +Content-Language: en +X-Effective-URL: http://none/argh +Content-Length: 391 + + + +Unknown Host + + + +

Unknown Host

+
+ + +Description: Unable to locate the server requested --- +the server does not have a DNS entry. Perhaps there is a misspelling +in the server name, or the server no longer exists. Double-check the +name and try again. + +
+ +====== +HTTP/1.1 200 OK +Date: `` +Age: `` +Transfer-Encoding: chunked +Connection: close +Server: ATS/`` +X-Effective-URL: http://127.0.0.1:SERVER_PORT/argh + +0 + +====== +HTTP/1.1 200 OK +Date: `` +Age: `` +Transfer-Encoding: chunked +Connection: close +Server: ATS/`` +X-Effective-URL: http://127.0.0.1:SERVER_PORT/two/argh + +0 + +====== +HTTP/1.1 200 OK +Date: `` +Age: `` +Transfer-Encoding: chunked +Connection: close +Server: ATS/`` +X-Effective-URL: http://127.0.0.1:SERVER_PORT/argh + +0 + +====== diff --git a/tests/gold_tests/pluginTest/xdebug/x_effective_url/three.in b/tests/gold_tests/pluginTest/xdebug/x_effective_url/three.in new file mode 100644 index 00000000000..7076c1a249c --- /dev/null +++ b/tests/gold_tests/pluginTest/xdebug/x_effective_url/three.in @@ -0,0 +1,5 @@ +GET /argh HTTP/1.1 +Host: three123 +X-Debug: X-effective-url +Connection: close + diff --git a/tests/gold_tests/pluginTest/xdebug/x_effective_url/two.in b/tests/gold_tests/pluginTest/xdebug/x_effective_url/two.in new file mode 100644 index 00000000000..52ded33b4f0 --- /dev/null +++ b/tests/gold_tests/pluginTest/xdebug/x_effective_url/two.in @@ -0,0 +1,5 @@ +GET /argh HTTP/1.1 +Host: two +X-Debug: X-EFFECTIVE-URL +Connection: close + diff --git a/tests/gold_tests/pluginTest/xdebug/x_effective_url/x_effective_url.test.py b/tests/gold_tests/pluginTest/xdebug/x_effective_url/x_effective_url.test.py new file mode 100644 index 00000000000..ed1c3b54300 --- /dev/null +++ b/tests/gold_tests/pluginTest/xdebug/x_effective_url/x_effective_url.test.py @@ -0,0 +1,81 @@ +# 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 xdebug plugin X-Effective header +''' + +server = Test.MakeOriginServer("server") + +request_header = { + "headers": "GET /argh HTTP/1.1\r\nHost: doesnotmatter\r\n\r\n", "timestamp": "1469733493.993", "body": ""} +response_header = {"headers": "HTTP/1.1 200 OK\r\nConnection: close\r\n\r\n", + "timestamp": "1469733493.993", "body": ""} +server.addResponse("sessionlog.json", request_header, response_header) + +request_header_two = { + "headers": "GET /two/argh HTTP/1.1\r\nHost: doesnotmatter\r\n\r\n", "timestamp": "1469733493.993", "body": ""} +server.addResponse("sessionlog.json", request_header_two, response_header) + +ts = Test.MakeATSProcess("ts") + +ts.Disk.records_config.update({ + 'proxy.config.url_remap.remap_required': 0, + 'proxy.config.diags.debug.enabled': 0, +}) + +ts.Disk.plugin_config.AddLine('xdebug.so') + +ts.Disk.remap_config.AddLine( + "map http://one http://127.0.0.1:{0}".format(server.Variables.Port) +) +ts.Disk.remap_config.AddLine( + "map http://two http://127.0.0.1:{0}".format(server.Variables.Port) + "/two" +) +ts.Disk.remap_config.AddLine( + "regex_map http://three[0-9]+ http://127.0.0.1:{0}".format(server.Variables.Port) +) + +tr = Test.AddTestRun() +tr.Processes.Default.StartBefore(Test.Processes.ts) +tr.Processes.Default.StartBefore(Test.Processes.server) +tr.Processes.Default.Command = "cp {}/tcp_client.py {}/tcp_client.py".format( + Test.Variables.AtsTestToolsDir, Test.RunDirectory) +tr.Processes.Default.ReturnCode = 0 + + +def sendMsg(msgFile): + + tr = Test.AddTestRun() + tr.Processes.Default.Command = ( + "( python3 {}/tcp_client.py 127.0.0.1 {} {}/{}.in".format( + Test.RunDirectory, ts.Variables.port, Test.TestDirectory, msgFile) + + " ; echo '======' ) | sed 's/:{}/:SERVER_PORT/' >> {}/out.log 2>&1 ".format( + server.Variables.Port, Test.RunDirectory) + ) + tr.Processes.Default.ReturnCode = 0 + + +sendMsg('none') +sendMsg('one') +sendMsg('two') +sendMsg('three') + +tr = Test.AddTestRun() +tr.Processes.Default.Command = "echo test out.gold" +tr.Processes.Default.ReturnCode = 0 +f = tr.Disk.File("out.log") +f.Content = "out.gold" From 7010ed9748f6a91dce9ff9254fc3e9df4e756bb6 Mon Sep 17 00:00:00 2001 From: Jarkko Hietaniemi Date: Thu, 10 Jun 2021 08:36:15 +0300 Subject: [PATCH 3/4] Change the expected response code from 502 to 500. Note that the response code is as such irrelevant in this test since what is being tested is the request header rewriting. Strangely, in local testing the --- tests/gold_tests/pluginTest/xdebug/x_effective_url/out.gold | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/gold_tests/pluginTest/xdebug/x_effective_url/out.gold b/tests/gold_tests/pluginTest/xdebug/x_effective_url/out.gold index 2c14aa13de0..7af772ad449 100644 --- a/tests/gold_tests/pluginTest/xdebug/x_effective_url/out.gold +++ b/tests/gold_tests/pluginTest/xdebug/x_effective_url/out.gold @@ -1,4 +1,4 @@ -HTTP/1.1 502 Cannot find server. +HTTP/1.1 500 Cannot find server. Date: `` Connection: close Server: ATS/`` From 60252d542c5b5d49b81d135ead0c631bab03f9ed Mon Sep 17 00:00:00 2001 From: Jarkko Hietaniemi Date: Tue, 20 Jul 2021 13:49:25 +0300 Subject: [PATCH 4/4] Tighter scope as suggested by ywkaraas. --- plugins/xdebug/xdebug.cc | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/plugins/xdebug/xdebug.cc b/plugins/xdebug/xdebug.cc index 604f7ddf95d..9d34655d942 100644 --- a/plugins/xdebug/xdebug.cc +++ b/plugins/xdebug/xdebug.cc @@ -380,8 +380,6 @@ InjectRemapHeader(TSHttpTxn txn, TSMBuffer buffer, TSMLoc hdr) static void InjectEffectiveURLHeader(TSHttpTxn txn, TSMBuffer buffer, TSMLoc hdr) { - TSMLoc dst = TS_NULL_MLOC; - struct { char *ptr; int len; @@ -392,16 +390,13 @@ InjectEffectiveURLHeader(TSHttpTxn txn, TSMBuffer buffer, TSMLoc hdr) strval.ptr = TSHttpTxnEffectiveUrlStringGet(txn, &strval.len); if (strval.ptr != nullptr && strval.len > 0) { - dst = FindOrMakeHdrField(buffer, hdr, "X-Effective-URL", lengthof("X-Effective-URL")); + TSMLoc dst = FindOrMakeHdrField(buffer, hdr, "X-Effective-URL", lengthof("X-Effective-URL")); if (dst != TS_NULL_MLOC) { TSReleaseAssert(TSMimeHdrFieldValueStringInsert(buffer, hdr, dst, -1 /* idx */, strval.ptr, strval.len) == TS_SUCCESS); + TSHandleMLocRelease(buffer, hdr, dst); } } - if (dst != TS_NULL_MLOC) { - TSHandleMLocRelease(buffer, hdr, dst); - } - TSfree(strval.ptr); }