You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@trafficserver.apache.org by jp...@apache.org on 2013/12/10 18:30:24 UTC
[2/3] git commit: TS-2426: add the xdebug plugin
TS-2426: add the xdebug plugin
The xdebug plugin scans X-Debug header values and emits the requested
debug information. The plugin is named after the X- prefix of the
headers that is scans and emits.
The values we scan for are names of debug headers. The first header
to be supported is X-Cache-Key, which report the cache lookup URL
used buy the request. the second header supported is the Via header,
which causes a verbose Via header to be emitted for the request.
Project: http://git-wip-us.apache.org/repos/asf/trafficserver/repo
Commit: http://git-wip-us.apache.org/repos/asf/trafficserver/commit/14667c65
Tree: http://git-wip-us.apache.org/repos/asf/trafficserver/tree/14667c65
Diff: http://git-wip-us.apache.org/repos/asf/trafficserver/diff/14667c65
Branch: refs/heads/master
Commit: 14667c65ff72d6af5da9bec62c41548076093091
Parents: 5e256d2
Author: James Peach <jp...@apache.org>
Authored: Tue Dec 3 15:03:36 2013 -0800
Committer: James Peach <jp...@apache.org>
Committed: Tue Dec 10 09:26:51 2013 -0800
----------------------------------------------------------------------
CHANGES | 3 +
configure.ac | 1 +
plugins/experimental/Makefile.am | 23 +--
plugins/experimental/xdebug/xdebug.cc | 217 +++++++++++++++++++++++++++++
4 files changed, 234 insertions(+), 10 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/trafficserver/blob/14667c65/CHANGES
----------------------------------------------------------------------
diff --git a/CHANGES b/CHANGES
index 49488e9..30afc6c 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,6 +1,9 @@
-*- coding: utf-8 -*-
Changes with Apache Traffic Server 4.2.0
+
+ *) [TS-2426] Add a new plugin, xdebug, for cache debugging using HTTP headers.
+
*) [TS-2077] Remove pipeline configurations, they were no-op's anyways. We
still support pipelining (we always do), it's just not treated specially
(or optimized).
http://git-wip-us.apache.org/repos/asf/trafficserver/blob/14667c65/configure.ac
----------------------------------------------------------------------
diff --git a/configure.ac b/configure.ac
index fd41a1b..c16f89f 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1935,6 +1935,7 @@ AC_CONFIG_FILES([
plugins/experimental/tcp_info/Makefile
plugins/experimental/healthchecks/Makefile
plugins/experimental/remap_stats/Makefile
+ plugins/experimental/xdebug/Makefile
plugins/gzip/Makefile
plugins/libloader/Makefile
plugins/header_filter/Makefile
http://git-wip-us.apache.org/repos/asf/trafficserver/blob/14667c65/plugins/experimental/Makefile.am
----------------------------------------------------------------------
diff --git a/plugins/experimental/Makefile.am b/plugins/experimental/Makefile.am
index b0e4d98..3d5a453 100644
--- a/plugins/experimental/Makefile.am
+++ b/plugins/experimental/Makefile.am
@@ -15,19 +15,22 @@
# limitations under the License.
if BUILD_EXPERIMENTAL_PLUGINS
+
SUBDIRS = \
- lua \
- ts_lua \
+ authproxy \
buffer_upload \
- esi \
- rfc5861 \
- tcp_info \
- custom_redirect \
- metalink \
- spdy \
channel_stats \
- authproxy \
+ custom_redirect \
+ esi \
geoip_acl \
healthchecks \
- remap_stats
+ lua \
+ metalink \
+ remap_stats \
+ rfc5861 \
+ spdy \
+ tcp_info \
+ ts_lua \
+ xdebug
+
endif
http://git-wip-us.apache.org/repos/asf/trafficserver/blob/14667c65/plugins/experimental/xdebug/xdebug.cc
----------------------------------------------------------------------
diff --git a/plugins/experimental/xdebug/xdebug.cc b/plugins/experimental/xdebug/xdebug.cc
new file mode 100644
index 0000000..e33ffa3
--- /dev/null
+++ b/plugins/experimental/xdebug/xdebug.cc
@@ -0,0 +1,217 @@
+/*
+ * 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.
+ */
+
+#include <ts/ts.h>
+#include <stdlib.h>
+#include <strings.h>
+
+// The name of the debug request header. This should probably be configurable.
+#define X_DEBUG_HEADER "X-Debug"
+
+#define XHEADER_X_CACHE_KEY 0x0004u
+
+static int XArgIndex = 0;
+static TSCont XInjectHeadersCont = NULL;
+
+// Return the length of a string literal.
+template <int N> unsigned
+lengthof(const char (&str)[N]) {
+ return N - 1;
+}
+
+static TSMLoc
+FindOrMakeHdrField(TSMBuffer buffer, TSMLoc hdr, const char * name, unsigned len)
+{
+ TSMLoc field;
+
+ field = TSMimeHdrFieldFind(buffer, hdr, name, len);
+ if (field == TS_NULL_MLOC) {
+ if (TSMimeHdrFieldCreateNamed(buffer, hdr, name, len, &field) == TS_SUCCESS) {
+ TSReleaseAssert(TSMimeHdrFieldAppend(buffer, hdr, field) == TS_SUCCESS);
+ }
+ }
+
+ return field;
+}
+
+static void
+InjectCacheKeyHeader(TSHttpTxn txn, TSMBuffer buffer, TSMLoc hdr)
+{
+ TSMLoc url = TS_NULL_MLOC;
+ TSMLoc dst = TS_NULL_MLOC;
+
+ struct { char * ptr; int len; } strval = { NULL, 0 };
+
+ TSDebug("xdebug", "attempting to inject X-Cache-Key header");
+
+ if (TSUrlCreate(buffer, &url) != TS_SUCCESS) {
+ goto done;
+ }
+
+ if (TSHttpTxnCacheLookupUrlGet(txn, buffer, url) != TS_SUCCESS) {
+ goto done;
+ }
+
+ strval.ptr = TSUrlStringGet(buffer, url, &strval.len);
+ if (strval.ptr == NULL || strval.len == 0) {
+ goto done;
+ }
+
+ // Create a new response header field.
+ dst = FindOrMakeHdrField(buffer, hdr, "X-Cache-Key", lengthof("X-Cache-Key"));
+ if (dst == TS_NULL_MLOC) {
+ goto done;
+ }
+
+ // Now copy the cache lookup URL into the response header.
+ TSReleaseAssert(
+ TSMimeHdrFieldValueStringInsert(buffer, hdr, dst, 0 /* idx */, strval.ptr, strval.len) == TS_SUCCESS
+ );
+
+done:
+ if (dst != TS_NULL_MLOC) {
+ TSHandleMLocRelease(buffer, hdr, dst);
+ }
+
+ if (url != TS_NULL_MLOC) {
+ TSHandleMLocRelease(buffer, TS_NULL_MLOC, url);
+ }
+
+ TSfree(strval.ptr);
+}
+
+static int
+XInjectResponseHeaders(TSCont contp, TSEvent event, void * edata)
+{
+ TSHttpTxn txn = (TSHttpTxn)edata;
+ intptr_t xheaders = 0;
+ TSMBuffer buffer;
+ TSMLoc hdr;
+
+ TSReleaseAssert(event == TS_EVENT_HTTP_SEND_RESPONSE_HDR);
+
+ xheaders = (intptr_t)TSHttpTxnArgGet(txn, XArgIndex);
+ if (xheaders == 0) {
+ goto done;
+ }
+
+ if (TSHttpTxnClientRespGet(txn, &buffer, &hdr) == TS_ERROR) {
+ goto done;
+ }
+
+ if (xheaders & XHEADER_X_CACHE_KEY) {
+ InjectCacheKeyHeader(txn, buffer, hdr);
+ }
+
+done:
+ TSHttpTxnReenable(txn, TS_EVENT_HTTP_CONTINUE);
+ return TS_EVENT_NONE;
+}
+
+// Scan the client request headers and determine which debug headers they
+// want in the response.
+static int
+XScanRequestHeaders(TSCont contp, TSEvent event, void * edata)
+{
+ TSHttpTxn txn = (TSHttpTxn)edata;
+ intptr_t xheaders = 0;
+ TSMLoc field, next;
+ TSMBuffer buffer;
+ TSMLoc hdr;
+
+ TSReleaseAssert(event == TS_EVENT_HTTP_READ_REQUEST_HDR);
+
+ if (TSHttpTxnClientReqGet(txn, &buffer, &hdr) == TS_ERROR) {
+ goto done;
+ }
+
+ TSDebug("xdebug", "scanning for %s header values", X_DEBUG_HEADER);
+
+ // Walk the X-Debug header values and determine what to inject into the response.
+ field = TSMimeHdrFieldFind(buffer, hdr, X_DEBUG_HEADER, lengthof(X_DEBUG_HEADER));
+ while (field != TS_NULL_MLOC) {
+ int count = TSMimeHdrFieldValuesCount(buffer, hdr, field);
+
+ for (int i = 0; i < count; ++i) {
+ const char * value;
+ int vsize;
+
+ value = TSMimeHdrFieldValueStringGet(buffer, hdr, field, i, &vsize);
+ if (value == NULL || vsize == 0) {
+ continue;
+ }
+
+ if (strncasecmp("x-cache-key", value, vsize) == 0) {
+ xheaders |= XHEADER_X_CACHE_KEY;
+ } else if (strncasecmp("via", value, vsize) == 0) {
+ // 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 {
+ TSDebug("xdebug", "ignoring unrecognized debug tag '%.*s'", vsize, value);
+ }
+ }
+
+ // Get the next duplicate.
+ next = TSMimeHdrFieldNextDup(buffer, hdr, field);
+
+ // Destroy the current field that we have. We don't want this to go through and potentially confuse the origin.
+ TSMimeHdrFieldRemove(buffer, hdr, field);
+ TSMimeHdrFieldDestroy(buffer, hdr, field);
+
+ // Now release our reference.
+ TSHandleMLocRelease(buffer, hdr, field);
+
+ // And go to the next field.
+ field = next;
+ }
+
+ if (xheaders) {
+ TSHttpTxnHookAdd(txn, TS_HTTP_SEND_RESPONSE_HDR_HOOK, XInjectHeadersCont);
+ TSHttpTxnArgSet(txn, XArgIndex, (void *)xheaders);
+ }
+
+done:
+ TSHttpTxnReenable(txn, TS_EVENT_HTTP_CONTINUE);
+ return TS_EVENT_NONE;
+}
+
+void
+TSPluginInit(int argc, const char *argv[])
+{
+ TSPluginRegistrationInfo info;
+
+ info.plugin_name = (char *)"xdebug";
+ info.vendor_name = (char *)"Apache Software Foundation";
+ info.support_email = (char *)"dev@trafficserver.apache.org";
+
+ if (TSPluginRegister(TS_SDK_VERSION_3_0, &info) != TS_SUCCESS) {
+ TSError("xdebug plugin registration failed");
+ }
+
+ TSReleaseAssert(
+ TSHttpArgIndexReserve("xdebug", "xdebug header requests" , &XArgIndex) == TS_SUCCESS
+ );
+
+ TSReleaseAssert(
+ XInjectHeadersCont = TSContCreate(XInjectResponseHeaders, NULL)
+ );
+
+ TSHttpHookAdd(TS_HTTP_READ_REQUEST_HDR_HOOK, TSContCreate(XScanRequestHeaders, NULL));
+}
+
+// vim: set ts=2 sw=2 et :