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 2010/01/13 20:32:09 UTC

svn commit: r898911 - in /incubator/trafficserver/traffic/trunk: ./ proxy/ proxy/config/ proxy/http2/remap/

Author: zwoop
Date: Wed Jan 13 19:32:09 2010
New Revision: 898911

URL: http://svn.apache.org/viewvc?rev=898911&view=rev
Log:
TS-80: Support regular expressions in the host fields of remap rules.

       Author: Manjesh Nilange
       Review: Leif

Modified:
    incubator/trafficserver/traffic/trunk/configure.ac
    incubator/trafficserver/traffic/trunk/proxy/Makefile.am
    incubator/trafficserver/traffic/trunk/proxy/config/remap.config
    incubator/trafficserver/traffic/trunk/proxy/http2/remap/RemapProcessor.cc
    incubator/trafficserver/traffic/trunk/proxy/http2/remap/UrlMapping.cc
    incubator/trafficserver/traffic/trunk/proxy/http2/remap/UrlMapping.h
    incubator/trafficserver/traffic/trunk/proxy/http2/remap/UrlRewrite.cc
    incubator/trafficserver/traffic/trunk/proxy/http2/remap/UrlRewrite.h

Modified: incubator/trafficserver/traffic/trunk/configure.ac
URL: http://svn.apache.org/viewvc/incubator/trafficserver/traffic/trunk/configure.ac?rev=898911&r1=898910&r2=898911&view=diff
==============================================================================
--- incubator/trafficserver/traffic/trunk/configure.ac (original)
+++ incubator/trafficserver/traffic/trunk/configure.ac Wed Jan 13 19:32:09 2010
@@ -428,6 +428,11 @@
     AC_MSG_FAILURE([No DB interface found])
 fi
 
+AC_CHECK_LIB([pcre], [pcre_exec], 
+  [AC_SUBST([LIBPCRE],["-lpcre"])],
+  [AC_MSG_FAILURE([check for pcre failed. Have you installed pcre-devel?])],
+)
+
 AC_CHECK_FUNCS([clock_gettime kqueue epoll_ctl posix_memalign lrand48_r srand48_r])
 
 if test "$ac_cv_func_epoll_ctl" = "yes"; then

Modified: incubator/trafficserver/traffic/trunk/proxy/Makefile.am
URL: http://svn.apache.org/viewvc/incubator/trafficserver/traffic/trunk/proxy/Makefile.am?rev=898911&r1=898910&r2=898911&view=diff
==============================================================================
--- incubator/trafficserver/traffic/trunk/proxy/Makefile.am (original)
+++ incubator/trafficserver/traffic/trunk/proxy/Makefile.am Wed Jan 13 19:32:09 2010
@@ -170,7 +170,7 @@
   $(top_builddir)/iocore/eventsystem/libinkevent.a \
   $(top_builddir)/libinktomi++/libinktomi++.a \
   @LIBTHREAD@ @LIBSOCKET@ @LIBNSL@ @LIBRESOLV@ @LIBRT@ \
-  @LIBREGEX@ @LIBDB@ @LIBSSL@ @LIBTCL@ @LIBDL@ \
+  @LIBREGEX@ @LIBPCRE@ @LIBDB@ @LIBSSL@ @LIBTCL@ @LIBDL@ \
   @LIBEXPAT@ @LIBDEMANGLE@ @LIBICONV@ \
   @LIBMLD@ @LIBEXC@ -lm
 
@@ -228,7 +228,7 @@
   $(top_builddir)/iocore/eventsystem/libinkevent.a \
   $(top_builddir)/libinktomi++/libinktomi++.a \
   @LIBTHREAD@ @LIBSOCKET@ @LIBNSL@ @LIBRESOLV@ @LIBRT@ \
-  @LIBREGEX@ @LIBDB@ @LIBSSL@ @LIBTCL@ @LIBDL@ \
+  @LIBREGEX@ @LIBPCRE@ @LIBDB@ @LIBSSL@ @LIBTCL@ @LIBDL@ \
   @LIBEXPAT@ @LIBDEMANGLE@ @LIBMLD@ @LIBEXC@ @LIBICONV@ -lm
 
 logstats_CPPFLAGS = \
@@ -290,7 +290,7 @@
   $(top_builddir)/iocore/eventsystem/libinkevent.a \
   $(top_builddir)/libinktomi++/libinktomi++.a \
   @LIBTHREAD@ @LIBSOCKET@ @LIBNSL@ @LIBRESOLV@ @LIBRT@ \
-  @LIBREGEX@ @LIBDB@ @LIBSSL@ @LIBTCL@ @LIBDL@ \
+  @LIBREGEX@ @LIBPCRE@ @LIBDB@ @LIBSSL@ @LIBTCL@ @LIBDL@ \
   @LIBEXPAT@ @LIBDEMANGLE@ @LIBMLD@ @LIBEXC@ @LIBICONV@ -lm
 
 sac_SOURCES = sac.cc
@@ -347,7 +347,7 @@
   $(top_builddir)/librecords/librecprocess.a \
   $(top_builddir)/libinktomi++/libinktomi++.a \
   @LIBTHREAD@ @LIBSOCKET@ @LIBNSL@ @LIBRESOLV@ @LIBRT@ \
-  @LIBREGEX@ @LIBDB@ @LIBSSL@ @LIBTCL@ @LIBDL@ \
+  @LIBREGEX@ @LIBPCRE@ @LIBDB@ @LIBSSL@ @LIBTCL@ @LIBDL@ \
   @LIBEXPAT@ @LIBDEMANGLE@ @LIBMLD@ @LIBEXC@ @LIBICONV@ -lm
 
 cust_log_fmt_cnvrt_SOURCES = cust_log_fmt_cnvrt.cc

Modified: incubator/trafficserver/traffic/trunk/proxy/config/remap.config
URL: http://svn.apache.org/viewvc/incubator/trafficserver/traffic/trunk/proxy/config/remap.config?rev=898911&r1=898910&r2=898911&view=diff
==============================================================================
--- incubator/trafficserver/traffic/trunk/proxy/config/remap.config (original)
+++ incubator/trafficserver/traffic/trunk/proxy/config/remap.config Wed Jan 13 19:32:09 2010
@@ -8,7 +8,11 @@
 #  <filtering arguments> are optional ACL-like argumens unique for each remap rule
 #
 #  Five different types of mappings are possible -- 'map', 'map_with_referer',
-#  'reverse_map', 'redirect', and 'redirect_temporary'.
+#  'reverse_map', 'redirect', and 'redirect_temporary'. Each of these map types
+#  can be prefixed with the string 'regex_' to indicate that the rule will have
+#  regular expression strings. See the last part of this description for more 
+#  information on regex support.
+#
 #  The 'map' mapping is the most straightforward.  Requests that match the
 #  from URL are changed into the to URL.  The user agent will see the new
 #  page but will not be notified of the address change.
@@ -107,3 +111,13 @@
 # .defflt  disable_delete_purge @action=deny @method=delete @method=purge
 # .useflt  disable_all
 # .useflt  disable_delete_purge
+#
+#  Regex support: Regular expressions can be specified in the rules with the 
+#  following limitations:
+#
+#  1) Only the host field can have regexes - the scheme, port and other fields cannot
+#     (use yts_regex_remap plugin for path manipulation using regexes)
+#  2) The number of capturing sub-patterns is limited to 9; this means $0 through $9 can
+#     be used as substitution place holders ($0 will be the entire input string)
+#  3) The number of substitutions in the expansion string is limited to 10
+#

Modified: incubator/trafficserver/traffic/trunk/proxy/http2/remap/RemapProcessor.cc
URL: http://svn.apache.org/viewvc/incubator/trafficserver/traffic/trunk/proxy/http2/remap/RemapProcessor.cc?rev=898911&r1=898910&r2=898911&view=diff
==============================================================================
--- incubator/trafficserver/traffic/trunk/proxy/http2/remap/RemapProcessor.cc (original)
+++ incubator/trafficserver/traffic/trunk/proxy/http2/remap/RemapProcessor.cc Wed Jan 13 19:32:09 2010
@@ -59,7 +59,7 @@
   ink_assert(redirect_url != NULL);
 
   if (unlikely(rewrite_table->num_rules_forward == 0)) {
-    ink_assert(rewrite_table->lookup_table == NULL);
+    ink_assert(rewrite_table->forward_mappings.empty());
     return false;
   }
   // Since we are called before request validity checking
@@ -79,8 +79,8 @@
     //  host headers.)
     proxy_request = true;
     map =
-      rewrite_table->TableLookup(rewrite_table->lookup_table, request_url, request_url->port_get(), request_url_host,
-                                 request_url_host_len, tag);
+      rewrite_table->forwardMappingLookup(request_url, request_url->port_get(), request_url_host,
+                                          request_url_host_len, tag);
   } else {
     // Server request.  Use the host header to figure out where
     // it goes
@@ -109,7 +109,7 @@
     }
 
     Debug("url_rewrite", "[lookup] attempting normal lookup");
-    map = rewrite_table->TableLookup(rewrite_table->lookup_table, request_url, request_port, host_hdr, host_len, tag);
+    map = rewrite_table->forwardMappingLookup(request_url, request_port, host_hdr, host_len, tag);
 
     // Save this information for later
     s->hh_info.host_len = host_len;
@@ -120,7 +120,7 @@
     //   they function as default rules for server requests
     if (map == NULL && rewrite_table->nohost_rules && *host_hdr != '\0') {
       Debug("url_rewrite", "[lookup] nothing matched");
-      map = rewrite_table->TableLookup(rewrite_table->lookup_table, request_url, 0, "", 0, tag);
+      map = rewrite_table->forwardMappingLookup(request_url, 0, "", 0, tag);
     }
 
     if (map && orig_url) {

Modified: incubator/trafficserver/traffic/trunk/proxy/http2/remap/UrlMapping.cc
URL: http://svn.apache.org/viewvc/incubator/trafficserver/traffic/trunk/proxy/http2/remap/UrlMapping.cc?rev=898911&r1=898910&r2=898911&view=diff
==============================================================================
--- incubator/trafficserver/traffic/trunk/proxy/http2/remap/UrlMapping.cc (original)
+++ incubator/trafficserver/traffic/trunk/proxy/http2/remap/UrlMapping.cc Wed Jan 13 19:32:09 2010
@@ -26,13 +26,13 @@
 /**
  * 
 **/
-url_mapping::url_mapping()
+url_mapping::url_mapping(int rank /* = 0 */)
 :next(NULL), next_root_schema(NULL), next_schema(NULL), next_empty(NULL),
 next_unique(NULL), next_hash(NULL), lookup_helper(NULL), from_path_len(0), fromURL(), toURL(),
 homePageRedirect(false), unique(false), default_redirect_url(false), optional_referer(false),
 negative_referer(false), no_negative_cache(false), wildcard_from_scheme(false), pristine_host_hdr(-1),
 chunking_enabled(-1), tag(NULL), filter_redirect_url(NULL), map_id(0), referer_list(0), redir_chunk_list(0),
-filter(NULL), _plugin_count(0), _cur_instance_count(0)
+filter(NULL), _plugin_count(0), _cur_instance_count(0), _rank(rank)
 { /* nop */ ;
 }
 

Modified: incubator/trafficserver/traffic/trunk/proxy/http2/remap/UrlMapping.h
URL: http://svn.apache.org/viewvc/incubator/trafficserver/traffic/trunk/proxy/http2/remap/UrlMapping.h?rev=898911&r1=898910&r2=898911&view=diff
==============================================================================
--- incubator/trafficserver/traffic/trunk/proxy/http2/remap/UrlMapping.h (original)
+++ incubator/trafficserver/traffic/trunk/proxy/http2/remap/UrlMapping.h Wed Jan 13 19:32:09 2010
@@ -101,7 +101,7 @@
 class url_mapping
 {
 public:
-  url_mapping();
+  url_mapping(int rank = 0);
   ~url_mapping();
   url_mapping *next;            // next in main list (primary hash by host name)
   url_mapping *next_root_schema;        // list of different schemas (valid only for root nodes)
@@ -137,11 +137,15 @@
   redirect_tag_str *redir_chunk_list;
   acl_filter_rule *filter;      // acl filtering (list of rules)
   unsigned int _plugin_count;
+
+  int getRank() const { return _rank; };
+
 private:
     bool set_instance(remap_plugin_info *, ihandle *);
     std::deque<remap_plugin_info *>_plugin_list;
     std::map<remap_plugin_info *, ihandle *>_instance_map;
   int _cur_instance_count;
+  int _rank;
 };
 
 

Modified: incubator/trafficserver/traffic/trunk/proxy/http2/remap/UrlRewrite.cc
URL: http://svn.apache.org/viewvc/incubator/trafficserver/traffic/trunk/proxy/http2/remap/UrlRewrite.cc?rev=898911&r1=898910&r2=898911&view=diff
==============================================================================
--- incubator/trafficserver/traffic/trunk/proxy/http2/remap/UrlRewrite.cc (original)
+++ incubator/trafficserver/traffic/trunk/proxy/http2/remap/UrlRewrite.cc Wed Jan 13 19:32:09 2010
@@ -485,12 +485,15 @@
 
 
 UrlRewrite::UrlRewrite(char *file_var_in)
-:lookup_table(NULL), reverse_table(NULL), permanent_redirect_table(NULL),
-temporary_redirect_table(NULL), nohost_rules(0), reverse_proxy(0), pristine_host_hdr(0), backdoor_enabled(0),
+:nohost_rules(0), reverse_proxy(0), pristine_host_hdr(0), backdoor_enabled(0),
 mgmt_autoconf_port(0), default_to_pac(0), default_to_pac_port(0), file_var(NULL), ts_name(NULL),
 http_default_redirect_url(NULL), num_rules_forward(0), num_rules_reverse(0), num_rules_redirect_permanent(0),
 num_rules_redirect_temporary(0), remap_pi_list(NULL)
 {
+
+  forward_mappings.hash_lookup = reverse_mappings.hash_lookup = 
+    permanent_redirects.hash_lookup = temporary_redirects.hash_lookup = NULL;
+  
   char *config_file = NULL;
 
   ink_assert(file_var_in != NULL);
@@ -538,6 +541,9 @@
     Warning("something failed during BuildTable() -- check your remap plugins!");
   }
 
+  pcre_malloc = &ink_malloc;
+  pcre_free = &ink_free;
+
   if (is_debug_tag_set("url_rewrite"))
     Print();
 }
@@ -549,10 +555,10 @@
   xfree(this->ts_name);
   xfree(this->http_default_redirect_url);
 
-  DestroyTable(lookup_table);
-  DestroyTable(reverse_table);
-  DestroyTable(permanent_redirect_table);
-  DestroyTable(temporary_redirect_table);
+  DestroyStore(forward_mappings);
+  DestroyStore(reverse_mappings);
+  DestroyStore(permanent_redirects);
+  DestroyStore(temporary_redirects);
 
   if (remap_pi_list) {
     remap_pi_list->delete_my_list();
@@ -638,7 +644,7 @@
 
 /** Deallocated a hash table and all the url_mappings in it. */
 void
-UrlRewrite::DestroyTable(InkHashTable * h_table)
+UrlRewrite::_destroyTable(InkHashTable * h_table)
 {
   InkHashTableEntry *ht_entry;
   InkHashTableIteratorState ht_iter;
@@ -666,21 +672,21 @@
          num_rules_reverse + num_rules_redirect_temporary + num_rules_redirect_permanent);
   printf("  Reverse Proxy is %s\n", (reverse_proxy == 0) ? "Off" : "On");
 
-  if (lookup_table != NULL) {
+  if (forward_mappings.hash_lookup != NULL) {
     printf("  Forward Mapping Table with %d entries\n", num_rules_forward);
-    PrintTable(lookup_table);
+    PrintTable(forward_mappings.hash_lookup);
   }
-  if (reverse_table != NULL) {
+  if (reverse_mappings.hash_lookup != NULL) {
     printf("  Reverse Mapping Table with %d entries\n", num_rules_reverse);
-    PrintTable(reverse_table);
+    PrintTable(reverse_mappings.hash_lookup);
   }
-  if (permanent_redirect_table != NULL) {
+  if (permanent_redirects.hash_lookup != NULL) {
     printf("  Permanent Redirect Mapping Table with %d entries\n", num_rules_redirect_permanent);
-    PrintTable(permanent_redirect_table);
+    PrintTable(permanent_redirects.hash_lookup);
   }
-  if (temporary_redirect_table != NULL) {
+  if (temporary_redirects.hash_lookup != NULL) {
     printf("  Temporary Redirect Mapping Table with %d entries\n", num_rules_redirect_temporary);
-    PrintTable(temporary_redirect_table);
+    PrintTable(temporary_redirects.hash_lookup);
   }
   if (http_default_redirect_url != NULL) {
     printf("  Referer filter default redirect URL: \"%s\"\n", http_default_redirect_url);
@@ -715,8 +721,8 @@
 
 */
 url_mapping *
-UrlRewrite::TableLookup(InkHashTable * h_table, URL * request_url,
-                        int request_port, const char *request_host, int host_len, char *tag)
+UrlRewrite::_tableLookup(InkHashTable * h_table, URL * request_url,
+                        int request_port, const char *request_host, int request_host_len, char *tag)
 {
   url_mapping *ht_entry, *um;
   ums_helper *lh;
@@ -725,13 +731,13 @@
   URL *map_from;
   int ht_result, tmp, from_path_len, request_path_len;
 
-  if (unlikely(!request_host || !request_url || host_len < 0))
+  if (unlikely(!request_host || !request_url || request_host_len < 0))
     return NULL;
 
   // Canonicalize the string to lower case so that lookup
   //   is case insensitive
-  if (unlikely((host_len + 1) > (int) sizeof(host_lower_buf))) {
-    if (unlikely((request_host_lower = (xfree_buf_ptr = ((char *) xmalloc(host_len + 1)))) == NULL))
+  if (unlikely((request_host_len + 1) > (int) sizeof(host_lower_buf))) {
+    if (unlikely((request_host_lower = (xfree_buf_ptr = ((char *) xmalloc(request_host_len + 1)))) == NULL))
       return NULL;              // impossible
   } else {
     request_host_lower = &host_lower_buf[0];
@@ -739,12 +745,12 @@
   }
 
   // Copy and tolower    
-  for (tmp = 0; tmp < host_len; tmp++) {
+  for (tmp = 0; tmp < request_host_len; tmp++) {
     if ((ht_result = (request_host_lower[tmp] = request_host[tmp])) >= 'A' && ht_result <= 'Z') {
       request_host_lower[tmp] = (ht_result + ('a' - 'A'));
     }
   }
-  request_host_lower[host_len] = 0;
+  request_host_lower[request_host_len] = 0;
 
   ht_result = ink_hash_table_lookup(h_table, request_host_lower, (void **) &ht_entry);
 
@@ -1175,7 +1181,7 @@
     new_loc_length;
 
   if (unlikely(num_rules_reverse == 0)) {
-    ink_assert(reverse_table == NULL);
+    ink_assert(reverse_mappings.empty());
     return false;
   }
 
@@ -1190,7 +1196,7 @@
   location_url.parse(location_hdr, loc_length);
 
   host = location_url.host_get(&host_len);
-  map = TableLookup(reverse_table, &location_url, location_url.port_get(), host, host_len, tag);
+  map = reverseMappingLookup(&location_url, location_url.port_get(), host, host_len, tag);
 
   if (map != NULL) {            /* HDR FIX ME
                                    Debug("url_rewrite", "Location header before rewrite: %s",
@@ -1249,7 +1255,7 @@
   ink_assert(redirect_url != NULL);
 
   if (unlikely(num_rules_forward == 0)) {
-    ink_assert(lookup_table == NULL);
+    ink_assert(forward_mappings.empty());
     return false;
   }
   // Since are called before request validity checking
@@ -1266,7 +1272,7 @@
     //  the request URL since some user-agents send broken
     //  host headers.)
     proxy_request = true;
-    map = TableLookup(lookup_table, request_url, request_url->port_get(), request_url_host, request_url_host_len, tag);
+    map = forwardMappingLookup(request_url, request_url->port_get(), request_url_host, request_url_host_len, tag);
   } else {                      // Server request.  Use the host header to figure out where
     //    it goes
     int host_len, host_hdr_len;
@@ -1293,7 +1299,7 @@
       }
     }
 
-    map = TableLookup(lookup_table, request_url, request_port, host_hdr, host_len, tag);
+    map = forwardMappingLookup(request_url, request_port, host_hdr, host_len, tag);
 
     // Save this information for passing to DoRemap
     hh_info.host_len = host_len;
@@ -1304,7 +1310,7 @@
     // If no rules match, check empty host rules since
     //   they function as default rules for server requests
     if (map == NULL && nohost_rules && *host_hdr != '\0') {
-      map = TableLookup(lookup_table, request_url, 0, "", 0, tag);
+      map = forwardMappingLookup(request_url, 0, "", 0, tag);
     }
   }
 
@@ -1575,10 +1581,10 @@
   // want quick redirects and not want to worry about all the existing
   // permanent rules
   if (prt) {
-    permanent_redirect = TableLookup(permanent_redirect_table, request_url, request_port, host, host_len, tag);
+    permanent_redirect = permanentRedirectLookup(request_url, request_port, host, host_len, tag);
   }
   if (trt) {
-    temporary_redirect = TableLookup(temporary_redirect_table, request_url, request_port, host, host_len, tag);
+    temporary_redirect = temporaryRedirectLookup(request_url, request_port, host, host_len, tag);
   }
   if (temporary_redirect != NULL) {
     mappingType = TEMPORARY_REDIRECT;
@@ -1669,6 +1675,15 @@
   return length;
 }
 
+inline void
+UrlRewrite::_addToStore(MappingsStore &store, url_mapping *new_mapping, RegexMapping &reg_map,
+                        char *src_host, bool is_cur_mapping_regex, int &count)
+{
+  is_cur_mapping_regex ? store.regex_list.push_back(reg_map) : 
+    TableInsert(store.hash_lookup, new_mapping, src_host);
+  ++count;
+}
+
 /**
   Reads the configuration file and creates a new hash table.
 
@@ -1707,10 +1722,14 @@
   int state, error;
   int tok_count;
 
-  ink_assert(lookup_table == NULL);
-  ink_assert(reverse_table == NULL);
-  ink_assert(permanent_redirect_table == NULL);
-  ink_assert(temporary_redirect_table == NULL);
+  RegexMapping reg_map;
+  bool is_cur_mapping_regex;
+  const char *type_id_str;
+  
+  ink_assert(forward_mappings.empty());
+  ink_assert(reverse_mappings.empty());
+  ink_assert(permanent_redirects.empty());
+  ink_assert(temporary_redirects.empty());
   ink_assert(num_rules_forward == 0);
   ink_assert(num_rules_reverse == 0);
   ink_assert(num_rules_redirect_permanent == 0);
@@ -1723,10 +1742,10 @@
     return 1;
   }
 
-  lookup_table = ink_hash_table_create(InkHashTableKeyType_String);
-  reverse_table = ink_hash_table_create(InkHashTableKeyType_String);
-  permanent_redirect_table = ink_hash_table_create(InkHashTableKeyType_String);
-  temporary_redirect_table = ink_hash_table_create(InkHashTableKeyType_String);
+  forward_mappings.hash_lookup = ink_hash_table_create(InkHashTableKeyType_String);
+  reverse_mappings.hash_lookup = ink_hash_table_create(InkHashTableKeyType_String);
+  permanent_redirects.hash_lookup = ink_hash_table_create(InkHashTableKeyType_String);
+  temporary_redirects.hash_lookup = ink_hash_table_create(InkHashTableKeyType_String);
 
   bti.paramc = (bti.argc = 0);
   memset(bti.paramv, 0, sizeof(bti.paramv));
@@ -1799,21 +1818,25 @@
       cln++;
       continue;
     }
+
+    is_cur_mapping_regex = (strncasecmp("regex_", bti.paramv[0], 6) == 0);
+    type_id_str = is_cur_mapping_regex ? (bti.paramv[0] + 6) : bti.paramv[0];
+
     // Check to see whether is a reverse or forward mapping
-    if (!strcasecmp("reverse_map", bti.paramv[0])) {
+    if (!strcasecmp("reverse_map", type_id_str)) {
       Debug("url_rewrite", "[BuildTable] - REVERSE_MAP");
       maptype = REVERSE_MAP;
-    } else if (!strcasecmp("map", bti.paramv[0])) {
+    } else if (!strcasecmp("map", type_id_str)) {
       Debug("url_rewrite", "[BuildTable] - %s",
             ((bti.remap_optflg & REMAP_OPTFLG_MAP_WITH_REFERER) == 0) ? "FORWARD_MAP" : "FORWARD_MAP_REFERER");
       maptype = ((bti.remap_optflg & REMAP_OPTFLG_MAP_WITH_REFERER) == 0) ? FORWARD_MAP : FORWARD_MAP_REFERER;
-    } else if (!strcasecmp("redirect", bti.paramv[0])) {
+    } else if (!strcasecmp("redirect", type_id_str)) {
       Debug("url_rewrite", "[BuildTable] - PERMANENT_REDIRECT");
       maptype = PERMANENT_REDIRECT;
-    } else if (!strcasecmp("redirect_temporary", bti.paramv[0])) {
+    } else if (!strcasecmp("redirect_temporary", type_id_str)) {
       Debug("url_rewrite", "[BuildTable] - TEMPORARY_REDIRECT");
       maptype = TEMPORARY_REDIRECT;
-    } else if (!strcasecmp("map_with_referer", bti.paramv[0])) {
+    } else if (!strcasecmp("map_with_referer", type_id_str)) {
       Debug("url_rewrite", "[BuildTable] - FORWARD_MAP_REFERER");
       maptype = FORWARD_MAP_REFERER;
     } else {
@@ -1825,7 +1848,7 @@
       continue;
     }
 
-    new_mapping = NEW(new url_mapping);
+    new_mapping = NEW(new url_mapping(cln));  // use line # for rank for now
 
     // apply filter rules if we have to
     if ((errStr = process_filter_opt(new_mapping, &bti, errStrBuf, sizeof(errStrBuf))) != NULL) {
@@ -2012,28 +2035,39 @@
     fromHost_lower[fromHostLen] = 0;
     LowerCaseStr(fromHost_lower);
 
+    if (is_cur_mapping_regex) {
+      // it's ok to reuse reg_map as previous content (if any)
+      // would be "reference-copied" into regex mapping lists
+      if (!_processRegexMappingConfig(new_mapping, reg_map)) {
+        errStr = "Could not process regex mapping config line";
+        goto MAP_ERROR;
+      }
+      Debug("url_rewrite_regex", "Configured regex rule for host [%s]", fromHost_lower);
+    }
 
     switch (maptype) {
     case FORWARD_MAP:
     case FORWARD_MAP_REFERER:
-      TableInsert(lookup_table, new_mapping, fromHost_lower);
-      num_rules_forward++;
-      SetHomePageRedirectFlag(new_mapping);
+      _addToStore(forward_mappings, new_mapping, reg_map, fromHost_lower, 
+                  is_cur_mapping_regex, num_rules_forward);
+      SetHomePageRedirectFlag(new_mapping);   // @todo: is this applicable to regex mapping too?
       break;
     case REVERSE_MAP:
-      TableInsert(reverse_table, new_mapping, fromHost_lower);
-      num_rules_reverse++;
+      _addToStore(reverse_mappings, new_mapping, reg_map, fromHost_lower, 
+                  is_cur_mapping_regex, num_rules_reverse);
       new_mapping->homePageRedirect = false;
       break;
     case PERMANENT_REDIRECT:
-      TableInsert(permanent_redirect_table, new_mapping, fromHost_lower);
-      num_rules_redirect_permanent++;
+      _addToStore(permanent_redirects, new_mapping, reg_map, fromHost_lower, 
+                  is_cur_mapping_regex, num_rules_redirect_permanent);
       break;
     case TEMPORARY_REDIRECT:
-      TableInsert(temporary_redirect_table, new_mapping, fromHost_lower);
-      num_rules_redirect_temporary++;
+      _addToStore(temporary_redirects, new_mapping, reg_map, fromHost_lower, 
+                  is_cur_mapping_regex, num_rules_redirect_temporary);
       break;
     default:
+      // 'default' required to avoid compiler warning; unsupported map
+      // type would have been dealt with much before this
       break;
     };
 
@@ -2070,7 +2104,7 @@
             u_mapping->toURL.copy(&new_mapping->toURL);
             if (bti.paramv[3] != NULL)
               u_mapping->tag = xstrdup(&(bti.paramv[3][0]));
-            TableInsert(lookup_table, u_mapping, ipv4_name);
+            TableInsert(forward_mappings.hash_lookup, u_mapping, ipv4_name);
             num_rules_forward++;
             SetHomePageRedirectFlag(u_mapping);
           }
@@ -2110,7 +2144,7 @@
             u_mapping->toURL.copy(&new_mapping->toURL);
             if (bti.paramv[3] != NULL)
               u_mapping->tag = xstrdup(&(bti.paramv[3][0]));
-            TableInsert(lookup_table, u_mapping, ipv4_name);
+            TableInsert(forward_mappings.hash_lookup, u_mapping, ipv4_name);
             num_rules_forward++;
             SetHomePageRedirectFlag(u_mapping);
           }
@@ -2143,7 +2177,7 @@
             u_mapping->toURL.host_set(ipv4_name, strlen(ipv4_name));
             if (bti.paramv[3] != NULL)
               u_mapping->tag = xstrdup(&(bti.paramv[3][0]));
-            TableInsert(reverse_table, u_mapping, fromHost_lower);
+            TableInsert(reverse_mappings.hash_lookup, u_mapping, fromHost_lower);
             num_rules_reverse++;
             u_mapping->homePageRedirect = false;
           }
@@ -2218,43 +2252,43 @@
   // since this is more specific
   if (unlikely(backdoor_enabled)) {
     new_mapping = SetupBackdoorMapping();
-    TableInsert(lookup_table, new_mapping, "");
+    TableInsert(forward_mappings.hash_lookup, new_mapping, "");
     num_rules_forward++;
   }
   // Add the default mapping to the manager PAC file
   //  if we need it
   if (default_to_pac) {
     new_mapping = SetupPacMapping();
-    TableInsert(lookup_table, new_mapping, "");
+    TableInsert(forward_mappings.hash_lookup, new_mapping, "");
     num_rules_forward++;
   }
   // Destroy unused tables
   if (num_rules_forward == 0) {
-    lookup_table = ink_hash_table_destroy(lookup_table);
+    forward_mappings.hash_lookup = ink_hash_table_destroy(forward_mappings.hash_lookup);
   } else {
-    if (ink_hash_table_isbound(lookup_table, "")) {
+    if (ink_hash_table_isbound(forward_mappings.hash_lookup, "")) {
       nohost_rules = 1;
     }
   }
 
   if (num_rules_reverse == 0) {
-    reverse_table = ink_hash_table_destroy(reverse_table);
+    reverse_mappings.hash_lookup = ink_hash_table_destroy(reverse_mappings.hash_lookup);
   }
 
   if (num_rules_redirect_permanent == 0) {
-    permanent_redirect_table = ink_hash_table_destroy(permanent_redirect_table);
+    permanent_redirects.hash_lookup = ink_hash_table_destroy(permanent_redirects.hash_lookup);
   }
 
   if (num_rules_redirect_temporary == 0) {
-    temporary_redirect_table = ink_hash_table_destroy(temporary_redirect_table);
+    temporary_redirects.hash_lookup = ink_hash_table_destroy(temporary_redirects.hash_lookup);
   }
 
   xfree(file_buf);
 
-  CreateLookupHelper(lookup_table);
-  CreateLookupHelper(reverse_table);
-  CreateLookupHelper(permanent_redirect_table);
-  CreateLookupHelper(temporary_redirect_table);
+  CreateLookupHelper(forward_mappings.hash_lookup);
+  CreateLookupHelper(reverse_mappings.hash_lookup);
+  CreateLookupHelper(permanent_redirects.hash_lookup);
+  CreateLookupHelper(temporary_redirects.hash_lookup);
 
   return 0;
 }
@@ -2373,9 +2407,9 @@
 UrlRewrite::forwardTableLookupExt(URL * request_url, int request_port, const char *request_host, int host_len,
                                   char *tag)
 {
-  if (lookup_table) {
-    url_mapping *m = TableLookup(lookup_table, request_url, request_port,
-                                 request_host, host_len, tag);
+  if (forward_mappings.hash_lookup) {
+    url_mapping *m = _tableLookup(forward_mappings.hash_lookup, request_url, request_port,
+                                  request_host, host_len, tag);
 
     return NEW(new url_mapping_ext(m));
   }
@@ -2387,9 +2421,9 @@
 UrlRewrite::reverseTableLookupExt(URL * request_url, int request_port, const char *request_host, int host_len,
                                   char *tag)
 {
-  if (reverse_table) {
-    url_mapping *m = TableLookup(reverse_table, request_url, request_port,
-                                 request_host, host_len, tag);
+  if (reverse_mappings.hash_lookup) {
+    url_mapping *m = _tableLookup(reverse_mappings.hash_lookup, request_url, request_port,
+                                  request_host, host_len, tag);
 
     return NEW(new url_mapping_ext(m));
   }
@@ -2577,7 +2611,7 @@
     ink_snprintf(errbuf, errbufsize, "Can't create new remap instance for plugin \"%s\" - %s", c,
                  tmpbuf[0] ? tmpbuf : "Unknown plugin error");
     Error("Failed to create new instance for plugin %s (non-zero retval)... bailing out", pi->path);
-                /**
+ 	 	 /**
 		 * fail here, otherwise we *will* fail later
 		 * and that's some jacked backtrace inside CreateTableLookup [see bug 2316658]
 		 * at least this one will be obvious
@@ -2594,3 +2628,285 @@
 
   return 0;
 }
+
+/**  First looks up the hash table for "simple" mappings and then the
+     regex mappings.  Only higher-ranked regex mappings are examined if
+     a hash mapping is found; or else all regex mappings are examined
+
+     Returns highest-ranked mapping on success, NULL on failure
+*/
+url_mapping *
+UrlRewrite::_mappingLookup(MappingsStore &mappings, URL *request_url,
+                           int request_port, const char *request_host, int request_host_len, char *tag)
+{
+  int rank_ceiling = -1;
+  url_mapping *mapping = _tableLookup(mappings.hash_lookup, request_url, request_port, request_host, 
+                                      request_host_len, tag);
+  if (mapping != NULL) {
+    rank_ceiling = mapping->getRank();
+    Debug("url_rewrite_regex", "Found 'simple' mapping with rank %d", rank_ceiling);
+  }
+  url_mapping *regex_mapping = _regexMappingLookup(mappings.regex_list, request_url, request_port, 
+                                                   request_host, request_host_len, tag, rank_ceiling);
+  if (regex_mapping) {
+    mapping = regex_mapping;
+    Debug("url_rewrite_regex", "Using regex mapping with rank %d", mapping->getRank());
+  }
+  return mapping;
+}
+
+// does not null terminate return string 
+int
+UrlRewrite::_expandSubstitutions(int *matches_info, const RegexMapping &reg_map,
+                                 const char *matched_string, 
+                                 char *dest_buf, int dest_buf_size)
+{
+  int cur_buf_size = 0;
+  int token_start = 0;
+  int n_bytes_needed;
+  int match_index;
+  for (int i = 0; i < reg_map.n_substitutions; ++i) {
+    // first copy preceding bytes
+    n_bytes_needed = reg_map.substitution_markers[i] - token_start;
+    if ((cur_buf_size + n_bytes_needed) > dest_buf_size) {
+      goto lOverFlow;
+    }
+    memcpy(dest_buf + cur_buf_size, reg_map.to_url_host_template + token_start, n_bytes_needed);
+    cur_buf_size += n_bytes_needed;
+    
+    // then copy the sub pattern match
+    match_index = reg_map.substitution_ids[i] * 2;
+    n_bytes_needed = matches_info[match_index + 1] - matches_info[match_index];
+    if ((cur_buf_size + n_bytes_needed) > dest_buf_size) {
+      goto lOverFlow;
+    }
+    memcpy(dest_buf + cur_buf_size, matched_string + matches_info[match_index], n_bytes_needed);
+    cur_buf_size += n_bytes_needed;
+    
+    token_start = reg_map.substitution_markers[i] + 2; // skip the place holder
+  }
+  
+  // copy last few bytes (if any)
+  if (token_start < reg_map.to_url_host_template_len) {
+    n_bytes_needed = reg_map.to_url_host_template_len - token_start;
+    if ((cur_buf_size + n_bytes_needed) > dest_buf_size) {
+      goto lOverFlow;
+    }
+    memcpy(dest_buf + cur_buf_size, reg_map.to_url_host_template + token_start, n_bytes_needed);
+    cur_buf_size += n_bytes_needed;
+  }
+  Debug("url_rewrite_regex", "Expanded substitutions and returning string [%.*s] with length %d", 
+        cur_buf_size, dest_buf, cur_buf_size);
+  return cur_buf_size;
+  
+ lOverFlow:
+  Error("Overflow while expanding substitutions");
+  return 0;
+}
+
+url_mapping *
+UrlRewrite::_regexMappingLookup(RegexMappingList &regex_mappings, URL *request_url, int request_port, 
+                                const char *request_host, int request_host_len, char *tag, int rank_ceiling)
+{
+  url_mapping *retval = NULL;
+  RegexMappingList::iterator list_iter;
+
+  if (rank_ceiling == -1) { // we will now look at all regex mappings
+    rank_ceiling = INT_MAX;
+    Debug("url_rewrite_regex", "Going to match all regexes");
+  }
+  else {
+    Debug("url_rewrite_regex", "Going to match regexes with rank <= %d", rank_ceiling);
+  }
+
+  int request_scheme_len, reg_map_scheme_len;
+  const char *request_scheme = request_url->scheme_get(&request_scheme_len), *reg_map_scheme;
+
+  int request_path_len, reg_map_path_len;
+  const char *request_path = request_url->path_get(&request_path_len), *reg_map_path;
+
+  for (list_iter = regex_mappings.begin(); list_iter != regex_mappings.end(); ++list_iter) {
+    RegexMapping &reg_map = *list_iter; // handy pointer
+    int reg_map_rank = reg_map.url_map->getRank();
+    if (reg_map_rank > rank_ceiling) {
+      break;
+    }
+
+    reg_map_scheme = reg_map.url_map->fromURL.scheme_get(&reg_map_scheme_len);
+    if ((request_scheme_len != reg_map_scheme_len) ||
+        strncmp(request_scheme, reg_map_scheme, request_scheme_len)) {
+      Debug("url_rewrite_regex", "Skipping regex with rank %d as scheme does not match request scheme",
+            reg_map_rank);
+      continue;
+    }
+    
+    if (reg_map.url_map->fromURL.port_get() != request_port) {
+      Debug("url_rewrite_regex", "Skipping regex with rank %d as regex map port does not match request port. "
+            "regex map port: %d, request port %d", 
+            reg_map_rank, reg_map.url_map->fromURL.port_get(), request_port);
+      continue;
+    }
+
+    reg_map_path = reg_map.url_map->fromURL.path_get(&reg_map_path_len);
+    if ((request_path_len < reg_map_path_len) ||
+        strncmp(reg_map_path, request_path, reg_map_path_len)) { // use the shorter path length here
+      Debug("url_rewrite_regex", "Skipping regex with rank %d as path does not cover request path",
+            reg_map_rank);
+      continue;
+    }
+
+    int matches_info[MAX_REGEX_SUBS * 3];
+    int match_result = pcre_exec(reg_map.re, reg_map.re_extra, request_host, request_host_len,
+                                 0, 0, matches_info, (sizeof(matches_info) / sizeof(int)));
+    if (match_result > 0) {
+      Debug("url_rewrite_regex", "Request URL host [%.*s] matched regex in mapping of rank %d "
+            "with %d possible substitutions", request_host_len, request_host, reg_map_rank, match_result);
+      
+      char buf[MAX_URL_STR_SIZE];
+      int buf_len;
+      
+      // Expand substitutions in the host field from the stored template
+      buf_len = _expandSubstitutions(matches_info, reg_map, request_host, 
+                                     buf, MAX_URL_STR_SIZE);
+      reg_map.url_map->toURL.host_set(buf, buf_len);
+      
+      Debug("url_rewrite_regex", "Expanded toURL to [%.*s]", 
+            reg_map.url_map->toURL.length_get(), reg_map.url_map->toURL.string_get_ref());
+      retval = reg_map.url_map;
+      break;
+    } else if (match_result == PCRE_ERROR_NOMATCH) {
+      Debug("url_rewrite_regex", "Request URL host [%.*s] did NOT match regex in mapping of rank %d", 
+            request_host_len, request_host, reg_map_rank);
+    } else {
+      Error("pcre_exec() failed with error code %d", match_result);
+      break;
+    }
+  }
+
+  return retval;
+}
+
+void
+UrlRewrite::_destroyList(RegexMappingList &mappings) 
+{
+  RegexMappingList::iterator list_iter;
+  for (list_iter = mappings.begin(); list_iter != mappings.end(); ++list_iter) {
+    RegexMapping &reg_map = *list_iter; // handy reference
+    delete reg_map.url_map;
+    if (reg_map.re) {
+      pcre_free(reg_map.re);
+    }
+    if (reg_map.re_extra) {
+      pcre_free(reg_map.re_extra);
+    }
+    if (reg_map.to_url_host_template) {
+      ink_free(reg_map.to_url_host_template);
+    }
+  }
+  mappings.clear();
+}
+
+/** will process the regex mapping configuration and create objects in
+    output argument reg_map. It assumes existing data in reg_map is
+    inconsequential and will be perfunctorily null-ed;
+*/
+bool
+UrlRewrite::_processRegexMappingConfig(url_mapping *new_mapping, RegexMapping &reg_map)
+{
+  char *regex_str;
+  const char *str;
+  int str_index;
+  const char *from_host;
+  int from_host_len;
+  const char *to_host;
+  int to_host_len;
+  int substitution_id;
+  int substitution_count = 0;
+
+  // we get a NULL-terminated version because that is what 
+  // pcre_compile needs
+  from_host = new_mapping->fromURL.host_get(&from_host_len);
+  regex_str = static_cast<char *>(ink_malloc(from_host_len + 1));
+  memcpy(regex_str, from_host, from_host_len);
+  regex_str[from_host_len] = '\0';
+  
+  reg_map.re = NULL;
+  reg_map.re_extra = NULL;
+  reg_map.to_url_host_template = NULL;
+  reg_map.to_url_host_template_len = 0;
+  reg_map.n_substitutions = 0;
+  
+  reg_map.url_map = new_mapping;
+
+  reg_map.re = pcre_compile(regex_str, 0, &str, &str_index, NULL);
+  if (reg_map.re == NULL) {
+    Error("pcre_compile failed! Regex has error starting at %s", regex_str + str_index);
+    goto lFail;
+  }
+  
+  reg_map.re_extra = pcre_study(reg_map.re, 0, &str);
+  if ((reg_map.re_extra == NULL) && (str != NULL)) {
+    Error("pcre_study failed with message [%s]", str);
+    goto lFail;
+  }
+
+  int n_captures;
+  if (pcre_fullinfo(reg_map.re, reg_map.re_extra, PCRE_INFO_CAPTURECOUNT, &n_captures) != 0) {
+    Error("pcre_fullinfo failed!");
+    goto lFail;
+  }
+  if (n_captures >= MAX_REGEX_SUBS) { // off by one for $0 (implicit capture)
+    Error("Regex has %d capturing subpatterns (including entire regex); Max allowed: %d", 
+          n_captures + 1, MAX_REGEX_SUBS);
+    goto lFail;
+  }
+
+  to_host = new_mapping->toURL.host_get(&to_host_len);
+  for (int i = 0; i < (to_host_len - 1); ++i) {
+    if (to_host[i] == '$') {
+      if (substitution_count > MAX_REGEX_SUBS) {
+        Error("Cannot have more than %d substitutions in mapping with host [%s]",
+              MAX_REGEX_SUBS, regex_str);
+        goto lFail;
+      }
+      substitution_id = to_host[i + 1] - '0';
+      if ((substitution_id < 0) || (substitution_id > n_captures)) {
+        Error("Substitution id [%c] has no corresponding capture pattern in regex [%s]",
+              to_host[i + 1], regex_str);
+        goto lFail;
+      }
+      reg_map.substitution_markers[reg_map.n_substitutions] = i;
+      reg_map.substitution_ids[reg_map.n_substitutions] = substitution_id;
+      ++reg_map.n_substitutions;
+    }
+  }
+
+  // so the regex itself is stored in fromURL.host; string to match
+  // will be in the request; string to use for substitutions will be
+  // in this buffer and finally the substituted string will be stored
+  // in toURL.host on every successful regex match
+  str = new_mapping->toURL.host_get(&str_index); // reusing str and str_index
+  reg_map.to_url_host_template_len = str_index;
+  reg_map.to_url_host_template = static_cast<char *>(ink_malloc(str_index));
+  memcpy(reg_map.to_url_host_template, str, str_index);
+
+  ink_free(regex_str);
+  return true;
+  
+ lFail:
+  if (reg_map.re) {
+    pcre_free(reg_map.re);
+    reg_map.re = NULL;
+  }
+  if (reg_map.re_extra) {
+    pcre_free(reg_map.re_extra);
+    reg_map.re_extra = NULL;
+  }
+  if (reg_map.to_url_host_template) {
+    ink_free(reg_map.to_url_host_template);
+    reg_map.to_url_host_template = NULL;
+    reg_map.to_url_host_template_len = 0;
+  }
+  ink_free(regex_str);
+  return false;
+}

Modified: incubator/trafficserver/traffic/trunk/proxy/http2/remap/UrlRewrite.h
URL: http://svn.apache.org/viewvc/incubator/trafficserver/traffic/trunk/proxy/http2/remap/UrlRewrite.h?rev=898911&r1=898910&r2=898911&view=diff
==============================================================================
--- incubator/trafficserver/traffic/trunk/proxy/http2/remap/UrlRewrite.h (original)
+++ incubator/trafficserver/traffic/trunk/proxy/http2/remap/UrlRewrite.h Wed Jan 13 19:32:09 2010
@@ -28,6 +28,9 @@
 #include "UrlMapping.h"
 #include "UmsHelper.h"
 
+#include <pcre.h>
+#include <list>
+
 #define URL_REMAP_FILTER_NONE         0x00000000
 #define URL_REMAP_FILTER_REFERER      0x00000001        /* enable "referer" header validation */
 #define URL_REMAP_FILTER_REDIRECT_FMT 0x00010000        /* enable redirect URL formatting */
@@ -89,14 +92,79 @@
   url_mapping_ext *reverseTableLookupExt(URL * request_url,
                                          int request_port, const char *request_host, int host_len, char *tag = 0);
 //  private:
+
+  static const int MAX_REGEX_SUBS = 10;
+
+  struct RegexMapping
+  {
+    url_mapping *url_map;
+    pcre *re;
+    pcre_extra *re_extra;
+    
+    // we store the host-string-to-substitute here; if a match is found,
+    // the substitutions are made and the resulting url is stored
+    // directly in toURL's host field
+    char *to_url_host_template; 
+    int to_url_host_template_len;
+
+    // stores the number of substitutions
+    int n_substitutions;     
+    
+    // these two together point to template string places where
+    // substitutions need to be made and the matching substring
+    // to use
+    int substitution_markers[MAX_REGEX_SUBS]; 
+    int substitution_ids[MAX_REGEX_SUBS];
+  };
+  
+  typedef std::list<RegexMapping> RegexMappingList;
+  
+  struct MappingsStore 
+  {
+    InkHashTable *hash_lookup;
+    RegexMappingList regex_list;
+    bool empty() 
+    {
+      return ((hash_lookup == NULL) && (regex_list.size() == 0));
+    }
+  };
+  
   void PerformACLFiltering(HttpTransact::State * s, url_mapping * mapping);
   url_mapping *SetupPacMapping();       // manager proxy-autconfig mapping
   url_mapping *SetupBackdoorMapping();
   void PrintTable(InkHashTable * h_table);
-  void DestroyTable(InkHashTable * h_table);
+  void DestroyStore(MappingsStore &store) 
+  {
+    _destroyTable(store.hash_lookup);
+    _destroyList(store.regex_list);
+  }
   void TableInsert(InkHashTable * h_table, url_mapping * mapping, char *src_host);
-  url_mapping *TableLookup(InkHashTable * h_table, URL * request_url,
-                           int request_port, const char *request_host, int host_len, char *tag = NULL);
+
+  MappingsStore forward_mappings;
+  MappingsStore reverse_mappings;
+  MappingsStore permanent_redirects;
+  MappingsStore temporary_redirects;
+
+  url_mapping *forwardMappingLookup(URL *request_url, int request_port, const char *request_host, 
+                                    int request_host_len, char *tag = NULL) 
+  {
+    return _mappingLookup(forward_mappings, request_url, request_port, request_host, request_host_len, tag);
+  }
+  url_mapping *reverseMappingLookup(URL *request_url, int request_port, const char *request_host, 
+                                    int request_host_len, char *tag = NULL) 
+  {
+    return _mappingLookup(reverse_mappings, request_url, request_port, request_host, request_host_len, tag);
+  }
+  url_mapping *permanentRedirectLookup(URL *request_url, int request_port, const char *request_host, 
+                                       int request_host_len, char *tag = NULL) 
+  {
+    return _mappingLookup(permanent_redirects, request_url, request_port, request_host, request_host_len, tag);
+  }
+  url_mapping *temporaryRedirectLookup(URL *request_url, int request_port, const char *request_host, 
+                                       int request_host_len, char *tag = NULL) 
+  {
+    return _mappingLookup(temporary_redirects, request_url, request_port, request_host, request_host_len, tag);
+  }
   int DoRemap(HttpTransact::State * s, HTTPHdr * request_header, url_mapping * mapPtr,
               URL * request_url, char **redirect = NULL, host_hdr_info * hh_ptr = NULL);
   int UrlWhack(char *toWhack, int *origLength);
@@ -106,10 +174,6 @@
   int load_remap_plugin(char *argv[], int argc, url_mapping * mp, char *errbuf, int errbufsize, int jump_to_argc,
                         int *plugin_found_at);
 
-  InkHashTable *lookup_table;
-  InkHashTable *reverse_table;
-  InkHashTable *permanent_redirect_table;
-  InkHashTable *temporary_redirect_table;
   int nohost_rules;
   int reverse_proxy;
   int pristine_host_hdr;
@@ -130,6 +194,24 @@
   int num_rules_redirect_permanent;
   int num_rules_redirect_temporary;
   remap_plugin_info *remap_pi_list;
+
+private:
+  url_mapping *_mappingLookup(MappingsStore &mappings, URL *request_url,
+                              int request_port, const char *request_host, int request_host_len, char *tag);
+  url_mapping *_tableLookup(InkHashTable * h_table, URL * request_url,
+                            int request_port, const char *request_host, int request_host_len, char *tag);
+  url_mapping *_regexMappingLookup(RegexMappingList &regex_mappings,
+                                   URL * request_url, int request_port, const char *request_host, 
+                                   int request_host_len, char *tag, int rank_ceiling);
+  int _expandSubstitutions(int *matches_info, const RegexMapping &reg_map,
+                           const char *matched_string, char *dest_buf, int dest_buf_size);
+  bool _processRegexMappingConfig(url_mapping *new_mapping, RegexMapping &reg_map);
+  void _destroyTable(InkHashTable *h_table);
+  void _destroyList(RegexMappingList &regexes);
+  inline void _addToStore(MappingsStore &store, url_mapping *new_mapping, RegexMapping &reg_map,
+                          char *src_host, bool is_cur_mapping_regex, int &count);
+
+  static const int MAX_URL_STR_SIZE = 1024;
 };
 
 #endif