You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@trafficserver.apache.org by zw...@apache.org on 2013/12/14 22:51:45 UTC

[36/50] 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/5.0.x
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 :