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(cmd->temp_pool, NULL, conf, new->real);
int reuse = 0;
if (!worker) {
- const char *err = ap_proxy_define_worker(cmd->pool, &worker, NULL, conf, r, 0);
+ const char *err;
+ if (use_regex) {
+ err = ap_proxy_define_match_worker(cmd->pool, &worker, NULL,
+ conf, r, 0);
+ }
+ else {
+ err = ap_proxy_define_worker(cmd->pool, &worker, NULL,
+ conf, r, 0);
+ }
if (err)
return apr_pstrcat(cmd->temp_pool, "ProxyPass ", err, NULL);
PROXY_COPY_CONF_PARAMS(worker, conf);
- } else {
+ }
+ else if ((use_regex != 0) ^ (worker->s->is_name_matchable)) {
+ return apr_pstrcat(cmd->temp_pool, "ProxyPass/<Proxy> and "
+ "ProxyPassMatch/<ProxyMatch> can't be used "
+ "altogether with the same worker name ",
+ "(", worker->s->name, ")", NULL);
+ }
+ else {
reuse = 1;
ap_log_error(APLOG_MARK, APLOG_INFO, 0, cmd->server, APLOGNO(01145)
"Sharing worker '%s' instead of creating new worker '%s'",
char *word, *val;
proxy_balancer *balancer = NULL;
proxy_worker *worker = NULL;
+ int use_regex = 0;
const char *err = ap_check_cmd_context(cmd, NOT_IN_DIR_LOC_FILE);
proxy_server_conf *sconf =
if (!r) {
return "Regex could not be compiled";
}
+ use_regex = 1;
}
/* initialize our config and fetch it */
worker = ap_proxy_get_worker(cmd->temp_pool, NULL, sconf,
de_socketfy(cmd->temp_pool, (char*)conf->p));
if (!worker) {
- err = ap_proxy_define_worker(cmd->pool, &worker, NULL,
- sconf, conf->p, 0);
+ if (use_regex) {
+ err = ap_proxy_define_match_worker(cmd->pool, &worker, NULL,
+ sconf, conf->p, 0);
+ }
+ else {
+ err = ap_proxy_define_worker(cmd->pool, &worker, NULL,
+ sconf, conf->p, 0);
+ }
if (err)
return apr_pstrcat(cmd->temp_pool, thiscmd->name,
" ", err, NULL);
}
+ else if ((use_regex != 0) ^ (worker->s->is_name_matchable)) {
+ return apr_pstrcat(cmd->temp_pool, "ProxyPass/<Proxy> and "
+ "ProxyPassMatch/<ProxyMatch> can't be used "
+ "altogether with the same worker name ",
+ "(", worker->s->name, ")", NULL);
+ }
}
if (worker == NULL && balancer == NULL) {
return apr_pstrcat(cmd->pool, thiscmd->name,
unsigned int keepalive_set:1;
unsigned int disablereuse_set:1;
unsigned int was_malloced:1;
+ unsigned int is_name_matchable:1;
} proxy_worker_shared;
#define ALIGNED_PROXY_WORKER_SHARED_SIZE (APR_ALIGN_DEFAULT(sizeof(proxy_worker_shared)))
const char *url,
int do_malloc);
+/**
+ * Define and Allocate space for the ap_strcmp_match()able worker to proxy
+ * configuration.
+ * @param p memory pool to allocate worker from
+ * @param worker the new worker
+ * @param balancer the balancer that the worker belongs to
+ * @param conf current proxy server configuration
+ * @param url url containing worker name (produces match pattern)
+ * @param do_malloc true if shared struct should be malloced
+ * @return error message or NULL if successful (*worker is new worker)
+ */
+PROXY_DECLARE(char *) ap_proxy_define_match_worker(apr_pool_t *p,
+ proxy_worker **worker,
+ proxy_balancer *balancer,
+ proxy_server_conf *conf,
+ const char *url,
+ int do_malloc);
+
/**
* Share a defined proxy worker via shm
* @param worker worker to be shared
return apr_pstrcat(p, "unix:", worker->s->uds_path, "|", worker->s->name, NULL);
}
+/*
+ * Taken from ap_strcmp_match() :
+ * Match = 0, NoMatch = 1, Abort = -1, Inval = -2
+ * Based loosely on sections of wildmat.c by Rich Salz
+ * Hmmm... shouldn't this really go component by component?
+ *
+ * Adds handling of the "\<any>" => "<any>" unescaping.
+ */
+static int ap_proxy_strcmp_ematch(const char *str, const char *expected)
+{
+ apr_size_t x, y;
+
+ for (x = 0, y = 0; expected[y]; ++y, ++x) {
+ if ((!str[x]) && (expected[y] != '$' || !apr_isdigit(expected[y + 1])))
+ return -1;
+ if (expected[y] == '$' && apr_isdigit(expected[y + 1])) {
+ while (expected[y] == '$' && apr_isdigit(expected[y + 1]))
+ y += 2;
+ if (!expected[y])
+ return 0;
+ while (str[x]) {
+ int ret;
+ if ((ret = ap_proxy_strcmp_ematch(&str[x++], &expected[y])) != 1)
+ return ret;
+ }
+ return -1;
+ }
+ else if (expected[y] == '\\') {
+ /* NUL is an invalid char! */
+ if (!expected[++y])
+ return -2;
+ }
+ if (str[x] != expected[y])
+ return 1;
+ }
+ return (str[x] != '\0');
+}
+
PROXY_DECLARE(proxy_worker *) ap_proxy_get_worker(apr_pool_t *p,
proxy_balancer *balancer,
proxy_server_conf *conf,
if ( ((worker_name_length = strlen(worker->s->name)) <= url_length)
&& (worker_name_length >= min_match)
&& (worker_name_length > max_match)
- && (strncmp(url_copy, worker->s->name, worker_name_length) == 0) ) {
+ && (worker->s->is_name_matchable
+ || strncmp(url_copy, worker->s->name,
+ worker_name_length) == 0)
+ && (!worker->s->is_name_matchable
+ || ap_proxy_strcmp_ematch(url_copy,
+ worker->s->name) == 0) ) {
max_worker = worker;
max_match = worker_name_length;
}
-
}
} else {
worker = (proxy_worker *)conf->workers->elts;
if ( ((worker_name_length = strlen(worker->s->name)) <= url_length)
&& (worker_name_length >= min_match)
&& (worker_name_length > max_match)
- && (strncmp(url_copy, worker->s->name, worker_name_length) == 0) ) {
+ && (worker->s->is_name_matchable
+ || strncmp(url_copy, worker->s->name,
+ worker_name_length) == 0)
+ && (!worker->s->is_name_matchable
+ || ap_proxy_strcmp_ematch(url_copy,
+ worker->s->name) == 0) ) {
max_worker = worker;
max_match = worker_name_length;
}
wshared->hash.def = ap_proxy_hashfunc(wshared->name, PROXY_HASHFUNC_DEFAULT);
wshared->hash.fnv = ap_proxy_hashfunc(wshared->name, PROXY_HASHFUNC_FNV);
wshared->was_malloced = (do_malloc != 0);
+ wshared->is_name_matchable = 0;
if (sockpath) {
if (PROXY_STRNCPY(wshared->uds_path, sockpath) != APR_SUCCESS) {
return apr_psprintf(p, "worker uds path (%s) too long", sockpath);
return NULL;
}
+PROXY_DECLARE(char *) ap_proxy_define_match_worker(apr_pool_t *p,
+ proxy_worker **worker,
+ proxy_balancer *balancer,
+ proxy_server_conf *conf,
+ const char *url,
+ int do_malloc)
+{
+ char *err;
+
+ err = ap_proxy_define_worker(p, worker, balancer, conf, url, do_malloc);
+ if (err) {
+ return err;
+ }
+
+ (*worker)->s->is_name_matchable = 1;
+ return NULL;
+}
+
/*
* Create an already defined worker and free up memory
*/