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;


Reply via email to