From 87ec9ac1fa72d014deae547788ac478c25bddec1 Mon Sep 17 00:00:00 2001 From: Jasmine Emanouel Date: Fri, 14 Jun 2024 16:03:44 +1000 Subject: [PATCH 01/11] Add set-body-custom to header_rewrite options (cherry picked from commit 5bd999953b2605898f15714453250cb7e5e403f9) (cherry picked from commit 08c614ef0089b175a5b6cee205b748416efb87cd) --- doc/admin-guide/plugins/header_rewrite.en.rst | 23 ++++ plugins/header_rewrite/factory.cc | 3 +- plugins/header_rewrite/operators.cc | 129 ++++++++++++++++++ plugins/header_rewrite/operators.h | 21 +++ .../gold/header_rewrite-custom_body.gold | 10 ++ .../header_rewrite_custom_body.test.py | 89 ++++++++++++ .../rules/rule_set_custom_body.conf | 18 +++ 7 files changed, 292 insertions(+), 1 deletion(-) create mode 100644 tests/gold_tests/pluginTest/header_rewrite/gold/header_rewrite-custom_body.gold create mode 100644 tests/gold_tests/pluginTest/header_rewrite/header_rewrite_custom_body.test.py create mode 100644 tests/gold_tests/pluginTest/header_rewrite/rules/rule_set_custom_body.conf diff --git a/doc/admin-guide/plugins/header_rewrite.en.rst b/doc/admin-guide/plugins/header_rewrite.en.rst index a5128b698fb..2c662630c04 100644 --- a/doc/admin-guide/plugins/header_rewrite.en.rst +++ b/doc/admin-guide/plugins/header_rewrite.en.rst @@ -704,6 +704,29 @@ set-body Sets the body to ````. Can also be used to delete a body with ``""``. This is only useful when overriding the origin status, i.e. intercepting/pre-empting a request so that you can override the body from the body-factory with your own. +set-custom-body +~~~~~~~~ +:: + + set-custom-body + +Will call ```` (see URL in `URL Parts`_) to retrieve a custom error response +and set the body with the result. Triggering this rule on a OK transaction will +send a 500 status code to the client with the desired response. If this is triggered +on any error status codes, that original status code will be sent to the client. + +An example config would look like + cond %{READ_RESPONSE_HDR_HOOK} + set-custom-body http://www.example.com/second + +Where ``http://www.example.com/second`` is the destination to retrieve the custom response from. +This can be enabled per-mapping or globally. +Ensure there is a remap rule for the second endpoint aswell! +An example remap config would look like + map /first http://www.example.com/first @plugin=header_rewrite.so @pparam=cond1.conf + map /second http://www.example.com/second + + set-config ~~~~~~~~~~ :: diff --git a/plugins/header_rewrite/factory.cc b/plugins/header_rewrite/factory.cc index 531f390f24c..a566af613f1 100644 --- a/plugins/header_rewrite/factory.cc +++ b/plugins/header_rewrite/factory.cc @@ -77,7 +77,8 @@ operator_factory(const std::string &op) o = new OperatorSetHttpCntl(); } else if (op == "run-plugin") { o = new OperatorRunPlugin(); - + } else if (op == "set-custom-body") { + o = new OperatorSetCustomBody(); } else { TSError("[%s] Unknown operator: %s", PLUGIN_NAME, op.c_str()); return nullptr; diff --git a/plugins/header_rewrite/operators.cc b/plugins/header_rewrite/operators.cc index b22f04253a4..0b727bde5cb 100644 --- a/plugins/header_rewrite/operators.cc +++ b/plugins/header_rewrite/operators.cc @@ -30,6 +30,78 @@ #include "operators.h" #include "ts/apidefs.h" +namespace +{ +const unsigned int LOCAL_IP_ADDRESS = 0x0100007f; +const unsigned int MAX_SIZE = 256; +const int LOCAL_PORT = 8080; + +static int +handleFetchEvents(TSCont cont, TSEvent event, void *edata) +{ + TSHttpTxn http_txn = static_cast(TSContDataGet(cont)); + + switch (static_cast(event)) { + case OperatorSetCustomBody::TS_EVENT_FETCHSM_SUCCESS: { + TSHttpTxn fetchsm_txn = static_cast(edata); + int data_len; + const char *data_start = TSFetchRespGet(fetchsm_txn, &data_len); + const char *data_end = data_start + data_len; + if (data_start != nullptr) { + TSHttpTxnErrorBodySet(http_txn, TSstrdup(data_start), (data_end - data_start), nullptr); + } + TSHttpTxnReenable(http_txn, TS_EVENT_HTTP_ERROR); + } break; + case OperatorSetCustomBody::TS_EVENT_FETCHSM_FAILURE: { + Dbg(pi_dbg_ctl, "OperatorSetBodyCustom: Error getting custom body"); + TSHttpTxnReenable(http_txn, TS_EVENT_HTTP_CONTINUE); + } break; + case OperatorSetCustomBody::TS_EVENT_FETCHSM_TIMEOUT: { + Dbg(pi_dbg_ctl, "OperatorSetBodyCustom: Timeout getting custom body"); + TSHttpTxnReenable(http_txn, TS_EVENT_HTTP_CONTINUE); + } break; + case TS_EVENT_HTTP_TXN_CLOSE: { + TSContDestroy(cont); + TSHttpTxnReenable(http_txn, TS_EVENT_HTTP_CONTINUE); + } break; + case TS_EVENT_HTTP_SEND_RESPONSE_HDR: + // Do nothing + // The transaction is reenabled with the FetchSM transaction + break; + default: + TSWarning("Warning: handleFetchEvents got unknown event: %d", event); + break; + } + return 0; +} + +TSReturnCode +createRequestString(const std::string_view &value, char (&req_buf)[MAX_SIZE], int *req_buf_size) +{ + const char *start = value.data(); + const char *end = start + value.size(); + TSMLoc url_loc; + TSMBuffer url_buf = TSMBufferCreate(); + int host_len, url_len = 0; + + if (TSUrlCreate(url_buf, &url_loc) == TS_SUCCESS && TSUrlParse(url_buf, url_loc, &start, end) == TS_PARSE_DONE) { + const char *host = TSUrlHostGet(url_buf, url_loc, &host_len); + const char *url = TSUrlStringGet(url_buf, url_loc, &url_len); + + *req_buf_size = snprintf(req_buf, MAX_SIZE, "GET %.*s HTTP/1.1\r\nHost: %.*s\r\n\r\n", url_len, url, host_len, host); + + TSMBufferDestroy(url_buf); + + return TS_SUCCESS; + } else { + Dbg(pi_dbg_ctl, "Failed to parse url %s", start); + TSMBufferDestroy(url_buf); + return TS_ERROR; + } +} + +} // namespace + // OperatorConfig void OperatorSetConfig::initialize(Parser &p) @@ -1219,3 +1291,60 @@ OperatorRunPlugin::exec(const Resources &res) const _plugin->doRemap(res.txnp, res._rri); } } + +// OperatorSetBody +void +OperatorSetCustomBody::initialize(Parser &p) +{ + Operator::initialize(p); + // we want the arg since body only takes one value + _value.set_value(p.get_arg()); + require_resources(RSRC_SERVER_RESPONSE_HEADERS); + require_resources(RSRC_RESPONSE_STATUS); +} + +void +OperatorSetCustomBody::initialize_hooks() +{ + add_allowed_hook(TS_HTTP_READ_RESPONSE_HDR_HOOK); +} + +void +OperatorSetCustomBody::exec(const Resources &res) const +{ + if (TSHttpTxnIsInternal(res.txnp)) { + // If this is triggered by an internal transaction, a infinte loop may occur + // It should only be triggered by the original transaction sent by the client + Dbg(pi_dbg_ctl, "OperatorSetCustomBody triggered by an internal transaction"); + return; + } + + char req_buf[MAX_SIZE]; + int req_buf_size = 0; + if (createRequestString(_value.get_value(), req_buf, &req_buf_size) == TS_SUCCESS) { + TSCont fetchCont = TSContCreate(handleFetchEvents, TSMutexCreate()); + TSContDataSet(fetchCont, static_cast(res.txnp)); + + TSHttpTxnHookAdd(res.txnp, TS_HTTP_SEND_RESPONSE_HDR_HOOK, fetchCont); + TSHttpTxnHookAdd(res.txnp, TS_HTTP_TXN_CLOSE_HOOK, fetchCont); + + TSFetchEvent event_ids; + event_ids.success_event_id = TS_EVENT_FETCHSM_SUCCESS; + event_ids.failure_event_id = TS_EVENT_FETCHSM_FAILURE; + event_ids.timeout_event_id = TS_EVENT_FETCHSM_TIMEOUT; + + struct sockaddr_in addr; + addr.sin_family = AF_INET; + addr.sin_addr.s_addr = LOCAL_IP_ADDRESS; + addr.sin_port = LOCAL_PORT; + TSFetchUrl(static_cast(req_buf), req_buf_size, reinterpret_cast(&addr), fetchCont, + AFTER_BODY, event_ids); + + // Forces original status code in event TSHttpTxnErrorBodySet changed + // the code or another condition was set conflicting with this one. + // Set here because res is the only structure that contains the original status code. + TSHttpTxnStatusSet(res.txnp, res.resp_status); + } else { + TSError(PLUGIN_NAME, "OperatorSetCustomBody:exec:: Could not create request"); + } +} diff --git a/plugins/header_rewrite/operators.h b/plugins/header_rewrite/operators.h index dc7b19ee4a1..73f8bb5d5be 100644 --- a/plugins/header_rewrite/operators.h +++ b/plugins/header_rewrite/operators.h @@ -478,3 +478,24 @@ class OperatorRunPlugin : public Operator private: RemapPluginInst *_plugin = nullptr; }; + +class OperatorSetCustomBody : public Operator +{ +public: + OperatorSetCustomBody() { Dbg(pi_dbg_ctl, "Calling CTOR for OperatorSetBodyCustom"); } + + // noncopyable + OperatorSetCustomBody(const OperatorSetCustomBody &) = delete; + void operator=(const OperatorSetCustomBody &) = delete; + + void initialize(Parser &p) override; + + enum { TS_EVENT_FETCHSM_SUCCESS = 70000, TS_EVENT_FETCHSM_FAILURE = 70001, TS_EVENT_FETCHSM_TIMEOUT = 70002 }; + +protected: + void initialize_hooks() override; + void exec(const Resources &res) const override; + +private: + Value _value; +}; diff --git a/tests/gold_tests/pluginTest/header_rewrite/gold/header_rewrite-custom_body.gold b/tests/gold_tests/pluginTest/header_rewrite/gold/header_rewrite-custom_body.gold new file mode 100644 index 00000000000..88834255540 --- /dev/null +++ b/tests/gold_tests/pluginTest/header_rewrite/gold/header_rewrite-custom_body.gold @@ -0,0 +1,10 @@ +HTTP/1.1 404 Not Found +Date: `` +Proxy-Connection: close +Server: ATS/`` +Content-Length: `` +Content-Type: `` + +Custom body found +`` + diff --git a/tests/gold_tests/pluginTest/header_rewrite/header_rewrite_custom_body.test.py b/tests/gold_tests/pluginTest/header_rewrite/header_rewrite_custom_body.test.py new file mode 100644 index 00000000000..26d76782041 --- /dev/null +++ b/tests/gold_tests/pluginTest/header_rewrite/header_rewrite_custom_body.test.py @@ -0,0 +1,89 @@ +# 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 for successful response manipulation using set-custom-body +''' +Test.ContinueOnFail = True +Test.testName = "CUSTOM_BODY" + + +class HeaderRewriteCustomBodyTest: + + def __init__(self): + self.setUpOriginServer() + self.setUpTS() + + def setUpOriginServer(self): + self.server = Test.MakeOriginServer("server") + + def setUpTS(self): + self.ts = Test.MakeATSProcess("ts") + + # Request/response for original transaction + request_header = { + "headers": "GET /test HTTP/1.1\r\nHost: www.example.com\r\n\r\n", + "timestamp": "1469733493.993", + "body": "" + } + response_header = { + "headers": "HTTP/1.1 404 Not Found\r\nConnection: close\r\n\r\n", + "timestamp": "1469733493.993", + "body": "" + } + self.server.addResponse("sessionfile.log", request_header, response_header) + # Request/response for custom body transaction + request_header = { + "headers": "GET /404 HTTP/1.1\r\nHost: www.example.com\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": "Custom body found" + } + self.server.addResponse("sessionfile.log", request_header, response_header) + + self.ts.Disk.records_config.update({ + 'proxy.config.diags.debug.enabled': 1, + 'proxy.config.diags.debug.tags': 'header.*', + }) + # Set header rewrite rules + self.ts.Setup.CopyAs('rules/rule_set_custom_body.conf', Test.RunDirectory) + self.ts.Disk.remap_config.AddLine( + 'map http://www.example.com/test http://127.0.0.1:{0}/test @plugin=header_rewrite.so @pparam={1}/rule_set_custom_body.conf' + .format(self.server.Variables.Port, Test.RunDirectory)) + self.ts.Disk.remap_config.AddLine( + 'map http://www.example.com/404 http://127.0.0.1:{0}/404'.format(self.server.Variables.Port)) + + def runTraffic(self): + tr = Test.AddTestRun() + tr.Processes.Default.Command = ( + 'curl --proxy 127.0.0.1:{0} "http://www.example.com/test" -H "Proxy-Connection: keep-alive" -verbose -silent'.format( + self.ts.Variables.port)) + tr.Processes.Default.ReturnCode = 0 + tr.Processes.Default.StartBefore(self.server, ready=When.PortOpen(self.server.Variables.Port)) + tr.Processes.Default.StartBefore(Test.Processes.ts) + tr.Processes.Default.Streams.stdout = "gold/header_rewrite-custom_body.gold" + tr.StillRunningAfter = self.server + self.ts.Disk.traffic_out.Content = "gold/header_rewrite-tag.gold" + + def run(self): + self.runTraffic() + + +HeaderRewriteCustomBodyTest().run() diff --git a/tests/gold_tests/pluginTest/header_rewrite/rules/rule_set_custom_body.conf b/tests/gold_tests/pluginTest/header_rewrite/rules/rule_set_custom_body.conf new file mode 100644 index 00000000000..d2aac8fcdba --- /dev/null +++ b/tests/gold_tests/pluginTest/header_rewrite/rules/rule_set_custom_body.conf @@ -0,0 +1,18 @@ +# +# 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. +cond %{READ_RESPONSE_HDR_HOOK} +set-custom-body http://www.example.com/404 From d6a4410d50b0107d11ff51ffdcba5ca79f1493a4 Mon Sep 17 00:00:00 2001 From: Jasmine Emanouel Date: Fri, 21 Jun 2024 14:37:08 +1000 Subject: [PATCH 02/11] Update set-custom-body response body to exclude headers (#780) * Update response body to exclude headers * Update tests to check both response with headers and response body only * Update header_rewrite_custom_body.test.py * Fix tests to check headers and body (cherry picked from commit cb552b63d6755a554edc5b67721f35678b38163b) (cherry picked from commit e12f4798d0d46bd90c810f8f3a7a067ea3b2c76f) --- plugins/header_rewrite/operators.cc | 19 ++++++++++++++++--- .../gold/header_rewrite-custom_body.gold | 10 ---------- .../gold/header_rewrite-custom_body_body.gold | 1 + .../header_rewrite-custom_body_headers.gold | 9 +++++++++ .../header_rewrite_custom_body.test.py | 15 ++++++++------- 5 files changed, 34 insertions(+), 20 deletions(-) delete mode 100644 tests/gold_tests/pluginTest/header_rewrite/gold/header_rewrite-custom_body.gold create mode 100644 tests/gold_tests/pluginTest/header_rewrite/gold/header_rewrite-custom_body_body.gold create mode 100644 tests/gold_tests/pluginTest/header_rewrite/gold/header_rewrite-custom_body_headers.gold diff --git a/plugins/header_rewrite/operators.cc b/plugins/header_rewrite/operators.cc index 0b727bde5cb..85b96b16217 100644 --- a/plugins/header_rewrite/operators.cc +++ b/plugins/header_rewrite/operators.cc @@ -46,9 +46,22 @@ handleFetchEvents(TSCont cont, TSEvent event, void *edata) TSHttpTxn fetchsm_txn = static_cast(edata); int data_len; const char *data_start = TSFetchRespGet(fetchsm_txn, &data_len); - const char *data_end = data_start + data_len; - if (data_start != nullptr) { - TSHttpTxnErrorBodySet(http_txn, TSstrdup(data_start), (data_end - data_start), nullptr); + if (data_start && (data_len > 0)) { + const char *data_end = data_start + data_len; + TSHttpParser parser = TSHttpParserCreate(); + TSMBuffer hdr_buf = TSMBufferCreate(); + TSMLoc hdr_loc = TSHttpHdrCreate(hdr_buf); + TSHttpHdrTypeSet(hdr_buf, hdr_loc, TS_HTTP_TYPE_RESPONSE); + if (TSHttpHdrParseResp(parser, hdr_buf, hdr_loc, &data_start, data_end) == TS_PARSE_DONE) { + TSHttpTxnErrorBodySet(http_txn, TSstrdup(data_start), (data_end - data_start), nullptr); + } else { + TSWarning("[%s] Unable to parse set-custom-body fetch response", __FUNCTION__); + } + TSHttpParserDestroy(parser); + TSHandleMLocRelease(hdr_buf, nullptr, hdr_loc); + TSMBufferDestroy(hdr_buf); + } else { + TSWarning("[%s] Successful set-custom-body fetch did not result in any content", __FUNCTION__); } TSHttpTxnReenable(http_txn, TS_EVENT_HTTP_ERROR); } break; diff --git a/tests/gold_tests/pluginTest/header_rewrite/gold/header_rewrite-custom_body.gold b/tests/gold_tests/pluginTest/header_rewrite/gold/header_rewrite-custom_body.gold deleted file mode 100644 index 88834255540..00000000000 --- a/tests/gold_tests/pluginTest/header_rewrite/gold/header_rewrite-custom_body.gold +++ /dev/null @@ -1,10 +0,0 @@ -HTTP/1.1 404 Not Found -Date: `` -Proxy-Connection: close -Server: ATS/`` -Content-Length: `` -Content-Type: `` - -Custom body found -`` - diff --git a/tests/gold_tests/pluginTest/header_rewrite/gold/header_rewrite-custom_body_body.gold b/tests/gold_tests/pluginTest/header_rewrite/gold/header_rewrite-custom_body_body.gold new file mode 100644 index 00000000000..3e37495f65b --- /dev/null +++ b/tests/gold_tests/pluginTest/header_rewrite/gold/header_rewrite-custom_body_body.gold @@ -0,0 +1 @@ +Custom body found diff --git a/tests/gold_tests/pluginTest/header_rewrite/gold/header_rewrite-custom_body_headers.gold b/tests/gold_tests/pluginTest/header_rewrite/gold/header_rewrite-custom_body_headers.gold new file mode 100644 index 00000000000..2029a726b80 --- /dev/null +++ b/tests/gold_tests/pluginTest/header_rewrite/gold/header_rewrite-custom_body_headers.gold @@ -0,0 +1,9 @@ +`` +< HTTP/1.1 404 Not Found +< Date: `` +< Proxy-Connection: keep-alive +< Server: ATS/`` +< Content-Length: 18 +< Content-Type: text/html +`` + diff --git a/tests/gold_tests/pluginTest/header_rewrite/header_rewrite_custom_body.test.py b/tests/gold_tests/pluginTest/header_rewrite/header_rewrite_custom_body.test.py index 26d76782041..86233a8e3c9 100644 --- a/tests/gold_tests/pluginTest/header_rewrite/header_rewrite_custom_body.test.py +++ b/tests/gold_tests/pluginTest/header_rewrite/header_rewrite_custom_body.test.py @@ -42,7 +42,7 @@ def setUpTS(self): response_header = { "headers": "HTTP/1.1 404 Not Found\r\nConnection: close\r\n\r\n", "timestamp": "1469733493.993", - "body": "" + "body": "404 Not Found" } self.server.addResponse("sessionfile.log", request_header, response_header) # Request/response for custom body transaction @@ -54,7 +54,7 @@ def setUpTS(self): response_header = { "headers": "HTTP/1.1 200 OK\r\nConnection: close\r\n\r\n", "timestamp": "1469733493.993", - "body": "Custom body found" + "body": "Custom body found\n" } self.server.addResponse("sessionfile.log", request_header, response_header) @@ -73,13 +73,14 @@ def setUpTS(self): def runTraffic(self): tr = Test.AddTestRun() tr.Processes.Default.Command = ( - 'curl --proxy 127.0.0.1:{0} "http://www.example.com/test" -H "Proxy-Connection: keep-alive" -verbose -silent'.format( - self.ts.Variables.port)) + 'curl -s -v --proxy 127.0.0.1:{0} "http://www.example.com/test"'.format(self.ts.Variables.port)) tr.Processes.Default.ReturnCode = 0 - tr.Processes.Default.StartBefore(self.server, ready=When.PortOpen(self.server.Variables.Port)) - tr.Processes.Default.StartBefore(Test.Processes.ts) - tr.Processes.Default.Streams.stdout = "gold/header_rewrite-custom_body.gold" + tr.Processes.Default.StartBefore(self.server) + tr.Processes.Default.StartBefore(self.ts) + tr.Processes.Default.Streams.stderr = "gold/header_rewrite-custom_body_headers.gold" + tr.Processes.Default.Streams.stdout = "gold/header_rewrite-custom_body_body.gold" tr.StillRunningAfter = self.server + self.ts.Disk.traffic_out.Content = "gold/header_rewrite-tag.gold" def run(self): From 49c65f0215c9762eff9847732102beba25f75ad3 Mon Sep 17 00:00:00 2001 From: Jasmine Emanouel Date: Fri, 21 Jun 2024 15:00:56 +1000 Subject: [PATCH 03/11] Remove debug check due to known issue (cherry picked from commit 964b12cc21a9a7c3f9d3fd50286e4cd2d2757bcc) --- .../header_rewrite/header_rewrite_custom_body.test.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/gold_tests/pluginTest/header_rewrite/header_rewrite_custom_body.test.py b/tests/gold_tests/pluginTest/header_rewrite/header_rewrite_custom_body.test.py index 86233a8e3c9..889bde7217e 100644 --- a/tests/gold_tests/pluginTest/header_rewrite/header_rewrite_custom_body.test.py +++ b/tests/gold_tests/pluginTest/header_rewrite/header_rewrite_custom_body.test.py @@ -81,8 +81,6 @@ def runTraffic(self): tr.Processes.Default.Streams.stdout = "gold/header_rewrite-custom_body_body.gold" tr.StillRunningAfter = self.server - self.ts.Disk.traffic_out.Content = "gold/header_rewrite-tag.gold" - def run(self): self.runTraffic() From fbb05370be7072994fc409ae6dd845c97620280f Mon Sep 17 00:00:00 2001 From: Jasmine Emanouel Date: Mon, 24 Jun 2024 15:28:22 +1000 Subject: [PATCH 04/11] Fix formatting Remove whitespaces doc formatting fix Doc formatting fix --- doc/admin-guide/plugins/header_rewrite.en.rst | 17 +++++++++-------- .../header_rewrite-custom_body_headers.gold | 1 - .../rules/rule_set_custom_body.conf | 2 +- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/doc/admin-guide/plugins/header_rewrite.en.rst b/doc/admin-guide/plugins/header_rewrite.en.rst index 2c662630c04..4b789334d25 100644 --- a/doc/admin-guide/plugins/header_rewrite.en.rst +++ b/doc/admin-guide/plugins/header_rewrite.en.rst @@ -705,28 +705,29 @@ Sets the body to ````. Can also be used to delete a body with ``""``. This intercepting/pre-empting a request so that you can override the body from the body-factory with your own. set-custom-body -~~~~~~~~ +~~~~~~~~~~~~~~~~ :: set-custom-body -Will call ```` (see URL in `URL Parts`_) to retrieve a custom error response -and set the body with the result. Triggering this rule on a OK transaction will -send a 500 status code to the client with the desired response. If this is triggered +Will call ```` (see URL in `URL Parts`_) to retrieve a custom error response +and set the body with the result. Triggering this rule on a OK transaction will +send a 500 status code to the client with the desired response. If this is triggered on any error status codes, that original status code will be sent to the client. An example config would look like - cond %{READ_RESPONSE_HDR_HOOK} + + cond %{READ_RESPONSE_HDR_HOOK} set-custom-body http://www.example.com/second -Where ``http://www.example.com/second`` is the destination to retrieve the custom response from. -This can be enabled per-mapping or globally. +Where ``http://www.example.com/second`` is the destination to retrieve the custom response from. +This can be enabled per-mapping or globally. Ensure there is a remap rule for the second endpoint aswell! An example remap config would look like + map /first http://www.example.com/first @plugin=header_rewrite.so @pparam=cond1.conf map /second http://www.example.com/second - set-config ~~~~~~~~~~ :: diff --git a/tests/gold_tests/pluginTest/header_rewrite/gold/header_rewrite-custom_body_headers.gold b/tests/gold_tests/pluginTest/header_rewrite/gold/header_rewrite-custom_body_headers.gold index 2029a726b80..90ae8988f87 100644 --- a/tests/gold_tests/pluginTest/header_rewrite/gold/header_rewrite-custom_body_headers.gold +++ b/tests/gold_tests/pluginTest/header_rewrite/gold/header_rewrite-custom_body_headers.gold @@ -6,4 +6,3 @@ < Content-Length: 18 < Content-Type: text/html `` - diff --git a/tests/gold_tests/pluginTest/header_rewrite/rules/rule_set_custom_body.conf b/tests/gold_tests/pluginTest/header_rewrite/rules/rule_set_custom_body.conf index d2aac8fcdba..3fc5de4c067 100644 --- a/tests/gold_tests/pluginTest/header_rewrite/rules/rule_set_custom_body.conf +++ b/tests/gold_tests/pluginTest/header_rewrite/rules/rule_set_custom_body.conf @@ -14,5 +14,5 @@ # 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. -cond %{READ_RESPONSE_HDR_HOOK} +cond %{READ_RESPONSE_HDR_HOOK} set-custom-body http://www.example.com/404 From 2e7f7b3cab728316a0762a3dc88967d070cff4c5 Mon Sep 17 00:00:00 2001 From: Jasmine Emanouel Date: Tue, 25 Jun 2024 11:23:45 +1000 Subject: [PATCH 05/11] Rename to set-body-from --- doc/admin-guide/plugins/header_rewrite.en.rst | 8 ++++---- plugins/header_rewrite/factory.cc | 4 ++-- plugins/header_rewrite/operators.cc | 12 +++++------ plugins/header_rewrite/operators.h | 8 ++++---- ...=> header_rewrite-set_body_from_body.gold} | 0 ...header_rewrite-set_body_from_headers.gold} | 0 ...y => header_rewrite_set_body_from.test.py} | 20 ++++++++----------- ...stom_body.conf => rule_set_body_from.conf} | 2 +- 8 files changed, 25 insertions(+), 29 deletions(-) rename tests/gold_tests/pluginTest/header_rewrite/gold/{header_rewrite-custom_body_body.gold => header_rewrite-set_body_from_body.gold} (100%) rename tests/gold_tests/pluginTest/header_rewrite/gold/{header_rewrite-custom_body_headers.gold => header_rewrite-set_body_from_headers.gold} (100%) rename tests/gold_tests/pluginTest/header_rewrite/{header_rewrite_custom_body.test.py => header_rewrite_set_body_from.test.py} (84%) rename tests/gold_tests/pluginTest/header_rewrite/rules/{rule_set_custom_body.conf => rule_set_body_from.conf} (95%) diff --git a/doc/admin-guide/plugins/header_rewrite.en.rst b/doc/admin-guide/plugins/header_rewrite.en.rst index 4b789334d25..894fd04e4bb 100644 --- a/doc/admin-guide/plugins/header_rewrite.en.rst +++ b/doc/admin-guide/plugins/header_rewrite.en.rst @@ -704,11 +704,11 @@ set-body Sets the body to ````. Can also be used to delete a body with ``""``. This is only useful when overriding the origin status, i.e. intercepting/pre-empting a request so that you can override the body from the body-factory with your own. -set-custom-body -~~~~~~~~~~~~~~~~ +set-body-from +~~~~~~~~~~~~~ :: - set-custom-body + set-body-from Will call ```` (see URL in `URL Parts`_) to retrieve a custom error response and set the body with the result. Triggering this rule on a OK transaction will @@ -718,7 +718,7 @@ on any error status codes, that original status code will be sent to the client. An example config would look like cond %{READ_RESPONSE_HDR_HOOK} - set-custom-body http://www.example.com/second + set-body-from http://www.example.com/second Where ``http://www.example.com/second`` is the destination to retrieve the custom response from. This can be enabled per-mapping or globally. diff --git a/plugins/header_rewrite/factory.cc b/plugins/header_rewrite/factory.cc index a566af613f1..346265f893f 100644 --- a/plugins/header_rewrite/factory.cc +++ b/plugins/header_rewrite/factory.cc @@ -77,8 +77,8 @@ operator_factory(const std::string &op) o = new OperatorSetHttpCntl(); } else if (op == "run-plugin") { o = new OperatorRunPlugin(); - } else if (op == "set-custom-body") { - o = new OperatorSetCustomBody(); + } else if (op == "set-body-from") { + o = new OperatorSetBodyFrom(); } else { TSError("[%s] Unknown operator: %s", PLUGIN_NAME, op.c_str()); return nullptr; diff --git a/plugins/header_rewrite/operators.cc b/plugins/header_rewrite/operators.cc index 85b96b16217..48177ac8d4e 100644 --- a/plugins/header_rewrite/operators.cc +++ b/plugins/header_rewrite/operators.cc @@ -42,7 +42,7 @@ handleFetchEvents(TSCont cont, TSEvent event, void *edata) TSHttpTxn http_txn = static_cast(TSContDataGet(cont)); switch (static_cast(event)) { - case OperatorSetCustomBody::TS_EVENT_FETCHSM_SUCCESS: { + case OperatorSetBodyFrom::TS_EVENT_FETCHSM_SUCCESS: { TSHttpTxn fetchsm_txn = static_cast(edata); int data_len; const char *data_start = TSFetchRespGet(fetchsm_txn, &data_len); @@ -65,11 +65,11 @@ handleFetchEvents(TSCont cont, TSEvent event, void *edata) } TSHttpTxnReenable(http_txn, TS_EVENT_HTTP_ERROR); } break; - case OperatorSetCustomBody::TS_EVENT_FETCHSM_FAILURE: { + case OperatorSetBodyFrom::TS_EVENT_FETCHSM_FAILURE: { Dbg(pi_dbg_ctl, "OperatorSetBodyCustom: Error getting custom body"); TSHttpTxnReenable(http_txn, TS_EVENT_HTTP_CONTINUE); } break; - case OperatorSetCustomBody::TS_EVENT_FETCHSM_TIMEOUT: { + case OperatorSetBodyFrom::TS_EVENT_FETCHSM_TIMEOUT: { Dbg(pi_dbg_ctl, "OperatorSetBodyCustom: Timeout getting custom body"); TSHttpTxnReenable(http_txn, TS_EVENT_HTTP_CONTINUE); } break; @@ -1307,7 +1307,7 @@ OperatorRunPlugin::exec(const Resources &res) const // OperatorSetBody void -OperatorSetCustomBody::initialize(Parser &p) +OperatorSetBodyFrom::initialize(Parser &p) { Operator::initialize(p); // we want the arg since body only takes one value @@ -1317,13 +1317,13 @@ OperatorSetCustomBody::initialize(Parser &p) } void -OperatorSetCustomBody::initialize_hooks() +OperatorSetBodyFrom::initialize_hooks() { add_allowed_hook(TS_HTTP_READ_RESPONSE_HDR_HOOK); } void -OperatorSetCustomBody::exec(const Resources &res) const +OperatorSetBodyFrom::exec(const Resources &res) const { if (TSHttpTxnIsInternal(res.txnp)) { // If this is triggered by an internal transaction, a infinte loop may occur diff --git a/plugins/header_rewrite/operators.h b/plugins/header_rewrite/operators.h index 73f8bb5d5be..940b67ae684 100644 --- a/plugins/header_rewrite/operators.h +++ b/plugins/header_rewrite/operators.h @@ -479,14 +479,14 @@ class OperatorRunPlugin : public Operator RemapPluginInst *_plugin = nullptr; }; -class OperatorSetCustomBody : public Operator +class OperatorSetBodyFrom : public Operator { public: - OperatorSetCustomBody() { Dbg(pi_dbg_ctl, "Calling CTOR for OperatorSetBodyCustom"); } + OperatorSetBodyFrom() { Dbg(pi_dbg_ctl, "Calling CTOR for OperatorSetBodyCustom"); } // noncopyable - OperatorSetCustomBody(const OperatorSetCustomBody &) = delete; - void operator=(const OperatorSetCustomBody &) = delete; + OperatorSetBodyFrom(const OperatorSetBodyFrom &) = delete; + void operator=(const OperatorSetBodyFrom &) = delete; void initialize(Parser &p) override; diff --git a/tests/gold_tests/pluginTest/header_rewrite/gold/header_rewrite-custom_body_body.gold b/tests/gold_tests/pluginTest/header_rewrite/gold/header_rewrite-set_body_from_body.gold similarity index 100% rename from tests/gold_tests/pluginTest/header_rewrite/gold/header_rewrite-custom_body_body.gold rename to tests/gold_tests/pluginTest/header_rewrite/gold/header_rewrite-set_body_from_body.gold diff --git a/tests/gold_tests/pluginTest/header_rewrite/gold/header_rewrite-custom_body_headers.gold b/tests/gold_tests/pluginTest/header_rewrite/gold/header_rewrite-set_body_from_headers.gold similarity index 100% rename from tests/gold_tests/pluginTest/header_rewrite/gold/header_rewrite-custom_body_headers.gold rename to tests/gold_tests/pluginTest/header_rewrite/gold/header_rewrite-set_body_from_headers.gold diff --git a/tests/gold_tests/pluginTest/header_rewrite/header_rewrite_custom_body.test.py b/tests/gold_tests/pluginTest/header_rewrite/header_rewrite_set_body_from.test.py similarity index 84% rename from tests/gold_tests/pluginTest/header_rewrite/header_rewrite_custom_body.test.py rename to tests/gold_tests/pluginTest/header_rewrite/header_rewrite_set_body_from.test.py index 889bde7217e..8b1c67496c4 100644 --- a/tests/gold_tests/pluginTest/header_rewrite/header_rewrite_custom_body.test.py +++ b/tests/gold_tests/pluginTest/header_rewrite/header_rewrite_set_body_from.test.py @@ -15,13 +15,13 @@ # limitations under the License. Test.Summary = ''' -Test for successful response manipulation using set-custom-body +Test for successful response manipulation using set-body-from ''' Test.ContinueOnFail = True -Test.testName = "CUSTOM_BODY" +Test.testName = "SET_BODY_FROM" -class HeaderRewriteCustomBodyTest: +class HeaderRewriteSetBodyFromTest: def __init__(self): self.setUpOriginServer() @@ -58,14 +58,10 @@ def setUpTS(self): } self.server.addResponse("sessionfile.log", request_header, response_header) - self.ts.Disk.records_config.update({ - 'proxy.config.diags.debug.enabled': 1, - 'proxy.config.diags.debug.tags': 'header.*', - }) # Set header rewrite rules - self.ts.Setup.CopyAs('rules/rule_set_custom_body.conf', Test.RunDirectory) + self.ts.Setup.CopyAs('rules/rule_set_body_from.conf', Test.RunDirectory) self.ts.Disk.remap_config.AddLine( - 'map http://www.example.com/test http://127.0.0.1:{0}/test @plugin=header_rewrite.so @pparam={1}/rule_set_custom_body.conf' + 'map http://www.example.com/test http://127.0.0.1:{0}/test @plugin=header_rewrite.so @pparam={1}/rule_set_body_from.conf' .format(self.server.Variables.Port, Test.RunDirectory)) self.ts.Disk.remap_config.AddLine( 'map http://www.example.com/404 http://127.0.0.1:{0}/404'.format(self.server.Variables.Port)) @@ -77,12 +73,12 @@ def runTraffic(self): tr.Processes.Default.ReturnCode = 0 tr.Processes.Default.StartBefore(self.server) tr.Processes.Default.StartBefore(self.ts) - tr.Processes.Default.Streams.stderr = "gold/header_rewrite-custom_body_headers.gold" - tr.Processes.Default.Streams.stdout = "gold/header_rewrite-custom_body_body.gold" + tr.Processes.Default.Streams.stderr = "gold/header_rewrite-set_body_from_headers.gold" + tr.Processes.Default.Streams.stdout = "gold/header_rewrite-set_body_from_body.gold" tr.StillRunningAfter = self.server def run(self): self.runTraffic() -HeaderRewriteCustomBodyTest().run() +HeaderRewriteSetBodyFromTest().run() diff --git a/tests/gold_tests/pluginTest/header_rewrite/rules/rule_set_custom_body.conf b/tests/gold_tests/pluginTest/header_rewrite/rules/rule_set_body_from.conf similarity index 95% rename from tests/gold_tests/pluginTest/header_rewrite/rules/rule_set_custom_body.conf rename to tests/gold_tests/pluginTest/header_rewrite/rules/rule_set_body_from.conf index 3fc5de4c067..850c72e088f 100644 --- a/tests/gold_tests/pluginTest/header_rewrite/rules/rule_set_custom_body.conf +++ b/tests/gold_tests/pluginTest/header_rewrite/rules/rule_set_body_from.conf @@ -15,4 +15,4 @@ # See the License for the specific language governing permissions and # limitations under the License. cond %{READ_RESPONSE_HDR_HOOK} -set-custom-body http://www.example.com/404 +set-body-from http://www.example.com/404 From 11b095ad0475823b605be8cca31820ef5bfcca2e Mon Sep 17 00:00:00 2001 From: Jasmine Emanouel Date: Wed, 26 Jun 2024 17:05:42 +1000 Subject: [PATCH 06/11] Add test for failed second call --- plugins/header_rewrite/operators.cc | 10 +-- plugins/header_rewrite/operators.h | 2 +- ...eader_rewrite-set_body_from_body_fail.gold | 1 + ...er_rewrite-set_body_from_headers_fail.gold | 8 +++ .../header_rewrite_set_body_from.test.py | 62 ++++++++++--------- .../rules/rule_set_body_from.conf | 5 ++ 6 files changed, 54 insertions(+), 34 deletions(-) create mode 100644 tests/gold_tests/pluginTest/header_rewrite/gold/header_rewrite-set_body_from_body_fail.gold create mode 100644 tests/gold_tests/pluginTest/header_rewrite/gold/header_rewrite-set_body_from_headers_fail.gold diff --git a/plugins/header_rewrite/operators.cc b/plugins/header_rewrite/operators.cc index 48177ac8d4e..5af35dfcb0e 100644 --- a/plugins/header_rewrite/operators.cc +++ b/plugins/header_rewrite/operators.cc @@ -36,7 +36,7 @@ const unsigned int LOCAL_IP_ADDRESS = 0x0100007f; const unsigned int MAX_SIZE = 256; const int LOCAL_PORT = 8080; -static int +int handleFetchEvents(TSCont cont, TSEvent event, void *edata) { TSHttpTxn http_txn = static_cast(TSContDataGet(cont)); @@ -66,11 +66,11 @@ handleFetchEvents(TSCont cont, TSEvent event, void *edata) TSHttpTxnReenable(http_txn, TS_EVENT_HTTP_ERROR); } break; case OperatorSetBodyFrom::TS_EVENT_FETCHSM_FAILURE: { - Dbg(pi_dbg_ctl, "OperatorSetBodyCustom: Error getting custom body"); + Dbg(pi_dbg_ctl, "OperatorSetBodyFrom: Error getting custom body"); TSHttpTxnReenable(http_txn, TS_EVENT_HTTP_CONTINUE); } break; case OperatorSetBodyFrom::TS_EVENT_FETCHSM_TIMEOUT: { - Dbg(pi_dbg_ctl, "OperatorSetBodyCustom: Timeout getting custom body"); + Dbg(pi_dbg_ctl, "OperatorSetBodyFrom: Timeout getting custom body"); TSHttpTxnReenable(http_txn, TS_EVENT_HTTP_CONTINUE); } break; case TS_EVENT_HTTP_TXN_CLOSE: { @@ -1328,7 +1328,7 @@ OperatorSetBodyFrom::exec(const Resources &res) const if (TSHttpTxnIsInternal(res.txnp)) { // If this is triggered by an internal transaction, a infinte loop may occur // It should only be triggered by the original transaction sent by the client - Dbg(pi_dbg_ctl, "OperatorSetCustomBody triggered by an internal transaction"); + Dbg(pi_dbg_ctl, "OperatorSetBodyFrom triggered by an internal transaction"); return; } @@ -1358,6 +1358,6 @@ OperatorSetBodyFrom::exec(const Resources &res) const // Set here because res is the only structure that contains the original status code. TSHttpTxnStatusSet(res.txnp, res.resp_status); } else { - TSError(PLUGIN_NAME, "OperatorSetCustomBody:exec:: Could not create request"); + TSError(PLUGIN_NAME, "OperatorSetBodyFrom:exec:: Could not create request"); } } diff --git a/plugins/header_rewrite/operators.h b/plugins/header_rewrite/operators.h index 940b67ae684..2c4712a67bb 100644 --- a/plugins/header_rewrite/operators.h +++ b/plugins/header_rewrite/operators.h @@ -482,7 +482,7 @@ class OperatorRunPlugin : public Operator class OperatorSetBodyFrom : public Operator { public: - OperatorSetBodyFrom() { Dbg(pi_dbg_ctl, "Calling CTOR for OperatorSetBodyCustom"); } + OperatorSetBodyFrom() { Dbg(pi_dbg_ctl, "Calling CTOR for OperatorSetBodyFrom"); } // noncopyable OperatorSetBodyFrom(const OperatorSetBodyFrom &) = delete; diff --git a/tests/gold_tests/pluginTest/header_rewrite/gold/header_rewrite-set_body_from_body_fail.gold b/tests/gold_tests/pluginTest/header_rewrite/gold/header_rewrite-set_body_from_body_fail.gold new file mode 100644 index 00000000000..7acf375871c --- /dev/null +++ b/tests/gold_tests/pluginTest/header_rewrite/gold/header_rewrite-set_body_from_body_fail.gold @@ -0,0 +1 @@ +Fail diff --git a/tests/gold_tests/pluginTest/header_rewrite/gold/header_rewrite-set_body_from_headers_fail.gold b/tests/gold_tests/pluginTest/header_rewrite/gold/header_rewrite-set_body_from_headers_fail.gold new file mode 100644 index 00000000000..82720c3b94c --- /dev/null +++ b/tests/gold_tests/pluginTest/header_rewrite/gold/header_rewrite-set_body_from_headers_fail.gold @@ -0,0 +1,8 @@ +`` +< HTTP/1.1 404 Not Found +< Date: `` +< Proxy-Connection: keep-alive +< Server: ATS/`` +< Content-Length: 5 +< Content-Type: text/html +`` diff --git a/tests/gold_tests/pluginTest/header_rewrite/header_rewrite_set_body_from.test.py b/tests/gold_tests/pluginTest/header_rewrite/header_rewrite_set_body_from.test.py index 8b1c67496c4..75edfbfa1e5 100644 --- a/tests/gold_tests/pluginTest/header_rewrite/header_rewrite_set_body_from.test.py +++ b/tests/gold_tests/pluginTest/header_rewrite/header_rewrite_set_body_from.test.py @@ -33,46 +33,52 @@ def setUpOriginServer(self): def setUpTS(self): self.ts = Test.MakeATSProcess("ts") - # Request/response for original transaction - request_header = { - "headers": "GET /test HTTP/1.1\r\nHost: www.example.com\r\n\r\n", - "timestamp": "1469733493.993", - "body": "" - } - response_header = { - "headers": "HTTP/1.1 404 Not Found\r\nConnection: close\r\n\r\n", - "timestamp": "1469733493.993", - "body": "404 Not Found" - } - self.server.addResponse("sessionfile.log", request_header, response_header) + # Response for original transaction + response_header = {"headers": "HTTP/1.1 404 Not Found\r\nConnection: close\r\n\r\n", "body": "404 Not Found"} + + # Request/response for original failed transaction + fail_1_request_header = {"headers": "GET /fail HTTP/1.1\r\nHost: www.example.com\r\n\r\n"} + self.server.addResponse("sessionfile.log", fail_1_request_header, response_header) + + # Request/response for custom body transaction + fail_2_request_header = {"headers": "GET /404_fail HTTP/1.1\r\nHost: www.example.com\r\n\r\n"} + fail_2_response_header = {"headers": "HTTP/1.1 502 \r\nConnection: close\r\n\r\n", "body": "Fail\n"} + self.server.addResponse("sessionfile.log", fail_2_request_header, fail_2_response_header) + + # Request/response for original Successful transaction + success_1_request_header = {"headers": "GET /success HTTP/1.1\r\nHost: www.example.com\r\n\r\n"} + self.server.addResponse("sessionfile.log", success_1_request_header, response_header) + # Request/response for custom body transaction - request_header = { - "headers": "GET /404 HTTP/1.1\r\nHost: www.example.com\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": "Custom body found\n" - } - self.server.addResponse("sessionfile.log", request_header, response_header) + success_2_request_header = {"headers": "GET /404 HTTP/1.1\r\nHost: www.example.com\r\n\r\n"} + success_2_response_header = {"headers": "HTTP/1.1 200 OK\r\nConnection: close\r\n\r\n", "body": "Custom body found\n"} + self.server.addResponse("sessionfile.log", success_2_request_header, success_2_response_header) # Set header rewrite rules self.ts.Setup.CopyAs('rules/rule_set_body_from.conf', Test.RunDirectory) self.ts.Disk.remap_config.AddLine( - 'map http://www.example.com/test http://127.0.0.1:{0}/test @plugin=header_rewrite.so @pparam={1}/rule_set_body_from.conf' - .format(self.server.Variables.Port, Test.RunDirectory)) - self.ts.Disk.remap_config.AddLine( - 'map http://www.example.com/404 http://127.0.0.1:{0}/404'.format(self.server.Variables.Port)) + """\ + map http://www.example.com/success http://127.0.0.1:{0}/success @plugin=header_rewrite.so @pparam={1}/rule_set_body_from.conf + map http://www.example.com/fail http://127.0.0.1:{0}/fail @plugin=header_rewrite.so @pparam={1}/rule_set_body_from.conf + map http://www.example.com/404 http://127.0.0.1:{0}/404 + map http://www.example.com/404_fail http://127.0.0.1:{0}/404_fail + """.format(self.server.Variables.Port, Test.RunDirectory)) def runTraffic(self): tr = Test.AddTestRun() tr.Processes.Default.Command = ( - 'curl -s -v --proxy 127.0.0.1:{0} "http://www.example.com/test"'.format(self.ts.Variables.port)) + 'curl -s -v --proxy 127.0.0.1:{0} "http://www.example.com/fail"'.format(self.ts.Variables.port)) tr.Processes.Default.ReturnCode = 0 tr.Processes.Default.StartBefore(self.server) tr.Processes.Default.StartBefore(self.ts) + tr.Processes.Default.Streams.stderr = "gold/header_rewrite-set_body_from_headers_fail.gold" + tr.Processes.Default.Streams.stdout = "gold/header_rewrite-set_body_from_body_fail.gold" + tr.StillRunningAfter = self.server + + tr = Test.AddTestRun() + tr.Processes.Default.Command = ( + 'curl -s -v --proxy 127.0.0.1:{0} "http://www.example.com/success"'.format(self.ts.Variables.port)) + tr.Processes.Default.ReturnCode = 0 tr.Processes.Default.Streams.stderr = "gold/header_rewrite-set_body_from_headers.gold" tr.Processes.Default.Streams.stdout = "gold/header_rewrite-set_body_from_body.gold" tr.StillRunningAfter = self.server diff --git a/tests/gold_tests/pluginTest/header_rewrite/rules/rule_set_body_from.conf b/tests/gold_tests/pluginTest/header_rewrite/rules/rule_set_body_from.conf index 850c72e088f..a02235eca58 100644 --- a/tests/gold_tests/pluginTest/header_rewrite/rules/rule_set_body_from.conf +++ b/tests/gold_tests/pluginTest/header_rewrite/rules/rule_set_body_from.conf @@ -15,4 +15,9 @@ # See the License for the specific language governing permissions and # limitations under the License. cond %{READ_RESPONSE_HDR_HOOK} +cond %{CLIENT-URL:PATH} = "success" set-body-from http://www.example.com/404 + +cond %{READ_RESPONSE_HDR_HOOK} +cond %{CLIENT-URL:PATH} = "fail" +set-body-from http://www.example.com/404_fail From e71943ae461202930707d4ab5d823b78c557dcb7 Mon Sep 17 00:00:00 2001 From: Jasmine Emanouel Date: Thu, 27 Jun 2024 10:23:45 +1000 Subject: [PATCH 07/11] Add more test cases --- doc/admin-guide/plugins/header_rewrite.en.rst | 6 +- plugins/header_rewrite/operators.cc | 2 +- .../header_rewrite-set_body_from_200.gold | 9 ++ .../header_rewrite-set_body_from_body.gold | 1 - ...eader_rewrite-set_body_from_body_fail.gold | 1 - ...=> header_rewrite-set_body_from_fail.gold} | 1 + ...header_rewrite-set_body_from_success.gold} | 0 .../header_rewrite_set_body_from.test.py | 122 ++++++++++++++---- ...om.conf => rule_set_body_from_plugin.conf} | 8 +- .../rules/rule_set_body_from_remap.conf | 24 ++++ 10 files changed, 137 insertions(+), 37 deletions(-) create mode 100644 tests/gold_tests/pluginTest/header_rewrite/gold/header_rewrite-set_body_from_200.gold delete mode 100644 tests/gold_tests/pluginTest/header_rewrite/gold/header_rewrite-set_body_from_body.gold delete mode 100644 tests/gold_tests/pluginTest/header_rewrite/gold/header_rewrite-set_body_from_body_fail.gold rename tests/gold_tests/pluginTest/header_rewrite/gold/{header_rewrite-set_body_from_headers_fail.gold => header_rewrite-set_body_from_fail.gold} (96%) rename tests/gold_tests/pluginTest/header_rewrite/gold/{header_rewrite-set_body_from_headers.gold => header_rewrite-set_body_from_success.gold} (100%) rename tests/gold_tests/pluginTest/header_rewrite/rules/{rule_set_body_from.conf => rule_set_body_from_plugin.conf} (82%) create mode 100644 tests/gold_tests/pluginTest/header_rewrite/rules/rule_set_body_from_remap.conf diff --git a/doc/admin-guide/plugins/header_rewrite.en.rst b/doc/admin-guide/plugins/header_rewrite.en.rst index 894fd04e4bb..18b65b1f2a3 100644 --- a/doc/admin-guide/plugins/header_rewrite.en.rst +++ b/doc/admin-guide/plugins/header_rewrite.en.rst @@ -711,9 +711,9 @@ set-body-from set-body-from Will call ```` (see URL in `URL Parts`_) to retrieve a custom error response -and set the body with the result. Triggering this rule on a OK transaction will +and set the body with the result. Triggering this rule on an OK transaction will send a 500 status code to the client with the desired response. If this is triggered -on any error status codes, that original status code will be sent to the client. +on any error status code, that original status code will be sent to the client. An example config would look like @@ -722,7 +722,7 @@ An example config would look like Where ``http://www.example.com/second`` is the destination to retrieve the custom response from. This can be enabled per-mapping or globally. -Ensure there is a remap rule for the second endpoint aswell! +Ensure there is a remap rule for the second endpoint as well! An example remap config would look like map /first http://www.example.com/first @plugin=header_rewrite.so @pparam=cond1.conf diff --git a/plugins/header_rewrite/operators.cc b/plugins/header_rewrite/operators.cc index 5af35dfcb0e..5bd4ddd25a0 100644 --- a/plugins/header_rewrite/operators.cc +++ b/plugins/header_rewrite/operators.cc @@ -82,7 +82,7 @@ handleFetchEvents(TSCont cont, TSEvent event, void *edata) // The transaction is reenabled with the FetchSM transaction break; default: - TSWarning("Warning: handleFetchEvents got unknown event: %d", event); + TSError("Warning: handleFetchEvents got unknown event: %d", event); break; } return 0; diff --git a/tests/gold_tests/pluginTest/header_rewrite/gold/header_rewrite-set_body_from_200.gold b/tests/gold_tests/pluginTest/header_rewrite/gold/header_rewrite-set_body_from_200.gold new file mode 100644 index 00000000000..612e8117c57 --- /dev/null +++ b/tests/gold_tests/pluginTest/header_rewrite/gold/header_rewrite-set_body_from_200.gold @@ -0,0 +1,9 @@ +`` +< HTTP/1.1 500 INKApi Error +< Date: `` +< Proxy-Connection: keep-alive +< Server: ATS/`` +< Content-Length: 18 +< Content-Type: text/html +`` +Custom body found diff --git a/tests/gold_tests/pluginTest/header_rewrite/gold/header_rewrite-set_body_from_body.gold b/tests/gold_tests/pluginTest/header_rewrite/gold/header_rewrite-set_body_from_body.gold deleted file mode 100644 index 3e37495f65b..00000000000 --- a/tests/gold_tests/pluginTest/header_rewrite/gold/header_rewrite-set_body_from_body.gold +++ /dev/null @@ -1 +0,0 @@ -Custom body found diff --git a/tests/gold_tests/pluginTest/header_rewrite/gold/header_rewrite-set_body_from_body_fail.gold b/tests/gold_tests/pluginTest/header_rewrite/gold/header_rewrite-set_body_from_body_fail.gold deleted file mode 100644 index 7acf375871c..00000000000 --- a/tests/gold_tests/pluginTest/header_rewrite/gold/header_rewrite-set_body_from_body_fail.gold +++ /dev/null @@ -1 +0,0 @@ -Fail diff --git a/tests/gold_tests/pluginTest/header_rewrite/gold/header_rewrite-set_body_from_headers_fail.gold b/tests/gold_tests/pluginTest/header_rewrite/gold/header_rewrite-set_body_from_fail.gold similarity index 96% rename from tests/gold_tests/pluginTest/header_rewrite/gold/header_rewrite-set_body_from_headers_fail.gold rename to tests/gold_tests/pluginTest/header_rewrite/gold/header_rewrite-set_body_from_fail.gold index 82720c3b94c..4a37a9d00fd 100644 --- a/tests/gold_tests/pluginTest/header_rewrite/gold/header_rewrite-set_body_from_headers_fail.gold +++ b/tests/gold_tests/pluginTest/header_rewrite/gold/header_rewrite-set_body_from_fail.gold @@ -6,3 +6,4 @@ < Content-Length: 5 < Content-Type: text/html `` +Fail diff --git a/tests/gold_tests/pluginTest/header_rewrite/gold/header_rewrite-set_body_from_headers.gold b/tests/gold_tests/pluginTest/header_rewrite/gold/header_rewrite-set_body_from_success.gold similarity index 100% rename from tests/gold_tests/pluginTest/header_rewrite/gold/header_rewrite-set_body_from_headers.gold rename to tests/gold_tests/pluginTest/header_rewrite/gold/header_rewrite-set_body_from_success.gold diff --git a/tests/gold_tests/pluginTest/header_rewrite/header_rewrite_set_body_from.test.py b/tests/gold_tests/pluginTest/header_rewrite/header_rewrite_set_body_from.test.py index 75edfbfa1e5..ba4d7cb4750 100644 --- a/tests/gold_tests/pluginTest/header_rewrite/header_rewrite_set_body_from.test.py +++ b/tests/gold_tests/pluginTest/header_rewrite/header_rewrite_set_body_from.test.py @@ -18,7 +18,6 @@ Test for successful response manipulation using set-body-from ''' Test.ContinueOnFail = True -Test.testName = "SET_BODY_FROM" class HeaderRewriteSetBodyFromTest: @@ -30,59 +29,128 @@ def __init__(self): def setUpOriginServer(self): self.server = Test.MakeOriginServer("server") - def setUpTS(self): - self.ts = Test.MakeATSProcess("ts") - # Response for original transaction response_header = {"headers": "HTTP/1.1 404 Not Found\r\nConnection: close\r\n\r\n", "body": "404 Not Found"} - # Request/response for original failed transaction - fail_1_request_header = {"headers": "GET /fail HTTP/1.1\r\nHost: www.example.com\r\n\r\n"} - self.server.addResponse("sessionfile.log", fail_1_request_header, response_header) + # Request/response for original transaction where transaction returns a 200 status code + remap_success_request_header = {"headers": "GET /200 HTTP/1.1\r\nHost: www.example.com\r\n\r\n"} + ooo = {"headers": "HTTP/1.1 200 OK\r\nConnection: close\r\n\r\n", "body": "200 OK"} + + self.server.addResponse("sessionfile.log", remap_success_request_header, ooo) + + # Request/response for original transaction with failed second tranasaction + remap_fail_1_request_header = {"headers": "GET /remap_fail HTTP/1.1\r\nHost: www.example.com\r\n\r\n"} + self.server.addResponse("sessionfile.log", remap_fail_1_request_header, response_header) + + plugin_fail_1_request_header = {"headers": "GET /plugin_fail HTTP/1.1\r\nHost: www.example.com\r\n\r\n"} + self.server.addResponse("sessionfile.log", plugin_fail_1_request_header, response_header) + + # Request/response for original successful transaction with successful second tranasaction + remap_success_1_request_header = {"headers": "GET /remap_success HTTP/1.1\r\nHost: www.example.com\r\n\r\n"} + self.server.addResponse("sessionfile.log", remap_success_1_request_header, response_header) + + plugin_success_1_request_header = {"headers": "GET /plugin_success HTTP/1.1\r\nHost: www.example.com\r\n\r\n"} + self.server.addResponse("sessionfile.log", plugin_success_1_request_header, response_header) - # Request/response for custom body transaction - fail_2_request_header = {"headers": "GET /404_fail HTTP/1.1\r\nHost: www.example.com\r\n\r\n"} + # Request/response for custom body transaction that fails to retrieve body + fail_2_request_header = {"headers": "GET /502.html HTTP/1.1\r\nHost: www.example.com\r\n\r\n"} fail_2_response_header = {"headers": "HTTP/1.1 502 \r\nConnection: close\r\n\r\n", "body": "Fail\n"} self.server.addResponse("sessionfile.log", fail_2_request_header, fail_2_response_header) - # Request/response for original Successful transaction - success_1_request_header = {"headers": "GET /success HTTP/1.1\r\nHost: www.example.com\r\n\r\n"} - self.server.addResponse("sessionfile.log", success_1_request_header, response_header) - - # Request/response for custom body transaction - success_2_request_header = {"headers": "GET /404 HTTP/1.1\r\nHost: www.example.com\r\n\r\n"} + # Request/response for custom body transaction that successfully retrieves body + success_2_request_header = {"headers": "GET /404.html HTTP/1.1\r\nHost: www.example.com\r\n\r\n"} success_2_response_header = {"headers": "HTTP/1.1 200 OK\r\nConnection: close\r\n\r\n", "body": "Custom body found\n"} self.server.addResponse("sessionfile.log", success_2_request_header, success_2_response_header) + def setUpTS(self): + self.ts = Test.MakeATSProcess("ts") + # Set header rewrite rules - self.ts.Setup.CopyAs('rules/rule_set_body_from.conf', Test.RunDirectory) + self.ts.Setup.CopyAs('rules/rule_set_body_from_remap.conf', Test.RunDirectory) + self.ts.Setup.CopyAs('rules/rule_set_body_from_plugin.conf', Test.RunDirectory) self.ts.Disk.remap_config.AddLine( """\ - map http://www.example.com/success http://127.0.0.1:{0}/success @plugin=header_rewrite.so @pparam={1}/rule_set_body_from.conf - map http://www.example.com/fail http://127.0.0.1:{0}/fail @plugin=header_rewrite.so @pparam={1}/rule_set_body_from.conf - map http://www.example.com/404 http://127.0.0.1:{0}/404 - map http://www.example.com/404_fail http://127.0.0.1:{0}/404_fail + map http://www.example.com/remap_success http://127.0.0.1:{0}/remap_success @plugin=header_rewrite.so @pparam={1}/rule_set_body_from_remap.conf + map http://www.example.com/200 http://127.0.0.1:{0}/200 @plugin=header_rewrite.so @pparam={1}/rule_set_body_from_remap.conf + map http://www.example.com/remap_fail http://127.0.0.1:{0}/remap_fail @plugin=header_rewrite.so @pparam={1}/rule_set_body_from_remap.conf + map http://www.example.com/plugin_success http://127.0.0.1:{0}/plugin_success + map http://www.example.com/plugin_fail http://127.0.0.1:{0}/plugin_fail + map http://www.example.com/404.html http://127.0.0.1:{0}/404.html + map http://www.example.com/502.html http://127.0.0.1:{0}/502.html """.format(self.server.Variables.Port, Test.RunDirectory)) + self.ts.Disk.plugin_config.AddLine('header_rewrite.so {0}/rule_set_body_from_plugin.conf'.format(Test.RunDirectory)) - def runTraffic(self): + def test_setBodyFromFails_remap(self): + ''' + Test where set-body-from request fails + Triggered from remap file + ''' tr = Test.AddTestRun() tr.Processes.Default.Command = ( - 'curl -s -v --proxy 127.0.0.1:{0} "http://www.example.com/fail"'.format(self.ts.Variables.port)) + 'curl -s -v --proxy 127.0.0.1:{0} "http://www.example.com/remap_fail"'.format(self.ts.Variables.port)) tr.Processes.Default.ReturnCode = 0 tr.Processes.Default.StartBefore(self.server) tr.Processes.Default.StartBefore(self.ts) - tr.Processes.Default.Streams.stderr = "gold/header_rewrite-set_body_from_headers_fail.gold" - tr.Processes.Default.Streams.stdout = "gold/header_rewrite-set_body_from_body_fail.gold" + tr.Processes.Default.Streams.All = "gold/header_rewrite-set_body_from_fail.gold" + tr.StillRunningAfter = self.server + + def test_setBodyFromSucceeds_remap(self): + ''' + Test where set-body-from request succeeds + Triggered from remap file + ''' + tr = Test.AddTestRun() + tr.Processes.Default.Command = ( + 'curl -s -v --proxy 127.0.0.1:{0} "http://www.example.com/remap_success"'.format(self.ts.Variables.port)) + tr.Processes.Default.ReturnCode = 0 + tr.Processes.Default.Streams.All = "gold/header_rewrite-set_body_from_success.gold" + tr.StillRunningAfter = self.server + + def test_setBodyFromSucceeds_plugin(self): + ''' + Test where set-body-from request succeeds + Triggered from plugin file + ''' + tr = Test.AddTestRun() + tr.Processes.Default.Command = ( + 'curl -s -v --proxy 127.0.0.1:{0} "http://www.example.com/plugin_success"'.format(self.ts.Variables.port)) + tr.Processes.Default.ReturnCode = 0 + tr.Processes.Default.Streams.All = "gold/header_rewrite-set_body_from_success.gold" tr.StillRunningAfter = self.server + def test_setBodyFromFails_plugin(self): + ''' + Test where set-body-from request fails + Triggered from plugin file + ''' tr = Test.AddTestRun() tr.Processes.Default.Command = ( - 'curl -s -v --proxy 127.0.0.1:{0} "http://www.example.com/success"'.format(self.ts.Variables.port)) + 'curl -s -v --proxy 127.0.0.1:{0} "http://www.example.com/plugin_fail"'.format(self.ts.Variables.port)) tr.Processes.Default.ReturnCode = 0 - tr.Processes.Default.Streams.stderr = "gold/header_rewrite-set_body_from_headers.gold" - tr.Processes.Default.Streams.stdout = "gold/header_rewrite-set_body_from_body.gold" + tr.Processes.Default.Streams.All = "gold/header_rewrite-set_body_from_fail.gold" tr.StillRunningAfter = self.server + def test_setBodyFromSucceeds_200(self): + ''' + Test where set-body-from request succeeds and returns 200 OK + Triggered from remap file + This is tested because right now, TSHttpTxnErrorBodySet will change OK status codes to 500 INKApi Error + Ideally, this would not occur. + ''' + tr = Test.AddTestRun() + tr.Processes.Default.Command = ( + 'curl -s -v --proxy 127.0.0.1:{0} "http://www.example.com/200"'.format(self.ts.Variables.port)) + tr.Processes.Default.ReturnCode = 0 + tr.Processes.Default.Streams.All = "gold/header_rewrite-set_body_from_200.gold" + tr.StillRunningAfter = self.server + + def runTraffic(self): + self.test_setBodyFromFails_remap() + self.test_setBodyFromSucceeds_remap() + self.test_setBodyFromSucceeds_plugin() + self.test_setBodyFromFails_plugin() + self.test_setBodyFromSucceeds_200() + def run(self): self.runTraffic() diff --git a/tests/gold_tests/pluginTest/header_rewrite/rules/rule_set_body_from.conf b/tests/gold_tests/pluginTest/header_rewrite/rules/rule_set_body_from_plugin.conf similarity index 82% rename from tests/gold_tests/pluginTest/header_rewrite/rules/rule_set_body_from.conf rename to tests/gold_tests/pluginTest/header_rewrite/rules/rule_set_body_from_plugin.conf index a02235eca58..2ebb62dd0ec 100644 --- a/tests/gold_tests/pluginTest/header_rewrite/rules/rule_set_body_from.conf +++ b/tests/gold_tests/pluginTest/header_rewrite/rules/rule_set_body_from_plugin.conf @@ -15,9 +15,9 @@ # See the License for the specific language governing permissions and # limitations under the License. cond %{READ_RESPONSE_HDR_HOOK} -cond %{CLIENT-URL:PATH} = "success" -set-body-from http://www.example.com/404 +cond %{CLIENT-URL:PATH} = "plugin_success" +set-body-from http://www.example.com/404.html cond %{READ_RESPONSE_HDR_HOOK} -cond %{CLIENT-URL:PATH} = "fail" -set-body-from http://www.example.com/404_fail +cond %{CLIENT-URL:PATH} = "plugin_fail" +set-body-from http://www.example.com/502.html diff --git a/tests/gold_tests/pluginTest/header_rewrite/rules/rule_set_body_from_remap.conf b/tests/gold_tests/pluginTest/header_rewrite/rules/rule_set_body_from_remap.conf new file mode 100644 index 00000000000..f6bff020910 --- /dev/null +++ b/tests/gold_tests/pluginTest/header_rewrite/rules/rule_set_body_from_remap.conf @@ -0,0 +1,24 @@ +# +# 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. +cond %{READ_RESPONSE_HDR_HOOK} +cond %{CLIENT-URL:PATH} = "remap_success" [OR] +cond %{CLIENT-URL:PATH} = "200" +set-body-from http://www.example.com/404.html + +cond %{READ_RESPONSE_HDR_HOOK} +cond %{CLIENT-URL:PATH} = "remap_fail" +set-body-from http://www.example.com/502.html From dd1ceec75ab098fb80da7f1163ded16877375f98 Mon Sep 17 00:00:00 2001 From: Jasmine Emanouel Date: Thu, 27 Jun 2024 11:07:33 +1000 Subject: [PATCH 08/11] Clarify test cases --- .../header_rewrite-set_body_from_200.gold | 1 + ...ader_rewrite-set_body_from_conn_fail.gold} | 0 ...ader_rewrite-set_body_from_remap_fail.gold | 23 +++++++++++++++++++ .../header_rewrite_set_body_from.test.py | 10 ++++---- .../rules/rule_set_body_from_plugin.conf | 2 +- .../rules/rule_set_body_from_remap.conf | 2 +- 6 files changed, 32 insertions(+), 6 deletions(-) rename tests/gold_tests/pluginTest/header_rewrite/gold/{header_rewrite-set_body_from_fail.gold => header_rewrite-set_body_from_conn_fail.gold} (100%) create mode 100644 tests/gold_tests/pluginTest/header_rewrite/gold/header_rewrite-set_body_from_remap_fail.gold diff --git a/tests/gold_tests/pluginTest/header_rewrite/gold/header_rewrite-set_body_from_200.gold b/tests/gold_tests/pluginTest/header_rewrite/gold/header_rewrite-set_body_from_200.gold index 612e8117c57..90c34b6eb54 100644 --- a/tests/gold_tests/pluginTest/header_rewrite/gold/header_rewrite-set_body_from_200.gold +++ b/tests/gold_tests/pluginTest/header_rewrite/gold/header_rewrite-set_body_from_200.gold @@ -7,3 +7,4 @@ < Content-Type: text/html `` Custom body found +`` diff --git a/tests/gold_tests/pluginTest/header_rewrite/gold/header_rewrite-set_body_from_fail.gold b/tests/gold_tests/pluginTest/header_rewrite/gold/header_rewrite-set_body_from_conn_fail.gold similarity index 100% rename from tests/gold_tests/pluginTest/header_rewrite/gold/header_rewrite-set_body_from_fail.gold rename to tests/gold_tests/pluginTest/header_rewrite/gold/header_rewrite-set_body_from_conn_fail.gold diff --git a/tests/gold_tests/pluginTest/header_rewrite/gold/header_rewrite-set_body_from_remap_fail.gold b/tests/gold_tests/pluginTest/header_rewrite/gold/header_rewrite-set_body_from_remap_fail.gold new file mode 100644 index 00000000000..572287d1b33 --- /dev/null +++ b/tests/gold_tests/pluginTest/header_rewrite/gold/header_rewrite-set_body_from_remap_fail.gold @@ -0,0 +1,23 @@ +`` +< HTTP/1.1 404 Not Found +< Date: `` +< Proxy-Connection: keep-alive +< Server: ATS/`` +< Content-Length: 297 +< Content-Type: text/html +`` + + +Not Found on Accelerator + + + +

Not Found on Accelerator

+
+ + +Description: Your request on the specified host was not found. +Check the location and try again. + +
+ diff --git a/tests/gold_tests/pluginTest/header_rewrite/header_rewrite_set_body_from.test.py b/tests/gold_tests/pluginTest/header_rewrite/header_rewrite_set_body_from.test.py index ba4d7cb4750..3a43ab1c25f 100644 --- a/tests/gold_tests/pluginTest/header_rewrite/header_rewrite_set_body_from.test.py +++ b/tests/gold_tests/pluginTest/header_rewrite/header_rewrite_set_body_from.test.py @@ -53,7 +53,7 @@ def setUpOriginServer(self): self.server.addResponse("sessionfile.log", plugin_success_1_request_header, response_header) # Request/response for custom body transaction that fails to retrieve body - fail_2_request_header = {"headers": "GET /502.html HTTP/1.1\r\nHost: www.example.com\r\n\r\n"} + fail_2_request_header = {"headers": "GET /502 HTTP/1.1\r\nHost: www.example.com\r\n\r\n"} fail_2_response_header = {"headers": "HTTP/1.1 502 \r\nConnection: close\r\n\r\n", "body": "Fail\n"} self.server.addResponse("sessionfile.log", fail_2_request_header, fail_2_response_header) @@ -76,7 +76,7 @@ def setUpTS(self): map http://www.example.com/plugin_success http://127.0.0.1:{0}/plugin_success map http://www.example.com/plugin_fail http://127.0.0.1:{0}/plugin_fail map http://www.example.com/404.html http://127.0.0.1:{0}/404.html - map http://www.example.com/502.html http://127.0.0.1:{0}/502.html + map http://www.example.com/502 http://127.0.0.1:{0}/502 """.format(self.server.Variables.Port, Test.RunDirectory)) self.ts.Disk.plugin_config.AddLine('header_rewrite.so {0}/rule_set_body_from_plugin.conf'.format(Test.RunDirectory)) @@ -84,6 +84,7 @@ def test_setBodyFromFails_remap(self): ''' Test where set-body-from request fails Triggered from remap file + This uses the case where no remap rule is provided ''' tr = Test.AddTestRun() tr.Processes.Default.Command = ( @@ -91,7 +92,7 @@ def test_setBodyFromFails_remap(self): tr.Processes.Default.ReturnCode = 0 tr.Processes.Default.StartBefore(self.server) tr.Processes.Default.StartBefore(self.ts) - tr.Processes.Default.Streams.All = "gold/header_rewrite-set_body_from_fail.gold" + tr.Processes.Default.Streams.All = "gold/header_rewrite-set_body_from_remap_fail.gold" tr.StillRunningAfter = self.server def test_setBodyFromSucceeds_remap(self): @@ -121,13 +122,14 @@ def test_setBodyFromSucceeds_plugin(self): def test_setBodyFromFails_plugin(self): ''' Test where set-body-from request fails + This uses the case where the second endpoint cannot connect to the requested server Triggered from plugin file ''' tr = Test.AddTestRun() tr.Processes.Default.Command = ( 'curl -s -v --proxy 127.0.0.1:{0} "http://www.example.com/plugin_fail"'.format(self.ts.Variables.port)) tr.Processes.Default.ReturnCode = 0 - tr.Processes.Default.Streams.All = "gold/header_rewrite-set_body_from_fail.gold" + tr.Processes.Default.Streams.All = "gold/header_rewrite-set_body_from_conn_fail.gold" tr.StillRunningAfter = self.server def test_setBodyFromSucceeds_200(self): diff --git a/tests/gold_tests/pluginTest/header_rewrite/rules/rule_set_body_from_plugin.conf b/tests/gold_tests/pluginTest/header_rewrite/rules/rule_set_body_from_plugin.conf index 2ebb62dd0ec..f12ba2a5a92 100644 --- a/tests/gold_tests/pluginTest/header_rewrite/rules/rule_set_body_from_plugin.conf +++ b/tests/gold_tests/pluginTest/header_rewrite/rules/rule_set_body_from_plugin.conf @@ -20,4 +20,4 @@ set-body-from http://www.example.com/404.html cond %{READ_RESPONSE_HDR_HOOK} cond %{CLIENT-URL:PATH} = "plugin_fail" -set-body-from http://www.example.com/502.html +set-body-from http://www.example.com/502 diff --git a/tests/gold_tests/pluginTest/header_rewrite/rules/rule_set_body_from_remap.conf b/tests/gold_tests/pluginTest/header_rewrite/rules/rule_set_body_from_remap.conf index f6bff020910..351e17f7b8d 100644 --- a/tests/gold_tests/pluginTest/header_rewrite/rules/rule_set_body_from_remap.conf +++ b/tests/gold_tests/pluginTest/header_rewrite/rules/rule_set_body_from_remap.conf @@ -21,4 +21,4 @@ set-body-from http://www.example.com/404.html cond %{READ_RESPONSE_HDR_HOOK} cond %{CLIENT-URL:PATH} = "remap_fail" -set-body-from http://www.example.com/502.html +set-body-from http://www.example.com/fail From 22855243feb665e75c1256b63a010a67615701e9 Mon Sep 17 00:00:00 2001 From: Jasmine Emanouel Date: Thu, 27 Jun 2024 14:00:32 +1000 Subject: [PATCH 09/11] Update tests --- plugins/header_rewrite/operators.cc | 2 +- ...eader_rewrite-set_body_from_conn_fail.gold | 20 +++++++++++++++++-- .../header_rewrite_set_body_from.test.py | 10 +++------- .../rules/rule_set_body_from_plugin.conf | 5 ++++- 4 files changed, 26 insertions(+), 11 deletions(-) diff --git a/plugins/header_rewrite/operators.cc b/plugins/header_rewrite/operators.cc index 5bd4ddd25a0..0bb87f89c32 100644 --- a/plugins/header_rewrite/operators.cc +++ b/plugins/header_rewrite/operators.cc @@ -82,7 +82,7 @@ handleFetchEvents(TSCont cont, TSEvent event, void *edata) // The transaction is reenabled with the FetchSM transaction break; default: - TSError("Warning: handleFetchEvents got unknown event: %d", event); + TSError("[%s] handleFetchEvents got unknown event: %d", PLUGIN_NAME, event); break; } return 0; diff --git a/tests/gold_tests/pluginTest/header_rewrite/gold/header_rewrite-set_body_from_conn_fail.gold b/tests/gold_tests/pluginTest/header_rewrite/gold/header_rewrite-set_body_from_conn_fail.gold index 4a37a9d00fd..d98797800dd 100644 --- a/tests/gold_tests/pluginTest/header_rewrite/gold/header_rewrite-set_body_from_conn_fail.gold +++ b/tests/gold_tests/pluginTest/header_rewrite/gold/header_rewrite-set_body_from_conn_fail.gold @@ -3,7 +3,23 @@ < Date: `` < Proxy-Connection: keep-alive < Server: ATS/`` -< Content-Length: 5 +< Content-Length: 391 < Content-Type: text/html `` -Fail + + +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. + +
+ diff --git a/tests/gold_tests/pluginTest/header_rewrite/header_rewrite_set_body_from.test.py b/tests/gold_tests/pluginTest/header_rewrite/header_rewrite_set_body_from.test.py index 3a43ab1c25f..91e7d514d69 100644 --- a/tests/gold_tests/pluginTest/header_rewrite/header_rewrite_set_body_from.test.py +++ b/tests/gold_tests/pluginTest/header_rewrite/header_rewrite_set_body_from.test.py @@ -52,11 +52,6 @@ def setUpOriginServer(self): plugin_success_1_request_header = {"headers": "GET /plugin_success HTTP/1.1\r\nHost: www.example.com\r\n\r\n"} self.server.addResponse("sessionfile.log", plugin_success_1_request_header, response_header) - # Request/response for custom body transaction that fails to retrieve body - fail_2_request_header = {"headers": "GET /502 HTTP/1.1\r\nHost: www.example.com\r\n\r\n"} - fail_2_response_header = {"headers": "HTTP/1.1 502 \r\nConnection: close\r\n\r\n", "body": "Fail\n"} - self.server.addResponse("sessionfile.log", fail_2_request_header, fail_2_response_header) - # Request/response for custom body transaction that successfully retrieves body success_2_request_header = {"headers": "GET /404.html HTTP/1.1\r\nHost: www.example.com\r\n\r\n"} success_2_response_header = {"headers": "HTTP/1.1 200 OK\r\nConnection: close\r\n\r\n", "body": "Custom body found\n"} @@ -68,6 +63,7 @@ def setUpTS(self): # Set header rewrite rules self.ts.Setup.CopyAs('rules/rule_set_body_from_remap.conf', Test.RunDirectory) self.ts.Setup.CopyAs('rules/rule_set_body_from_plugin.conf', Test.RunDirectory) + self.ts.Disk.remap_config.AddLine( """\ map http://www.example.com/remap_success http://127.0.0.1:{0}/remap_success @plugin=header_rewrite.so @pparam={1}/rule_set_body_from_remap.conf @@ -76,8 +72,8 @@ def setUpTS(self): map http://www.example.com/plugin_success http://127.0.0.1:{0}/plugin_success map http://www.example.com/plugin_fail http://127.0.0.1:{0}/plugin_fail map http://www.example.com/404.html http://127.0.0.1:{0}/404.html - map http://www.example.com/502 http://127.0.0.1:{0}/502 - """.format(self.server.Variables.Port, Test.RunDirectory)) + map http://www.example.com/plugin_no_server http://127.0.0.1::{2}/plugin_no_server + """.format(self.server.Variables.Port, Test.RunDirectory, Test.GetTcpPort("bad_port"))) self.ts.Disk.plugin_config.AddLine('header_rewrite.so {0}/rule_set_body_from_plugin.conf'.format(Test.RunDirectory)) def test_setBodyFromFails_remap(self): diff --git a/tests/gold_tests/pluginTest/header_rewrite/rules/rule_set_body_from_plugin.conf b/tests/gold_tests/pluginTest/header_rewrite/rules/rule_set_body_from_plugin.conf index f12ba2a5a92..c4c83abb17d 100644 --- a/tests/gold_tests/pluginTest/header_rewrite/rules/rule_set_body_from_plugin.conf +++ b/tests/gold_tests/pluginTest/header_rewrite/rules/rule_set_body_from_plugin.conf @@ -14,10 +14,13 @@ # 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 uses cond %{CLIENT-URL:PATH} to differentiate tests +# It is not needed to make set-body-from work cond %{READ_RESPONSE_HDR_HOOK} cond %{CLIENT-URL:PATH} = "plugin_success" set-body-from http://www.example.com/404.html cond %{READ_RESPONSE_HDR_HOOK} cond %{CLIENT-URL:PATH} = "plugin_fail" -set-body-from http://www.example.com/502 +set-body-from http://www.example.com/plugin_no_server From 0f6e7a0dee01e07dc489bfa920e01a3cda72ad3d Mon Sep 17 00:00:00 2001 From: Jasmine Emanouel Date: Fri, 5 Jul 2024 15:01:06 +0100 Subject: [PATCH 10/11] Update header_rewrite.en.rst --- doc/admin-guide/plugins/header_rewrite.en.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/admin-guide/plugins/header_rewrite.en.rst b/doc/admin-guide/plugins/header_rewrite.en.rst index 18b65b1f2a3..7d971a0f4df 100644 --- a/doc/admin-guide/plugins/header_rewrite.en.rst +++ b/doc/admin-guide/plugins/header_rewrite.en.rst @@ -714,6 +714,7 @@ Will call ```` (see URL in `URL Parts`_) to retrieve a custom error respons and set the body with the result. Triggering this rule on an OK transaction will send a 500 status code to the client with the desired response. If this is triggered on any error status code, that original status code will be sent to the client. +**Note**: This config should only be set using READ_RESPONSE_HDR_HOOK An example config would look like From ead8e5f1980f1a46d2cdf50b9db7a9267a1a3767 Mon Sep 17 00:00:00 2001 From: Jasmine Emanouel Date: Mon, 15 Jul 2024 09:50:10 +1000 Subject: [PATCH 11/11] Fix flakey test --- .../gold/header_rewrite-set_body_from_200.gold | 9 --------- .../header_rewrite-set_body_from_conn_fail.gold | 8 -------- .../header_rewrite-set_body_from_remap_fail.gold | 8 -------- .../header_rewrite-set_body_from_success.gold | 9 +-------- .../header_rewrite_set_body_from.test.py | 15 ++++++++++----- 5 files changed, 11 insertions(+), 38 deletions(-) diff --git a/tests/gold_tests/pluginTest/header_rewrite/gold/header_rewrite-set_body_from_200.gold b/tests/gold_tests/pluginTest/header_rewrite/gold/header_rewrite-set_body_from_200.gold index 90c34b6eb54..3e37495f65b 100644 --- a/tests/gold_tests/pluginTest/header_rewrite/gold/header_rewrite-set_body_from_200.gold +++ b/tests/gold_tests/pluginTest/header_rewrite/gold/header_rewrite-set_body_from_200.gold @@ -1,10 +1 @@ -`` -< HTTP/1.1 500 INKApi Error -< Date: `` -< Proxy-Connection: keep-alive -< Server: ATS/`` -< Content-Length: 18 -< Content-Type: text/html -`` Custom body found -`` diff --git a/tests/gold_tests/pluginTest/header_rewrite/gold/header_rewrite-set_body_from_conn_fail.gold b/tests/gold_tests/pluginTest/header_rewrite/gold/header_rewrite-set_body_from_conn_fail.gold index d98797800dd..70d40bddd16 100644 --- a/tests/gold_tests/pluginTest/header_rewrite/gold/header_rewrite-set_body_from_conn_fail.gold +++ b/tests/gold_tests/pluginTest/header_rewrite/gold/header_rewrite-set_body_from_conn_fail.gold @@ -1,11 +1,3 @@ -`` -< HTTP/1.1 404 Not Found -< Date: `` -< Proxy-Connection: keep-alive -< Server: ATS/`` -< Content-Length: 391 -< Content-Type: text/html -`` Unknown Host diff --git a/tests/gold_tests/pluginTest/header_rewrite/gold/header_rewrite-set_body_from_remap_fail.gold b/tests/gold_tests/pluginTest/header_rewrite/gold/header_rewrite-set_body_from_remap_fail.gold index 572287d1b33..8f069904f11 100644 --- a/tests/gold_tests/pluginTest/header_rewrite/gold/header_rewrite-set_body_from_remap_fail.gold +++ b/tests/gold_tests/pluginTest/header_rewrite/gold/header_rewrite-set_body_from_remap_fail.gold @@ -1,11 +1,3 @@ -`` -< HTTP/1.1 404 Not Found -< Date: `` -< Proxy-Connection: keep-alive -< Server: ATS/`` -< Content-Length: 297 -< Content-Type: text/html -`` Not Found on Accelerator diff --git a/tests/gold_tests/pluginTest/header_rewrite/gold/header_rewrite-set_body_from_success.gold b/tests/gold_tests/pluginTest/header_rewrite/gold/header_rewrite-set_body_from_success.gold index 90ae8988f87..3e37495f65b 100644 --- a/tests/gold_tests/pluginTest/header_rewrite/gold/header_rewrite-set_body_from_success.gold +++ b/tests/gold_tests/pluginTest/header_rewrite/gold/header_rewrite-set_body_from_success.gold @@ -1,8 +1 @@ -`` -< HTTP/1.1 404 Not Found -< Date: `` -< Proxy-Connection: keep-alive -< Server: ATS/`` -< Content-Length: 18 -< Content-Type: text/html -`` +Custom body found diff --git a/tests/gold_tests/pluginTest/header_rewrite/header_rewrite_set_body_from.test.py b/tests/gold_tests/pluginTest/header_rewrite/header_rewrite_set_body_from.test.py index 91e7d514d69..925458d5d8b 100644 --- a/tests/gold_tests/pluginTest/header_rewrite/header_rewrite_set_body_from.test.py +++ b/tests/gold_tests/pluginTest/header_rewrite/header_rewrite_set_body_from.test.py @@ -88,7 +88,8 @@ def test_setBodyFromFails_remap(self): tr.Processes.Default.ReturnCode = 0 tr.Processes.Default.StartBefore(self.server) tr.Processes.Default.StartBefore(self.ts) - tr.Processes.Default.Streams.All = "gold/header_rewrite-set_body_from_remap_fail.gold" + tr.Processes.Default.Streams.stdout = "gold/header_rewrite-set_body_from_remap_fail.gold" + tr.Processes.Default.Streams.stderr.Content = Testers.ContainsExpression("404 Not Found", "Expected 404 response") tr.StillRunningAfter = self.server def test_setBodyFromSucceeds_remap(self): @@ -100,7 +101,8 @@ def test_setBodyFromSucceeds_remap(self): tr.Processes.Default.Command = ( 'curl -s -v --proxy 127.0.0.1:{0} "http://www.example.com/remap_success"'.format(self.ts.Variables.port)) tr.Processes.Default.ReturnCode = 0 - tr.Processes.Default.Streams.All = "gold/header_rewrite-set_body_from_success.gold" + tr.Processes.Default.Streams.stdout = "gold/header_rewrite-set_body_from_success.gold" + tr.Processes.Default.Streams.stderr.Content = Testers.ContainsExpression("404 Not Found", "Expected 404 response") tr.StillRunningAfter = self.server def test_setBodyFromSucceeds_plugin(self): @@ -112,7 +114,8 @@ def test_setBodyFromSucceeds_plugin(self): tr.Processes.Default.Command = ( 'curl -s -v --proxy 127.0.0.1:{0} "http://www.example.com/plugin_success"'.format(self.ts.Variables.port)) tr.Processes.Default.ReturnCode = 0 - tr.Processes.Default.Streams.All = "gold/header_rewrite-set_body_from_success.gold" + tr.Processes.Default.Streams.stdout = "gold/header_rewrite-set_body_from_success.gold" + tr.Processes.Default.Streams.stderr.Content = Testers.ContainsExpression("404 Not Found", "Expected 404 response") tr.StillRunningAfter = self.server def test_setBodyFromFails_plugin(self): @@ -125,7 +128,8 @@ def test_setBodyFromFails_plugin(self): tr.Processes.Default.Command = ( 'curl -s -v --proxy 127.0.0.1:{0} "http://www.example.com/plugin_fail"'.format(self.ts.Variables.port)) tr.Processes.Default.ReturnCode = 0 - tr.Processes.Default.Streams.All = "gold/header_rewrite-set_body_from_conn_fail.gold" + tr.Processes.Default.Streams.stdout = "gold/header_rewrite-set_body_from_conn_fail.gold" + tr.Processes.Default.Streams.stderr.Content = Testers.ContainsExpression("404 Not Found", "Expected 404 response") tr.StillRunningAfter = self.server def test_setBodyFromSucceeds_200(self): @@ -139,7 +143,8 @@ def test_setBodyFromSucceeds_200(self): tr.Processes.Default.Command = ( 'curl -s -v --proxy 127.0.0.1:{0} "http://www.example.com/200"'.format(self.ts.Variables.port)) tr.Processes.Default.ReturnCode = 0 - tr.Processes.Default.Streams.All = "gold/header_rewrite-set_body_from_200.gold" + tr.Processes.Default.Streams.stdout = "gold/header_rewrite-set_body_from_200.gold" + tr.Processes.Default.Streams.stderr.Content = Testers.ContainsExpression("500 INKApi Error", "Expected 500 response") tr.StillRunningAfter = self.server def runTraffic(self):