Index: modules/proxy/mod_proxy.c
===================================================================
--- modules/proxy/mod_proxy.c	(revision 1025699)
+++ modules/proxy/mod_proxy.c	(working copy)
@@ -559,22 +559,105 @@
     }
     return ret;
 }
-static int proxy_trans(request_rec *r)
+
+static int proxy_trans_match(request_rec *r, struct proxy_alias *ent,
+        proxy_dir_conf *dconf)
 {
-    void *sconf = r->server->module_config;
-    proxy_server_conf *conf =
-    (proxy_server_conf *) ap_get_module_config(sconf, &proxy_module);
-    int i, len;
-    struct proxy_alias *ent = (struct proxy_alias *) conf->aliases->elts;
-    proxy_dir_conf *dconf = ap_get_module_config(r->per_dir_config,
-                                                 &proxy_module);
+    int len;
     const char *fake;
     const char *real;
     ap_regmatch_t regm[AP_MAX_REG_MATCH];
     ap_regmatch_t reg1[AP_MAX_REG_MATCH];
     char *found = NULL;
     int mismatch = 0;
+    unsigned int nocanon = ent->flags & PROXYPASS_NOCANON;
+    const char *use_uri = nocanon ? r->unparsed_uri : r->uri;
 
+    if ((dconf->interpolate_env == 1) && (ent->flags & PROXYPASS_INTERPOLATE)) {
+        fake = proxy_interpolate(r, ent->fake);
+        real = proxy_interpolate(r, ent->real);
+    }
+    else {
+        fake = ent->fake;
+        real = ent->real;
+    }
+    if (ent->regex) {
+        if (!ap_regexec(ent->regex, r->uri, AP_MAX_REG_MATCH, regm, 0)) {
+            if ((real[0] == '!') && (real[1] == '\0')) {
+                return DECLINED;
+            }
+            /* test that we haven't reduced the URI */
+            if (nocanon && ap_regexec(ent->regex, r->unparsed_uri,
+                    AP_MAX_REG_MATCH, reg1, 0)) {
+                mismatch = 1;
+                use_uri = r->uri;
+            }
+            found = ap_pregsub(r->pool, real, use_uri, AP_MAX_REG_MATCH,
+                    (use_uri == r->uri) ? regm : reg1);
+            /* 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, real)) {
+                found = apr_pstrcat(r->pool, "proxy:", found, NULL);
+            }
+            else {
+                found = apr_pstrcat(r->pool, "proxy:", real, use_uri, NULL);
+            }
+        }
+    }
+    else {
+        len = alias_match(r->uri, fake);
+
+        if (len != 0) {
+            if ((real[0] == '!') && (real[1] == '\0')) {
+                return DECLINED;
+            }
+            if (nocanon && len != alias_match(r->unparsed_uri, ent->fake)) {
+                mismatch = 1;
+                use_uri = r->uri;
+            }
+            found = apr_pstrcat(r->pool, "proxy:", real, use_uri + len, NULL);
+        }
+    }
+    if (mismatch) {
+        /* We made a reducing transformation, so we can't safely use
+         * unparsed_uri.  Safe fallback is to ignore nocanon.
+         */
+        ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r,
+                "Unescaped URL path matched ProxyPass; ignoring unsafe nocanon");
+    }
+
+    if (found) {
+        r->filename = found;
+        r->handler = "proxy-server";
+        r->proxyreq = PROXYREQ_REVERSE;
+        if (nocanon && !mismatch) {
+            /* mod_proxy_http needs to be told.  Different module. */
+            apr_table_setn(r->notes, "proxy-nocanon", "1");
+        }
+        return OK;
+    }
+
+    return DONE;
+}
+
+static int proxy_trans(request_rec *r)
+{
+    int i;
+    struct proxy_alias *ent;
+    proxy_dir_conf *dconf;
+    proxy_server_conf *conf;
+
     if (r->proxyreq) {
         /* someone has already set up the proxy, it was possibly ourselves
          * in proxy_detect
@@ -587,86 +670,27 @@
      * an issue because this is a hybrid proxy/origin server.
      */
 
-    for (i = 0; i < conf->aliases->nelts; i++) {
-        unsigned int nocanon = ent[i].flags & PROXYPASS_NOCANON;
-        const char *use_uri = nocanon ? r->unparsed_uri : r->uri;
-        if ((dconf->interpolate_env == 1)
-            && (ent[i].flags & PROXYPASS_INTERPOLATE)) {
-            fake = proxy_interpolate(r, ent[i].fake);
-            real = proxy_interpolate(r, ent[i].real);
-        }
-        else {
-            fake = ent[i].fake;
-            real = ent[i].real;
-        }
-        if (ent[i].regex) {
-            if (!ap_regexec(ent[i].regex, r->uri, AP_MAX_REG_MATCH, regm, 0)) {
-                if ((real[0] == '!') && (real[1] == '\0')) {
-                    return DECLINED;
-                }
-                /* test that we haven't reduced the URI */
-                if (nocanon && ap_regexec(ent[i].regex, r->unparsed_uri,
-                                          AP_MAX_REG_MATCH, reg1, 0)) {
-                    mismatch = 1;
-                    use_uri = r->uri;
-                }
-                found = ap_pregsub(r->pool, real, use_uri, AP_MAX_REG_MATCH,
-                                   (use_uri == r->uri) ? regm : reg1);
-                /* 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, real)) {
-                    found = apr_pstrcat(r->pool, "proxy:", found, NULL);
-                }
-                else {
-                    found = apr_pstrcat(r->pool, "proxy:", real,
-                                        use_uri, NULL);
-                }
-            }
-        }
-        else {
-            len = alias_match(r->uri, fake);
+    dconf = ap_get_module_config(r->per_dir_config, &proxy_module);
 
-            if (len != 0) {
-                if ((real[0] == '!') && (real[1] == '\0')) {
-                    return DECLINED;
-                }
-                if (nocanon
-                    && len != alias_match(r->unparsed_uri, ent[i].fake)) {
-                    mismatch = 1;
-                    use_uri = r->uri;
-                }
-                found = apr_pstrcat(r->pool, "proxy:", real,
-                                    use_uri + len, NULL);
-            }
+    /* short way - this location is reverse proxied? */
+    if (dconf->alias) {
+        int rv = proxy_trans_match(r, dconf->alias, dconf);
+        if (DONE != rv) {
+            return rv;
         }
-        if (mismatch) {
-            /* We made a reducing transformation, so we can't safely use
-             * unparsed_uri.  Safe fallback is to ignore nocanon.
-             */
-            ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r,
-                          "Unescaped URL path matched ProxyPass; ignoring unsafe nocanon");
-        }
+    }
 
-        if (found) {
-            r->filename = found;
-            r->handler = "proxy-server";
-            r->proxyreq = PROXYREQ_REVERSE;
-            if (nocanon && !mismatch) {
-                /* mod_proxy_http needs to be told.  Different module. */
-                apr_table_setn(r->notes, "proxy-nocanon", "1");
+    conf
+            = (proxy_server_conf *) ap_get_module_config(r->server->module_config, &proxy_module);
+
+    /* long way - walk the list of aliases, find a match */
+    if (conf->aliases->nelts) {
+        ent = (struct proxy_alias *) conf->aliases->elts;
+        for (i = 0; i < conf->aliases->nelts; i++) {
+            int rv = proxy_trans_match(r, &ent[i], dconf);
+            if (DONE != rv) {
+                return rv;
             }
-            return OK;
         }
     }
     return DECLINED;
@@ -1216,6 +1240,8 @@
     new->error_override = (add->error_override_set == 0) ? base->error_override
                                                         : add->error_override;
     new->error_override_set = add->error_override_set || base->error_override_set;
+    new->alias = (add->alias_set == 0) ? base->alias : add->alias;
+    new->alias_set = add->alias_set || base->alias_set;
     return new;
 }
 
@@ -1297,6 +1323,7 @@
 static const char *
     add_pass(cmd_parms *cmd, void *dummy, const char *arg, int is_regex)
 {
+    proxy_dir_conf *dconf = (proxy_dir_conf *)dummy;
     server_rec *s = cmd->server;
     proxy_server_conf *conf =
     (proxy_server_conf *) ap_get_module_config(s->module_config, &proxy_module);
@@ -1356,10 +1383,24 @@
         }
     };
 
-    if (r == NULL)
+    if (r == NULL) {
         return "ProxyPass|ProxyPassMatch needs a path when not defined in a location";
+    }
 
-    new = apr_array_push(conf->aliases);
+    /* if per directory, save away the single alias */
+    if (cmd->path) {
+        dconf->alias = apr_pcalloc(cmd->pool, sizeof(struct proxy_alias));
+        dconf->alias_set = 1;
+        new = dconf->alias;
+        if (apr_fnmatch_test(f)) {
+            use_regex = 1;
+        }
+    }
+    /* if per server, add to the alias array */
+    else {
+        new = apr_array_push(conf->aliases);
+    }
+
     new->fake = apr_pstrdup(cmd->pool, f);
     new->real = apr_pstrdup(cmd->pool, r);
     new->flags = flags;
Index: modules/proxy/mod_proxy.h
===================================================================
--- modules/proxy/mod_proxy.h	(revision 1025699)
+++ modules/proxy/mod_proxy.h	(working copy)
@@ -186,6 +186,7 @@
     const apr_strmatch_pattern* cookie_domain_str;
     signed char p_is_fnmatch; /* Is the path an fnmatch candidate? */
     signed char interpolate_env;
+    struct proxy_alias *alias;
 
     /**
      * the following setting masks the error page
@@ -199,6 +200,7 @@
     int preserve_host:1;
     int preserve_host_set:1;
     int error_override_set:1;
+    int alias_set:1;
 } proxy_dir_conf;
 
 /* if we interpolate env vars per-request, we'll need a per-request
