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]