Patch inline.

Index: modules/proxy/mod_proxy.h
===================================================================
--- modules/proxy/mod_proxy.h    (revision 1588466)
+++ modules/proxy/mod_proxy.h    (working copy)
@@ -605,23 +605,60 @@ typedef __declspec(dllimport) const char *


 /* Connection pool API */
+
 /**
+ * Return an UDS un-aware URL from the given @a url.
+ * @param p   memory pool used for the returned URL
+ * @param url the URL to split
+ * @param uds output for the UDS part of the URL (if not NULL)
+ * @return    the non-UDS part of the URL (if applicable), or the
+ *            given @a url otherwise
+ */
+APR_DECLARE_OPTIONAL_FN(char *, ap_proxy_split_url,
+                        (apr_pool_t *p, char *url, char **uds));
+
+/**
+ * Return an UDS aware URL from the given @a url and @a uds.
+ * @param p   memory pool used for the returned URL
+ * @param url the non-UDS part of the URL
+ * @param uds the UDS part of the URL (or NULL)
+ * @return    the full URL
+ */
+APR_DECLARE_OPTIONAL_FN(char *, ap_proxy_unsplit_url,
+                        (apr_pool_t *p, char *url, const char *uds));
+
+/**
  * Return the user-land, UDS aware worker name
  * @param p        memory pool used for displaying worker name
  * @param worker   the worker
  * @return         name
  */
-
 PROXY_DECLARE(char *) ap_proxy_worker_name(apr_pool_t *p,
                                            proxy_worker *worker);

 /**
+ * Get the worker from proxy configuration, splitting the @a url into
+ * @a to (remote) and @a by (local, eg. UDS) parts (if not NULL).
+ * @param p        memory pool used for finding worker
+ * @param balancer the balancer that the worker belongs to
+ * @param conf     current proxy server configuration
+ * @param url      url to find the worker from
+ * @return         proxy_worker or NULL if not found
+ */
+PROXY_DECLARE(proxy_worker *) ap_proxy_get_worker_ex(apr_pool_t *p,
+                                                     proxy_balancer *balancer,
+                                                     proxy_server_conf *conf,
+                                                     const char *url, int uds,
+                                                     char **to, char **by);
+/**
  * Get the worker from proxy configuration
  * @param p        memory pool used for finding worker
  * @param balancer the balancer that the worker belongs to
  * @param conf     current proxy server configuration
  * @param url      url to find the worker from
  * @return         proxy_worker or NULL if not found
+ * @remark This is equivalent to ap_proxy_get_worker(..., NULL, NULL),
+ *         so the url won't be split into remote/local parts
  */
 PROXY_DECLARE(proxy_worker *) ap_proxy_get_worker(apr_pool_t *p,
                                                   proxy_balancer *balancer,
Index: modules/proxy/proxy_util.h
===================================================================
--- modules/proxy/proxy_util.h    (revision 1588466)
+++ modules/proxy/proxy_util.h    (working copy)
@@ -40,6 +40,9 @@ PROXY_DECLARE_DATA extern const apr_strmatch_patte
  */
 void proxy_util_register_hooks(apr_pool_t *p);

+char *ap_proxy_split_url(apr_pool_t *p, char *url, char **uds);
+char *ap_proxy_unsplit_url(apr_pool_t *p, char *url, const char *uds);
+
 /** @} */

 #endif /* PROXY_UTIL_H_ */
Index: modules/proxy/mod_proxy_balancer.c
===================================================================
--- modules/proxy/mod_proxy_balancer.c    (revision 1588466)
+++ modules/proxy/mod_proxy_balancer.c    (working copy)
@@ -1173,7 +1173,8 @@ static int balancer_handler(request_rec *r)
             (val = apr_table_get(params, "b_nwrkr"))) {
             char *ret;
             proxy_worker *nworker;
-            nworker = ap_proxy_get_worker(r->pool, bsel, conf, val);
+            nworker = ap_proxy_get_worker_ex(r->pool, bsel, conf, val,
+                                             1, NULL, NULL);
             if (!nworker && storage->num_free_slots(bsel->wslot)) {
                 if ((rv = PROXY_GLOBAL_LOCK(bsel)) != APR_SUCCESS) {
                     ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(01194)
Index: modules/proxy/mod_proxy.c
===================================================================
--- modules/proxy/mod_proxy.c    (revision 1588466)
+++ modules/proxy/mod_proxy.c    (working copy)
@@ -1461,36 +1461,6 @@ static const char *
     return add_proxy(cmd, dummy, f1, r1, 1);
 }

-static char *de_socketfy(apr_pool_t *p, char *url)
-{
-    char *ptr;
-    /*
-     * We could be passed a URL during the config stage that contains
-     * the UDS path... ignore it
-     */
-    if (!strncasecmp(url, "unix:", 5) &&
-        ((ptr = ap_strchr(url, '|')) != NULL)) {
-        /* move past the 'unix:...|' UDS path info */
-        char *ret, *c;
-
-        ret = ptr + 1;
-        /* special case: "unix:....|scheme:" is OK, expand
-         * to "unix:....|scheme://localhost"
-         * */
-        c = ap_strchr(ret, ':');
-        if (c == NULL) {
-            return NULL;
-        }
-        if (c[1] == '\0') {
-            return apr_pstrcat(p, ret, "//localhost", NULL);
-        }
-        else {
-            return ret;
-        }
-    }
-    return url;
-}
-
 static const char *
     add_pass(cmd_parms *cmd, void *dummy, const char *arg, int is_regex)
 {
@@ -1582,7 +1552,7 @@ static const char *
     }

     new->fake = apr_pstrdup(cmd->pool, f);
-    new->real = apr_pstrdup(cmd->pool, de_socketfy(cmd->pool, r));
+    new->real = ap_proxy_split_url(cmd->pool, apr_pstrdup(cmd->pool, r), NULL);
     new->flags = flags;
     if (use_regex) {
         new->regex = ap_pregcomp(cmd->pool, f, AP_REG_EXTENDED);
@@ -1631,7 +1601,8 @@ static const char *
         new->balancer = balancer;
     }
     else {
-        proxy_worker *worker = ap_proxy_get_worker(cmd->temp_pool,
NULL, conf, de_socketfy(cmd->pool, r));
+        proxy_worker *worker = ap_proxy_get_worker_ex(cmd->temp_pool, NULL,
+                                                      conf, r, 1, NULL, NULL);
         int reuse = 0;
         if (!worker) {
             const char *err = ap_proxy_define_worker(cmd->pool,
&worker, NULL, conf, r, 0);
@@ -1643,14 +1614,15 @@ static const char *
             reuse = 1;
             ap_log_error(APLOG_MARK, APLOG_INFO, 0, cmd->server, APLOGNO(01145)
                          "Sharing worker '%s' instead of creating new
worker '%s'",
-                         ap_proxy_worker_name(cmd->pool, worker), new->real);
+                         ap_proxy_worker_name(cmd->temp_pool,
worker), new->real);
         }

         for (i = 0; i < arr->nelts; i++) {
             if (reuse) {
                 ap_log_error(APLOG_MARK, APLOG_WARNING, 0,
cmd->server, APLOGNO(01146)
                              "Ignoring parameter '%s=%s' for worker
'%s' because of worker sharing",
-                             elts[i].key, elts[i].val,
ap_proxy_worker_name(cmd->pool, worker));
+                             elts[i].key, elts[i].val,
ap_proxy_worker_name(cmd->temp_pool,
+
      worker));
             } else {
                 const char *err = set_worker_param(cmd->pool, worker,
elts[i].key,
                                                    elts[i].val);
@@ -2110,7 +2082,8 @@ static const char *add_member(cmd_parms *cmd, void
     }

     /* Try to find existing worker */
-    worker = ap_proxy_get_worker(cmd->temp_pool, balancer, conf,
de_socketfy(cmd->temp_pool, name));
+    worker = ap_proxy_get_worker_ex(cmd->temp_pool, balancer, conf, name,
+                                    1, NULL, NULL);
     if (!worker) {
         ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, cmd->server, APLOGNO(01147)
                      "Defining worker '%s' for balancer '%s'",
@@ -2196,7 +2169,8 @@ static const char *
         }
     }
     else {
-        worker = ap_proxy_get_worker(cmd->temp_pool, NULL, conf,
de_socketfy(cmd->temp_pool, name));
+        worker = ap_proxy_get_worker_ex(cmd->temp_pool, NULL, conf, name,
+                                        1, NULL, NULL);
         if (!worker) {
             if (in_proxy_section) {
                 err = ap_proxy_define_worker(cmd->pool, &worker, NULL,
@@ -2335,8 +2309,8 @@ static const char *proxysection(cmd_parms *cmd, vo
             }
         }
         else {
-            worker = ap_proxy_get_worker(cmd->temp_pool, NULL, sconf,
-                                         de_socketfy(cmd->temp_pool,
(char*)conf->p));
+            worker = ap_proxy_get_worker_ex(cmd->temp_pool, NULL, sconf,
+                                            (char*)conf->p, 1, NULL, NULL);
             if (!worker) {
                 err = ap_proxy_define_worker(cmd->pool, &worker, NULL,
                                           sconf, conf->p, 0);
Index: modules/proxy/proxy_util.c
===================================================================
--- modules/proxy/proxy_util.c    (revision 1588466)
+++ modules/proxy/proxy_util.c    (working copy)
@@ -1508,32 +1508,111 @@ PROXY_DECLARE(char *) ap_proxy_worker_name(apr_poo
     return apr_pstrcat(p, "unix:", worker->s->uds_path, "|",
worker->s->name, NULL);
 }

-PROXY_DECLARE(proxy_worker *) ap_proxy_get_worker(apr_pool_t *p,
-                                                  proxy_balancer *balancer,
-                                                  proxy_server_conf *conf,
-                                                  const char *url)
+char *ap_proxy_split_url(apr_pool_t *p, char *url, char **uds)
 {
+    char *ptr;
+    /*
+     * We could be passed a URL that contains the UDS path...
+     * If any, save it in *uds, and strip it.
+     */
+    if (uds) {
+        *uds = NULL;
+    }
+    if (!strncasecmp(url, "unix:", 5) &&
+        ((ptr = ap_strchr(url, '|')) != NULL)) {
+        /* move past the 'unix:...|' UDS path info */
+        char *ret, *c;
+
+        ret = ptr + 1;
+        /* special case: "unix:....|scheme:" is OK, expand
+         * to "unix:....|scheme://localhost"
+         * */
+        c = ap_strchr(ret, ':');
+        if (c == NULL) {
+            return NULL;
+        }
+        if (uds) {
+            *uds = url;
+            *ptr = '\0';
+        }
+        if (c[1] == '\0') {
+            return apr_pstrcat(p, ret, "//localhost", NULL);
+        }
+        else {
+            return ret;
+        }
+    }
+    return url;
+}
+
+char *ap_proxy_unsplit_url(apr_pool_t *p, char *url, const char *uds)
+{
+    if (uds) {
+        return apr_pstrcat(p, uds, "|", url, NULL);
+    }
+    else {
+        return url;
+    }
+}
+
+PROXY_DECLARE(proxy_worker *) ap_proxy_get_worker_ex(apr_pool_t *p,
+                                                     proxy_balancer *balancer,
+                                                     proxy_server_conf *conf,
+                                                     const char *url, int uds,
+                                                     char **to, char **by)
+{
     proxy_worker *worker;
     proxy_worker *max_worker = NULL;
-    int max_match = 0;
-    int url_length;
-    int min_match;
-    int worker_name_length;
+    apr_size_t max_match = 0;
+    apr_size_t url_length;
+    apr_size_t min_match;
+    apr_size_t worker_name_length;
     const char *c;
     char *url_copy;
     int i;

     if (!url) {
+        if (to) {
+            *to = NULL;
+        }
+        if (by) {
+            *by = NULL;
+        }
         return NULL;
     }

+    if (!uds) {
+        /* No real interest in *to or *by being used without uds,
+         * don't leave dangling pointers anyway.
+         */
+        if (to) {
+            *to = NULL;
+        }
+        if (by) {
+            *by = NULL;
+        }
+        url_length = 0;
+        url_copy = NULL;
+    }
+    else {
+        url_length = strlen(url);
+        url_copy = apr_pstrmemdup(p, url, url_length);
+        url_copy = ap_proxy_split_url(p, url_copy, by);
+        if (to) {
+            *to = url_copy;
+        }
+        url = url_copy;
+    }
+
     c = ap_strchr_c(url, ':');
     if (c == NULL || c[1] != '/' || c[2] != '/' || c[3] == '\0') {
         return NULL;
     }

-    url_length = strlen(url);
-    url_copy = apr_pstrmemdup(p, url, url_length);
+    if (!url_copy) {
+        url_length = strlen(url);
+        url_copy = apr_pstrmemdup(p, url, url_length);
+    }

     /*
      * We need to find the start of the path and
@@ -1554,13 +1633,13 @@ PROXY_DECLARE(char *) ap_proxy_worker_name(apr_poo
         ap_str_tolower(url_copy);
         min_match = strlen(url_copy);
     }
+
     /*
      * Do a "longest match" on the worker name to find the worker that
      * fits best to the URL, but keep in mind that we must have at least
      * a minimum matching of length min_match such that
      * scheme://hostname[:port] matches between worker and url.
      */
-
     if (balancer) {
         proxy_worker **workers = (proxy_worker **)balancer->workers->elts;
         for (i = 0; i < balancer->workers->nelts; i++, workers++) {
@@ -1590,7 +1669,15 @@ PROXY_DECLARE(char *) ap_proxy_worker_name(apr_poo
     return max_worker;
 }

+PROXY_DECLARE(proxy_worker *) ap_proxy_get_worker(apr_pool_t *p,
+                                                  proxy_balancer *balancer,
+                                                  proxy_server_conf *conf,
+                                                  const char *url)
+{
+    return ap_proxy_get_worker_ex(p, balancer, conf, url, 0, NULL, NULL);
+}

+
 /*
  * To create a worker from scratch first we define the
  * specifics of the worker; this is all local data.
@@ -1606,29 +1693,25 @@ PROXY_DECLARE(char *) ap_proxy_define_worker(apr_p
                                              int do_malloc)
 {
     int rv;
-    apr_uri_t uri, urisock;
+    apr_uri_t uri;
     proxy_worker_shared *wshared;
-    char *ptr, *sockpath = NULL;
+    char *ptr, *uds, *sockpath = NULL;

     /*
      * Look to see if we are using UDS:
      * require format: unix:/path/foo/bar.sock|http://ignored/path2/
      * This results in talking http to the socket at /path/foo/bar.sock
      */
-    ptr = ap_strchr((char *)url, '|');
-    if (ptr) {
-        *ptr = '\0';
-        rv = apr_uri_parse(p, url, &urisock);
-        if (rv == APR_SUCCESS && !strcasecmp(urisock.scheme, "unix")) {
-            sockpath = ap_runtime_dir_relative(p, urisock.path);;
-            url = ptr+1;    /* so we get the scheme for the uds */
+    ptr = apr_pstrdup(p, url);
+    ptr = ap_proxy_split_url(p, ptr, &uds);
+    if (uds) {
+        rv = apr_uri_parse(p, uds, &uri);
+        if (rv == APR_SUCCESS && !strcasecmp(uri.scheme, "unix")) {
+            sockpath = ap_runtime_dir_relative(p, uri.path);;
+            url = ptr;
         }
-        else {
-            *ptr = '|';
-        }
     }
     rv = apr_uri_parse(p, url, &uri);
-
     if (rv != APR_SUCCESS) {
         return apr_pstrcat(p, "Unable to parse URL: ", url, NULL);
     }
@@ -1906,8 +1989,23 @@ PROXY_DECLARE(int) ap_proxy_pre_request(proxy_work

     access_status = proxy_run_pre_request(worker, balancer, r, conf, url);
     if (access_status == DECLINED && *balancer == NULL) {
-        *worker = ap_proxy_get_worker(r->pool, NULL, conf, *url);
+        char *real_url = NULL, *uds_url = NULL;
+        if (apr_table_get(r->notes, "rewrite-proxy")) {
+            *worker = ap_proxy_get_worker_ex(r->pool, NULL, conf, *url,
+                                             1, &real_url, &uds_url);
+        }
+        else {
+            *worker = ap_proxy_get_worker(r->pool, NULL, conf, *url);
+        }
         if (*worker) {
+            if (uds_url) {
+                ap_log_rerror(APLOG_MARK, APLOG_TRACE2, 0, r,
+                              "%s: found worker %s for %s as %s",
+                              (*worker)->s->scheme, (*worker)->s->name,
+                              *url, real_url);
+                *url = real_url;
+            }
+            else
             ap_log_rerror(APLOG_MARK, APLOG_TRACE2, 0, r,
                           "%s: found worker %s for %s",
                           (*worker)->s->scheme, (*worker)->s->name, *url);
@@ -1932,8 +2030,6 @@ PROXY_DECLARE(int) ap_proxy_pre_request(proxy_work
         }
         else if (r->proxyreq == PROXYREQ_REVERSE) {
             if (conf->reverse) {
-                char *ptr;
-                char *ptr2;
                 ap_log_rerror(APLOG_MARK, APLOG_TRACE2, 0, r,
                               "*: found reverse proxy worker for %s", *url);
                 *balancer = NULL;
@@ -1953,27 +2049,21 @@ PROXY_DECLARE(int) ap_proxy_pre_request(proxy_work
                  * NOTE: Here we use a quick note lookup, but we could also
                  * check to see if r->filename starts with 'proxy:'
                  */
-                if (apr_table_get(r->notes, "rewrite-proxy") &&
-                    (ptr2 = ap_strcasestr(r->filename, "unix:")) &&
-                    (ptr = ap_strchr(ptr2, '|'))) {
+                if (uds_url) {
                     apr_uri_t urisock;
                     apr_status_t rv;
-                    *ptr = '\0';
-                    rv = apr_uri_parse(r->pool, ptr2, &urisock);
+                    rv = apr_uri_parse(r->pool, uds_url, &urisock);
                     if (rv == APR_SUCCESS) {
-                        char *rurl = ptr+1;
-                        char *sockpath =
ap_runtime_dir_relative(r->pool, urisock.path);
+                        char *sockpath = ap_runtime_dir_relative(r->pool,
+                                                                 urisock.path);
                         apr_table_setn(r->notes, "uds_path", sockpath);
-                        *url = apr_pstrdup(r->pool, rurl); /* so we
get the scheme for the uds */
+                        *url = real_url; /* so we get the scheme for the uds */
                         /* r->filename starts w/ "proxy:", so add after that */
-                        memmove(r->filename+6, rurl, strlen(rurl)+1);
+                        r->filename = apr_pstrcat(r->pool, "proxy:",
*url, NULL);
                         ap_log_rerror(APLOG_MARK, APLOG_TRACE2, 0, r,
                                       "*: rewrite of url due to
UDS(%s): %s (%s)",
                                       sockpath, *url, r->filename);
                     }
-                    else {
-                        *ptr = '|';
-                    }
                 }
             }
         }
@@ -3517,6 +3607,8 @@ PROXY_DECLARE(apr_port_t) ap_proxy_port_of_scheme(

 void proxy_util_register_hooks(apr_pool_t *p)
 {
+    APR_REGISTER_OPTIONAL_FN(ap_proxy_split_url);
+    APR_REGISTER_OPTIONAL_FN(ap_proxy_unsplit_url);
     APR_REGISTER_OPTIONAL_FN(ap_proxy_retry_worker);
     APR_REGISTER_OPTIONAL_FN(ap_proxy_clear_connection);
 }
Index: modules/mappers/mod_rewrite.c
===================================================================
--- modules/mappers/mod_rewrite.c    (revision 1588466)
+++ modules/mappers/mod_rewrite.c    (working copy)
@@ -97,6 +97,7 @@
 #include "util_mutex.h"

 #include "mod_ssl.h"
+#include "mod_proxy.h"

 #include "mod_rewrite.h"
 #include "ap_expr.h"
@@ -109,6 +110,11 @@ static ap_dbd_t *(*dbd_acquire)(request_rec*) = NU
 static void (*dbd_prepare)(server_rec*, const char*, const char*) = NULL;
 static const char* really_last_key = "rewrite_really_last";

+static char *(*proxy_split_url)(apr_pool_t *p, char *url,
+                                char **split) = NULL;
+static char *(*proxy_unsplit_url)(apr_pool_t *p, char *url,
+                                  const char *split) = NULL;
+
 /*
  * in order to improve performance on running production systems, you
  * may strip all rewritelog code entirely from mod_rewrite by using the
@@ -4173,6 +4179,17 @@ static int apply_rewrite_rule(rewriterule_entry *p
      * ourself).
      */
     if (p->flags & RULEFLAG_PROXY) {
+        char *split = NULL;
+
+        if (!proxy_split_url || !proxy_unsplit_url) {
+            ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, APLOGNO()
+                          "mod_rewrite: can't apply [P] rule without "
+                          "mod_proxy loaded: ignoring rule");
+            return 0;
+        }
+
+        r->filename = proxy_split_url(r->pool, r->filename, &split);
+
         /* For rules evaluated in server context, the mod_proxy fixup
          * hook can be relied upon to escape the URI as and when
          * necessary, since it occurs later.  If in directory context,
@@ -4192,6 +4209,9 @@ static int apply_rewrite_rule(rewriterule_entry *p
         rewritelog((r, 2, ctx->perdir, "forcing proxy-throughput with %s",
                     r->filename));

+        if (split) {
+            r->filename = proxy_unsplit_url(r->pool, r->filename, split);
+        }
         r->filename = apr_pstrcat(r->pool, "proxy:", r->filename, NULL);
         apr_table_setn(r->notes, "rewrite-proxy", "1");
         return 1;
@@ -4447,6 +4467,9 @@ static int post_config(apr_pool_t *p,
     rewrite_ssl_lookup = APR_RETRIEVE_OPTIONAL_FN(ssl_var_lookup);
     rewrite_is_https = APR_RETRIEVE_OPTIONAL_FN(ssl_is_https);

+    proxy_split_url = APR_RETRIEVE_OPTIONAL_FN(ap_proxy_split_url);
+    proxy_unsplit_url = APR_RETRIEVE_OPTIONAL_FN(ap_proxy_unsplit_url);
+
     return OK;
 }

[EOS]

Reply via email to