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/11/13 22:55:51 UTC
[26/50] [abbrv] git commit: TS-2316: header_rewrite: added
cookie-based conditions
TS-2316: header_rewrite: added cookie-based conditions
Submitted by: Alexey Ivanov <ai...@linkedin.com>
Sponsored by: LinkedIn
Project: http://git-wip-us.apache.org/repos/asf/trafficserver/repo
Commit: http://git-wip-us.apache.org/repos/asf/trafficserver/commit/3d37f51d
Tree: http://git-wip-us.apache.org/repos/asf/trafficserver/tree/3d37f51d
Diff: http://git-wip-us.apache.org/repos/asf/trafficserver/diff/3d37f51d
Branch: refs/heads/5.0.x
Commit: 3d37f51d1b1be4222dbb33afd2692e4a6ab11de7
Parents: b79c907
Author: Alexey Ivanov <ai...@linkedin.com>
Authored: Tue Nov 5 12:55:10 2013 -0800
Committer: Alexey Ivanov <ai...@linkedin.com>
Committed: Sun Nov 10 18:07:53 2013 -0800
----------------------------------------------------------------------
plugins/header_rewrite/conditions.cc | 65 +++++++++++++++++++++++++++++++
plugins/header_rewrite/conditions.h | 60 ++++++++++++++++++++++++++++
plugins/header_rewrite/factory.cc | 2 +
3 files changed, 127 insertions(+)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/trafficserver/blob/3d37f51d/plugins/header_rewrite/conditions.cc
----------------------------------------------------------------------
diff --git a/plugins/header_rewrite/conditions.cc b/plugins/header_rewrite/conditions.cc
index fdbb309..25bbae6 100644
--- a/plugins/header_rewrite/conditions.cc
+++ b/plugins/header_rewrite/conditions.cc
@@ -385,3 +385,68 @@ ConditionDBM::eval(const Resources& res)
return static_cast<const Matchers<std::string>*>(_matcher)->test(s);
}
+
+
+// ConditionCookie: request or response header
+void ConditionCookie::initialize(Parser& p)
+{
+ Condition::initialize(p);
+
+ Matchers<std::string>* match = new Matchers<std::string>(_cond_op);
+ match->set(p.get_arg());
+
+ _matcher = match;
+
+ require_resources(RSRC_CLIENT_REQUEST_HEADERS);
+}
+
+void ConditionCookie::append_value(std::string& s, const Resources& res)
+{
+ TSMBuffer bufp = res.client_bufp;
+ TSMLoc hdr_loc = res.client_hdr_loc;
+ TSMLoc field_loc;
+ int error;
+ int cookies_len;
+ int cookie_value_len;
+ const char *cookies;
+ const char *cookie_value;
+ const char * const cookie_name = _qualifier.c_str();
+ const int cookie_name_len = _qualifier.length();
+
+ // Sanity
+ if (bufp == NULL || hdr_loc == NULL)
+ return;
+
+ // Find Cookie
+ field_loc = TSMimeHdrFieldFind(bufp, hdr_loc, TS_MIME_FIELD_COOKIE, TS_MIME_LEN_COOKIE);
+ if (field_loc == NULL)
+ return;
+
+ // Get all cookies
+ // NB! Cookie field does not support commas, so we use index == 0
+ cookies = TSMimeHdrFieldValueStringGet(bufp, hdr_loc, field_loc, 0, &cookies_len);
+ if (cookies == NULL || cookies_len <= 0)
+ goto out_release_field;
+
+ // Find particular cookie's value
+ error = get_cookie_value(cookies, cookies_len, cookie_name, cookie_name_len, &cookie_value, &cookie_value_len);
+ if (error == TS_ERROR)
+ goto out_release_field;
+
+ TSDebug(PLUGIN_NAME, "Appending COOKIE(%s) to evaluation value -> %.*s", cookie_name, cookie_value_len, cookie_value);
+ s.append(cookie_value, cookie_value_len);
+
+ // Unwind
+out_release_field:
+ TSHandleMLocRelease(bufp, hdr_loc, field_loc);
+}
+
+bool ConditionCookie::eval(const Resources& res)
+{
+ std::string s;
+
+ append_value(s, res);
+ bool rval = static_cast<const Matchers<std::string>*>(_matcher)->test(s);
+ TSDebug(PLUGIN_NAME, "Evaluating COOKIE(%s): %s: rval: %d", _qualifier.c_str(), s.c_str(), rval);
+ return rval;
+}
http://git-wip-us.apache.org/repos/asf/trafficserver/blob/3d37f51d/plugins/header_rewrite/conditions.h
----------------------------------------------------------------------
diff --git a/plugins/header_rewrite/conditions.h b/plugins/header_rewrite/conditions.h
index 96d1db4..2f4d093 100644
--- a/plugins/header_rewrite/conditions.h
+++ b/plugins/header_rewrite/conditions.h
@@ -25,6 +25,7 @@
#include <string>
#include <ts/ts.h>
#include <boost/lexical_cast.hpp>
+#include <cstring>
#include "condition.h"
#include "matcher.h"
@@ -146,6 +147,65 @@ private:
};
+// cookie(name)
+class ConditionCookie: public Condition
+{
+public:
+ ConditionCookie()
+ {
+ TSDebug(PLUGIN_NAME_DBG, "Calling CTOR for ConditionCookie");
+ }
+ void initialize(Parser& p);
+ void append_value(std::string& s, const Resources& res);
+
+protected:
+ bool eval(const Resources& res);
+
+private:
+ DISALLOW_COPY_AND_ASSIGN(ConditionCookie);
+
+ // Nginx-style cookie parsing:
+ // nginx/src/http/ngx_http_parse.c:ngx_http_parse_multi_header_lines()
+ inline int
+ get_cookie_value(const char *buf, int buf_len, const char *name, int name_len,
+ const char **value, int *value_len)
+ {
+ const char *start, *last, *end;
+
+ // Sanity
+ if (buf == NULL || name == NULL || value == NULL || value_len == NULL)
+ return TS_ERROR;
+
+ start = buf;
+ end = buf + buf_len;
+
+ while (start < end) {
+ if (strncasecmp(start, name, name_len) != 0)
+ goto skip;
+
+ for (start += name_len; start < end && *start == ' '; start++);
+
+ if (start == end || *start++ != '=')
+ goto skip;
+
+ while (start < end && *start == ' ') { start++; }
+ for (last = start; last < end && *last != ';'; last++);
+
+ *value_len = last - start;
+ *value = start;
+ return TS_SUCCESS;
+skip:
+ while (start < end) {
+ char ch = *start++;
+ if (ch == ';' || ch == ',')
+ break;
+ }
+ while (start < end && *start == ' ') { start++; }
+ }
+ return TS_ERROR;
+ };
+};
+
// header
class ConditionHeader : public Condition
{
http://git-wip-us.apache.org/repos/asf/trafficserver/blob/3d37f51d/plugins/header_rewrite/factory.cc
----------------------------------------------------------------------
diff --git a/plugins/header_rewrite/factory.cc b/plugins/header_rewrite/factory.cc
index 9af8f25..208d42a 100644
--- a/plugins/header_rewrite/factory.cc
+++ b/plugins/header_rewrite/factory.cc
@@ -89,6 +89,8 @@ condition_factory(const std::string& cond)
c = new ConditionRandom();
} else if (c_name == "ACCESS") {
c = new ConditionAccess();
+ } else if (c_name == "COOKIE") {
+ c = new ConditionCookie();
} else if (c_name == "HEADER") { // This condition adapts to the hook
c = new ConditionHeader();
} else if (c_name == "PATH") {