httpd-cvs mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From j..@apache.org
Subject svn commit: r556976 - in /httpd/httpd/branches/2.2.x: CHANGES STATUS docs/manual/mod/mod_proxy.xml modules/proxy/mod_proxy.c modules/proxy/mod_proxy.h
Date Tue, 17 Jul 2007 17:22:37 GMT
Author: jim
Date: Tue Jul 17 10:22:35 2007
New Revision: 556976

URL: http://svn.apache.org/viewvc?view=rev&rev=556976
Log:
  *) mod_proxy: Added ProxyPassMatch directive, which is similar
     to ProxyPass but takes a regex local path prefix. [Jim Jagielski]


Modified:
    httpd/httpd/branches/2.2.x/CHANGES
    httpd/httpd/branches/2.2.x/STATUS
    httpd/httpd/branches/2.2.x/docs/manual/mod/mod_proxy.xml
    httpd/httpd/branches/2.2.x/modules/proxy/mod_proxy.c
    httpd/httpd/branches/2.2.x/modules/proxy/mod_proxy.h

Modified: httpd/httpd/branches/2.2.x/CHANGES
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.2.x/CHANGES?view=diff&rev=556976&r1=556975&r2=556976
==============================================================================
--- httpd/httpd/branches/2.2.x/CHANGES [utf-8] (original)
+++ httpd/httpd/branches/2.2.x/CHANGES [utf-8] Tue Jul 17 10:22:35 2007
@@ -21,6 +21,9 @@
      values could previously point to cleaned up storage.  PR 41551.
      [Davi Arnaut <davi haxent.com.br>]
 
+  *) mod_proxy: Added ProxyPassMatch directive, which is similar
+     to ProxyPass but takes a regex local path prefix. [Jim Jagielski]
+
   *) mod_cache: Do not set Date or Expires when they are missing from
      the original response or are invalid.  [Justin Erenkrantz]
 

Modified: httpd/httpd/branches/2.2.x/STATUS
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.2.x/STATUS?view=diff&rev=556976&r1=556975&r2=556976
==============================================================================
--- httpd/httpd/branches/2.2.x/STATUS (original)
+++ httpd/httpd/branches/2.2.x/STATUS Tue Jul 17 10:22:35 2007
@@ -77,14 +77,6 @@
 PATCHES ACCEPTED TO BACKPORT FROM TRUNK:
   [ start all new proposals below, under PATCHES PROPOSED. ]
 
-    * mod_proxy: Add in ProxyPassMatch directive, that allows
-     ProxyPass to take a regex.
-      Trunk version of patch:
-        http://svn.apache.org/viewvc?view=rev&revision=537429
-        http://svn.apache.org/viewvc?view=rev&revision=537599
-      2.2.x version of patch:
-        http://people.apache.org/~jim/patches/ppmatch.txt
-      +1: jim, jfclere, mturk
 
 PATCHES PROPOSED TO BACKPORT FROM TRUNK:
     

Modified: httpd/httpd/branches/2.2.x/docs/manual/mod/mod_proxy.xml
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.2.x/docs/manual/mod/mod_proxy.xml?view=diff&rev=556976&r1=556975&r2=556976
==============================================================================
--- httpd/httpd/branches/2.2.x/docs/manual/mod/mod_proxy.xml (original)
+++ httpd/httpd/branches/2.2.x/docs/manual/mod/mod_proxy.xml Tue Jul 17 10:22:35 2007
@@ -734,6 +734,38 @@
 </directivesynopsis>
 
 <directivesynopsis>
+<name>ProxyPassMatch</name>
+<description>Maps remote servers into the local server URL-space using regular expressions</description>
+<syntax>ProxyPassMatch [<var>regex</var>] !|<var>url</var>
[<var>key=value</var>
+	<var>[key=value</var> ...]]</syntax>
+<contextlist><context>server config</context><context>virtual host</context>
+<context>directory</context>
+</contextlist>
+
+<usage>
+    <p>This directive is equivalent to <directive module="mod_proxy">ProxyPass</directive>,
+       but makes use of regular expressions, instead of simple prefix matching. The
+       supplied regular expression is matched against the <var>url</var>, and
if it
+       matches, the server will substitute any parenthesized matches into the given
+       string and use it as a new <var>url</var>.</p>
+
+    <p>Suppose the local server has address <code>http://example.com/</code>;
+    then</p>
+
+    <example>
+      ProxyPassMatch ^(/.*\.gif)$ http://backend.example.com$1
+    </example>
+
+    <p>will cause a local request for
+    <code>http://example.com/mirror/foo/bar.gif</code> to be internally converted
+    into a proxy request to <code>http://backend.example.com/foo/bar.gif</code>.</p>
+
+    <p>The <code>!</code> directive is useful in situations where you don't
want
+    to reverse-proxy a subdirectory.</p>
+</usage>
+</directivesynopsis>
+
+<directivesynopsis>
 <name>ProxyPassReverse</name>
 <description>Adjusts the URL in HTTP response headers sent from a reverse
 proxied server</description>

Modified: httpd/httpd/branches/2.2.x/modules/proxy/mod_proxy.c
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.2.x/modules/proxy/mod_proxy.c?view=diff&rev=556976&r1=556975&r2=556976
==============================================================================
--- httpd/httpd/branches/2.2.x/modules/proxy/mod_proxy.c (original)
+++ httpd/httpd/branches/2.2.x/modules/proxy/mod_proxy.c Tue Jul 17 10:22:35 2007
@@ -432,6 +432,8 @@
     (proxy_server_conf *) ap_get_module_config(sconf, &proxy_module);
     int i, len;
     struct proxy_alias *ent = (struct proxy_alias *) conf->aliases->elts;
+    ap_regmatch_t regm[AP_MAX_REG_MATCH];
+    char *found = NULL;
 
     if (r->proxyreq) {
         /* someone has already set up the proxy, it was possibly ourselves
@@ -446,19 +448,53 @@
      */
 
     for (i = 0; i < conf->aliases->nelts; i++) {
-        len = alias_match(r->uri, ent[i].fake);
+        if (ent[i].regex) {
+            if (!ap_regexec(ent[i].regex, r->uri, AP_MAX_REG_MATCH, regm, 0)) {
+                if ((ent[i].real[0] == '!') && (ent[i].real[1] == '\0')) {
+                    return DECLINED;
+                }
+                found = ap_pregsub(r->pool, ent[i].real, r->uri, AP_MAX_REG_MATCH,
+                                   regm);
+                /* Note: The strcmp() below catches cases where there
+                 * was no regex substitution. This is so cases like:
+                 *
+                 *    ProxyPassMatch \.gif balancer://foo
+                 *
+                 * will work "as expected". The upshot is that the 2
+                 * directives below act the exact same way (ie: $1 is implied):
+                 *
+                 *    ProxyPassMatch ^(/.*\.gif)$ balancer://foo
+                 *    ProxyPassMatch ^(/.*\.gif)$ balancer://foo$1
+                 *
+                 * which may be confusing.
+                 */
+                if (found && strcmp(found, ent[i].real)) {
+                    found = apr_pstrcat(r->pool, "proxy:", found, NULL);
+                }
+                else {
+                    found = apr_pstrcat(r->pool, "proxy:", ent[i].real, r->uri,
+                                        NULL);
+                }
+            }
+        }
+        else {
+            len = alias_match(r->uri, ent[i].fake);
 
-       if (len > 0) {
-           if ((ent[i].real[0] == '!') && (ent[i].real[1] == 0)) {
-               return DECLINED;
-           }
-
-           r->filename = apr_pstrcat(r->pool, "proxy:", ent[i].real,
-                                     r->uri + len, NULL);
-           r->handler = "proxy-server";
-           r->proxyreq = PROXYREQ_REVERSE;
-           return OK;
-       }
+            if (len > 0) {
+                if ((ent[i].real[0] == '!') && (ent[i].real[1] == '\0')) {
+                    return DECLINED;
+                }
+
+                found = apr_pstrcat(r->pool, "proxy:", ent[i].real,
+                                    r->uri + len, NULL);
+            }
+        }
+        if (found) {
+            r->filename = found;
+            r->handler = "proxy-server";
+            r->proxyreq = PROXYREQ_REVERSE;
+            return OK;
+        }
     }
     return DECLINED;
 }
@@ -1031,7 +1067,7 @@
 }
 
 static const char *
-    add_pass(cmd_parms *cmd, void *dummy, const char *arg)
+    add_pass(cmd_parms *cmd, void *dummy, const char *arg, int is_regex)
 {
     server_rec *s = cmd->server;
     proxy_server_conf *conf =
@@ -1044,11 +1080,20 @@
     const apr_array_header_t *arr;
     const apr_table_entry_t *elts;
     int i;
+    int use_regex = is_regex;
 
     while (*arg) {
         word = ap_getword_conf(cmd->pool, &arg);
-        if (!f)
+        if (!f) {
+            if (!strcmp(word, "~")) {
+                if (is_regex) {
+                    return "ProxyPassMatch invalid syntax ('~' usage).";
+                }
+                use_regex = 1;
+                continue;
+            }
             f = word;
+        }
         else if (!r)
             r = word;
         else {
@@ -1056,16 +1101,16 @@
             if (!val) {
                 if (cmd->path) {
                     if (*r == '/') {
-                        return "ProxyPass can not have a path when defined in "
+                        return "ProxyPass|ProxyPassMatch can not have a path when defined
in "
                                "a location.";
                     }
                     else {
-                        return "Invalid ProxyPass parameter. Parameter must "
+                        return "Invalid ProxyPass|ProxyPassMatch parameter. Parameter must
"
                                "be in the form 'key=value'.";
                     }
                 }
                 else {
-                    return "Invalid ProxyPass parameter. Parameter must be "
+                    return "Invalid ProxyPass|ProxyPassMatch parameter. Parameter must be
"
                            "in the form 'key=value'.";
                 }
             }
@@ -1076,11 +1121,20 @@
     };
 
     if (r == NULL)
-        return "ProxyPass needs a path when not defined in a location";
+        return "ProxyPass|ProxyPassMatch needs a path when not defined in a location";
 
     new = apr_array_push(conf->aliases);
     new->fake = apr_pstrdup(cmd->pool, f);
     new->real = apr_pstrdup(cmd->pool, r);
+    if (use_regex) {
+        new->regex = ap_pregcomp(cmd->pool, f, AP_REG_EXTENDED);
+        if (new->regex == NULL)
+            return "Regular expression could not be compiled.";
+    }
+    else {
+        new->regex = NULL;
+    }
+
     if (r[0] == '!' && r[1] == '\0')
         return NULL;
 
@@ -1123,6 +1177,19 @@
 }
 
 static const char *
+    add_pass_noregex(cmd_parms *cmd, void *dummy, const char *arg)
+{
+    return add_pass(cmd, dummy, arg, 0);
+}
+
+static const char *
+    add_pass_regex(cmd_parms *cmd, void *dummy, const char *arg)
+{
+    return add_pass(cmd, dummy, arg, 1);
+}
+
+
+static const char *
     add_pass_reverse(cmd_parms *cmd, void *dconf, const char *f, const char *r)
 {
     proxy_dir_conf *conf = dconf;
@@ -1700,7 +1767,9 @@
      "a scheme, partial URL or '*' and a proxy server"),
     AP_INIT_TAKE2("ProxyRemoteMatch", add_proxy_regex, NULL, RSRC_CONF,
      "a regex pattern and a proxy server"),
-    AP_INIT_RAW_ARGS("ProxyPass", add_pass, NULL, RSRC_CONF|ACCESS_CONF,
+    AP_INIT_RAW_ARGS("ProxyPass", add_pass_noregex, NULL, RSRC_CONF|ACCESS_CONF,
+     "a virtual path and a URL"),
+    AP_INIT_RAW_ARGS("ProxyPassMatch", add_pass_regex, NULL, RSRC_CONF|ACCESS_CONF,
      "a virtual path and a URL"),
     AP_INIT_TAKE12("ProxyPassReverse", add_pass_reverse, NULL, RSRC_CONF|ACCESS_CONF,
      "a virtual path and a URL for reverse proxy behaviour"),

Modified: httpd/httpd/branches/2.2.x/modules/proxy/mod_proxy.h
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.2.x/modules/proxy/mod_proxy.h?view=diff&rev=556976&r1=556975&r2=556976
==============================================================================
--- httpd/httpd/branches/2.2.x/modules/proxy/mod_proxy.h (original)
+++ httpd/httpd/branches/2.2.x/modules/proxy/mod_proxy.h Tue Jul 17 10:22:35 2007
@@ -109,6 +109,7 @@
 struct proxy_alias {
     const char  *real;
     const char  *fake;
+    ap_regex_t  *regex;
 };
 
 struct dirconn_entry {



Mime
View raw message