Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

BZ-69233: backport to 2.4.x #469

Open
wants to merge 3 commits into
base: 2.4.x
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions changes-entries/bz69233.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
*) mod_proxy: Honor parameters of ProxyPassMatch workers with substitution
in the host name or port. PR 69233. [Yann Ylavic]
ylavic marked this conversation as resolved.
Show resolved Hide resolved
3 changes: 2 additions & 1 deletion include/ap_mmn.h
Original file line number Diff line number Diff line change
Expand Up @@ -607,14 +607,15 @@
* and CONN_STATE_PROCESSING
* 20120211.136 (2.4.63-dev) Add wait_io field to struct process_score
* 20120211.137 (2.4.63-dev) Add AP_MPMQ_CAN_WAITIO
* 20120211.138 (2.4.63-dev) Add is_host_matchable to proxy_worker_shared
*/

#define MODULE_MAGIC_COOKIE 0x41503234UL /* "AP24" */

#ifndef MODULE_MAGIC_NUMBER_MAJOR
#define MODULE_MAGIC_NUMBER_MAJOR 20120211
#endif
#define MODULE_MAGIC_NUMBER_MINOR 137 /* 0...n */
#define MODULE_MAGIC_NUMBER_MINOR 138 /* 0...n */

/**
* Determine if the server's current MODULE_MAGIC_NUMBER is at least a
Expand Down
1 change: 1 addition & 0 deletions modules/proxy/mod_proxy.h
Original file line number Diff line number Diff line change
Expand Up @@ -493,6 +493,7 @@ typedef struct {
unsigned int address_ttl_set:1;
apr_int32_t address_ttl; /* backend address' TTL (seconds) */
apr_uint32_t address_expiry; /* backend address' next expiry time */
unsigned int is_host_matchable:1;
} proxy_worker_shared;

#define ALIGNED_PROXY_WORKER_SHARED_SIZE (APR_ALIGN_DEFAULT(sizeof(proxy_worker_shared)))
Expand Down
80 changes: 42 additions & 38 deletions modules/proxy/proxy_util.c
Original file line number Diff line number Diff line change
Expand Up @@ -1826,18 +1826,41 @@ static int ap_proxy_strcmp_ematch(const char *str, const char *expected)
return 0;
}

static int worker_matches(proxy_worker *worker,
const char *url, apr_size_t url_len,
apr_size_t min_match, apr_size_t *max_match,
unsigned int mask)
{
apr_size_t name_len = strlen(worker->s->name_ex);
if (name_len <= url_len
&& name_len > *max_match
/* min_match is the length of the scheme://host part only of url,
* so it's used as a fast path to avoid the match when url is too
* small, but it's irrelevant when the worker host contains globs
* (i.e. ->is_host_matchable).
*/
&& (worker->s->is_name_matchable
? ((mask & AP_PROXY_WORKER_IS_MATCH)
&& (worker->s->is_host_matchable || name_len >= min_match)
&& !ap_proxy_strcmp_ematch(url, worker->s->name_ex))
: ((mask & AP_PROXY_WORKER_IS_PREFIX)
&& (name_len >= min_match)
&& !strncmp(url, worker->s->name_ex, name_len)))) {
*max_match = name_len;
return 1;
}
return 0;
}

PROXY_DECLARE(proxy_worker *) ap_proxy_get_worker_ex(apr_pool_t *p,
proxy_balancer *balancer,
proxy_server_conf *conf,
const char *url,
unsigned int mask)
{
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 min_match, max_match = 0;
apr_size_t url_len;
const char *c;
char *url_copy;
int i;
Expand All @@ -1858,8 +1881,8 @@ PROXY_DECLARE(proxy_worker *) ap_proxy_get_worker_ex(apr_pool_t *p,
return NULL;
}

url_length = strlen(url);
url_copy = apr_pstrmemdup(p, url, url_length);
url_len = strlen(url);
url_copy = apr_pstrmemdup(p, url, url_len);

/* Default to lookup for both _PREFIX and _MATCH workers */
if (!(mask & (AP_PROXY_WORKER_IS_PREFIX | AP_PROXY_WORKER_IS_MATCH))) {
Expand All @@ -1885,48 +1908,28 @@ PROXY_DECLARE(proxy_worker *) ap_proxy_get_worker_ex(apr_pool_t *p,
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++) {
worker = *workers;
if ( ((worker_name_length = strlen(worker->s->name_ex)) <= url_length)
&& (worker_name_length >= min_match)
&& (worker_name_length > max_match)
&& (worker->s->is_name_matchable
|| ((mask & AP_PROXY_WORKER_IS_PREFIX)
&& strncmp(url_copy, worker->s->name_ex,
worker_name_length) == 0))
&& (!worker->s->is_name_matchable
|| ((mask & AP_PROXY_WORKER_IS_MATCH)
&& ap_proxy_strcmp_ematch(url_copy,
worker->s->name_ex) == 0)) ) {
max_worker = worker;
max_match = worker_name_length;
proxy_worker **worker = (proxy_worker **)balancer->workers->elts;
for (i = 0; i < balancer->workers->nelts; i++, worker++) {
if (worker_matches(*worker, url_copy, url_len,
min_match, &max_match, mask)) {
max_worker = *worker;
}
}
} else {
worker = (proxy_worker *)conf->workers->elts;
}
else {
proxy_worker *worker = (proxy_worker *)conf->workers->elts;
for (i = 0; i < conf->workers->nelts; i++, worker++) {
if ( ((worker_name_length = strlen(worker->s->name_ex)) <= url_length)
&& (worker_name_length >= min_match)
&& (worker_name_length > max_match)
&& (worker->s->is_name_matchable
|| ((mask & AP_PROXY_WORKER_IS_PREFIX)
&& strncmp(url_copy, worker->s->name_ex,
worker_name_length) == 0))
&& (!worker->s->is_name_matchable
|| ((mask & AP_PROXY_WORKER_IS_MATCH)
&& ap_proxy_strcmp_ematch(url_copy,
worker->s->name_ex) == 0)) ) {
if (worker_matches(worker, url_copy, url_len,
min_match, &max_match, mask)) {
max_worker = worker;
max_match = worker_name_length;
}
}
}
Expand Down Expand Up @@ -2132,6 +2135,7 @@ PROXY_DECLARE(char *) ap_proxy_define_worker_ex(apr_pool_t *p,
wshared->was_malloced = (mask & AP_PROXY_WORKER_IS_MALLOCED) != 0;
if (mask & AP_PROXY_WORKER_IS_MATCH) {
wshared->is_name_matchable = 1;
wshared->is_host_matchable = (address_not_reusable != 0);

/* Before AP_PROXY_WORKER_IS_MATCH (< 2.4.47), a regex worker with
* dollar substitution was never matched against any actual URL, thus
Expand Down