Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions doc/admin-guide/plugins/xdebug.en.rst
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,15 @@ configuration option, ``--header``. E.g.

This overrides the default ``X-Debug`` header name.

All the debug headers are disabled by default, and you need to enable them
selectively by passing header names to ``--enable`` option.

--enable=x-remap,x-cache

This enables ``X-Remap`` and ``X-Cache``. If a client's request has
``X-Debug: x-remap, x-cache, probe``, XDebug will only injects ``X-Reamp`` and
``X-Cache``.


Debugging Headers
=================
Expand Down
116 changes: 93 additions & 23 deletions plugins/xdebug/xdebug.cc
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#include <cstdint>
#include <cinttypes>
#include <string_view>
#include <algorithm>
#include <unistd.h>

#include <ts/ts.h>
Expand Down Expand Up @@ -84,6 +85,46 @@ enum {
XHEADER_X_PSELECT_KEY = 1u << 10,
XHEADER_X_CACHE_INFO = 1u << 11,
XHEADER_X_EFFECTIVE_URL = 1u << 12,
XHEADER_VIA = 1u << 13,
XHEADER_DIAGS = 1u << 14,
XHEADER_ALL = UINT_MAX
};

static unsigned int allowedHeaders = 0;

constexpr std::string_view HEADER_NAME_X_CACHE_KEY = "x-cache-key";
constexpr std::string_view HEADER_NAME_X_MILESTONES = "x-milestones";
constexpr std::string_view HEADER_NAME_X_CACHE = "x-cache";
constexpr std::string_view HEADER_NAME_X_GENERATION = "x-cache-generation";
constexpr std::string_view HEADER_NAME_X_TRANSACTION_ID = "x-transaction-id";
constexpr std::string_view HEADER_NAME_X_DUMP_HEADERS = "x-dump-headers";
constexpr std::string_view HEADER_NAME_X_REMAP = "x-remap";
constexpr std::string_view HEADER_NAME_X_PROBE_HEADERS = "probe";
constexpr std::string_view HEADER_NAME_X_PSELECT_KEY = "x-parentselection-key";
constexpr std::string_view HEADER_NAME_X_CACHE_INFO = "x-cache-info";
constexpr std::string_view HEADER_NAME_X_EFFECTIVE_URL = "x-effective-url";
constexpr std::string_view HEADER_NAME_VIA = "via";
constexpr std::string_view HEADER_NAME_DIAGS = "diags";
constexpr std::string_view HEADER_NAME_ALL = "all";

constexpr struct XHeader {
std::string_view name;
unsigned int flag;
} header_flags[] = {
{HEADER_NAME_X_CACHE_KEY, XHEADER_X_CACHE_KEY},
{HEADER_NAME_X_MILESTONES, XHEADER_X_MILESTONES},
{HEADER_NAME_X_CACHE, XHEADER_X_CACHE},
{HEADER_NAME_X_GENERATION, XHEADER_X_GENERATION},
{HEADER_NAME_X_TRANSACTION_ID, XHEADER_X_TRANSACTION_ID},
{HEADER_NAME_X_DUMP_HEADERS, XHEADER_X_DUMP_HEADERS},
{HEADER_NAME_X_REMAP, XHEADER_X_REMAP},
{HEADER_NAME_X_PROBE_HEADERS, XHEADER_X_PROBE_HEADERS},
{HEADER_NAME_X_PSELECT_KEY, XHEADER_X_PSELECT_KEY},
{HEADER_NAME_X_CACHE_INFO, XHEADER_X_CACHE_INFO},
{HEADER_NAME_X_EFFECTIVE_URL, XHEADER_X_EFFECTIVE_URL},
{HEADER_NAME_VIA, XHEADER_VIA},
{HEADER_NAME_DIAGS, XHEADER_DIAGS},
{HEADER_NAME_ALL, XHEADER_ALL},
};

static TSCont XInjectHeadersCont = nullptr;
Expand Down Expand Up @@ -623,30 +664,30 @@ XScanRequestHeaders(TSCont /* contp */, TSEvent event, void *edata)
continue;
}

#define header_field_eq(name, vptr, vlen) (((int)lengthof(name) == vlen) && (strncasecmp(name, vptr, vlen) == 0))

if (header_field_eq("x-cache-key", value, vsize)) {
xheaders |= XHEADER_X_CACHE_KEY;
} else if (header_field_eq("x-cache-info", value, vsize)) {
xheaders |= XHEADER_X_CACHE_INFO;
} else if (header_field_eq("x-milestones", value, vsize)) {
xheaders |= XHEADER_X_MILESTONES;
} else if (header_field_eq("x-cache", value, vsize)) {
xheaders |= XHEADER_X_CACHE;
} else if (header_field_eq("x-cache-generation", value, vsize)) {
xheaders |= XHEADER_X_GENERATION;
} else if (header_field_eq("x-transaction-id", value, vsize)) {
xheaders |= XHEADER_X_TRANSACTION_ID;
} else if (header_field_eq("x-remap", value, vsize)) {
xheaders |= XHEADER_X_REMAP;
} else if (header_field_eq("via", value, vsize)) {
#define header_field_eq(name, vptr, vlen) (((int)name.size() == vlen) && (strncasecmp(name.data(), vptr, vlen) == 0))

if (header_field_eq(HEADER_NAME_X_CACHE_KEY, value, vsize)) {
xheaders |= XHEADER_X_CACHE_KEY & allowedHeaders;
} else if (header_field_eq(HEADER_NAME_X_CACHE_INFO, value, vsize)) {
xheaders |= XHEADER_X_CACHE_INFO & allowedHeaders;
} else if (header_field_eq(HEADER_NAME_X_MILESTONES, value, vsize)) {
xheaders |= XHEADER_X_MILESTONES & allowedHeaders;
} else if (header_field_eq(HEADER_NAME_X_CACHE, value, vsize)) {
xheaders |= XHEADER_X_CACHE & allowedHeaders;
} else if (header_field_eq(HEADER_NAME_X_GENERATION, value, vsize)) {
xheaders |= XHEADER_X_GENERATION & allowedHeaders;
} else if (header_field_eq(HEADER_NAME_X_TRANSACTION_ID, value, vsize)) {
xheaders |= XHEADER_X_TRANSACTION_ID & allowedHeaders;
} else if (header_field_eq(HEADER_NAME_X_REMAP, value, vsize)) {
xheaders |= XHEADER_X_REMAP & allowedHeaders;
} else if (header_field_eq(HEADER_NAME_VIA, value, vsize) && (XHEADER_VIA & allowedHeaders)) {
// If the client requests the Via header, enable verbose Via debugging for this transaction.
TSHttpTxnConfigIntSet(txn, TS_CONFIG_HTTP_INSERT_RESPONSE_VIA_STR, 3);
} else if (header_field_eq("diags", value, vsize)) {
} else if (header_field_eq(HEADER_NAME_DIAGS, value, vsize) && (XHEADER_DIAGS & allowedHeaders)) {
// Enable diagnostics for DebugTxn()'s only
TSHttpTxnCntlSet(txn, TS_HTTP_CNTL_TXN_DEBUG, true);

} else if (header_field_eq("probe", value, vsize)) {
} else if (header_field_eq(HEADER_NAME_X_PROBE_HEADERS, value, vsize) && (XHEADER_X_PROBE_HEADERS & allowedHeaders)) {
xheaders |= XHEADER_X_PROBE_HEADERS;

auto &auxData = AuxDataMgr::data(txn);
Expand All @@ -667,8 +708,8 @@ XScanRequestHeaders(TSCont /* contp */, TSEvent event, void *edata)
TSHttpTxnTransformedRespCache(txn, 0);
TSHttpTxnUntransformedRespCache(txn, 0);

} else if (header_field_eq("x-parentselection-key", value, vsize)) {
xheaders |= XHEADER_X_PSELECT_KEY;
} else if (header_field_eq(HEADER_NAME_X_PSELECT_KEY, value, vsize)) {
xheaders |= XHEADER_X_PSELECT_KEY & allowedHeaders;

} else if (isFwdFieldValue(std::string_view(value, vsize), fwdCnt)) {
if (fwdCnt > 0) {
Expand All @@ -677,8 +718,8 @@ XScanRequestHeaders(TSCont /* contp */, TSEvent event, void *edata)
snprintf(newVal, sizeof(newVal), "fwd=%" PRIiMAX, fwdCnt - 1);
TSMimeHdrFieldValueStringSet(buffer, hdr, field, i, newVal, std::strlen(newVal));
}
} else if (header_field_eq("x-effective-url", value, vsize)) {
xheaders |= XHEADER_X_EFFECTIVE_URL;
} else if (header_field_eq(HEADER_NAME_X_EFFECTIVE_URL, value, vsize)) {
xheaders |= XHEADER_X_EFFECTIVE_URL & allowedHeaders;
} else {
TSDebug("xdebug", "ignoring unrecognized debug tag '%.*s'", vsize, value);
}
Expand Down Expand Up @@ -744,10 +785,32 @@ XDeleteDebugHdr(TSCont /* contp */, TSEvent event, void *edata)
return TS_EVENT_NONE;
}

static void
updateAllowedHeaders(const char *optarg)
{
char *list;
char *token;
char *last;

list = TSstrdup(optarg);
std::transform(list, list + strlen(list), list, ::tolower);
for (token = strtok_r(list, ",", &last); token; token = strtok_r(nullptr, ",", &last)) {
const auto ite = std::find_if(std::begin(header_flags), std::end(header_flags),
[token](const struct XHeader &x) { return x.name.compare(token) == 0; });
if (ite != std::end(header_flags)) {
allowedHeaders |= ite->flag;
} else {
TSError("[xdebug] Unknown header name: %s", token);
}
}
TSfree(list);
}

void
TSPluginInit(int argc, const char *argv[])
{
static const struct option longopt[] = {{const_cast<char *>("header"), required_argument, nullptr, 'h'},
{const_cast<char *>("enable"), required_argument, nullptr, 'e'},
{nullptr, no_argument, nullptr, '\0'}};
TSPluginRegistrationInfo info;

Expand All @@ -767,13 +830,20 @@ TSPluginInit(int argc, const char *argv[])
case 'h':
xDebugHeader.str = TSstrdup(optarg);
break;
case 'e':
updateAllowedHeaders(optarg);
break;
}

if (opt == -1) {
break;
}
}

if (allowedHeaders == 0) {
TSError("[xdebug] No features are enabled");
}

if (nullptr == xDebugHeader.str) {
xDebugHeader.str = TSstrdup("X-Debug"); // We malloc this, for consistency for future plugin unload events
}
Expand Down
2 changes: 1 addition & 1 deletion tests/gold_tests/cache/cache-control.test.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@
server.addResponse("sessionlog.json", request_header3, response_header3)

# ATS Configuration
ts.Disk.plugin_config.AddLine('xdebug.so')
ts.Disk.plugin_config.AddLine('xdebug.so --enable=x-cache,x-cache-key,via')
ts.Disk.records_config.update({
'proxy.config.diags.debug.enabled': 1,
'proxy.config.diags.debug.tags': 'http',
Expand Down
2 changes: 1 addition & 1 deletion tests/gold_tests/cache/cache-generation-clear.test.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
'proxy.config.config_update_interval_ms': 1,
})

ts.Disk.plugin_config.AddLine('xdebug.so')
ts.Disk.plugin_config.AddLine('xdebug.so --enable=x-cache,x-cache-key,via,x-cache-generation')
ts.Disk.remap_config.AddLines([
'map /default/ http://127.0.0.1/ @plugin=generator.so',
# line 2
Expand Down
2 changes: 1 addition & 1 deletion tests/gold_tests/cache/cache-generation-disjoint.test.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
'proxy.config.config_update_interval_ms': 1,

})
ts.Disk.plugin_config.AddLine('xdebug.so')
ts.Disk.plugin_config.AddLine('xdebug.so --enable=x-cache,x-cache-key,via,x-cache-generation')
ts.Disk.remap_config.AddLines([
'map /default/ http://127.0.0.1/ @plugin=generator.so',
# line 2
Expand Down
2 changes: 1 addition & 1 deletion tests/gold_tests/cache/disjoint-wait-for-cache.test.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
'proxy.config.config_update_interval_ms': 1,
'proxy.config.http.wait_for_cache': 3,
})
ts.Disk.plugin_config.AddLine('xdebug.so')
ts.Disk.plugin_config.AddLine('xdebug.so --enable=x-cache,x-cache-key,via,x-cache-generation')
ts.Disk.remap_config.AddLines([
'map /default/ http://127.0.0.1/ @plugin=generator.so',
# line 2
Expand Down
2 changes: 1 addition & 1 deletion tests/gold_tests/headers/cache_and_req_body.test.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
server.addResponse("sessionlog.json", request_header, response_header)

# ATS Configuration
ts.Disk.plugin_config.AddLine('xdebug.so')
ts.Disk.plugin_config.AddLine('xdebug.so --enable=x-cache,x-cache-key,via')
ts.Disk.records_config.update({
'proxy.config.diags.debug.enabled': 1,
'proxy.config.diags.debug.tags': 'http',
Expand Down
2 changes: 1 addition & 1 deletion tests/gold_tests/headers/cachedIMSRange.test.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@

# ATS Configuration
ts = Test.MakeATSProcess("ts", enable_tls=True)
ts.Disk.plugin_config.AddLine('xdebug.so')
ts.Disk.plugin_config.AddLine('xdebug.so --enable=x-cache,x-cache-key,via')
ts.addDefaultSSLFiles()
ts.Disk.ssl_multicert_config.AddLine(
'dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,7 @@
])

# cache debug
ts.Disk.plugin_config.AddLine('xdebug.so')
ts.Disk.plugin_config.AddLine('xdebug.so --enable=x-cache,x-parentselection-key')

# minimal configuration
ts.Disk.records_config.update({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,7 @@
])

# cache debug
ts.Disk.plugin_config.AddLine('xdebug.so')
ts.Disk.plugin_config.AddLine('xdebug.so --enable=x-cache,x-cache-key')

# enable debug
ts.Disk.records_config.update({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@
)

# cache debug
ts.Disk.plugin_config.AddLine('xdebug.so')
ts.Disk.plugin_config.AddLine('xdebug.so --enable=x-cache')

# minimal configuration
ts.Disk.records_config.update({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@
ts.Disk.plugin_config.AddLines([
'cachekey.so --include-headers=Range --static-prefix=foo',
'cache_range_requests.so --no-modify-cachekey',
'xdebug.so',
'xdebug.so --enable=x-cache,x-cache-key,x-parentselection-key',
])

# minimal configuration
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@
])

# cache debug
ts.Disk.plugin_config.AddLine('xdebug.so')
ts.Disk.plugin_config.AddLine('xdebug.so --enable=x-cache')

# minimal configuration
ts.Disk.records_config.update({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@
server.addResponse("sessionlog.json", request_header_3, response_header_3)

# Configure ATS server
ts.Disk.plugin_config.AddLine('xdebug.so')
ts.Disk.plugin_config.AddLine('xdebug.so --enable=x-cache')
ts.Disk.plugin_config.AddLine(
'regex_revalidate.so -d -c regex_revalidate.conf'
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@
server.addResponse("sessionlog.json", request_header_1, response_header_1)

# Configure ATS server
ts.Disk.plugin_config.AddLine('xdebug.so')
ts.Disk.plugin_config.AddLine('xdebug.so --enable=x-cache')
ts.Disk.plugin_config.AddLine(
'regex_revalidate.so -d -c regex_revalidate.conf -l revalidate.log'
)
Expand Down
2 changes: 1 addition & 1 deletion tests/gold_tests/pluginTest/slice/slice_prefetch.test.py
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@
' @plugin=cache_range_requests.so',
])

ts.Disk.plugin_config.AddLine('xdebug.so')
ts.Disk.plugin_config.AddLine('xdebug.so --enable=x-cache')
ts.Disk.logging_yaml.AddLines([
'logging:',
' formats:',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ def to_httpdate(dt):
' @plugin=cache_range_requests.so @pparam=--ims-header=crr-foo',
])

ts.Disk.plugin_config.AddLine('xdebug.so')
ts.Disk.plugin_config.AddLine('xdebug.so --enable=x-cache')

ts.Disk.records_config.update({
'proxy.config.diags.debug.enabled': 0,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
'proxy.config.diags.debug.tags': 'http'
})

ts.Disk.plugin_config.AddLine('xdebug.so')
ts.Disk.plugin_config.AddLine('xdebug.so --enable=x-cache-info')

ts.Disk.remap_config.AddLine(
"map http://one http://127.0.0.1:{0}".format(server.Variables.Port)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
'proxy.config.diags.debug.enabled': 0,
})

ts.Disk.plugin_config.AddLine('xdebug.so')
ts.Disk.plugin_config.AddLine('xdebug.so --enable=x-effective-url')

ts.Disk.remap_config.AddLine(
"map http://one http://127.0.0.1:{0}".format(server.Variables.Port)
Expand Down
2 changes: 1 addition & 1 deletion tests/gold_tests/pluginTest/xdebug/x_remap/x_remap.test.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
# 'proxy.config.diags.debug.tags': 'xdebug'
})

ts.Disk.plugin_config.AddLine('xdebug.so')
ts.Disk.plugin_config.AddLine('xdebug.so --enable=x-remap,probe')

ts.Disk.remap_config.AddLine(
"map http://one http://127.0.0.1:{0}".format(server.Variables.Port)
Expand Down