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 2014/04/17 18:44:07 UTC

[08/50] git commit: TS-2690 Fixes for escalation plugin

TS-2690 Fixes for escalation plugin

This fixes the following:

1. Change to use the API for following redirects.
2. Make it only replace the "host" portions of a URL
3. Cleanup.


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

Branch: refs/heads/5.0.x
Commit: d3e2d2ce5ddf9f9eb07ece751b79ef810e291bd1
Parents: dfc2a8f
Author: Leif Hedstrom <zw...@apache.org>
Authored: Wed Apr 2 10:03:31 2014 -0600
Committer: Leif Hedstrom <zw...@apache.org>
Committed: Thu Apr 10 06:50:21 2014 -0600

----------------------------------------------------------------------
 plugins/experimental/escalate/escalate.cc | 140 +++++++++++++------------
 1 file changed, 75 insertions(+), 65 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/trafficserver/blob/d3e2d2ce/plugins/experimental/escalate/escalate.cc
----------------------------------------------------------------------
diff --git a/plugins/experimental/escalate/escalate.cc b/plugins/experimental/escalate/escalate.cc
index 7181111..d013b27 100644
--- a/plugins/experimental/escalate/escalate.cc
+++ b/plugins/experimental/escalate/escalate.cc
@@ -28,64 +28,84 @@
 #include <getopt.h>
 #include <string.h>
 #include <string>
-#include <sstream>
 #include <iterator>
 #include <map>
 
+
+// Constants
+const char PLUGIN_NAME[] = "escalate";
+
+
+static int EscalateResponse(TSCont, TSEvent, void *);
+
 struct EscalationState
 {
-  typedef std::map<unsigned, TSMLoc> urlmap_type;
+  typedef std::map<unsigned, std::string> hostmap_type;
 
-  EscalationState() {
-    this->mbuf = TSMBufferCreate();
+  EscalationState()
+  {
+    handler = TSContCreate(EscalateResponse, NULL);
+    TSContDataSet(handler, this);
   }
 
-  ~EscalationState() {
-    TSMBufferDestroy(this->mbuf);
+  ~EscalationState()
+  {
+    TSContDestroy(handler);
   }
 
-  TSCont      handler;
-  urlmap_type urlmap;
-  TSMBuffer   mbuf;
+  TSCont       handler;
+  hostmap_type hostmap;
 };
 
-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)
+EscalateResponse(TSCont cont, TSEvent event, void* edata)
 {
-  EscalationState * es = (EscalationState *)TSContDataGet(cont);
-  TSHttpTxn         txn = (TSHttpTxn)edata;
-  TSMBuffer         buffer;
-  TSMLoc            hdr;
-  TSHttpStatus      status;
+  EscalationState* es = static_cast<EscalationState*>(TSContDataGet(cont));
+  TSHttpTxn        txn = (TSHttpTxn)edata;
+  TSMBuffer        response;
+  TSMLoc           resp_hdr;
 
-  TSDebug("escalate", "hit escalation hook with event %d", (int)event);
+  TSDebug(PLUGIN_NAME, "Recieved 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 */);
+  if (TS_SUCCESS == TSHttpTxnServerRespGet(txn, &response, &resp_hdr)) {
+    // Next, the respose status ...
+    TSHttpStatus status = TSHttpHdrStatusGet(response, resp_hdr);
+
+    // If we have an escalation URL for this response code, set the redirection URL and force it
+    // to be followed.
+    EscalationState::hostmap_type::iterator entry = es->hostmap.find((unsigned)status);
+
+    if (entry != es->hostmap.end()) {
+      TSMBuffer request;
+      TSMLoc    req_hdr;
+
+      TSDebug(PLUGIN_NAME, "found an escalation entry for HTTP status %u", (unsigned)status);
+      if (TS_SUCCESS == TSHttpTxnClientReqGet(txn, &request, &req_hdr)) {
+        TSMLoc url;
+
+        if (TS_SUCCESS == TSHttpHdrUrlGet(request, req_hdr, &url)) {
+          char* url_str;
+          int url_len;
+
+          // Update the request URL with the new Host to try.
+          TSUrlHostSet(request, url, entry->second.c_str(), entry->second.size());
+          url_str = TSUrlStringGet(request, url, &url_len);
+
+          TSDebug(PLUGIN_NAME, "Setting new URL to %.*s", url_len, url_str);
+          TSRedirectUrlSet(txn, url_str, url_len);
+
+          TSfree(static_cast<void*>(url_str));
+        }
+        // Release the response MLoc
+        TSHandleMLocRelease(request, TS_NULL_MLOC, req_hdr);
+      }
+    }
+
+    // Release the response MLoc
+    TSHandleMLocRelease(response, TS_NULL_MLOC, resp_hdr);
   }
 
   // Set the transaction free ...
@@ -94,52 +114,42 @@ EscalateResponse(TSCont cont, TSEvent event, void * edata)
 }
 
 TSReturnCode
-TSRemapInit(TSRemapInterface * /* api */, char * /* errbuf */, int /* bufsz */)
+TSRemapInit(TSRemapInterface* /* api */, char* /* errbuf */, int /* bufsz */)
 {
   return TS_SUCCESS;
 }
 
 TSReturnCode
-TSRemapNewInstance(int argc, char * argv[], void ** instance, char * errbuf, int errbuf_size)
+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);
+  EscalationState* es = new EscalationState();
 
   // 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;
+    unsigned status;
+    char*    sep;
 
-    // Each token should be a status code then a URL, separated by '='.
-    sep = strchr(argv[i], '=');
+    // 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)));
+    *sep = '\0';
+    status = strtol(argv[i], NULL, 10);
+
     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;
-    }
+    ++sep; // Skip over the ':'
 
     // OK, we have a valid status/URL pair.
-    es->urlmap[status] = url;
+    TSDebug(PLUGIN_NAME, "Redirect of HTTP status %u to %s", status, sep);
+    es->hostmap[status] = sep;
   }
 
   *instance = es;
@@ -151,15 +161,15 @@ fail:
 }
 
 void
-TSRemapDeleteInstance(void * instance)
+TSRemapDeleteInstance(void* instance)
 {
   delete (EscalationState *)instance;
 }
 
 TSRemapStatus
-TSRemapDoRemap(void * instance, TSHttpTxn txn, TSRemapRequestInfo * /* rri */)
+TSRemapDoRemap(void* instance, TSHttpTxn txn, TSRemapRequestInfo* /* rri */)
 {
-  EscalationState * es((EscalationState *)instance);
+  EscalationState* es = static_cast<EscalationState *>(instance);
 
   TSHttpTxnHookAdd(txn, TS_HTTP_READ_RESPONSE_HDR_HOOK, es->handler);
   return TSREMAP_NO_REMAP;