]> granicus.if.org Git - apache/commitdiff
mod_cache: Allow control over the base URL of reverse proxied requests
authorGraham Leggett <minfrin@apache.org>
Sun, 3 Oct 2010 13:23:39 +0000 (13:23 +0000)
committerGraham Leggett <minfrin@apache.org>
Sun, 3 Oct 2010 13:23:39 +0000 (13:23 +0000)
using the CacheKeyBaseURL directive, so that the cache key can be
calculated from the endpoint URL instead of the server URL.

git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1003963 13f79535-47bb-0310-9956-ffa450edef68

CHANGES
docs/manual/mod/mod_cache.xml
modules/cache/cache_storage.c
modules/cache/cache_util.h
modules/cache/mod_cache.c

diff --git a/CHANGES b/CHANGES
index 3dbdf4895f23baa9206ace007717e21f105872ee..ad471cdd04418304e438c46e3d090c42e870f5b9 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -6,6 +6,11 @@ Changes with Apache 2.3.9
      Fix a denial of service attack against mod_reqtimeout.
      [Stefan Fritsch]
 
+  *) mod_cache: Allow control over the base URL of reverse proxied requests
+     using the CacheKeyBaseURL directive, so that the cache key can be
+     calculated from the endpoint URL instead of the server URL. [Graham
+     Leggett]
+
   *) mod_cache: CacheLastModifiedFactor, CacheStoreNoStore, CacheStorePrivate,
      CacheStoreExpired, CacheIgnoreNoLastMod, CacheDefaultExpire,
      CacheMinExpire and CacheMaxExpire can be set per directory/location.
index 9759230e1b74b9528a3fa3d5d5b6919ea2e13fe8..a160537da42ef5c006015a63888226c5ffd2ac2a 100644 (file)
@@ -917,4 +917,35 @@ LastModified date.</description>
 </usage>
 </directivesynopsis>
 
+<directivesynopsis>
+<name>CacheKeyBaseURL</name>
+<description>Override the base URL of reverse proxied cache keys.</description>
+<syntax>CacheKeyBaseURL <var>URL</var></syntax>
+<default>CacheKeyBaseURL http://example.com</default>
+<contextlist><context>server config</context>
+<context>virtual host</context>
+</contextlist>
+<compatibility>Available in Apache 2.3.9 and later</compatibility>
+
+<usage>
+  <p>When the <directive module="mod_cache">CacheKeyBaseURL</directive> directive
+  is specified, the URL provided will be used as the base URL to calculate
+  the URL of the cache keys in the reverse proxy configuration. When not specified,
+  the scheme, hostname and port of the current virtual host is used to construct
+  the cache key. When a cluster of machines is present, and all cached entries
+  should be cached beneath the same cache key, a new base URL can be specified
+  with this directive.</p>
+
+  <example>
+    # Override the base URL of the cache key.<br />
+    CacheKeyBaseURL http://www.example.com/<br />
+  </example>
+
+  <note type="warning">Take care when setting this directive. If two separate virtual
+  hosts are accidentally given the same base URL, entries from one virtual host
+  will be served to the other.</note>
+
+</usage>
+</directivesynopsis>
+
 </modulesynopsis>
index 7b07e38533232cff2cb09aaa2a34a82ab202130c..d96b76c16226e66961b60cd9e3f9d6c959b77cec 100644 (file)
@@ -414,10 +414,15 @@ apr_status_t cache_generate_key_default(request_rec *r, apr_pool_t* p,
      * in the reverse proxy case.
      */
     if (!r->proxyreq || (r->proxyreq == PROXYREQ_REVERSE)) {
-        /* Use _default_ as the hostname if none present, as in mod_vhost */
-        hostname =  ap_get_server_name(r);
-        if (!hostname) {
-            hostname = "_default_";
+        if (conf->base_uri && conf->base_uri->hostname) {
+            hostname = conf->base_uri->hostname;
+        }
+        else {
+            /* Use _default_ as the hostname if none present, as in mod_vhost */
+            hostname =  ap_get_server_name(r);
+            if (!hostname) {
+                hostname = "_default_";
+            }
         }
     }
     else if(r->parsed_uri.hostname) {
@@ -449,7 +454,12 @@ apr_status_t cache_generate_key_default(request_rec *r, apr_pool_t* p,
         scheme = lcs;
     }
     else {
-        scheme = ap_http_scheme(r);
+        if (conf->base_uri && conf->base_uri->scheme) {
+            scheme = conf->base_uri->scheme;
+        }
+        else {
+            scheme = ap_http_scheme(r);
+        }
     }
 
     /*
@@ -460,7 +470,7 @@ apr_status_t cache_generate_key_default(request_rec *r, apr_pool_t* p,
      * scheme - if available. Otherwise use the port-number of the current
      * server.
      */
-    if(r->proxyreq && (r->proxyreq != PROXYREQ_REVERSE)) {
+    if (r->proxyreq && (r->proxyreq != PROXYREQ_REVERSE)) {
         if (r->parsed_uri.port_str) {
             port_str = apr_pcalloc(p, strlen(r->parsed_uri.port_str) + 2);
             port_str[0] = ':';
@@ -481,8 +491,16 @@ apr_status_t cache_generate_key_default(request_rec *r, apr_pool_t* p,
         }
     }
     else {
-        /* Use the server port */
-        port_str = apr_psprintf(p, ":%u", ap_get_server_port(r));
+        if (conf->base_uri && conf->base_uri->port_str) {
+            port_str = conf->base_uri->port_str;
+        }
+        else if (conf->base_uri && conf->base_uri->hostname) {
+            port_str = "";
+        }
+        else {
+            /* Use the server port */
+            port_str = apr_psprintf(p, ":%u", ap_get_server_port(r));
+        }
     }
 
     /*
index 19cd586bfe344cf029ccbc3443926bb9843ddf9f..ffcf8e708fe06b9b2480cca9edca3ffdac5a09aa 100644 (file)
@@ -149,6 +149,8 @@ typedef struct {
     int x_cache_set;
     int x_cache_detail;
     int x_cache_detail_set;
+    apr_uri_t *base_uri;
+    int base_uri_set;
 } cache_server_conf;
 
 typedef struct {
index 460887e89568faca0d36172bc930af304d441ce8..a9475d27bbdee14210a4194ad4e796b7e7e95090 100644 (file)
@@ -1612,6 +1612,10 @@ static void * merge_cache_config(apr_pool_t *p, void *basev, void *overridesv)
         (overrides->x_cache_detail_set == 0)
         ? base->x_cache_detail
         : overrides->x_cache_detail;
+    ps->base_uri =
+        (overrides->base_uri_set == 0)
+        ? base->base_uri
+        : overrides->base_uri;
     return ps;
 }
 
@@ -1981,6 +1985,28 @@ static const char *set_cache_x_cache_detail(cmd_parms *parms, void *dummy, int f
     return NULL;
 }
 
+static const char *set_cache_key_base_url(cmd_parms *parms, void *dummy,
+        const char *arg)
+{
+    cache_server_conf *conf;
+    apr_status_t rv;
+
+    conf =
+        (cache_server_conf *)ap_get_module_config(parms->server->module_config,
+                                                  &cache_module);
+    conf->base_uri = apr_pcalloc(parms->pool, sizeof(apr_uri_t));
+    rv = apr_uri_parse(parms->pool, arg, conf->base_uri);
+    if (rv != APR_SUCCESS) {
+        return apr_psprintf(parms->pool, "Could not parse '%s' as an URL.", arg);
+    }
+    else if (!conf->base_uri->scheme && !conf->base_uri->hostname &&
+            !conf->base_uri->port_str) {
+        return apr_psprintf(parms->pool, "URL '%s' must contain at least one of a scheme, a hostname or a port.", arg);
+    }
+    conf->base_uri_set = 1;
+    return NULL;
+}
+
 static int cache_post_config(apr_pool_t *p, apr_pool_t *plog,
                              apr_pool_t *ptemp, server_rec *s)
 {
@@ -2063,6 +2089,8 @@ static const command_rec cache_cmds[] =
     AP_INIT_FLAG("CacheDetailHeader", set_cache_x_cache_detail, NULL,
                  RSRC_CONF | ACCESS_CONF,
                  "Add a X-Cache-Detail header to responses. Default is off."),
+    AP_INIT_TAKE1("CacheKeyBaseURL", set_cache_key_base_url, NULL, RSRC_CONF,
+                  "Override the base URL of reverse proxied cache keys."),
     {NULL}
 };