You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@trafficserver.apache.org by bc...@apache.org on 2020/01/17 20:17:08 UTC
[trafficserver] branch master updated: Fix problems with "Probe"
option for X-Debug MIME header field. (#6197)
This is an automated email from the ASF dual-hosted git repository.
bcall pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/trafficserver.git
The following commit(s) were added to refs/heads/master by this push:
new 473e054 Fix problems with "Probe" option for X-Debug MIME header field. (#6197)
473e054 is described below
commit 473e0549cbb7bda763340b842d447d9db0d49879
Author: Walt Karas <wk...@verizonmedia.com>
AuthorDate: Fri Jan 17 14:16:57 2020 -0600
Fix problems with "Probe" option for X-Debug MIME header field. (#6197)
Fix problems with "Probe" option for X-Debug MIME header field.
- Adds exercise of "Probe" to the existing x_remap Au test.
- Remove memory leaks and risk of double deletion in xdebug plugin.
---
plugins/xdebug/Cleanup.h | 186 ++++++++++++
plugins/xdebug/Makefile.inc | 4 +-
plugins/xdebug/xdebug.cc | 69 +++--
plugins/xdebug/xdebug_transforms.cc | 44 +--
tests/gold_tests/pluginTest/xdebug/x_remap/four.in | 3 +-
tests/gold_tests/pluginTest/xdebug/x_remap/fwd1.in | 3 +-
tests/gold_tests/pluginTest/xdebug/x_remap/fwd2.in | 3 +-
tests/gold_tests/pluginTest/xdebug/x_remap/fwd3.in | 3 +-
tests/gold_tests/pluginTest/xdebug/x_remap/fwd4.in | 3 +-
tests/gold_tests/pluginTest/xdebug/x_remap/fwd5.in | 3 +-
tests/gold_tests/pluginTest/xdebug/x_remap/none.in | 3 +-
tests/gold_tests/pluginTest/xdebug/x_remap/one.in | 3 +-
.../gold_tests/pluginTest/xdebug/x_remap/out.gold | 315 ++++++++++++++++++++-
.../gold_tests/pluginTest/xdebug/x_remap/three.in | 3 +-
tests/gold_tests/pluginTest/xdebug/x_remap/two.in | 3 +-
.../pluginTest/xdebug/x_remap/x_remap.gold | 6 +-
.../pluginTest/xdebug/x_remap/x_remap.test.py | 4 +-
17 files changed, 577 insertions(+), 81 deletions(-)
diff --git a/plugins/xdebug/Cleanup.h b/plugins/xdebug/Cleanup.h
new file mode 100644
index 0000000..453903c
--- /dev/null
+++ b/plugins/xdebug/Cleanup.h
@@ -0,0 +1,186 @@
+/**
+ 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.
+ */
+
+/**
+ * @file Cleanup.h
+ * @brief Easy-to-use utilities to avoid resource leaks or double-releases of resources. Independent of the rest
+ * of the CPPAPI.
+ */
+
+#pragma once
+
+#include <type_traits>
+#include <memory>
+
+#include <ts/ts.h>
+
+namespace atscppapi
+{
+// For TS API types TSXxx with a TSXxxDestroy function, define standard deleter TSXxxDeleter, and use it to
+// define TSXxxUniqPtr (specialization of std::unique_ptr). X() is used when the destroy function returns void,
+// Y() is used when the destroy function returns TSReturnCode.
+
+#if defined(X)
+#error "X defined as preprocessor symbol"
+#endif
+
+#define X(NAME_SEGMENT) \
+ struct TS##NAME_SEGMENT##Deleter { \
+ void \
+ operator()(TS##NAME_SEGMENT ptr) \
+ { \
+ TS##NAME_SEGMENT##Destroy(ptr); \
+ } \
+ }; \
+ using TS##NAME_SEGMENT##UniqPtr = std::unique_ptr<std::remove_pointer_t<TS##NAME_SEGMENT>, TS##NAME_SEGMENT##Deleter>;
+
+#if defined(Y)
+#error "Y defined as preprocessor symbol"
+#endif
+
+#define Y(NAME_SEGMENT) \
+ struct TS##NAME_SEGMENT##Deleter { \
+ void \
+ operator()(TS##NAME_SEGMENT ptr) \
+ { \
+ TSAssert(TS##NAME_SEGMENT##Destroy(ptr) == TS_SUCCESS); \
+ } \
+ }; \
+ using TS##NAME_SEGMENT##UniqPtr = std::unique_ptr<std::remove_pointer_t<TS##NAME_SEGMENT>, TS##NAME_SEGMENT##Deleter>;
+
+Y(MBuffer) // Defines TSMBufferDeleter and TSMBufferUniqPtr.
+X(MimeParser) // Defines TSMimeParserDeleter and TSMimeParserUniqPtr.
+X(Thread) // Defines TSThreadDeleter and TSThreadUniqPtr.
+X(Mutex) // Defines TSMutexDeleter and TSMutexUniqPtr.
+Y(CacheKey) // Defines TSCacheKeyDeleter and TSCacheKeyUniqPtr.
+X(Cont) // Defines TSContDeleter and TSContUniqPtr.
+X(SslContext) // Defines TSSslContextDeleter and TSSslContextUniqPtr.
+X(IOBuffer) // Defines TSIOBufferDeleter and TSIOBufferUniqPtr.
+Y(TextLogObject) // Defines TSTextLogObjectDeleter and TSTextLogObjectUniqPtr.
+X(Uuid) // Defines TSUuidDeleter and TSUuidUniqPtr.
+
+#undef X
+#undef Y
+
+// Deleter and unique pointer for memory buffer returned by TSalloc(), TSrealloc(), Tstrdup(), TSsrtndup().
+//
+struct TSMemDeleter {
+ void
+ operator()(void *ptr)
+ {
+ TSfree(ptr);
+ }
+};
+using TSMemUniqPtr = std::unique_ptr<void, TSMemDeleter>;
+
+// Deleter and unique pointer for TSIOBufferReader. Care must be taken that the reader is deleted before the
+// TSIOBuffer to which it refers is deleted.
+//
+struct TSIOBufferReaderDeleter {
+ void
+ operator()(TSIOBufferReader ptr)
+ {
+ TSIOBufferReaderFree(ptr);
+ }
+};
+using TSIOBufferReaderUniqPtr = std::unique_ptr<std::remove_pointer_t<TSIOBufferReader>, TSIOBufferReaderDeleter>;
+
+class TxnAuxDataMgrBase
+{
+protected:
+ struct MgrData_ {
+ TSCont txnCloseContp = nullptr;
+ int txnArgIndex = -1;
+ };
+
+public:
+ class MgrData : private MgrData_
+ {
+ friend class TxnAuxDataMgrBase;
+ };
+
+protected:
+ static MgrData_ &
+ access(MgrData &md)
+ {
+ return md;
+ }
+};
+
+using TxnAuxMgrData = TxnAuxDataMgrBase::MgrData;
+
+// Class to manage auxilliary data for a transaction. If an instance is created for the transaction, the instance
+// will be deleted on the TXN_CLOSE transaction hook (which is always triggered for all transactions).
+// The TxnAuxData class must have a public default constructor.
+//
+template <class TxnAuxData, TxnAuxMgrData &MDRef> class TxnAuxDataMgr : private TxnAuxDataMgrBase
+{
+public:
+ using Data = TxnAuxData;
+
+ // This must be called from the plugin init function. arg_name is the name for the transaction argument used
+ // to store the pointer to the auxiliary data class instance. Repeated calls are ignored.
+ //
+ static void
+ init(char const *arg_name, char const *arg_desc = "per-transaction auxiliary data")
+ {
+ MgrData_ &md = access(MDRef);
+
+ if (md.txnArgIndex >= 0) {
+ return;
+ }
+
+ TSReleaseAssert(TSHttpTxnArgIndexReserve(arg_name, arg_desc, &md.txnArgIndex) == TS_SUCCESS);
+ TSReleaseAssert(md.txnCloseContp = TSContCreate(_deleteAuxData, nullptr));
+ }
+
+ // Get a reference to the auxiliary data for a transaction.
+ //
+ static TxnAuxData &
+ data(TSHttpTxn txn)
+ {
+ MgrData_ &md = access(MDRef);
+
+ TSAssert(md.txnArgIndex >= 0);
+
+ auto d = static_cast<TxnAuxData *>(TSHttpTxnArgGet(txn, md.txnArgIndex));
+ if (!d) {
+ d = new TxnAuxData;
+
+ TSHttpTxnArgSet(txn, md.txnArgIndex, d);
+
+ TSHttpTxnHookAdd(txn, TS_HTTP_TXN_CLOSE_HOOK, md.txnCloseContp);
+ }
+ return *d;
+ }
+
+private:
+ static int
+ _deleteAuxData(TSCont, TSEvent, void *edata)
+ {
+ MgrData_ &md = access(MDRef);
+
+ auto txn = static_cast<TSHttpTxn>(edata);
+ auto data = static_cast<TxnAuxData *>(TSHttpTxnArgGet(txn, md.txnArgIndex));
+ delete data;
+ TSHttpTxnReenable(txn, TS_EVENT_HTTP_CONTINUE);
+ return 0;
+ };
+};
+
+} // end namespace atscppapi
diff --git a/plugins/xdebug/Makefile.inc b/plugins/xdebug/Makefile.inc
index 1e41324..a69e223 100644
--- a/plugins/xdebug/Makefile.inc
+++ b/plugins/xdebug/Makefile.inc
@@ -15,4 +15,6 @@
# limitations under the License.
pkglib_LTLIBRARIES += xdebug/xdebug.la
-xdebug_xdebug_la_SOURCES = xdebug/xdebug.cc
+xdebug_xdebug_la_SOURCES = \
+xdebug/Cleanup.h \
+xdebug/xdebug.cc
diff --git a/plugins/xdebug/xdebug.cc b/plugins/xdebug/xdebug.cc
index a3a2443..3493575 100644
--- a/plugins/xdebug/xdebug.cc
+++ b/plugins/xdebug/xdebug.cc
@@ -22,6 +22,8 @@
#include <strings.h>
#include <sstream>
#include <cstring>
+#include <atomic>
+#include <memory>
#include <getopt.h>
#include <cstdint>
#include <cinttypes>
@@ -32,6 +34,34 @@
#include "tscore/ink_defs.h"
#include "tscpp/util/PostScript.h"
#include "tscpp/util/TextView.h"
+#include "Cleanup.h"
+
+namespace
+{
+struct BodyBuilder {
+ atscppapi::TSContUniqPtr transform_connp;
+ atscppapi::TSIOBufferUniqPtr output_buffer;
+ // It's important that output_reader comes after output_buffer so it will be deleted first.
+ atscppapi::TSIOBufferReaderUniqPtr output_reader;
+ TSVIO output_vio = nullptr;
+ bool wrote_prebody = false;
+ bool wrote_body = false;
+ bool hdr_ready = false;
+ std::atomic_flag wrote_postbody;
+
+ int64_t nbytes = 0;
+};
+
+struct XDebugTxnAuxData {
+ std::unique_ptr<BodyBuilder> body_builder;
+ unsigned xheaders = 0;
+};
+
+atscppapi::TxnAuxMgrData mgrData;
+
+using AuxDataMgr = atscppapi::TxnAuxDataMgr<XDebugTxnAuxData, mgrData>;
+
+} // end anonymous namespace
#include "xdebug_headers.cc"
#include "xdebug_transforms.cc"
@@ -53,8 +83,6 @@ enum {
XHEADER_X_PSELECT_KEY = 1u << 10,
};
-static int XArgIndex = 0;
-static int BodyBuilderArgIndex = 0;
static TSCont XInjectHeadersCont = nullptr;
static TSCont XDeleteDebugHdrCont = nullptr;
@@ -382,7 +410,7 @@ XInjectResponseHeaders(TSCont /* contp */, TSEvent event, void *edata)
TSReleaseAssert(event == TS_EVENT_HTTP_SEND_RESPONSE_HDR);
- uintptr_t xheaders = reinterpret_cast<uintptr_t>(TSHttpTxnArgGet(txn, XArgIndex));
+ unsigned xheaders = AuxDataMgr::data(txn).xheaders;
if (xheaders == 0) {
goto done;
}
@@ -422,14 +450,14 @@ XInjectResponseHeaders(TSCont /* contp */, TSEvent event, void *edata)
}
if (xheaders & XHEADER_X_PROBE_HEADERS) {
- BodyBuilder *data = static_cast<BodyBuilder *>(TSHttpTxnArgGet(txn, BodyBuilderArgIndex));
+ BodyBuilder *data = AuxDataMgr::data(txn).body_builder.get();
TSDebug("xdebug_transform", "XInjectResponseHeaders(): client resp header ready");
if (data == nullptr) {
TSHttpTxnReenable(txn, TS_EVENT_HTTP_ERROR);
return TS_ERROR;
}
data->hdr_ready = true;
- writePostBody(data);
+ writePostBody(txn, data);
}
if (xheaders & XHEADER_X_PSELECT_KEY) {
@@ -493,9 +521,9 @@ isFwdFieldValue(std::string_view value, intmax_t &fwdCnt)
static int
XScanRequestHeaders(TSCont /* contp */, TSEvent event, void *edata)
{
- TSHttpTxn txn = static_cast<TSHttpTxn>(edata);
- uintptr_t xheaders = 0;
- intmax_t fwdCnt = 0;
+ TSHttpTxn txn = static_cast<TSHttpTxn>(edata);
+ unsigned xheaders = 0;
+ intmax_t fwdCnt = 0;
TSMLoc field, next;
TSMBuffer buffer;
TSMLoc hdr;
@@ -550,26 +578,17 @@ XScanRequestHeaders(TSCont /* contp */, TSEvent event, void *edata)
} else if (header_field_eq("probe", value, vsize)) {
xheaders |= XHEADER_X_PROBE_HEADERS;
+ auto &auxData = AuxDataMgr::data(txn);
+
// prefix request headers and postfix response headers
BodyBuilder *data = new BodyBuilder();
- data->txn = txn;
+ auxData.body_builder.reset(data);
TSVConn connp = TSTransformCreate(body_transform, txn);
- TSContDataSet(connp, data);
+ data->transform_connp.reset(connp);
+ TSContDataSet(connp, txn);
TSHttpTxnHookAdd(txn, TS_HTTP_RESPONSE_TRANSFORM_HOOK, connp);
- // store data pointer in txnarg to use in global cont XInjectResponseHeaders
- TSHttpTxnArgSet(txn, BodyBuilderArgIndex, data);
-
- // create a self-cleanup on close
- auto cleanupBodyBuilder = [](TSCont /* contp */, TSEvent event, void *edata) -> int {
- TSHttpTxn txn = static_cast<TSHttpTxn>(edata);
- BodyBuilder *data = static_cast<BodyBuilder *>(TSHttpTxnArgGet(txn, BodyBuilderArgIndex));
- delete data;
- return TS_EVENT_NONE;
- };
- TSHttpTxnHookAdd(txn, TS_HTTP_TXN_CLOSE_HOOK, TSContCreate(cleanupBodyBuilder, nullptr));
-
// disable writing to cache because we are injecting data into the body.
TSHttpTxnReqCacheableSet(txn, 0);
TSHttpTxnRespCacheableSet(txn, 0);
@@ -608,7 +627,7 @@ XScanRequestHeaders(TSCont /* contp */, TSEvent event, void *edata)
TSDebug("xdebug", "adding response hook for header mask %p and forward count %" PRIiMAX, reinterpret_cast<void *>(xheaders),
fwdCnt);
TSHttpTxnHookAdd(txn, TS_HTTP_SEND_RESPONSE_HDR_HOOK, XInjectHeadersCont);
- TSHttpTxnArgSet(txn, XArgIndex, reinterpret_cast<void *>(xheaders));
+ AuxDataMgr::data(txn).xheaders = xheaders;
if (fwdCnt == 0) {
// X-Debug header has to be deleted, but not too soon for other plugins to see it.
@@ -688,9 +707,9 @@ TSPluginInit(int argc, const char *argv[])
}
xDebugHeader.len = strlen(xDebugHeader.str);
+ AuxDataMgr::init("xdebug");
+
// Setup the global hook
- TSReleaseAssert(TSHttpTxnArgIndexReserve("xdebug", "xdebug header requests", &XArgIndex) == TS_SUCCESS);
- TSReleaseAssert(TSHttpTxnArgIndexReserve("bodyTransform", "BodyBuilder*", &XArgIndex) == TS_SUCCESS);
TSReleaseAssert(XInjectHeadersCont = TSContCreate(XInjectResponseHeaders, nullptr));
TSReleaseAssert(XDeleteDebugHdrCont = TSContCreate(XDeleteDebugHdr, nullptr));
TSHttpHookAdd(TS_HTTP_READ_REQUEST_HDR_HOOK, TSContCreate(XScanRequestHeaders, nullptr));
diff --git a/plugins/xdebug/xdebug_transforms.cc b/plugins/xdebug/xdebug_transforms.cc
index a5bc75a..e1019e7 100644
--- a/plugins/xdebug/xdebug_transforms.cc
+++ b/plugins/xdebug/xdebug_transforms.cc
@@ -21,25 +21,11 @@
#include <stdio.h>
#include <string.h>
#include <functional>
-#include <atomic>
#include "ts/ts.h"
static const std::string_view MultipartBoundary{"\r\n--- ATS xDebug Probe Injection Boundary ---\r\n\r\n"};
-struct BodyBuilder {
- TSVIO output_vio = nullptr;
- TSIOBuffer output_buffer = nullptr;
- TSIOBufferReader output_reader = nullptr;
- bool wrote_prebody = false;
- bool wrote_body = false;
- bool hdr_ready = false;
- std::atomic_flag wrote_postbody;
-
- int64_t nbytes = 0;
- TSHttpTxn txn = nullptr;
-};
-
static char Hostname[1024];
static std::string
@@ -65,12 +51,12 @@ getPostBody(TSHttpTxn txn)
}
static void
-writePostBody(BodyBuilder *data)
+writePostBody(TSHttpTxn txn, BodyBuilder *data)
{
if (data->wrote_body && data->hdr_ready && !data->wrote_postbody.test_and_set()) {
TSDebug("xdebug_transform", "body_transform(): Writing postbody headers...");
- std::string postbody = getPostBody(data->txn);
- TSIOBufferWrite(data->output_buffer, postbody.data(), postbody.length());
+ std::string postbody = getPostBody(txn);
+ TSIOBufferWrite(data->output_buffer.get(), postbody.data(), postbody.length());
data->nbytes += postbody.length();
TSVIONBytesSet(data->output_vio, data->nbytes);
TSVIOReenable(data->output_vio);
@@ -80,15 +66,13 @@ writePostBody(BodyBuilder *data)
static int
body_transform(TSCont contp, TSEvent event, void *edata)
{
- BodyBuilder *data = static_cast<BodyBuilder *>(TSContDataGet(contp));
+ TSHttpTxn txn = static_cast<TSHttpTxn>(TSContDataGet(contp));
+ BodyBuilder *data = AuxDataMgr::data(txn).body_builder.get();
if (!data) {
- TSContDestroy(contp);
return TS_ERROR;
}
if (TSVConnClosedGet(contp)) {
- // write connection destroyed. cleanup.
- delete data;
- TSContDestroy(contp);
+ // write connection destroyed.
return 0;
}
@@ -108,16 +92,16 @@ body_transform(TSCont contp, TSEvent event, void *edata)
TSDebug("xdebug_transform", "body_transform(): Event is TS_EVENT_VCONN_WRITE_READY");
// fall through
default:
- if (!data->output_buffer) {
- data->output_buffer = TSIOBufferCreate();
- data->output_reader = TSIOBufferReaderAlloc(data->output_buffer);
- data->output_vio = TSVConnWrite(TSTransformOutputVConnGet(contp), contp, data->output_reader, INT64_MAX);
+ if (!data->output_buffer.get()) {
+ data->output_buffer.reset(TSIOBufferCreate());
+ data->output_reader.reset(TSIOBufferReaderAlloc(data->output_buffer.get()));
+ data->output_vio = TSVConnWrite(TSTransformOutputVConnGet(contp), contp, data->output_reader.get(), INT64_MAX);
}
if (data->wrote_prebody == false) {
TSDebug("xdebug_transform", "body_transform(): Writing prebody headers...");
- std::string prebody = getPreBody(data->txn);
- TSIOBufferWrite(data->output_buffer, prebody.data(), prebody.length()); // write prebody
+ std::string prebody = getPreBody(txn);
+ TSIOBufferWrite(data->output_buffer.get(), prebody.data(), prebody.length()); // write prebody
data->wrote_prebody = true;
data->nbytes += prebody.length();
}
@@ -127,7 +111,7 @@ body_transform(TSCont contp, TSEvent event, void *edata)
if (!src_buf) {
// upstream continuation shuts down write operation.
data->wrote_body = true;
- writePostBody(data);
+ writePostBody(txn, data);
return 0;
}
@@ -150,7 +134,7 @@ body_transform(TSCont contp, TSEvent event, void *edata)
// Write post body content and update output VIO
data->wrote_body = true;
data->nbytes += TSVIONDoneGet(src_vio);
- writePostBody(data);
+ writePostBody(txn, data);
TSContCall(TSVIOContGet(src_vio), TS_EVENT_VCONN_WRITE_COMPLETE, src_vio);
}
}
diff --git a/tests/gold_tests/pluginTest/xdebug/x_remap/four.in b/tests/gold_tests/pluginTest/xdebug/x_remap/four.in
index 1982451..6842039 100644
--- a/tests/gold_tests/pluginTest/xdebug/x_remap/four.in
+++ b/tests/gold_tests/pluginTest/xdebug/x_remap/four.in
@@ -1,4 +1,5 @@
GET /not_there HTTP/1.1
Host: two
-X-Debug: X-Remap
+X-Debug: X-Remap, Probe
+Connection: close
diff --git a/tests/gold_tests/pluginTest/xdebug/x_remap/fwd1.in b/tests/gold_tests/pluginTest/xdebug/x_remap/fwd1.in
index c67c8ea..82f3fa5 100644
--- a/tests/gold_tests/pluginTest/xdebug/x_remap/fwd1.in
+++ b/tests/gold_tests/pluginTest/xdebug/x_remap/fwd1.in
@@ -1,4 +1,5 @@
GET /argh HTTP/1.1
Host: two
-X-Debug: X-Remap, fwd
+X-Debug: X-Remap, fwd, Probe
+Connection: close
diff --git a/tests/gold_tests/pluginTest/xdebug/x_remap/fwd2.in b/tests/gold_tests/pluginTest/xdebug/x_remap/fwd2.in
index 8cb9e7c..4f7ea91 100644
--- a/tests/gold_tests/pluginTest/xdebug/x_remap/fwd2.in
+++ b/tests/gold_tests/pluginTest/xdebug/x_remap/fwd2.in
@@ -1,4 +1,5 @@
GET /argh HTTP/1.1
Host: two
-X-Debug: X-Remap, fwd=0
+X-Debug: X-Remap, fwd=0, probe
+Connection: close
diff --git a/tests/gold_tests/pluginTest/xdebug/x_remap/fwd3.in b/tests/gold_tests/pluginTest/xdebug/x_remap/fwd3.in
index 47402f2..42c187a 100644
--- a/tests/gold_tests/pluginTest/xdebug/x_remap/fwd3.in
+++ b/tests/gold_tests/pluginTest/xdebug/x_remap/fwd3.in
@@ -1,4 +1,5 @@
GET /argh HTTP/1.1
Host: two
-X-Debug: X-Remap, fwd= 1
+X-Debug: X-Remap, fwd= 1, Probe
+Connection: close
diff --git a/tests/gold_tests/pluginTest/xdebug/x_remap/fwd4.in b/tests/gold_tests/pluginTest/xdebug/x_remap/fwd4.in
index 75ca74b..db3ce25 100644
--- a/tests/gold_tests/pluginTest/xdebug/x_remap/fwd4.in
+++ b/tests/gold_tests/pluginTest/xdebug/x_remap/fwd4.in
@@ -1,4 +1,5 @@
GET /argh HTTP/1.1
Host: two
-X-Debug: X-Remap, fwd = 999999
+X-Debug: PROBE, X-Remap, fwd = 999999
+Connection: close
diff --git a/tests/gold_tests/pluginTest/xdebug/x_remap/fwd5.in b/tests/gold_tests/pluginTest/xdebug/x_remap/fwd5.in
index 3b3e9af..02b44e7 100644
--- a/tests/gold_tests/pluginTest/xdebug/x_remap/fwd5.in
+++ b/tests/gold_tests/pluginTest/xdebug/x_remap/fwd5.in
@@ -1,4 +1,5 @@
GET /argh HTTP/1.1
Host: two
-X-Debug: X-Remap, fwd = 999999xxx
+X-Debug: X-Remap, fwd = 999999xxx, Probe
+Connection: close
diff --git a/tests/gold_tests/pluginTest/xdebug/x_remap/none.in b/tests/gold_tests/pluginTest/xdebug/x_remap/none.in
index 6e5b719..a077b72 100644
--- a/tests/gold_tests/pluginTest/xdebug/x_remap/none.in
+++ b/tests/gold_tests/pluginTest/xdebug/x_remap/none.in
@@ -1,4 +1,5 @@
GET /argh HTTP/1.1
Host: none
-X-Debug: X-Remap
+X-Debug: X-Remap, Probe
+Connection: close
diff --git a/tests/gold_tests/pluginTest/xdebug/x_remap/one.in b/tests/gold_tests/pluginTest/xdebug/x_remap/one.in
index 48306be..6a35a87 100644
--- a/tests/gold_tests/pluginTest/xdebug/x_remap/one.in
+++ b/tests/gold_tests/pluginTest/xdebug/x_remap/one.in
@@ -1,4 +1,5 @@
GET /argh HTTP/1.1
Host: one
-X-Debug: X-Remap
+X-Debug: X-Remap, probe
+Connection: close
diff --git a/tests/gold_tests/pluginTest/xdebug/x_remap/out.gold b/tests/gold_tests/pluginTest/xdebug/x_remap/out.gold
index 0619bd2..4b1e265 100644
--- a/tests/gold_tests/pluginTest/xdebug/x_remap/out.gold
+++ b/tests/gold_tests/pluginTest/xdebug/x_remap/out.gold
@@ -1,6 +1,6 @@
HTTP/1.1 502 Cannot find server.
Date: ``
-Connection: keep-alive
+Connection: close
Server: ATS/``
Cache-Control: no-store
Content-Type: text/html
@@ -30,10 +30,42 @@ HTTP/1.1 200 OK
Date: ``
Age: ``
Transfer-Encoding: chunked
-Connection: keep-alive
+Connection: close
Server: ATS/``
X-Remap: from=http://one/, to=http://127.0.0.1:SERVER_PORT/
+``
+{'xDebugProbeAt' : '``
+ 'captured':[{'type':'request', 'side':'client', 'headers': {
+ 'Host' : '127.0.0.1:SERVER_PORT',
+ 'Connection' : 'close',
+ }},{'type':'request', 'side':'server', 'headers': {
+ 'Host' : '127.0.0.1:SERVER_PORT',
+ 'Client-ip' : '127.0.0.1',
+ 'X-Forwarded-For' : '127.0.0.1',
+ 'Via' : 'http/1.1 traffic_server[``
+ }}
+ ]
+}
+--- ATS xDebug Probe Injection Boundary ---
+
+
+--- ATS xDebug Probe Injection Boundary ---
+
+{'xDebugProbeAt' : '``
+ 'captured':[{'type':'response', 'side':'server', 'headers': {
+ 'Connection' : 'close',
+ 'Date' : '``
+ }},{'type':'response', 'side':'client', 'headers': {
+ 'Date' : '``
+ 'Age' : '0',
+ 'Transfer-Encoding' : 'chunked',
+ 'Connection' : 'close',
+ 'Server' : 'ATS/``
+ 'X-Remap' : 'from=http://one/, to=http://127.0.0.1:SERVER_PORT/',
+ }}
+ ]
+}
0
======
@@ -41,10 +73,42 @@ HTTP/1.1 200 OK
Date: ``
Age: ``
Transfer-Encoding: chunked
-Connection: keep-alive
+Connection: close
Server: ATS/``
X-Remap: from=http://two/, to=http://127.0.0.1:SERVER_PORT/
+``
+{'xDebugProbeAt' : '``
+ 'captured':[{'type':'request', 'side':'client', 'headers': {
+ 'Host' : '127.0.0.1:SERVER_PORT',
+ 'Connection' : 'close',
+ }},{'type':'request', 'side':'server', 'headers': {
+ 'Host' : '127.0.0.1:SERVER_PORT',
+ 'Client-ip' : '127.0.0.1',
+ 'X-Forwarded-For' : '127.0.0.1',
+ 'Via' : 'http/1.1 traffic_server[``
+ }}
+ ]
+}
+--- ATS xDebug Probe Injection Boundary ---
+
+
+--- ATS xDebug Probe Injection Boundary ---
+
+{'xDebugProbeAt' : '``
+ 'captured':[{'type':'response', 'side':'server', 'headers': {
+ 'Connection' : 'close',
+ 'Date' : '``
+ }},{'type':'response', 'side':'client', 'headers': {
+ 'Date' : '``
+ 'Age' : '0',
+ 'Transfer-Encoding' : 'chunked',
+ 'Connection' : 'close',
+ 'Server' : 'ATS/``
+ 'X-Remap' : 'from=http://two/, to=http://127.0.0.1:SERVER_PORT/',
+ }}
+ ]
+}
0
======
@@ -52,10 +116,42 @@ HTTP/1.1 200 OK
Date: ``
Age: ``
Transfer-Encoding: chunked
-Connection: keep-alive
+Connection: close
Server: ATS/``
X-Remap: from=http://three[0-9]+/, to=http://127.0.0.1:SERVER_PORT/
+``
+{'xDebugProbeAt' : '``
+ 'captured':[{'type':'request', 'side':'client', 'headers': {
+ 'Host' : '127.0.0.1:SERVER_PORT',
+ 'Connection' : 'close',
+ }},{'type':'request', 'side':'server', 'headers': {
+ 'Host' : '127.0.0.1:SERVER_PORT',
+ 'Client-ip' : '127.0.0.1',
+ 'X-Forwarded-For' : '127.0.0.1',
+ 'Via' : 'http/1.1 traffic_server[``
+ }}
+ ]
+}
+--- ATS xDebug Probe Injection Boundary ---
+
+
+--- ATS xDebug Probe Injection Boundary ---
+
+{'xDebugProbeAt' : '``
+ 'captured':[{'type':'response', 'side':'server', 'headers': {
+ 'Connection' : 'close',
+ 'Date' : '``
+ }},{'type':'response', 'side':'client', 'headers': {
+ 'Date' : '``
+ 'Age' : '0',
+ 'Transfer-Encoding' : 'chunked',
+ 'Connection' : 'close',
+ 'Server' : 'ATS/``
+ 'X-Remap' : 'from=http://three[0-9]+/, to=http://127.0.0.1:SERVER_PORT/',
+ }}
+ ]
+}
0
======
@@ -64,9 +160,42 @@ Server: ATS/``
Date: ``
Age: ``
Transfer-Encoding: chunked
-Connection: keep-alive
+Connection: close
X-Remap: from=http://two/, to=http://127.0.0.1:SERVER_PORT/
+``
+{'xDebugProbeAt' : '``
+ 'captured':[{'type':'request', 'side':'client', 'headers': {
+ 'Host' : '127.0.0.1:SERVER_PORT',
+ 'Connection' : 'close',
+ }},{'type':'request', 'side':'server', 'headers': {
+ 'Host' : '127.0.0.1:SERVER_PORT',
+ 'Client-ip' : '127.0.0.1',
+ 'X-Forwarded-For' : '127.0.0.1',
+ 'Via' : 'http/1.1 traffic_server[``
+ }}
+ ]
+}
+--- ATS xDebug Probe Injection Boundary ---
+
+
+--- ATS xDebug Probe Injection Boundary ---
+
+{'xDebugProbeAt' : '``
+ 'captured':[{'type':'response', 'side':'server', 'headers': {
+ 'Server' : 'MicroServer',
+ 'Connection' : 'close',
+ 'Date' : '``
+ }},{'type':'response', 'side':'client', 'headers': {
+ 'Server' : 'ATS/``
+ 'Date' : '``
+ 'Age' : '0',
+ 'Transfer-Encoding' : 'chunked',
+ 'Connection' : 'close',
+ 'X-Remap' : 'from=http://two/, to=http://127.0.0.1:SERVER_PORT/',
+ }}
+ ]
+}
0
======
@@ -74,10 +203,44 @@ HTTP/1.1 200 OK
Date: ``
Age: ``
Transfer-Encoding: chunked
-Connection: keep-alive
+Connection: close
Server: ATS/``
X-Remap: from=http://two/, to=http://127.0.0.1:SERVER_PORT/
+``
+{'xDebugProbeAt' : '``
+ 'captured':[{'type':'request', 'side':'client', 'headers': {
+ 'Host' : '127.0.0.1:SERVER_PORT',
+ 'X-Debug' : 'X-Remap, fwd, Probe',
+ 'Connection' : 'close',
+ }},{'type':'request', 'side':'server', 'headers': {
+ 'Host' : '127.0.0.1:SERVER_PORT',
+ 'X-Debug' : 'X-Remap, fwd, Probe',
+ 'Client-ip' : '127.0.0.1',
+ 'X-Forwarded-For' : '127.0.0.1',
+ 'Via' : 'http/1.1 traffic_server[``
+ }}
+ ]
+}
+--- ATS xDebug Probe Injection Boundary ---
+
+
+--- ATS xDebug Probe Injection Boundary ---
+
+{'xDebugProbeAt' : '``
+ 'captured':[{'type':'response', 'side':'server', 'headers': {
+ 'Connection' : 'close',
+ 'Date' : '``
+ }},{'type':'response', 'side':'client', 'headers': {
+ 'Date' : '``
+ 'Age' : '0',
+ 'Transfer-Encoding' : 'chunked',
+ 'Connection' : 'close',
+ 'Server' : 'ATS/``
+ 'X-Remap' : 'from=http://two/, to=http://127.0.0.1:SERVER_PORT/',
+ }}
+ ]
+}
0
======
@@ -85,10 +248,42 @@ HTTP/1.1 200 OK
Date: ``
Age: ``
Transfer-Encoding: chunked
-Connection: keep-alive
+Connection: close
Server: ATS/``
X-Remap: from=http://two/, to=http://127.0.0.1:SERVER_PORT/
+``
+{'xDebugProbeAt' : '``
+ 'captured':[{'type':'request', 'side':'client', 'headers': {
+ 'Host' : '127.0.0.1:SERVER_PORT',
+ 'Connection' : 'close',
+ }},{'type':'request', 'side':'server', 'headers': {
+ 'Host' : '127.0.0.1:SERVER_PORT',
+ 'Client-ip' : '127.0.0.1',
+ 'X-Forwarded-For' : '127.0.0.1',
+ 'Via' : 'http/1.1 traffic_server[``
+ }}
+ ]
+}
+--- ATS xDebug Probe Injection Boundary ---
+
+
+--- ATS xDebug Probe Injection Boundary ---
+
+{'xDebugProbeAt' : '``
+ 'captured':[{'type':'response', 'side':'server', 'headers': {
+ 'Connection' : 'close',
+ 'Date' : '``
+ }},{'type':'response', 'side':'client', 'headers': {
+ 'Date' : '``
+ 'Age' : '0',
+ 'Transfer-Encoding' : 'chunked',
+ 'Connection' : 'close',
+ 'Server' : 'ATS/``
+ 'X-Remap' : 'from=http://two/, to=http://127.0.0.1:SERVER_PORT/',
+ }}
+ ]
+}
0
======
@@ -96,10 +291,44 @@ HTTP/1.1 200 OK
Date: ``
Age: ``
Transfer-Encoding: chunked
-Connection: keep-alive
+Connection: close
Server: ATS/``
X-Remap: from=http://two/, to=http://127.0.0.1:SERVER_PORT/
+``
+{'xDebugProbeAt' : '``
+ 'captured':[{'type':'request', 'side':'client', 'headers': {
+ 'Host' : '127.0.0.1:SERVER_PORT',
+ 'X-Debug' : 'X-Remap, fwd=0, Probe',
+ 'Connection' : 'close',
+ }},{'type':'request', 'side':'server', 'headers': {
+ 'Host' : '127.0.0.1:SERVER_PORT',
+ 'X-Debug' : 'X-Remap, fwd=0, Probe',
+ 'Client-ip' : '127.0.0.1',
+ 'X-Forwarded-For' : '127.0.0.1',
+ 'Via' : 'http/1.1 traffic_server[``
+ }}
+ ]
+}
+--- ATS xDebug Probe Injection Boundary ---
+
+
+--- ATS xDebug Probe Injection Boundary ---
+
+{'xDebugProbeAt' : '``
+ 'captured':[{'type':'response', 'side':'server', 'headers': {
+ 'Connection' : 'close',
+ 'Date' : '``
+ }},{'type':'response', 'side':'client', 'headers': {
+ 'Date' : '``
+ 'Age' : '0',
+ 'Transfer-Encoding' : 'chunked',
+ 'Connection' : 'close',
+ 'Server' : 'ATS/``
+ 'X-Remap' : 'from=http://two/, to=http://127.0.0.1:SERVER_PORT/',
+ }}
+ ]
+}
0
======
@@ -107,10 +336,44 @@ HTTP/1.1 200 OK
Date: ``
Age: ``
Transfer-Encoding: chunked
-Connection: keep-alive
+Connection: close
Server: ATS/``
X-Remap: from=http://two/, to=http://127.0.0.1:SERVER_PORT/
+``
+{'xDebugProbeAt' : '``
+ 'captured':[{'type':'request', 'side':'client', 'headers': {
+ 'Host' : '127.0.0.1:SERVER_PORT',
+ 'X-Debug' : 'PROBE, X-Remap, fwd=999998',
+ 'Connection' : 'close',
+ }},{'type':'request', 'side':'server', 'headers': {
+ 'Host' : '127.0.0.1:SERVER_PORT',
+ 'X-Debug' : 'PROBE, X-Remap, fwd=999998',
+ 'Client-ip' : '127.0.0.1',
+ 'X-Forwarded-For' : '127.0.0.1',
+ 'Via' : 'http/1.1 traffic_server[``
+ }}
+ ]
+}
+--- ATS xDebug Probe Injection Boundary ---
+
+
+--- ATS xDebug Probe Injection Boundary ---
+
+{'xDebugProbeAt' : '``
+ 'captured':[{'type':'response', 'side':'server', 'headers': {
+ 'Connection' : 'close',
+ 'Date' : '``
+ }},{'type':'response', 'side':'client', 'headers': {
+ 'Date' : '``
+ 'Age' : '0',
+ 'Transfer-Encoding' : 'chunked',
+ 'Connection' : 'close',
+ 'Server' : 'ATS/``
+ 'X-Remap' : 'from=http://two/, to=http://127.0.0.1:SERVER_PORT/',
+ }}
+ ]
+}
0
======
@@ -118,10 +381,42 @@ HTTP/1.1 200 OK
Date: ``
Age: ``
Transfer-Encoding: chunked
-Connection: keep-alive
+Connection: close
Server: ATS/``
X-Remap: from=http://two/, to=http://127.0.0.1:SERVER_PORT/
+``
+{'xDebugProbeAt' : '``
+ 'captured':[{'type':'request', 'side':'client', 'headers': {
+ 'Host' : '127.0.0.1:SERVER_PORT',
+ 'Connection' : 'close',
+ }},{'type':'request', 'side':'server', 'headers': {
+ 'Host' : '127.0.0.1:SERVER_PORT',
+ 'Client-ip' : '127.0.0.1',
+ 'X-Forwarded-For' : '127.0.0.1',
+ 'Via' : 'http/1.1 traffic_server[``
+ }}
+ ]
+}
+--- ATS xDebug Probe Injection Boundary ---
+
+
+--- ATS xDebug Probe Injection Boundary ---
+
+{'xDebugProbeAt' : '``
+ 'captured':[{'type':'response', 'side':'server', 'headers': {
+ 'Connection' : 'close',
+ 'Date' : '``
+ }},{'type':'response', 'side':'client', 'headers': {
+ 'Date' : '``
+ 'Age' : '0',
+ 'Transfer-Encoding' : 'chunked',
+ 'Connection' : 'close',
+ 'Server' : 'ATS/``
+ 'X-Remap' : 'from=http://two/, to=http://127.0.0.1:SERVER_PORT/',
+ }}
+ ]
+}
0
======
diff --git a/tests/gold_tests/pluginTest/xdebug/x_remap/three.in b/tests/gold_tests/pluginTest/xdebug/x_remap/three.in
index b525bf8..1d9612a 100644
--- a/tests/gold_tests/pluginTest/xdebug/x_remap/three.in
+++ b/tests/gold_tests/pluginTest/xdebug/x_remap/three.in
@@ -1,4 +1,5 @@
GET /argh HTTP/1.1
Host: three123
-X-Debug: X-Remap
+X-Debug: X-Remap, Probe
+Connection: close
diff --git a/tests/gold_tests/pluginTest/xdebug/x_remap/two.in b/tests/gold_tests/pluginTest/xdebug/x_remap/two.in
index c971a91..514d173 100644
--- a/tests/gold_tests/pluginTest/xdebug/x_remap/two.in
+++ b/tests/gold_tests/pluginTest/xdebug/x_remap/two.in
@@ -1,4 +1,5 @@
GET /argh HTTP/1.1
Host: two
-X-Debug: X-Remap
+X-Debug: PROBE, X-Remap
+Connection: close
diff --git a/tests/gold_tests/pluginTest/xdebug/x_remap/x_remap.gold b/tests/gold_tests/pluginTest/xdebug/x_remap/x_remap.gold
index d0baa81..5a1e2fd 100644
--- a/tests/gold_tests/pluginTest/xdebug/x_remap/x_remap.gold
+++ b/tests/gold_tests/pluginTest/xdebug/x_remap/x_remap.gold
@@ -6,13 +6,13 @@ X_DEBUG MISSING
-
X_DEBUG MISSING
-
-X-Remap, fwd
+X-Remap, fwd, Probe
-
X_DEBUG MISSING
-
-X-Remap, fwd=0
+X-Remap, fwd=0, Probe
-
-X-Remap, fwd=999998
+PROBE, X-Remap, fwd=999998
-
X_DEBUG MISSING
-
diff --git a/tests/gold_tests/pluginTest/xdebug/x_remap/x_remap.test.py b/tests/gold_tests/pluginTest/xdebug/x_remap/x_remap.test.py
index 89db82a..73773d8 100644
--- a/tests/gold_tests/pluginTest/xdebug/x_remap/x_remap.test.py
+++ b/tests/gold_tests/pluginTest/xdebug/x_remap/x_remap.test.py
@@ -15,13 +15,13 @@
# limitations under the License.
Test.Summary = '''
-Test xdebug plugin X-Remap and fwd headers
+Test xdebug plugin X-Remap, Probe and fwd headers
'''
server = Test.MakeOriginServer("server", options={'--load': (Test.TestDirectory + '/x_remap-observer.py')})
request_header = {
- "headers": "GET /argh HTTP/1.1\r\nHost: doesnotmatter\r\n\r\n", "timestamp": "1469733493.993", "body": ""}
+ "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)