From: Colm MacCarthaigh Date: Mon, 19 Sep 2005 12:10:34 +0000 (+0000) Subject: Backport r239420 and r239421 to the 2.2.x branch; Enhance X-Git-Tag: 2.1.8~50 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=bf61af9527211b996401fd1548f595533f9d7f3b;p=thirdparty%2Fapache%2Fhttpd.git Backport r239420 and r239421 to the 2.2.x branch; Enhance CacheEnable/CacheDisable to be of use to proxy servers. git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.2.x@290133 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/CHANGES b/CHANGES index 63f169ced9c..9113d33879f 100644 --- a/CHANGES +++ b/CHANGES @@ -1,6 +1,10 @@ -*- coding: utf-8 -*- Changes with Apache 2.1.8 + *) mod_cache: Enhance CacheEnable/CacheDisable to control caching on a + per-protocol, per-host and per-path basis. Intended for proxy + configurations. [Colm MacCarthaigh] + *) mod_disk_cache: Canonicalise the storage key, for improved hit/miss ratio. [Colm MacCarthaigh] diff --git a/modules/cache/cache_storage.c b/modules/cache/cache_storage.c index e949847fe81..5d781602702 100644 --- a/modules/cache/cache_storage.c +++ b/modules/cache/cache_storage.c @@ -169,7 +169,7 @@ 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; @@ -245,7 +245,7 @@ int cache_select_url(request_rec *r, char *url) /* headers do not match, so Vary failed */ ap_log_error(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, r->server, - "cache_select_url(): Vary header mismatch."); + "cache_select(): Vary header mismatch."); return DECLINED; } } diff --git a/modules/cache/cache_util.c b/modules/cache/cache_util.c index 21c6fee5bbe..a3650e2db23 100644 --- a/modules/cache/cache_util.c +++ b/modules/cache/cache_util.c @@ -24,23 +24,65 @@ extern module AP_MODULE_DECLARE_DATA cache_module; +/* Determine if "url" matches the hostname, scheme and port and path + * in "filter". All but the path comparisons are case-insensitive. + */ +static int uri_meets_conditions(apr_uri_t filter, int pathlen, apr_uri_t url) +{ + /* Compare the hostnames */ + if(filter.hostname) { + if (!url.hostname) { + return 0; + } + else if (strcasecmp(filter.hostname, url.hostname)) { + return 0; + } + } + + /* Compare the schemes */ + if(filter.scheme) { + if (!url.scheme) { + return 0; + } + else if (strcasecmp(filter.scheme, url.scheme)) { + return 0; + } + } + + /* Compare the ports */ + if(filter.port_str) { + if (url.port_str && filter.port != url.port) { + return 0; + } + /* NOTE: ap_port_of_scheme will return 0 if given NULL input */ + else if (filter.port != apr_uri_port_of_scheme(url.scheme)) { + return 0; + } + } + else if(url.port_str && filter.scheme) { + if (apr_uri_port_of_scheme(filter.scheme) == url.port) { + return 0; + } + } + + /* Url has met all of the filter conditions so far, determine + * if the paths match. + */ + return !strncmp(filter.path, url.path, pathlen); +} CACHE_DECLARE(cache_provider_list *)ap_cache_get_providers(request_rec *r, cache_server_conf *conf, - const char *url) + apr_uri_t uri) { cache_provider_list *providers = NULL; int i; - /* we can't cache if there's no URL */ - /* Is this case even possible?? */ - if (!url) return NULL; - /* loop through all the cacheenable entries */ for (i = 0; i < conf->cacheenable->nelts; i++) { struct cache_enable *ent = (struct cache_enable *)conf->cacheenable->elts; - if ((ent[i].url) && !strncasecmp(url, ent[i].url, ent[i].urllen)) { + if (uri_meets_conditions(ent[i].url, ent[i].pathlen, uri)) { /* Fetch from global config and add to the list. */ cache_provider *provider; provider = ap_lookup_provider(CACHE_PROVIDER_GROUP, ent[i].type, @@ -77,7 +119,7 @@ CACHE_DECLARE(cache_provider_list *)ap_cache_get_providers(request_rec *r, for (i = 0; i < conf->cachedisable->nelts; i++) { struct cache_disable *ent = (struct cache_disable *)conf->cachedisable->elts; - if ((ent[i].url) && !strncasecmp(url, ent[i].url, ent[i].urllen)) { + if (uri_meets_conditions(ent[i].url, ent[i].pathlen, uri)) { /* Stop searching now. */ return NULL; } diff --git a/modules/cache/mod_cache.c b/modules/cache/mod_cache.c index ff0074c07d8..0bd4d23663e 100644 --- a/modules/cache/mod_cache.c +++ b/modules/cache/mod_cache.c @@ -50,11 +50,7 @@ static int cache_url_handler(request_rec *r, int lookup) { apr_status_t rv; const char *auth; - apr_uri_t uri; - char *url; - char *path; cache_provider_list *providers; - cache_info *info; cache_request_rec *cache; cache_server_conf *conf; apr_bucket_brigade *out; @@ -64,18 +60,13 @@ static int cache_url_handler(request_rec *r, int lookup) return DECLINED; } - uri = r->parsed_uri; - url = r->unparsed_uri; - path = uri.path; - info = NULL; - conf = (cache_server_conf *) ap_get_module_config(r->server->module_config, &cache_module); /* * Which cache module (if any) should handle this request? */ - if (!(providers = ap_cache_get_providers(r, conf, path))) { + if (!(providers = ap_cache_get_providers(r, conf, r->parsed_uri))) { return DECLINED; } @@ -114,7 +105,7 @@ static int cache_url_handler(request_rec *r, int lookup) * add cache_out filter * return OK */ - rv = cache_select_url(r, url); + rv = cache_select(r); if (rv != OK) { if (rv == DECLINED) { if (!lookup) { @@ -219,7 +210,7 @@ static int cache_out_filter(ap_filter_t *f, apr_bucket_brigade *bb) * restore the status into it's handle. */ r->status = cache->handle->cache_obj->info.status; - /* recall_headers() was called in cache_select_url() */ + /* recall_headers() was called in cache_select() */ cache->provider->recall_body(cache->handle, r->pool, bb); /* This filter is done once it has served up its content */ @@ -988,8 +979,15 @@ static const char *add_cache_enable(cmd_parms *parms, void *dummy, &cache_module); new = apr_array_push(conf->cacheenable); new->type = type; - new->url = url; - new->urllen = strlen(url); + if (apr_uri_parse(parms->pool, url, &(new->url))) { + return NULL; + } + if (new->url.path) { + new->pathlen = strlen(new->url.path); + } else { + new->pathlen = 1; + new->url.path = "/"; + } return NULL; } @@ -1003,8 +1001,15 @@ static const char *add_cache_disable(cmd_parms *parms, void *dummy, (cache_server_conf *)ap_get_module_config(parms->server->module_config, &cache_module); new = apr_array_push(conf->cachedisable); - new->url = url; - new->urllen = strlen(url); + if (apr_uri_parse(parms->pool, url, &(new->url))) { + return NULL; + } + if (new->url.path) { + new->pathlen = strlen(new->url.path); + } else { + new->pathlen = 1; + new->url.path = "/"; + } return NULL; } diff --git a/modules/cache/mod_cache.h b/modules/cache/mod_cache.h index 2e6fcf1d20d..744f7cc5b12 100644 --- a/modules/cache/mod_cache.h +++ b/modules/cache/mod_cache.h @@ -104,14 +104,15 @@ #endif struct cache_enable { - const char *url; + apr_uri_t url; const char *type; apr_size_t urllen; + apr_size_t pathlen; }; struct cache_disable { - const char *url; - apr_size_t urllen; + apr_uri_t url; + apr_size_t pathlen; }; /* static information about the local cache */ @@ -257,7 +258,7 @@ CACHE_DECLARE(void) ap_cache_usec2hex(apr_time_t j, char *y); CACHE_DECLARE(char *) ap_cache_generate_name(apr_pool_t *p, int dirlevels, int dirlength, const char *name); -CACHE_DECLARE(cache_provider_list *)ap_cache_get_providers(request_rec *r, cache_server_conf *conf, const char *url); +CACHE_DECLARE(cache_provider_list *)ap_cache_get_providers(request_rec *r, cache_server_conf *conf, apr_uri_t uri); CACHE_DECLARE(int) ap_cache_liststr(apr_pool_t *p, const char *list, const char *key, char **val); CACHE_DECLARE(const char *)ap_cache_tokstr(apr_pool_t *p, const char *list, const char **str); @@ -274,7 +275,7 @@ CACHE_DECLARE(apr_table_t *)ap_cache_cacheable_hdrs_out(apr_pool_t *pool, */ int cache_remove_url(cache_request_rec *cache, apr_pool_t *p); int cache_create_entity(request_rec *r, char *url, apr_off_t size); -int cache_select_url(request_rec *r, char *url); +int cache_select(request_rec *r); apr_status_t cache_generate_key_default( request_rec *r, apr_pool_t*p, char**key ); /** * create a key for the cache based on the request record diff --git a/modules/cache/mod_disk_cache.c b/modules/cache/mod_disk_cache.c index 4983874ed13..d13ec557d2b 100644 --- a/modules/cache/mod_disk_cache.c +++ b/modules/cache/mod_disk_cache.c @@ -981,7 +981,7 @@ static apr_status_t store_headers(cache_handle_t *h, request_rec *r, cache_info } /* Parse the vary header and dump those fields from the headers_in. */ - /* FIXME: Make call to the same thing cache_select_url calls to crack Vary. */ + /* FIXME: Make call to the same thing cache_select calls to crack Vary. */ if (r->headers_in) { apr_table_t *headers_in;