From: Ruediger Pluem Date: Thu, 21 May 2009 10:42:54 +0000 (+0000) Subject: * Add CacheIgnoreURLSessionIdentifiers directive to ignore X-Git-Tag: 2.3.3~553 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=d2700640cd3e79f7187b011658861067a7126bff;p=apache * Add CacheIgnoreURLSessionIdentifiers directive to ignore defined session identifiers encoded in the URL when caching. git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@777042 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/CHANGES b/CHANGES index 8354a68789..c88cfbec6d 100644 --- a/CHANGES +++ b/CHANGES @@ -6,6 +6,10 @@ Changes with Apache 2.3.3 mod_proxy_ajp: Avoid delivering content from a previous request which failed to send a request body. PR 46949 [Ruediger Pluem] + *) mod_cache: Add CacheIgnoreURLSessionIdentifiers directive to ignore + defined session identifiers encoded in the URL when caching. + [Ruediger Pluem] + *) mod_rewrite: Fix the error string returned by RewriteRule. RewriteRule returned "RewriteCond: bad flag delimiters" when the 3rd argument of RewriteRule was not started with "[" or not ended with "]". diff --git a/docs/manual/mod/mod_cache.xml b/docs/manual/mod/mod_cache.xml index 9a1ae8a809..5b9dd84da4 100644 --- a/docs/manual/mod/mod_cache.xml +++ b/docs/manual/mod/mod_cache.xml @@ -391,6 +391,41 @@ LastModified date. + +CacheIgnoreURLSessionIdentifiers +Ignore defined session identifiers encoded in the URL when caching + +CacheIgnoreURLSessionIdentifiers identifier [identifier] ... +CacheIgnoreURLSessionIdentifiers None +server configvirtual host + + + +

Sometimes applications encode the session identifier into the URL like in the following + Examples: +

+
    +
  • /someapplication/image.gif;jsessionid=123456789
  • +
  • /someapplication/image.gif?PHPSESSIONID=12345678
  • +
+

This causes cachable resources to be stored separately for each session, which + is often not desired. CacheIgnoreURLSessionIdentifiers lets + define a list of identifiers that are removed from the key that is used to identify + an entity in the cache, such that cachable resources are not stored separately for + each session. +

+ + Example 1 + CacheIgnoreURLSessionIdentifiers jsessionid + + + Example 2 + CacheIgnoreURLSessionIdentifiers None + + +
+
+ CacheStorePrivate Attempt to cache responses that the server has marked as private diff --git a/modules/cache/cache_storage.c b/modules/cache/cache_storage.c index f19375b952..6ce8ca3746 100644 --- a/modules/cache/cache_storage.c +++ b/modules/cache/cache_storage.c @@ -355,6 +355,7 @@ apr_status_t cache_generate_key_default(request_rec *r, apr_pool_t* p, char *port_str, *hn, *lcs; const char *hostname, *scheme; int i; + char *path, *querystring; cache = (cache_request_rec *) ap_get_module_config(r->request_config, &cache_module); @@ -472,14 +473,65 @@ apr_status_t cache_generate_key_default(request_rec *r, apr_pool_t* p, port_str = apr_psprintf(p, ":%u", ap_get_server_port(r)); } + /* + * Check if we need to ignore session identifiers in the URL and do so + * if needed. + */ + path = r->parsed_uri.path; + querystring = r->parsed_uri.query; + if (conf->ignore_session_id_set == CACHE_IGNORE_SESSION_ID_SET) { + int i; + char **identifier; + + identifier = (char **)conf->ignore_session_id->elts; + for (i = 0; i < conf->ignore_session_id->nelts; i++, identifier++) { + int len; + char *param; + + len = strlen(*identifier); + /* + * Check that we have a parameter separator in the last segment + * of the path and that the parameter matches our identifier + */ + if ((param = strrchr(path, ';')) + && !strncmp(param + 1, *identifier, len) + && (*(param + len + 1) == '=') + && !strchr(param + len + 2, '/')) { + path = apr_pstrndup(p, path, param - path); + break; + } + /* + * Check if the identifier is in the querystring and cut it out. + */ + if (querystring + && (param = strstr(querystring, *identifier)) + && (*(param + len) == '=') + ) { + char *amp; + + if (querystring != param) { + querystring = apr_pstrndup(p, querystring, + param - querystring); + } + else { + querystring = ""; + } + if ((amp = strchr(param + len + 1, '&'))) { + querystring = apr_pstrcat(p, querystring, amp + 1, NULL); + } + break; + } + } + } + /* Key format is a URI, optionally without the query-string */ if (conf->ignorequerystring) { *key = apr_pstrcat(p, scheme, "://", hostname, port_str, - r->parsed_uri.path, "?", NULL); + path, "?", NULL); } else { *key = apr_pstrcat(p, scheme, "://", hostname, port_str, - r->parsed_uri.path, "?", r->parsed_uri.query, NULL); + path, "?", querystring, NULL); } /* @@ -491,6 +543,9 @@ apr_status_t cache_generate_key_default(request_rec *r, apr_pool_t* p, * handler during following requests. */ cache->key = apr_pstrdup(r->pool, *key); + ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, NULL, + "cache: Key for entity %s?%s is %s", r->parsed_uri.path, + r->parsed_uri.query, *key); return APR_SUCCESS; } diff --git a/modules/cache/mod_cache.c b/modules/cache/mod_cache.c index b27c7fbb2a..76a4e37f4c 100644 --- a/modules/cache/mod_cache.c +++ b/modules/cache/mod_cache.c @@ -952,6 +952,9 @@ static void * create_cache_config(apr_pool_t *p, server_rec *s) /* flag indicating that query-string should be ignored when caching */ ps->ignorequerystring = 0; ps->ignorequerystring_set = 0; + /* array of identifiers that should not be used for key calculation */ + ps->ignore_session_id = apr_array_make(p, 10, sizeof(char *)); + ps->ignore_session_id_set = CACHE_IGNORE_SESSION_ID_UNSET; return ps; } @@ -1002,6 +1005,10 @@ static void * merge_cache_config(apr_pool_t *p, void *basev, void *overridesv) (overrides->ignorequerystring_set == 0) ? base->ignorequerystring : overrides->ignorequerystring; + ps->ignore_session_id = + (overrides->ignore_session_id_set == CACHE_IGNORE_HEADERS_UNSET) + ? base->ignore_session_id + : overrides->ignore_session_id; return ps; } static const char *set_cache_ignore_no_last_mod(cmd_parms *parms, void *dummy, @@ -1085,6 +1092,34 @@ static const char *add_ignore_header(cmd_parms *parms, void *dummy, return NULL; } +static const char *add_ignore_session_id(cmd_parms *parms, void *dummy, + const char *identifier) +{ + cache_server_conf *conf; + char **new; + + conf = + (cache_server_conf *)ap_get_module_config(parms->server->module_config, + &cache_module); + if (!strncasecmp(identifier, "None", 4)) { + /* if identifier None is listed clear array */ + conf->ignore_session_id->nelts = 0; + } + else { + if ((conf->ignore_session_id_set == CACHE_IGNORE_SESSION_ID_UNSET) || + (conf->ignore_session_id->nelts)) { + /* + * Only add identifier if no "None" has been found in identifier + * list so far. + */ + new = (char **)apr_array_push(conf->ignore_session_id); + (*new) = (char *)identifier; + } + } + conf->ignore_session_id_set = CACHE_IGNORE_SESSION_ID_SET; + return NULL; +} + static const char *add_cache_enable(cmd_parms *parms, void *dummy, const char *type, const char *url) @@ -1260,6 +1295,10 @@ static const command_rec cache_cmds[] = AP_INIT_FLAG("CacheIgnoreQueryString", set_cache_ignore_querystring, NULL, RSRC_CONF, "Ignore query-string when caching"), + AP_INIT_ITERATE("CacheIgnoreURLSessionIdentifiers", add_ignore_session_id, + NULL, RSRC_CONF, "A space separated list of session " + "identifiers that should be ignored for creating the key " + "of the cached entity."), AP_INIT_TAKE1("CacheLastModifiedFactor", set_cache_factor, NULL, RSRC_CONF, "The factor used to estimate Expires date from " "LastModified date"), diff --git a/modules/cache/mod_cache.h b/modules/cache/mod_cache.h index 50d96fe18c..6f2fdb4a5e 100644 --- a/modules/cache/mod_cache.h +++ b/modules/cache/mod_cache.h @@ -155,6 +155,12 @@ typedef struct { /** ignore query-string when caching */ int ignorequerystring; int ignorequerystring_set; + /** store the identifiers that should not be used for key calculation */ + apr_array_header_t *ignore_session_id; + /* flag if CacheIgnoreURLSessionIdentifiers has been set */ + #define CACHE_IGNORE_SESSION_ID_SET 1 + #define CACHE_IGNORE_SESSION_ID_UNSET 0 + int ignore_session_id_set; } cache_server_conf; /* cache info information */