Author: zwoop
Date: Thu Jan 27 04:53:39 2011
New Revision: 1063988
URL: http://svn.apache.org/viewvc?rev=1063988&view=rev
Log:
Add the "set" and "add" header operators, hacky but useful
Modified:
trafficserver/plugins/header_filter/CHANGES
trafficserver/plugins/header_filter/example.conf
trafficserver/plugins/header_filter/rules.cc
trafficserver/plugins/header_filter/rules.h
Modified: trafficserver/plugins/header_filter/CHANGES
URL:
http://svn.apache.org/viewvc/trafficserver/plugins/header_filter/CHANGES?rev=1063988&r1=1063987&r2=1063988&view=diff
==============================================================================
--- trafficserver/plugins/header_filter/CHANGES (original)
+++ trafficserver/plugins/header_filter/CHANGES Thu Jan 27 04:53:39 2011
@@ -2,4 +2,10 @@
Changes with Apache Traffic Server header_filter 1.0
+ *) Added support for the "add" and "set" operators, e.g.
+
+ [SEND_REQUEST_HDR]
+ Host =www.ogre.com=
+ X-Append-Header +Added by ATS+
+
*) This is a basic plugin for doing header_filtering.
Modified: trafficserver/plugins/header_filter/example.conf
URL:
http://svn.apache.org/viewvc/trafficserver/plugins/header_filter/example.conf?rev=1063988&r1=1063987&r2=1063988&view=diff
==============================================================================
--- trafficserver/plugins/header_filter/example.conf (original)
+++ trafficserver/plugins/header_filter/example.conf Thu Jan 27 04:53:39 2011
@@ -5,5 +5,14 @@
X-Foo ! "test"
+# This will do the following:
+# - nuke the cookie headers (all of them)
+# - Replace the Host: header with www.ogre.com
+# - Add a header X-Append-Header: Added by ATS
+#
+# There can only ever be one Host: header (the plugin assures that since we
use the set-operator)
+# but there can be more than one X-Append-Header (since we use the
add-operator).
[SEND_REQUEST_HDR]
Cookie
+ Host =www.ogre.com=
+ X-Append-Header +Added by ATS+
Modified: trafficserver/plugins/header_filter/rules.cc
URL:
http://svn.apache.org/viewvc/trafficserver/plugins/header_filter/rules.cc?rev=1063988&r1=1063987&r2=1063988&view=diff
==============================================================================
--- trafficserver/plugins/header_filter/rules.cc (original)
+++ trafficserver/plugins/header_filter/rules.cc Thu Jan 27 04:53:39 2011
@@ -27,7 +27,7 @@
namespace HeaderFilter {
-const char* QUAL_DELIMITERS = "!/\"*[";
+const char* QUAL_DELIMITERS = "!/\"*[+=";
// RulesEntry implementations
@@ -41,81 +41,118 @@ RulesEntry::append(RulesEntry* entry)
n->_next = entry;
}
+inline void
+add_header(TSMBuffer& reqp, TSMLoc& hdr_loc, const char* hdr, int hdr_len,
const char* val, int val_len)
+{
+ if (val_len <= 0) {
+ TSDebug(PLUGIN_NAME, "\tWould set header %s to an empty value, skipping",
hdr);
+ } else {
+ TSMLoc new_field = TSMimeHdrFieldCreate(reqp, hdr_loc);
+
+ if (new_field) {
+ TSMimeHdrFieldNameSet(reqp, hdr_loc, new_field, hdr, hdr_len);
+ TSMimeHdrFieldValueStringInsert(reqp, hdr_loc, new_field, -1, val,
val_len);
+ TSMimeHdrFieldAppend(reqp, hdr_loc, new_field);
+ TSHandleMLocRelease(reqp, hdr_loc, new_field);
+
+ TSDebug(PLUGIN_NAME, "\tAdded header %s: %s", hdr, val);
+ }
+ }
+}
+
void
RulesEntry::execute(TSMBuffer& reqp, TSMLoc& hdr_loc) const
{
- TSMLoc field;
+ if (_q_type == QUAL_ADD) {
+ add_header(reqp, hdr_loc, _header, _h_len, _qualifier, _q_len);
+ } else {
+ TSMLoc field = TSMimeHdrFieldFind(reqp, hdr_loc, _header, _h_len);
+ bool first_set = true;
- field = TSMimeHdrFieldFind(reqp, hdr_loc, _header, _h_len);
- while (field) {
- TSMLoc tmp;
- const char* val;
- int val_len = -1;
- bool nuke = false;
-
- if ((_q_type != QUAL_NONE) &&
- (TSMimeHdrFieldValueStringGet(reqp, hdr_loc, field, 0, &val, &val_len)
!= TS_SUCCESS))
- val_len = -1;
-
- switch (_q_type) {
- case QUAL_NONE:
- nuke = true;
- break;
- case QUAL_REGEX:
- if (val_len > 0) {
- nuke = pcre_exec(_rex, // the compiled pattern
- _extra, // Extra data from study (maybe)
- val, // the subject string
- val_len, // the length of the subject
- 0, // start at offset 0 in the
subject
- 0, // default options
- NULL, // no output vector for substring
information
- 0) >= 0;
- }
- break;
+ while (field) {
+ TSMLoc tmp;
+ const char* val;
+ int val_len = 0;
+ bool nuke = false;
+
+ if ((_q_type != QUAL_NONE) && (TSMimeHdrFieldValueStringGet(reqp,
hdr_loc, field, 0, &val, &val_len) != TS_SUCCESS))
+ val_len = 0;
+
+ switch (_q_type) {
+ case QUAL_NONE:
+ nuke = true;
+ break;
+ case QUAL_REGEX:
+ if (val_len > 0) {
+ nuke = pcre_exec(_rex, // the compiled pattern
+ _extra, // Extra data from study (maybe)
+ val, // the subject string
+ val_len, // the length of the subject
+ 0, // start at offset 0 in the
subject
+ 0, // default options
+ NULL, // no output vector for
substring information
+ 0) >= 0;
+ }
+ break;
- case QUAL_STRING:
- if (val_len == _q_len) {
- if (_options & PCRE_CASELESS) {
- nuke = !strncasecmp(_qualifier, val, val_len);
- } else {
- nuke = !memcmp(_qualifier, val, val_len);
+ case QUAL_STRING:
+ if (static_cast<size_t>(val_len) == _q_len) {
+ if (_options & PCRE_CASELESS) {
+ nuke = !strncasecmp(_qualifier, val, val_len);
+ } else {
+ nuke = !memcmp(_qualifier, val, val_len);
+ }
}
- }
- break;
+ break;
- case QUAL_PREFIX:
- if (val_len >= _q_len) {
- if (_options & PCRE_CASELESS) {
- nuke = !strncasecmp(_qualifier, val, _q_len);
- } else {
- nuke = !memcmp(_qualifier, val, _q_len);
+ case QUAL_PREFIX:
+ if (static_cast<size_t>(val_len) >= _q_len) {
+ if (_options & PCRE_CASELESS) {
+ nuke = !strncasecmp(_qualifier, val, _q_len);
+ } else {
+ nuke = !memcmp(_qualifier, val, _q_len);
+ }
}
- }
- break;
+ break;
- case QUAL_POSTFIX:
- if (val_len >= _q_len) {
- if (_options & PCRE_CASELESS) {
- nuke = !strncasecmp(_qualifier, val + val_len - _q_len, _q_len);
+ case QUAL_POSTFIX:
+ if (static_cast<size_t>(val_len) >= _q_len) {
+ if (_options & PCRE_CASELESS) {
+ nuke = !strncasecmp(_qualifier, val + val_len - _q_len, _q_len);
+ } else {
+ nuke = !memcmp(_qualifier, val + val_len - _q_len, _q_len);
+ }
+ }
+ break;
+ case QUAL_SET:
+ if (first_set) {
+ nuke = false;
+ first_set = false;
+ TSMimeHdrFieldValueStringSet(reqp, hdr_loc, field, -1, _qualifier,
_q_len);
+ TSDebug(PLUGIN_NAME, "\tSet header %s: %s", _header, _qualifier);
} else {
- nuke = !memcmp(_qualifier, val + val_len - _q_len, _q_len);
+ // Nuke all other "duplicates" of this header
+ nuke = true;
}
+
+ default:
+ break;
+ }
+
+ tmp = TSMimeHdrFieldNextDup(reqp, hdr_loc, field);
+ if (_inverse)
+ nuke = !nuke;
+ if (nuke) {
+ TSDebug(PLUGIN_NAME, "\tDeleting header %.*s", _h_len, _header);
+ TSMimeHdrFieldDestroy(reqp, hdr_loc, field);
}
- break;
- default:
- break;
+ TSHandleMLocRelease(reqp, hdr_loc, field);
+ field = tmp;
}
- tmp = TSMimeHdrFieldNextDup(reqp, hdr_loc, field);
- if (_inverse)
- nuke = !nuke;
- if (nuke) {
- TSDebug(PLUGIN_NAME, "\tDeleting header %.*s", _h_len, _header);
- TSMimeHdrFieldDestroy(reqp, hdr_loc, field);
+ if (first_set) { // We still didn't replace a value
+ add_header(reqp, hdr_loc, _header, _h_len, _qualifier, _q_len);
}
- TSHandleMLocRelease(reqp, hdr_loc, field);
- field = tmp;
}
}
@@ -222,6 +259,16 @@ Rules::parse_file(const char* filename)
type = QUAL_PREFIX;
trailer = "*";
break;
+ case '+':
+ type = QUAL_ADD;
+ inverse = false; // Can never inverse the add operator
+ trailer = "+";
+ break;
+ case '=':
+ type = QUAL_SET;
+ inverse = false; // Can never inverse the set operator
+ trailer = "=";
+ break;
default:
// TODO: Error case?
break;
@@ -265,7 +312,7 @@ Rules::execute(TSMBuffer& reqp, TSMLoc&
TSDebug(PLUGIN_NAME, "Executing rules(s) for hook %d", hook);
do {
n->execute(reqp, hdr_loc);
- } while (n = n->next());
+ } while (NULL != (n = n->next()));
}
}
Modified: trafficserver/plugins/header_filter/rules.h
URL:
http://svn.apache.org/viewvc/trafficserver/plugins/header_filter/rules.h?rev=1063988&r1=1063987&r2=1063988&view=diff
==============================================================================
--- trafficserver/plugins/header_filter/rules.h (original)
+++ trafficserver/plugins/header_filter/rules.h Thu Jan 27 04:53:39 2011
@@ -38,7 +38,10 @@ enum QualifierTypes {
QUAL_REGEX = 1, // Regular expression, /match/
QUAL_STRING = 2, // Full string, "match"
QUAL_PREFIX = 3, // Sub-string prefix, [match*
- QUAL_POSTFIX = 4 // Sub-string postfix, *match]
+ QUAL_POSTFIX = 4, // Sub-string postfix, *match]
+ // This is a semi-hack, but whatever (for now, until we get Lua module done!
+ QUAL_ADD = 5, // Add the header +string+
+ QUAL_SET = 6 // Set the header =string=, leaving only one
header with the new value
};
@@ -53,7 +56,7 @@ public:
_header = TSstrdup(s.c_str());
_h_len = s.length();
}
-
+
if (q.length() > 0) {
_qualifier = TSstrdup(q.c_str());
_q_len = q.length();
@@ -81,7 +84,7 @@ public:
if (_header)
TSfree(_header);
- if (_q_type = QUAL_REGEX) {
+ if (QUAL_REGEX == _q_type) {
if (_rex)
pcre_free(_rex);
if (_extra)
@@ -99,8 +102,9 @@ private:
DISALLOW_COPY_AND_ASSIGN(RulesEntry);
char* _header;
+ size_t _h_len,;
char* _qualifier;
- size_t _h_len, _q_len;
+ size_t _q_len;
QualifierTypes _q_type;
pcre* _rex;
pcre_extra* _extra;