]> git.ipfire.org Git - thirdparty/apache/httpd.git/commitdiff
*) mod_proxy: Honor parameters of ProxyPassMatch workers with substitution
authorJim Jagielski <jim@apache.org>
Tue, 7 Jan 2025 15:05:35 +0000 (15:05 +0000)
committerJim Jagielski <jim@apache.org>
Tue, 7 Jan 2025 15:05:35 +0000 (15:05 +0000)
                in the host name or port. PR 69233.

git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.4.x@1922958 13f79535-47bb-0310-9956-ffa450edef68

STATUS
include/ap_mmn.h
modules/proxy/mod_proxy.h
modules/proxy/proxy_util.c

diff --git a/STATUS b/STATUS
index b76df56223870bf37d72e36160ad0d7be2b2128d..c8eb5b4867f1169aa6bf8020d3c9e92da90bd520 100644 (file)
--- a/STATUS
+++ b/STATUS
@@ -157,15 +157,6 @@ RELEASE SHOWSTOPPERS:
 PATCHES ACCEPTED TO BACKPORT FROM TRUNK:
   [ start all new proposals below, under PATCHES PROPOSED. ]
 
-  *) mod_proxy: Honor parameters of ProxyPassMatch workers with substitution
-                in the host name or port. PR 69233.
-     trunk patch: https://svn.apache.org/r1912462
-                  https://svn.apache.org/r1919617
-                  https://svn.apache.org/r1919619
-     2.4.x patch: https://patch-diff.githubusercontent.com/raw/apache/httpd/pull/469.diff
-     PR: https://github.com/apache/httpd/pull/469
-     +1: ylavic, rpluem, jim
-
   *) mod_proxy_fcgi: Fix proxy-fcgi-pathinfo=full
      trunk patch: https://svn.apache.org/r1919547
                   https://svn.apache.org/r1921238
index 2e63617271eeb5a8bb5e0b491abcea47194c7229..c124eb5370e513f519db713e0f7cf5d230d443d0 100644 (file)
  *                           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
index cd388898c14057c55784a5cd6cd4cfdbd53f5e65..329d10fdaa9b05eafa7773ce96c6da96f6186e62 100644 (file)
@@ -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)))
index 1fc6bd6bca6d8882c1e7e6f82afe5a84fcb75ccb..2590b7ed3a22ec2dfcef7f7c7c8601b24bf205d3 100644 (file)
@@ -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;
@@ -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))) {
@@ -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;
             }
         }
     }
@@ -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