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 2014/01/17 20:51:28 UTC

git commit: TS-2508: escalation plugin

Updated Branches:
  refs/heads/master 6af333d39 -> 9fda6972b


TS-2508: escalation plugin

The escalation plugin is intended to allow Traffic Server to handle
origin errors by rerouting to a different URL. This doesn't currently
work, since the APIs it uses cause crashes. In it's current form,
it should be useful as a test case to work on fixing the APIs.


Project: http://git-wip-us.apache.org/repos/asf/trafficserver/repo
Commit: http://git-wip-us.apache.org/repos/asf/trafficserver/commit/9fda6972
Tree: http://git-wip-us.apache.org/repos/asf/trafficserver/tree/9fda6972
Diff: http://git-wip-us.apache.org/repos/asf/trafficserver/diff/9fda6972

Branch: refs/heads/master
Commit: 9fda6972b6c36a8075e7f780521a589b19c22aff
Parents: 6af333d
Author: James Peach <jp...@apache.org>
Authored: Fri Jan 10 10:48:37 2014 -0800
Committer: James Peach <jp...@apache.org>
Committed: Fri Jan 17 11:51:05 2014 -0800

----------------------------------------------------------------------
 CHANGES                                   |   2 +
 configure.ac                              |   1 +
 plugins/experimental/Makefile.am          |   1 +
 plugins/experimental/escalate/Makefile.am |  22 ++++
 plugins/experimental/escalate/escalate.cc | 166 +++++++++++++++++++++++++
 5 files changed, 192 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/trafficserver/blob/9fda6972/CHANGES
----------------------------------------------------------------------
diff --git a/CHANGES b/CHANGES
index a0d6ffd..be6efa7 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,6 +1,8 @@
                                                          -*- coding: utf-8 -*-
 Changes with Apache Traffic Server 4.2.0
 
+  *) [TS-2508] Add a *highly* experimental escalation plugin.
+
   *) [TS-2507] Fix the state transition logging in HttpSM::handle_server_setup_error.
 
   *) [TS-1648] Segmentation fault in dir_clear_range()

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/9fda6972/configure.ac
----------------------------------------------------------------------
diff --git a/configure.ac b/configure.ac
index ebffa6f..a71f578 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1940,6 +1940,7 @@ AC_CONFIG_FILES([
   plugins/experimental/buffer_upload/Makefile
   plugins/experimental/channel_stats/Makefile
   plugins/experimental/custom_redirect/Makefile
+  plugins/experimental/escalate/Makefile
   plugins/experimental/esi/Makefile
   plugins/experimental/geoip_acl/Makefile
   plugins/experimental/lua/Makefile

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/9fda6972/plugins/experimental/Makefile.am
----------------------------------------------------------------------
diff --git a/plugins/experimental/Makefile.am b/plugins/experimental/Makefile.am
index fae383d..d2d14ab 100644
--- a/plugins/experimental/Makefile.am
+++ b/plugins/experimental/Makefile.am
@@ -19,6 +19,7 @@ if BUILD_EXPERIMENTAL_PLUGINS
 SUBDIRS = \
  authproxy \
  balancer \
+ escalate \
  buffer_upload \
  channel_stats \
  custom_redirect \

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/9fda6972/plugins/experimental/escalate/Makefile.am
----------------------------------------------------------------------
diff --git a/plugins/experimental/escalate/Makefile.am b/plugins/experimental/escalate/Makefile.am
new file mode 100644
index 0000000..1537847
--- /dev/null
+++ b/plugins/experimental/escalate/Makefile.am
@@ -0,0 +1,22 @@
+#  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 $(top_srcdir)/build/plugins.mk
+
+pkglib_LTLIBRARIES = escalate.la
+escalate_la_SOURCES = escalate.cc
+escalate_la_LDFLAGS = $(TS_PLUGIN_LDFLAGS)
+

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/9fda6972/plugins/experimental/escalate/escalate.cc
----------------------------------------------------------------------
diff --git a/plugins/experimental/escalate/escalate.cc b/plugins/experimental/escalate/escalate.cc
new file mode 100644
index 0000000..7181111
--- /dev/null
+++ b/plugins/experimental/escalate/escalate.cc
@@ -0,0 +1,166 @@
+/** @file
+
+  Escalation plugin.
+
+  @section license License
+
+  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 <ts/remap.h>
+#include <ts/experimental.h>
+#include <stdio.h>
+#include <getopt.h>
+#include <string.h>
+#include <string>
+#include <sstream>
+#include <iterator>
+#include <map>
+
+struct EscalationState
+{
+  typedef std::map<unsigned, TSMLoc> urlmap_type;
+
+  EscalationState() {
+    this->mbuf = TSMBufferCreate();
+  }
+
+  ~EscalationState() {
+    TSMBufferDestroy(this->mbuf);
+  }
+
+  TSCont      handler;
+  urlmap_type urlmap;
+  TSMBuffer   mbuf;
+};
+
+static unsigned
+toint(const std::string& str)
+{
+  std::istringstream istr(str);
+  unsigned val;
+
+  istr >> val;
+  return val;
+}
+
+static int
+EscalateResponse(TSCont cont, TSEvent event, void * edata)
+{
+  EscalationState * es = (EscalationState *)TSContDataGet(cont);
+  TSHttpTxn         txn = (TSHttpTxn)edata;
+  TSMBuffer         buffer;
+  TSMLoc            hdr;
+  TSHttpStatus      status;
+
+  TSDebug("escalate", "hit escalation hook with event %d", (int)event);
+  TSReleaseAssert(event == TS_EVENT_HTTP_READ_RESPONSE_HDR);
+
+  // First, we need the server response ...
+  TSReleaseAssert(
+    TSHttpTxnServerRespGet(txn, &buffer, &hdr) == TS_SUCCESS
+  );
+
+  // Next, the respose status ...
+  status = TSHttpHdrStatusGet(buffer, hdr);
+
+  // If we have an escalation URL for this response code, set the redirection URL and force it
+  // to be followed.
+  EscalationState::urlmap_type::iterator entry = es->urlmap.find((unsigned)status);
+  if (entry != es->urlmap.end()) {
+    TSDebug("escalate", "found an escalation entry for HTTP status %u", (unsigned)status);
+    TSHttpTxnRedirectRequest(txn, es->mbuf, entry->second);
+    TSHttpTxnFollowRedirect(txn, 1 /* on */);
+  }
+
+  // Set the transaction free ...
+  TSHttpTxnReenable(txn, TS_EVENT_HTTP_CONTINUE);
+  return TS_EVENT_NONE;
+}
+
+TSReturnCode
+TSRemapInit(TSRemapInterface * /* api */, char * /* errbuf */, int /* bufsz */)
+{
+  return TS_SUCCESS;
+}
+
+TSReturnCode
+TSRemapNewInstance(int argc, char * argv[], void ** instance, char * errbuf, int errbuf_size)
+{
+  EscalationState * es((EscalationState *)instance);
+
+  es = new EscalationState();
+  es->handler = TSContCreate(EscalateResponse, NULL);
+  TSContDataSet(es->handler, es);
+
+  // The first two arguments are the "from" and "to" URL string. We can just
+  // skip those, since we only ever remap on the error path.
+  for (int i = 2; i < argc; ++i) {
+    unsigned  status;
+    TSMLoc    url;
+    char *    sep;
+
+    // Each token should be a status code then a URL, separated by '='.
+    sep = strchr(argv[i], '=');
+    if (sep == NULL) {
+      snprintf(errbuf, errbuf_size, "missing status code: %s", argv[i]);
+      goto fail;
+    }
+
+    status = toint(std::string(argv[i], std::distance(argv[i], sep)));
+    if (status < 100 || status > 599) {
+      snprintf(errbuf, errbuf_size, "invalid status code: %.*s", (int)std::distance(argv[i], sep), argv[i]);
+      goto fail;
+    }
+
+    TSReleaseAssert(TSUrlCreate(es->mbuf, &url) == TS_SUCCESS);
+
+    ++sep; // Skip over the '='.
+
+    TSDebug("escalate", "escalating HTTP status %u to %s", status, sep);
+    if (TSUrlParse(es->mbuf, url, (const char **)&sep, argv[i] + strlen(argv[i])) != TS_PARSE_DONE) {
+      snprintf(errbuf, errbuf_size, "invalid target URL: %s", sep);
+      goto fail;
+    }
+
+    // OK, we have a valid status/URL pair.
+    es->urlmap[status] = url;
+  }
+
+  *instance = es;
+  return TS_SUCCESS;
+
+fail:
+  delete es;
+  return TS_ERROR;
+}
+
+void
+TSRemapDeleteInstance(void * instance)
+{
+  delete (EscalationState *)instance;
+}
+
+TSRemapStatus
+TSRemapDoRemap(void * instance, TSHttpTxn txn, TSRemapRequestInfo * /* rri */)
+{
+  EscalationState * es((EscalationState *)instance);
+
+  TSHttpTxnHookAdd(txn, TS_HTTP_READ_RESPONSE_HDR_HOOK, es->handler);
+  return TSREMAP_NO_REMAP;
+}