]> granicus.if.org Git - apache/commitdiff
Merge r1543174, r1560367, r1560546, r1560689, r1560979, r1561137, r1561660 from trunk:
authorJim Jagielski <jim@apache.org>
Fri, 18 Apr 2014 15:27:42 +0000 (15:27 +0000)
committerJim Jagielski <jim@apache.org>
Fri, 18 Apr 2014 15:27:42 +0000 (15:27 +0000)
Correct logic... if this is a UDS socket, then bypass all
this.

make mod_rewrite and mod_proxy UDS work together...

Adjust url as required, following what we did to r->filename.
Save some cycles when searching...

Tuck away UDS path in request-rec, since worker isn't
thread-safe. Protect from NULL refs.

Reflow logic... pull UDS stuff out

handle leak. thx to Y^2

r->filename should maintain the proxy: prefix for PHP-FPM
Reviewed/backported by: jim

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

STATUS
modules/mappers/mod_rewrite.c
modules/proxy/mod_proxy.c
modules/proxy/mod_proxy.h
modules/proxy/proxy_util.c

diff --git a/STATUS b/STATUS
index aa83dca0f465c63f4306f25a66e91c1b255b09ae..eec238a4e1e05b41272123d9c6e19a40be377e1c 100644 (file)
--- a/STATUS
+++ b/STATUS
@@ -100,18 +100,6 @@ RELEASE SHOWSTOPPERS:
 PATCHES ACCEPTED TO BACKPORT FROM TRUNK:
   [ start all new proposals below, under PATCHES PROPOSED. ]
 
-   * proxy_util.c: Allow mod_rewrite to also use UDS for proxied links.
-     trunk patch: http://svn.apache.org/r1543174
-                  http://svn.apache.org/r1560367
-                  http://svn.apache.org/r1560546
-                  http://svn.apache.org/r1560689
-                  http://svn.apache.org/r1560979
-                  http://svn.apache.org/r1561137
-                  http://svn.apache.org/r1561660
-     2.4.x patch: trunk works
-                  http://people.apache.org/~jim/patches/uds-rewrite.patch
-     +1: jim, humbedooh, ylavic
-
    * mod_proxy_wstunnel: wstunnel rollup for connection handling
      trunk patch: http://svn.apache.org/r1587036 (set backend->close)
                   http://svn.apache.org/r1587040 (remove reqtimeout)
index 7646407bf384c78c98c54abf5ce154726ca6d7c9..ad77fd6c34359995078b3b806d9ddd65d96e344d 100644 (file)
@@ -4161,6 +4161,7 @@ static int apply_rewrite_rule(rewriterule_entry *p, rewrite_ctx *ctx)
                     r->filename));
 
         r->filename = apr_pstrcat(r->pool, "proxy:", r->filename, NULL);
+        apr_table_setn(r->notes, "rewrite-proxy", "1");
         return 1;
     }
 
index 22a022099b3c11062392c73cb8bec5a998fa1293..57f9e41b8718d8926843e1c19cf8b80c8b7b9d77 100644 (file)
@@ -2631,6 +2631,8 @@ static void child_init(apr_pool_t *p, server_rec *s)
                 ap_proxy_hashfunc(conf->forward->s->name, PROXY_HASHFUNC_FNV);
             /* Do not disable worker in case of errors */
             conf->forward->s->status |= PROXY_WORKER_IGNORE_ERRORS;
+            /* Mark as the "generic" worker */
+            conf->forward->s->status |= PROXY_WORKER_GENERIC;
             ap_proxy_initialize_worker(conf->forward, s, conf->pool);
             /* Disable address cache for generic forward worker */
             conf->forward->s->is_address_reusable = 0;
@@ -2646,6 +2648,8 @@ static void child_init(apr_pool_t *p, server_rec *s)
                 ap_proxy_hashfunc(reverse->s->name, PROXY_HASHFUNC_FNV);
             /* Do not disable worker in case of errors */
             reverse->s->status |= PROXY_WORKER_IGNORE_ERRORS;
+            /* Mark as the "generic" worker */
+            reverse->s->status |= PROXY_WORKER_GENERIC;
             conf->reverse = reverse;
             ap_proxy_initialize_worker(conf->reverse, s, conf->pool);
             /* Disable address cache for generic reverse worker */
index 67a9015be99e5682b0660d27361410c3c82b172b..585ace89eb001eb683284565f7d99c2d7ed7915e 100644 (file)
@@ -275,6 +275,7 @@ struct proxy_conn_pool {
 #define PROXY_WORKER_INITIALIZED    0x0001
 #define PROXY_WORKER_IGNORE_ERRORS  0x0002
 #define PROXY_WORKER_DRAIN          0x0004
+#define PROXY_WORKER_GENERIC        0x0008
 #define PROXY_WORKER_IN_SHUTDOWN    0x0010
 #define PROXY_WORKER_DISABLED       0x0020
 #define PROXY_WORKER_STOPPED        0x0040
@@ -286,6 +287,7 @@ struct proxy_conn_pool {
 #define PROXY_WORKER_INITIALIZED_FLAG    'O'
 #define PROXY_WORKER_IGNORE_ERRORS_FLAG  'I'
 #define PROXY_WORKER_DRAIN_FLAG          'N'
+#define PROXY_WORKER_GENERIC_FLAG        'G'
 #define PROXY_WORKER_IN_SHUTDOWN_FLAG    'U'
 #define PROXY_WORKER_DISABLED_FLAG       'D'
 #define PROXY_WORKER_STOPPED_FLAG        'S'
@@ -306,6 +308,8 @@ PROXY_WORKER_DISABLED | PROXY_WORKER_STOPPED | PROXY_WORKER_IN_ERROR )
 
 #define PROXY_WORKER_IS_DRAINING(f)   ( (f)->s->status &  PROXY_WORKER_DRAIN )
 
+#define PROXY_WORKER_IS_GENERIC(f)   ( (f)->s->status &  PROXY_WORKER_GENERIC )
+
 /* default worker retry timeout in seconds */
 #define PROXY_WORKER_DEFAULT_RETRY    60
 
index b9944ccbdc92e96a8c87e30ee091bd2bbf2896e4..741830c0b8f70a1d7dce01e1e0f04f48722e8c2a 100644 (file)
@@ -1931,6 +1931,8 @@ PROXY_DECLARE(int) ap_proxy_pre_request(proxy_worker **worker,
         }
         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;
@@ -1942,6 +1944,36 @@ PROXY_DECLARE(int) ap_proxy_pre_request(proxy_worker **worker,
                  * regarding the Connection header in the request.
                  */
                 apr_table_setn(r->subprocess_env, "proxy-nokeepalive", "1");
+                /*
+                 * In the case of the generic reverse proxy, we need to see if we
+                 * were passed a UDS url (eg: from mod_proxy) and adjust uds_path
+                 * as required.
+                 *
+                 * 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, '|'))) {
+                    apr_uri_t urisock;
+                    apr_status_t rv;
+                    *ptr = '\0';
+                    rv = apr_uri_parse(r->pool, ptr2, &urisock);
+                    if (rv == APR_SUCCESS) {
+                        char *rurl = ptr+1;
+                        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 */
+                        /* r->filename starts w/ "proxy:", so add after that */
+                        memmove(r->filename+6, rurl, strlen(rurl)+1);
+                        ap_log_rerror(APLOG_MARK, APLOG_TRACE2, 0, r,
+                                      "*: rewrite of url due to UDS(%s): %s (%s)",
+                                      sockpath, *url, r->filename);
+                    }
+                    else {
+                        *ptr = '|';
+                    }
+                }
             }
         }
     }
@@ -2101,29 +2133,6 @@ PROXY_DECLARE(int) ap_proxy_acquire_connection(const char *proxy_function,
     (*conn)->close  = 0;
     (*conn)->inreslist = 0;
 
-    if (*worker->s->uds_path) {
-        if ((*conn)->uds_path == NULL) {
-            /* use (*conn)->pool instead of worker->cp->pool to match lifetime */
-            (*conn)->uds_path = apr_pstrdup((*conn)->pool, worker->s->uds_path);
-        }
-        if ((*conn)->uds_path) {
-            ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(02545)
-                         "%s: has determined UDS as %s",
-                         proxy_function, (*conn)->uds_path);
-        }
-        else {
-            /* should never happen */
-            ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(02546)
-                         "%s: cannot determine UDS (%s)",
-                         proxy_function, worker->s->uds_path);
-
-        }
-    }
-    else {
-        (*conn)->uds_path = NULL;
-    }
-
-
     return OK;
 }
 
@@ -2154,6 +2163,7 @@ ap_proxy_determine_connection(apr_pool_t *p, request_rec *r,
     int server_port;
     apr_status_t err = APR_SUCCESS;
     apr_status_t uerr = APR_SUCCESS;
+    const char *uds_path;
 
     /*
      * Break up the URL to determine the host to connect to
@@ -2194,85 +2204,116 @@ ap_proxy_determine_connection(apr_pool_t *p, request_rec *r,
      *      to check host and port on the conn and be careful about
      *      spilling the cached addr from the worker.
      */
-    if (!conn->hostname || !worker->s->is_address_reusable ||
-        worker->s->disablereuse || *worker->s->uds_path) {
-        if (proxyname) {
-            conn->hostname = apr_pstrdup(conn->pool, proxyname);
-            conn->port = proxyport;
-            /*
-             * If we have a forward proxy and the protocol is HTTPS,
-             * then we need to prepend a HTTP CONNECT request before
-             * sending our actual HTTPS requests.
-             * Save our real backend data for using it later during HTTP CONNECT.
-             */
-            if (conn->is_ssl) {
-                const char *proxy_auth;
-
-                forward_info *forward = apr_pcalloc(conn->pool, sizeof(forward_info));
-                conn->forward = forward;
-                forward->use_http_connect = 1;
-                forward->target_host = apr_pstrdup(conn->pool, uri->hostname);
-                forward->target_port = uri->port;
-                /* Do we want to pass Proxy-Authorization along?
-                 * If we haven't used it, then YES
-                 * If we have used it then MAYBE: RFC2616 says we MAY propagate it.
-                 * So let's make it configurable by env.
-                 * The logic here is the same used in mod_proxy_http.
-                 */
-                proxy_auth = apr_table_get(r->headers_in, "Proxy-Authorization");
-                if (proxy_auth != NULL &&
-                    proxy_auth[0] != '\0' &&
-                    r->user == NULL && /* we haven't yet authenticated */
-                    apr_table_get(r->subprocess_env, "Proxy-Chain-Auth")) {
-                    forward->proxy_auth = apr_pstrdup(conn->pool, proxy_auth);
-                }
-            }
+    uds_path = (*worker->s->uds_path ? worker->s->uds_path : apr_table_get(r->notes, "uds_path"));
+    if (uds_path) {
+        if (conn->uds_path == NULL) {
+            /* use (*conn)->pool instead of worker->cp->pool to match lifetime */
+            conn->uds_path = apr_pstrdup(conn->pool, uds_path);
         }
-        else {
-            conn->hostname = apr_pstrdup(conn->pool, uri->hostname);
-            conn->port = uri->port;
+        if (conn->uds_path) {
+            ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(02545)
+                         "%s: has determined UDS as %s",
+                         uri->scheme, conn->uds_path);
         }
-        socket_cleanup(conn);
-        if (!(*worker->s->uds_path) &&
-            (!worker->s->is_address_reusable || worker->s->disablereuse)) {
-            /*
-             * Only do a lookup if we should not reuse the backend address.
-             * Otherwise we will look it up once for the worker.
-             */
-            err = apr_sockaddr_info_get(&(conn->addr),
-                                        conn->hostname, APR_UNSPEC,
-                                        conn->port, 0,
-                                        conn->pool);
+        else {
+            /* should never happen */
+            ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(02546)
+                         "%s: cannot determine UDS (%s)",
+                         uri->scheme, uds_path);
+
         }
-    }
-    if (!(*worker->s->uds_path) && worker->s->is_address_reusable && !worker->s->disablereuse) {
         /*
-         * Looking up the backend address for the worker only makes sense if
-         * we can reuse the address.
+         * In UDS cases, some structs are NULL. Protect from de-refs
+         * and provide info for logging at the same time.
          */
-        if (!worker->cp->addr) {
-            if ((err = PROXY_THREAD_LOCK(worker)) != APR_SUCCESS) {
-                ap_log_rerror(APLOG_MARK, APLOG_ERR, err, r, APLOGNO(00945) "lock");
-                return HTTP_INTERNAL_SERVER_ERROR;
+        if (!conn->addr) {
+            apr_sockaddr_t *sa;
+            apr_sockaddr_info_get(&sa, NULL, APR_UNSPEC, 0, 0, conn->pool);
+            conn->addr = sa;
+        }
+        conn->hostname = "httpd-UDS";
+        conn->port = 0;
+    }
+    else {
+        int will_reuse = worker->s->is_address_reusable && !worker->s->disablereuse;
+        if (!conn->hostname || !will_reuse) {
+            if (proxyname) {
+                conn->hostname = apr_pstrdup(conn->pool, proxyname);
+                conn->port = proxyport;
+                /*
+                 * If we have a forward proxy and the protocol is HTTPS,
+                 * then we need to prepend a HTTP CONNECT request before
+                 * sending our actual HTTPS requests.
+                 * Save our real backend data for using it later during HTTP CONNECT.
+                 */
+                if (conn->is_ssl) {
+                    const char *proxy_auth;
+
+                    forward_info *forward = apr_pcalloc(conn->pool, sizeof(forward_info));
+                    conn->forward = forward;
+                    forward->use_http_connect = 1;
+                    forward->target_host = apr_pstrdup(conn->pool, uri->hostname);
+                    forward->target_port = uri->port;
+                    /* Do we want to pass Proxy-Authorization along?
+                     * If we haven't used it, then YES
+                     * If we have used it then MAYBE: RFC2616 says we MAY propagate it.
+                     * So let's make it configurable by env.
+                     * The logic here is the same used in mod_proxy_http.
+                     */
+                    proxy_auth = apr_table_get(r->headers_in, "Proxy-Authorization");
+                    if (proxy_auth != NULL &&
+                        proxy_auth[0] != '\0' &&
+                        r->user == NULL && /* we haven't yet authenticated */
+                        apr_table_get(r->subprocess_env, "Proxy-Chain-Auth")) {
+                        forward->proxy_auth = apr_pstrdup(conn->pool, proxy_auth);
+                    }
+                }
             }
-
+            else {
+                conn->hostname = apr_pstrdup(conn->pool, uri->hostname);
+                conn->port = uri->port;
+            }
+            if (!will_reuse) {
+                /*
+                 * Only do a lookup if we should not reuse the backend address.
+                 * Otherwise we will look it up once for the worker.
+                 */
+                err = apr_sockaddr_info_get(&(conn->addr),
+                                            conn->hostname, APR_UNSPEC,
+                                            conn->port, 0,
+                                            conn->pool);
+            }
+            socket_cleanup(conn);
+        }
+        if (will_reuse) {
             /*
-             * Worker can have the single constant backend adress.
-             * The single DNS lookup is used once per worker.
-             * If dynamic change is needed then set the addr to NULL
-             * inside dynamic config to force the lookup.
+             * Looking up the backend address for the worker only makes sense if
+             * we can reuse the address.
              */
-            err = apr_sockaddr_info_get(&(worker->cp->addr),
-                                        conn->hostname, APR_UNSPEC,
-                                        conn->port, 0,
-                                        worker->cp->pool);
-            conn->addr = worker->cp->addr;
-            if ((uerr = PROXY_THREAD_UNLOCK(worker)) != APR_SUCCESS) {
-                ap_log_rerror(APLOG_MARK, APLOG_ERR, uerr, r, APLOGNO(00946) "unlock");
+            if (!worker->cp->addr) {
+                if ((err = PROXY_THREAD_LOCK(worker)) != APR_SUCCESS) {
+                    ap_log_rerror(APLOG_MARK, APLOG_ERR, err, r, APLOGNO(00945) "lock");
+                    return HTTP_INTERNAL_SERVER_ERROR;
+                }
+
+                /*
+                 * Worker can have the single constant backend adress.
+                 * The single DNS lookup is used once per worker.
+                 * If dynamic change is needed then set the addr to NULL
+                 * inside dynamic config to force the lookup.
+                 */
+                err = apr_sockaddr_info_get(&(worker->cp->addr),
+                                            conn->hostname, APR_UNSPEC,
+                                            conn->port, 0,
+                                            worker->cp->pool);
+                conn->addr = worker->cp->addr;
+                if ((uerr = PROXY_THREAD_UNLOCK(worker)) != APR_SUCCESS) {
+                    ap_log_rerror(APLOG_MARK, APLOG_ERR, uerr, r, APLOGNO(00946) "unlock");
+                }
+            }
+            else {
+                conn->addr = worker->cp->addr;
             }
-        }
-        else {
-            conn->addr = worker->cp->addr;
         }
     }
     /* Close a possible existing socket if we are told to do so */