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 2016/03/07 23:17:24 UTC

trafficserver git commit: TS-2642 Adds a new operator %{NOW} to header_rewrite

Repository: trafficserver
Updated Branches:
  refs/heads/master 91a8444a5 -> 0792a4a3d


TS-2642 Adds a new operator %{NOW} to header_rewrite

This can be used to make time based decisions, such as denying
requests prior to a certain date. Or changing QOS settings based
on time of day.

This closes #517


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

Branch: refs/heads/master
Commit: 0792a4a3de317ce2977f1cdcc62801e563601428
Parents: 91a8444
Author: Leif Hedstrom <zw...@apache.org>
Authored: Fri Jan 22 12:15:03 2016 -0700
Committer: Leif Hedstrom <zw...@apache.org>
Committed: Mon Mar 7 15:14:32 2016 -0700

----------------------------------------------------------------------
 doc/admin-guide/plugins/header_rewrite.en.rst | 20 ++++++
 plugins/header_rewrite/Examples/Now           | 10 +++
 plugins/header_rewrite/conditions.cc          | 67 +++++++++++++++----
 plugins/header_rewrite/conditions.h           | 19 ++++++
 plugins/header_rewrite/factory.cc             |  5 +-
 plugins/header_rewrite/statement.cc           | 77 +++++++++++++++++++++-
 plugins/header_rewrite/statement.h            | 18 ++++-
 7 files changed, 199 insertions(+), 17 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/trafficserver/blob/0792a4a3/doc/admin-guide/plugins/header_rewrite.en.rst
----------------------------------------------------------------------
diff --git a/doc/admin-guide/plugins/header_rewrite.en.rst b/doc/admin-guide/plugins/header_rewrite.en.rst
index 4e2f18e..8100c41 100644
--- a/doc/admin-guide/plugins/header_rewrite.en.rst
+++ b/doc/admin-guide/plugins/header_rewrite.en.rst
@@ -264,6 +264,26 @@ METHOD
 The HTTP method (e.g. ``GET``, ``HEAD``, ``POST``, and so on) used by the
 client for this transaction.
 
+NOW
+~~~
+::
+
+   cond %{NOW} >1453484915
+
+This is the current time, in the local timezone as set on the machine,
+typically GMC. Without any further qualifiers, this is the time in seconds
+since EPOCH aka Unix time. Qualifiers can be used to give various other
+values, such as year, month etc.
+::
+
+   %{NOW:YEAR}      Current year (e.g. 2016)
+   %{NOW:MONTH}     Current month (0-11, 0 == January)
+   %{NOW:DAY}       Current day of the month (1-31)
+   %{NOW:HOUR}      Current hour (0-23, in the 24h system)
+   %{NOW:MIN}       Current minute (0-59}
+   %{NOW:WEEKDAY}   Current weekday (0-6, 0 == Sunday)
+   %{NOW:YEARDAY}   Current day of the year (0-365, 0 == Jan 1st)
+
 PATH
 ~~~~
 ::

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/0792a4a3/plugins/header_rewrite/Examples/Now
----------------------------------------------------------------------
diff --git a/plugins/header_rewrite/Examples/Now b/plugins/header_rewrite/Examples/Now
new file mode 100644
index 0000000..09a33bd
--- /dev/null
+++ b/plugins/header_rewrite/Examples/Now
@@ -0,0 +1,10 @@
+cond %{SEND_RESPONSE_HDR_HOOK} [AND]
+cond %{NOW} >1453484915
+     set-header X-Now %{NOW}
+     set-header X-Now-Year %{NOW:YEAR}
+     set-header X-Now-Month %{NOW:MONTH}
+     set-header X-Now-Day %{NOW:DAY}
+     set-header X-Now-Hour %{NOW:HOUR}
+     set-header X-Now-Min %{NOW:MINUTE}
+     set-header X-Now-WEEKDAY %{NOW:WEEKDAY}
+     set-header X-Now-YEARDAY %{NOW:YEARDAY}

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/0792a4a3/plugins/header_rewrite/conditions.cc
----------------------------------------------------------------------
diff --git a/plugins/header_rewrite/conditions.cc b/plugins/header_rewrite/conditions.cc
index 0f22400..4e6f29e 100644
--- a/plugins/header_rewrite/conditions.cc
+++ b/plugins/header_rewrite/conditions.cc
@@ -34,7 +34,6 @@ void
 ConditionStatus::initialize(Parser &p)
 {
   Condition::initialize(p);
-
   Matchers<TSHttpStatus> *match = new Matchers<TSHttpStatus>(_cond_op);
 
   match->set(static_cast<TSHttpStatus>(strtol(p.get_arg().c_str(), NULL, 10)));
@@ -77,8 +76,8 @@ void
 ConditionMethod::initialize(Parser &p)
 {
   Condition::initialize(p);
-
   Matchers<std::string> *match = new Matchers<std::string>(_cond_op);
+
   match->set(p.get_arg());
 
   _matcher = match;
@@ -120,12 +119,10 @@ void
 ConditionRandom::initialize(Parser &p)
 {
   struct timeval tv;
-
   Condition::initialize(p);
+  Matchers<unsigned int> *match = new Matchers<unsigned int>(_cond_op);
 
   gettimeofday(&tv, NULL);
-
-  Matchers<unsigned int> *match = new Matchers<unsigned int>(_cond_op);
   _seed = getpid() * tv.tv_usec;
   _max = strtol(_qualifier.c_str(), NULL, 10);
 
@@ -146,6 +143,7 @@ void
 ConditionRandom::append_value(std::string &s, const Resources & /* res ATS_UNUSED */)
 {
   std::ostringstream oss;
+
   oss << rand_r(&_seed) % _max;
   s += oss.str();
   TSDebug(PLUGIN_NAME, "Appending RANDOM(%d) to evaluation value -> %s", _max, s.c_str());
@@ -157,7 +155,6 @@ void
 ConditionAccess::initialize(Parser &p)
 {
   struct timeval tv;
-
   Condition::initialize(p);
 
   gettimeofday(&tv, NULL);
@@ -206,10 +203,9 @@ void
 ConditionHeader::initialize(Parser &p)
 {
   Condition::initialize(p);
-
   Matchers<std::string> *match = new Matchers<std::string>(_cond_op);
-  match->set(p.get_arg());
 
+  match->set(p.get_arg());
   _matcher = match;
 
   require_resources(RSRC_CLIENT_REQUEST_HEADERS);
@@ -256,7 +252,6 @@ ConditionHeader::append_value(std::string &s, const Resources &res)
   }
 }
 
-
 bool
 ConditionHeader::eval(const Resources &res)
 {
@@ -268,15 +263,15 @@ ConditionHeader::eval(const Resources &res)
   return rval;
 }
 
+
 // ConditionPath
 void
 ConditionPath::initialize(Parser &p)
 {
   Condition::initialize(p);
-
   Matchers<std::string> *match = new Matchers<std::string>(_cond_op);
-  match->set(p.get_arg());
 
+  match->set(p.get_arg());
   _matcher = match;
 }
 
@@ -308,13 +303,14 @@ ConditionPath::eval(const Resources &res)
   return static_cast<const Matchers<std::string> *>(_matcher)->test(s);
 }
 
+
 // ConditionQuery
 void
 ConditionQuery::initialize(Parser &p)
 {
   Condition::initialize(p);
-
   Matchers<std::string> *match = new Matchers<std::string>(_cond_op);
+
   match->set(p.get_arg());
   _matcher = match;
 }
@@ -324,6 +320,7 @@ ConditionQuery::append_value(std::string &s, const Resources &res)
 {
   int query_len = 0;
   const char *query = TSUrlHttpQueryGet(res._rri->requestBufp, res._rri->requestUrl, &query_len);
+
   TSDebug(PLUGIN_NAME, "Appending QUERY to evaluation value: %.*s", query_len, query);
   s.append(query, query_len);
 }
@@ -360,6 +357,7 @@ ConditionUrl::set_qualifier(const std::string &q)
 {
   Condition::set_qualifier(q);
 
+  TSDebug(PLUGIN_NAME, "\tParsing %%{URL:%s}", q.c_str());
   _url_qual = parse_url_qualifier(q);
 }
 
@@ -623,6 +621,7 @@ ConditionIncomingPort::append_value(std::string &s, const Resources &res)
   TSDebug(PLUGIN_NAME, "Appending %d to evaluation value -> %s", port, s.c_str());
 }
 
+
 // ConditionTransactCount
 void
 ConditionTransactCount::initialize(Parser &p)
@@ -666,3 +665,47 @@ ConditionTransactCount::append_value(std::string &s, Resources const &res)
     }
   }
 }
+
+
+// ConditionNow: time related conditions, such as time since epoch (default), hour, day etc.
+void
+ConditionNow::initialize(Parser &p)
+{
+  Condition::initialize(p);
+  Matchers<int64_t> *match = new Matchers<int64_t>(_cond_op);
+
+  match->set(static_cast<unsigned int64_t>(strtol(p.get_arg().c_str(), NULL, 10)));
+  _matcher = match;
+}
+
+
+void
+ConditionNow::set_qualifier(const std::string &q)
+{
+  Condition::set_qualifier(q);
+
+  TSDebug(PLUGIN_NAME, "\tParsing %%{NOW:%s} qualifier", q.c_str());
+  _now_qual = parse_now_qualifier(q);
+}
+
+
+void
+ConditionNow::append_value(std::string &s, const Resources & /* res ATS_UNUSED */)
+{
+  std::ostringstream oss;
+
+  oss << get_now_qualified(_now_qual);
+  s += oss.str();
+  TSDebug(PLUGIN_NAME, "Appending NOW() to evaluation value -> %s", s.c_str());
+}
+
+
+bool
+ConditionNow::eval(const Resources &res)
+{
+  int64_t now = get_now_qualified(_now_qual);
+
+  TSDebug(PLUGIN_NAME, "Evaluating NOW() -> %" PRId64, now);
+
+  return static_cast<const Matchers<int64_t> *>(_matcher)->test(now);
+}

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/0792a4a3/plugins/header_rewrite/conditions.h
----------------------------------------------------------------------
diff --git a/plugins/header_rewrite/conditions.h b/plugins/header_rewrite/conditions.h
index c905da5..5a77907 100644
--- a/plugins/header_rewrite/conditions.h
+++ b/plugins/header_rewrite/conditions.h
@@ -392,4 +392,23 @@ private:
   DISALLOW_COPY_AND_ASSIGN(ConditionTransactCount);
 };
 
+// now: Keeping track of current time / day / hour etc.
+class ConditionNow : public Condition
+{
+public:
+  explicit ConditionNow() : _now_qual(NOW_QUAL_EPOCH) { TSDebug(PLUGIN_NAME_DBG, "Calling CTOR for ConditionNow"); };
+
+  void initialize(Parser &p);
+  void set_qualifier(const std::string &q);
+  void append_value(std::string &s, const Resources &res);
+
+protected:
+  bool eval(const Resources &res);
+
+private:
+  DISALLOW_COPY_AND_ASSIGN(ConditionNow);
+  NowQualifiers _now_qual;
+};
+
+
 #endif // __CONDITIONS_H

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/0792a4a3/plugins/header_rewrite/factory.cc
----------------------------------------------------------------------
diff --git a/plugins/header_rewrite/factory.cc b/plugins/header_rewrite/factory.cc
index be1225b..1c6a901 100644
--- a/plugins/header_rewrite/factory.cc
+++ b/plugins/header_rewrite/factory.cc
@@ -127,13 +127,16 @@ condition_factory(const std::string &cond)
     c = new ConditionMethod();
   } else if (c_name == "TXN-COUNT") {
     c = new ConditionTransactCount();
+  } else if (c_name == "NOW") {
+    c = new ConditionNow();
   } else {
     TSError("[%s] Unknown condition: %s", PLUGIN_NAME, c_name.c_str());
     return NULL;
   }
 
-  if (c_qual != "")
+  if (c_qual != "") {
     c->set_qualifier(c_qual);
+  }
 
   return c;
 }

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/0792a4a3/plugins/header_rewrite/statement.cc
----------------------------------------------------------------------
diff --git a/plugins/header_rewrite/statement.cc b/plugins/header_rewrite/statement.cc
index 5ef247f..e6c3f58 100644
--- a/plugins/header_rewrite/statement.cc
+++ b/plugins/header_rewrite/statement.cc
@@ -19,8 +19,6 @@
 // statement.cc: Implementation of the statement base class.
 //
 //
-#include "ts/ts.h"
-
 #include "statement.h"
 
 void
@@ -74,10 +72,55 @@ Statement::initialize_hooks()
   add_allowed_hook(TS_REMAP_PSEUDO_HOOK);
 }
 
+// Time related functionality for statements. We return an int64_t here, to assure that
+// gettimeofday() / Epoch does not lose bits.
+int64_t
+Statement::get_now_qualified(NowQualifiers qual) const
+{
+  time_t now;
+
+  // First short circuit for the Epoch qualifier, since it needs less data
+  time(&now);
+  if (NOW_QUAL_EPOCH == qual) {
+    return static_cast<int64_t>(now);
+  } else {
+    struct tm res;
+
+    localtime_r(&now, &res);
+    switch (qual) {
+    case NOW_QUAL_EPOCH:
+      TSReleaseAssert(!"EPOCH should have been handled before");
+      break;
+    case NOW_QUAL_YEAR:
+      return static_cast<int64_t>(res.tm_year + 1900); // This makes more sense
+      break;
+    case NOW_QUAL_MONTH:
+      return static_cast<int64_t>(res.tm_mon);
+      break;
+    case NOW_QUAL_DAY:
+      return static_cast<int64_t>(res.tm_mday);
+      break;
+    case NOW_QUAL_HOUR:
+      return static_cast<int64_t>(res.tm_hour);
+      break;
+    case NOW_QUAL_MINUTE:
+      return static_cast<int64_t>(res.tm_min);
+      break;
+    case NOW_QUAL_WEEKDAY:
+      return static_cast<int64_t>(res.tm_wday);
+      break;
+    case NOW_QUAL_YEARDAY:
+      return static_cast<int64_t>(res.tm_yday);
+      break;
+    }
+  }
+  return 0;
+}
+
 
 // Parse URL qualifiers
 UrlQualifiers
-Statement::parse_url_qualifier(const std::string &q)
+Statement::parse_url_qualifier(const std::string &q) const
 {
   UrlQualifiers qual = URL_QUAL_NONE;
 
@@ -98,3 +141,31 @@ Statement::parse_url_qualifier(const std::string &q)
 
   return qual;
 }
+
+
+// Parse NOW qualifiers
+NowQualifiers
+Statement::parse_now_qualifier(const std::string &q) const
+{
+  NowQualifiers qual = NOW_QUAL_EPOCH; // Default is seconds since epoch
+
+  if (q == "EPOCH") {
+    qual = NOW_QUAL_EPOCH;
+  } else if (q == "YEAR") {
+    qual = NOW_QUAL_YEAR;
+  } else if (q == "MONTH") {
+    qual = NOW_QUAL_MONTH;
+  } else if (q == "DAY") {
+    qual = NOW_QUAL_DAY;
+  } else if (q == "HOUR") {
+    qual = NOW_QUAL_HOUR;
+  } else if (q == "MINUTE") {
+    qual = NOW_QUAL_MINUTE;
+  } else if (q == "WEEKDAY") {
+    qual = NOW_QUAL_WEEKDAY;
+  } else if (q == "YEARDAY") {
+    qual = NOW_QUAL_YEARDAY;
+  }
+
+  return qual;
+}

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/0792a4a3/plugins/header_rewrite/statement.h
----------------------------------------------------------------------
diff --git a/plugins/header_rewrite/statement.h b/plugins/header_rewrite/statement.h
index a7aa3c4..254cf55 100644
--- a/plugins/header_rewrite/statement.h
+++ b/plugins/header_rewrite/statement.h
@@ -24,6 +24,7 @@
 #define __STATEMENT_H__ 1
 
 #include <string>
+#include <time.h>
 #include <vector>
 
 #include "ts/ts.h"
@@ -45,6 +46,18 @@ enum UrlQualifiers {
   URL_QUAL_URL
 };
 
+// NOW data
+enum NowQualifiers {
+  NOW_QUAL_EPOCH,
+  NOW_QUAL_YEAR,
+  NOW_QUAL_MONTH,
+  NOW_QUAL_DAY,
+  NOW_QUAL_HOUR,
+  NOW_QUAL_MINUTE,
+  NOW_QUAL_WEEKDAY,
+  NOW_QUAL_YEARDAY
+};
+
 
 class Statement
 {
@@ -114,7 +127,10 @@ public:
 protected:
   virtual void initialize_hooks();
 
-  UrlQualifiers parse_url_qualifier(const std::string &q);
+  UrlQualifiers parse_url_qualifier(const std::string &q) const;
+  NowQualifiers parse_now_qualifier(const std::string &q) const;
+  int64_t get_now_qualified(NowQualifiers qual) const;
+
   void
   require_resources(const ResourceIDs ids)
   {