]> granicus.if.org Git - apache/blobdiff - modules/cache/cache_storage.c
Update the copyright year in all .c, .h and .xml files
[apache] / modules / cache / cache_storage.c
index 74beb182c0a217336c064c4183b57d6a363025b4..94beaffc6864eb93fc7f55d419159e6a7c4c13fd 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright 2001-2005 The Apache Software Foundation or its licensors, as
+/* Copyright 2001-2006 The Apache Software Foundation or its licensors, as
  * applicable.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
@@ -36,7 +36,7 @@ int cache_remove_url(cache_request_rec *cache, apr_pool_t *p)
     list = cache->providers;
 
     /* Remove the stale cache entry if present. If not, we're
-     * being called from outside of a request; remove the 
+     * being called from outside of a request; remove the
      * non-stalle handle.
      */
     h = cache->stale_handle ? cache->stale_handle : cache->handle;
@@ -66,13 +66,13 @@ int cache_remove_url(cache_request_rec *cache, apr_pool_t *p)
  * decide whether or not it wants to cache this particular entity.
  * If the size is unknown, a size of -1 should be set.
  */
-int cache_create_entity(request_rec *r, char *url, apr_off_t size)
+int cache_create_entity(request_rec *r, apr_off_t size)
 {
     cache_provider_list *list;
     cache_handle_t *h = apr_pcalloc(r->pool, sizeof(cache_handle_t));
     char *key;
     apr_status_t rv;
-    cache_request_rec *cache = (cache_request_rec *) 
+    cache_request_rec *cache = (cache_request_rec *)
                          ap_get_module_config(r->request_config, &cache_module);
 
     rv = cache_generate_key(r, r->pool, &key);
@@ -169,13 +169,13 @@ CACHE_DECLARE(void) ap_cache_accept_headers(cache_handle_t *h, request_rec *r,
  * This function returns OK if successful, DECLINED if no
  * cached entity fits the bill.
  */
-int cache_select_url(request_rec *r, char *url)
+int cache_select(request_rec *r)
 {
     cache_provider_list *list;
     apr_status_t rv;
     cache_handle_t *h;
     char *key;
-    cache_request_rec *cache = (cache_request_rec *) 
+    cache_request_rec *cache = (cache_request_rec *)
                          ap_get_module_config(r->request_config, &cache_module);
 
     rv = cache_generate_key(r, r->pool, &key);
@@ -200,7 +200,7 @@ int cache_select_url(request_rec *r, char *url)
 
             /*
              * Check Content-Negotiation - Vary
-             * 
+             *
              * At this point we need to make sure that the object we found in
              * the cache is the same object that would be delivered to the
              * client, when the effects of content negotiation are taken into
@@ -286,7 +286,7 @@ int cache_select_url(request_rec *r, char *url)
                     if (etag) {
                         apr_table_set(r->headers_in, "If-None-Match", etag);
                     }
-                    
+
                     if (lastmod) {
                         apr_table_set(r->headers_in, "If-Modified-Since",
                                       lastmod);
@@ -320,12 +320,97 @@ int cache_select_url(request_rec *r, char *url)
 apr_status_t cache_generate_key_default(request_rec *r, apr_pool_t* p,
                                         char**key)
 {
-    if (r->hostname) {
-        *key = apr_pstrcat(p, r->hostname, r->uri, "?", r->args, NULL);
+    char *port_str, *scheme, *hn;
+    const char * hostname;
+    int i;
+
+    /*
+     * Use the canonical name to improve cache hit rate, but only if this is
+     * not a proxy request or if this is a reverse proxy request.
+     * We need to handle both cases in the same manner as for the reverse proxy
+     * case we have the following situation:
+     *
+     * If a cached entry is looked up by mod_cache's quick handler r->proxyreq
+     * is still unset in the reverse proxy case as it only gets set in the
+     * translate name hook (either by ProxyPass or mod_rewrite) which is run
+     * after the quick handler hook. This is different to the forward proxy
+     * case where it gets set before the quick handler is run (in the
+     * post_read_request hook).
+     * If a cache entry is created by the CACHE_SAVE filter we always have
+     * r->proxyreq set correctly.
+     * So we must ensure that in the reverse proxy case we use the same code
+     * path and using the canonical name seems to be the right thing to do
+     * 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_";
+        }
+    }
+    else if(r->parsed_uri.hostname) {
+        /* Copy the parsed uri hostname */
+        hn = apr_pcalloc(p, strlen(r->parsed_uri.hostname) + 1);
+        for (i = 0; r->parsed_uri.hostname[i]; i++) {
+            hn[i] = apr_tolower(r->parsed_uri.hostname[i]);
+        }
+        /* const work-around */
+        hostname = hn;
     }
     else {
-        *key = apr_pstrcat(p, r->uri, "?", r->args, NULL);
+        /* We are a proxied request, with no hostname. Unlikely
+         * to get very far - but just in case */
+        hostname = "_default_";
     }
+
+    /* Copy the scheme, ensuring that it is lower case. If the parsed uri
+     * contains no string or if this is not a proxy request.
+     */
+    if (r->proxyreq && r->parsed_uri.scheme) {
+        /* Copy the scheme */
+        scheme = apr_pcalloc(p, strlen(r->parsed_uri.scheme) + 1);
+        for (i = 0; r->parsed_uri.scheme[i]; i++) {
+            scheme[i] = apr_tolower(r->parsed_uri.scheme[i]);
+        }
+    }
+    else {
+        scheme = "http";
+    }
+
+    /* If the content is locally generated, use the port-number of the
+     * current server. Otherwise. copy the URI's port-string (which may be a
+     * service name). If the URI contains no port-string, use apr-util's
+     * notion of the default port for that scheme - if available.
+     */
+    if(r->proxyreq) {
+        if (r->parsed_uri.port_str) {
+            port_str = apr_pcalloc(p, strlen(r->parsed_uri.port_str) + 2);
+            port_str[0] = ':';
+            for (i = 0; r->parsed_uri.port_str[i]; i++) {
+                port_str[i + 1] = apr_tolower(r->parsed_uri.port_str[i]);
+            }
+        }
+        else if (apr_uri_port_of_scheme(scheme)) {
+            port_str = apr_psprintf(p, ":%u", apr_uri_port_of_scheme(scheme));
+        }
+        else {
+            /* No port string given in the AbsoluteUri, and we have no
+             * idea what the default port for the scheme is. Leave it
+             * blank and live with the inefficiency of some extra cached
+             * entities.
+             */
+            port_str = "";
+        }
+    }
+    else {
+        /* Use the server port */
+        port_str = apr_psprintf(p, ":%u", ap_get_server_port(r));
+    }
+
+    /* Key format is a URI */
+    *key = apr_pstrcat(p, scheme, "://", hostname, port_str,
+                       r->parsed_uri.path, "?", r->args, NULL);
+
     return APR_SUCCESS;
 }
-