You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@httpd.apache.org by Justin Erenkrantz <ju...@erenkrantz.com> on 2004/08/01 19:29:11 UTC
[PATCH] mod_cache fixes: #4
--On Sunday, August 1, 2004 11:25 AM -0400 Bill Stoddard <bi...@wstoddard.com>
wrote:
> Too many changes in one patch. Break this up into multiple consumable in 15
> minute patches and I'll review them.
(This is probably the largest and most complicated one. At the bottom, I've
also pasted the current quick_handler function as I have it in my tree.)
* modules/experimental/mod_cache.c: Rewrite quick_handler.
Index: modules/experimental/mod_cache.c
===================================================================
RCS file: /home/cvs/httpd-2.0/modules/experimental/mod_cache.c,v
retrieving revision 1.83
diff -u -r1.83 mod_cache.c
--- modules/experimental/mod_cache.c 25 May 2004 18:01:02 -0000 1.83
+++ modules/experimental/mod_cache.c 1 Aug 2004 08:24:52 -0000
@@ -48,24 +48,30 @@
static int cache_url_handler(request_rec *r, int lookup)
{
apr_status_t rv;
- const char *cc_in, *pragma, *auth;
- apr_uri_t uri = r->parsed_uri;
- char *url = r->unparsed_uri;
+ const char *pragma, *auth;
+ apr_uri_t uri;
+ char *url;
apr_size_t urllen;
- char *path = uri.path;
+ char *path;
const char *types;
- cache_info *info = NULL;
+ cache_info *info;
cache_request_rec *cache;
cache_server_conf *conf;
+ apr_bucket_brigade *out;
- conf = (cache_server_conf *)
ap_get_module_config(r->server->module_config,
- &cache_module);
-
- /* we don't handle anything but GET */
+ /* Delay initialization until we know we are handling a GET */
if (r->method_number != M_GET) {
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?
*/
@@ -73,19 +79,8 @@
return DECLINED;
}
- urllen = strlen(url);
- if (urllen > MAX_URL_LENGTH) {
- ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
- "cache: URL exceeds length threshold: %s", url);
- return DECLINED;
- }
- /* DECLINE urls ending in / ??? EGP: why? */
- if (url[urllen-1] == '/') {
- return DECLINED;
- }
-
/* make space for the per request config */
- cache = (cache_request_rec *) ap_get_module_config(r->request_config,
+ cache = (cache_request_rec *) ap_get_module_config(r->request_config,
&cache_module);
if (!cache) {
cache = apr_pcalloc(r->pool, sizeof(cache_request_rec));
@@ -137,171 +132,106 @@
/*
* Try to serve this request from the cache.
*
- * If no existing cache file
- * add cache_in filter
- * If stale cache file
- * If conditional request
- * add cache_in filter
- * If non-conditional request
- * fudge response into a conditional
- * add cache_conditional filter
- * If fresh cache file
- * clear filter stack
- * add cache_out filter
+ * If no existing cache file (DECLINED)
+ * add cache_save filter
+ * If cached file (OK)
+ * If fresh cache file
+ * clear filter stack
+ * add cache_out filter
+ * return OK
+ * If stale cache file
+ * add cache_conditional filter (which updates cache)
*/
rv = cache_select_url(r, cache->types, url);
- if (DECLINED == rv) {
- if (!lookup) {
- /* no existing cache file */
- ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
- "cache: no cache - add cache_in filter and DECLINE");
- /* add cache_in filter to cache this request */
- ap_add_output_filter_handle(cache_in_filter_handle, NULL, r,
- r->connection);
+ if (rv != OK) {
+ if (rv == DECLINED) {
+ if (!lookup) {
+ /* add cache_save filter to cache this request */
+ ap_add_output_filter_handle(cache_save_filter_handle, NULL, r,
+ r->connection);
+ }
+ }
+ else {
+ /* error */
+ ap_log_error(APLOG_MARK, APLOG_ERR, rv, r->server,
+ "cache: error returned while checking for cached "
+ "file by %s cache", cache->type);
}
return DECLINED;
}
- else if (OK == rv) {
- /* RFC2616 13.2 - Check cache object expiration */
- cache->fresh = ap_cache_check_freshness(cache, r);
- if (cache->fresh) {
- /* fresh data available */
- apr_bucket_brigade *out;
- conn_rec *c = r->connection;
- if (lookup) {
- return OK;
- }
+ /* We have located a suitable cache file now. */
+ /* RFC2616 13.2 - Check cache object expiration */
+ cache->fresh = ap_cache_check_freshness(cache, r);
+
+ /* What we have in our cache isn't fresh. */
+ if (!cache->fresh) {
+ /* If our stale cached response was conditional... */
+ if (!lookup && ap_cache_request_is_conditional(r)) {
info = &(cache->handle->cache_obj->info);
- if (info && info->lastmod) {
- ap_update_mtime(r, info->lastmod);
+ /* fudge response into a conditional */
+ if (info && info->etag) {
+ /* if we have a cached etag */
+ apr_table_set(r->headers_in, "If-None-Match", info->etag);
}
-
- rv = ap_meets_conditions(r);
- if (rv != OK) {
- ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
- "cache: fresh cache - returning status %d", rv);
- return rv;
+ else if (info && info->lastmods) {
+ /* if we have a cached IMS */
+ apr_table_set(r->headers_in, "If-Modified-Since",
+ info->lastmods);
}
+ }
- /*
- * Not a conditionl request. Serve up the content
- */
- ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
- "cache: fresh cache - add cache_out filter and "
- "handle request");
+ /* Add cache_conditional_filter to see if we can salvage
+ * later.
+ */
+ ap_add_output_filter_handle(cache_conditional_filter_handle,
+ NULL, r, r->connection);
+ return DECLINED;
+ }
- /* We are in the quick handler hook, which means that no output
- * filters have been set. So lets run the insert_filter hook.
- */
- ap_run_insert_filter(r);
- ap_add_output_filter_handle(cache_out_filter_handle, NULL,
- r, r->connection);
-
- /* kick off the filter stack */
- out = apr_brigade_create(r->pool, c->bucket_alloc);
- if (APR_SUCCESS
- != (rv = ap_pass_brigade(r->output_filters, out))) {
- ap_log_error(APLOG_MARK, APLOG_ERR, rv, r->server,
- "cache: error returned while trying to return %s
"
- "cached data",
- cache->type);
- return rv;
- }
- return OK;
- }
- else {
- if (!r->err_headers_out) {
- r->err_headers_out = apr_table_make(r->pool, 3);
- }
- /* stale data available */
- if (lookup) {
- return DECLINED;
- }
+ /* fresh data available */
- ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
- "cache: stale cache - test conditional");
- /* if conditional request */
- if (ap_cache_request_is_conditional(r)) {
- ap_log_error(APLOG_MARK, APLOG_DEBUG, 0,
- r->server,
- "cache: conditional - add cache_in filter and "
- "DECLINE");
- /* Why not add CACHE_CONDITIONAL? */
- ap_add_output_filter_handle(cache_in_filter_handle, NULL,
- r, r->connection);
+ info = &(cache->handle->cache_obj->info);
- return DECLINED;
- }
- /* else if non-conditional request */
- else {
- /* Temporarily hack this to work the way it had been. Its
broken,
- * but its broken the way it was before. I'm working on
figuring
- * out why the filter add in the conditional filter doesn't
work. pjr
- *
- * info = &(cache->handle->cache_obj->info);
- *
- * Uncomment the above when the code in
cache_conditional_filter_handle
- * is properly fixed... pjr
- */
-
- /* fudge response into a conditional */
- if (info && info->etag) {
- ap_log_error(APLOG_MARK, APLOG_DEBUG, 0,
- r->server,
- "cache: nonconditional - fudge conditional "
- "by etag");
- /* if we have a cached etag */
- apr_table_set(r->headers_in, "If-None-Match", info->etag);
- }
- else if (info && info->lastmods) {
- ap_log_error(APLOG_MARK, APLOG_DEBUG, 0,
- r->server,
- "cache: nonconditional - fudge conditional "
- "by lastmod");
- /* if we have a cached IMS */
- apr_table_set(r->headers_in,
- "If-Modified-Since",
- info->lastmods);
- }
- else {
- /* something else - pretend there was no cache */
- ap_log_error(APLOG_MARK, APLOG_DEBUG, 0,
- r->server,
- "cache: nonconditional - no cached "
- "etag/lastmods - add cache_in and DECLINE");
-
- ap_add_output_filter_handle(cache_in_filter_handle, NULL,
- r, r->connection);
-
- return DECLINED;
- }
- /* add cache_conditional filter */
- ap_log_error(APLOG_MARK, APLOG_DEBUG, 0,
- r->server,
- "cache: nonconditional - add cache_conditional "
- "and DECLINE");
- ap_add_output_filter_handle(cache_conditional_filter_handle,
- NULL,
- r,
- r->connection);
+ if (info && info->lastmod) {
+ ap_update_mtime(r, info->lastmod);
+ }
- return DECLINED;
- }
- }
+ rv = ap_meets_conditions(r);
+ if (rv != OK) {
+ /* Return cached status. */
+ return rv;
}
- else {
- /* error */
- ap_log_error(APLOG_MARK, APLOG_ERR, rv,
- r->server,
- "cache: error returned while checking for cached file by
"
- "%s cache",
+
+ /* If we're a lookup, we can exit now instead of serving the content. */
+ if (lookup) {
+ return OK;
+ }
+
+ /* Serve up the content */
+
+ /* We are in the quick handler hook, which means that no output
+ * filters have been set. So lets run the insert_filter hook.
+ */
+ ap_run_insert_filter(r);
+ ap_add_output_filter_handle(cache_out_filter_handle, NULL,
+ r, r->connection);
+
+ /* kick off the filter stack */
+ out = apr_brigade_create(r->pool, r->connection->bucket_alloc);
+ rv = ap_pass_brigade(r->output_filters, out);
+ if (rv != APR_SUCCESS) {
+ ap_log_error(APLOG_MARK, APLOG_ERR, rv, r->server,
+ "cache: error returned while trying to return %s "
+ "cached data",
cache->type);
- return DECLINED;
+ return rv;
}
+
+ return OK;
}
/*
---new function---
static int cache_url_handler(request_rec *r, int lookup)
{
apr_status_t rv;
const char *pragma, *auth;
apr_uri_t uri;
char *url;
apr_size_t urllen;
char *path;
const char *types;
cache_info *info;
cache_request_rec *cache;
cache_server_conf *conf;
apr_bucket_brigade *out;
/* Delay initialization until we know we are handling a GET */
if (r->method_number != M_GET) {
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 (!(types = ap_cache_get_cachetype(r, conf, path))) {
return DECLINED;
}
/* make space for the per request config */
cache = (cache_request_rec *) ap_get_module_config(r->request_config,
&cache_module);
if (!cache) {
cache = apr_pcalloc(r->pool, sizeof(cache_request_rec));
ap_set_module_config(r->request_config, &cache_module, cache);
}
/* save away the type */
cache->types = types;
/*
* Are we allowed to serve cached info at all?
*/
/* find certain cache controlling headers */
pragma = apr_table_get(r->headers_in, "Pragma");
auth = apr_table_get(r->headers_in, "Authorization");
/* first things first - does the request allow us to return
* cached information at all? If not, just decline the request.
*
* Note that there is a big difference between not being allowed
* to cache a request (no-store) and not being allowed to return
* a cached request without revalidation (max-age=0).
*
* Caching is forbidden under the following circumstances:
*
* - RFC2616 14.9.2 Cache-Control: no-store
* - Pragma: no-cache
* - Any requests requiring authorization.
*/
if (conf->ignorecachecontrol == 1 && auth == NULL) {
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
"incoming request is asking for a uncached version of "
"%s, but we know better and are ignoring it", url);
}
else {
if (ap_cache_liststr(NULL, pragma, "no-cache", NULL) ||
auth != NULL) {
/* delete the previously cached file */
cache_remove_url(r, cache->types, url);
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
"cache: no-cache or authorization forbids caching "
"of %s", url);
return DECLINED;
}
}
/*
* Try to serve this request from the cache.
*
* If no existing cache file (DECLINED)
* add cache_save filter
* If cached file (OK)
* If fresh cache file
* clear filter stack
* add cache_out filter
* return OK
* If stale cache file
* add cache_conditional filter (which updates cache)
*/
rv = cache_select_url(r, cache->types, url);
if (rv != OK) {
if (rv == DECLINED) {
if (!lookup) {
/* add cache_save filter to cache this request */
ap_add_output_filter_handle(cache_save_filter_handle, NULL, r,
r->connection);
}
}
else {
/* error */
ap_log_error(APLOG_MARK, APLOG_ERR, rv, r->server,
"cache: error returned while checking for cached "
"file by %s cache", cache->type);
}
return DECLINED;
}
/* We have located a suitable cache file now. */
/* RFC2616 13.2 - Check cache object expiration */
cache->fresh = ap_cache_check_freshness(cache, r);
/* What we have in our cache isn't fresh. */
if (!cache->fresh) {
/* If our stale cached response was conditional... */
if (!lookup && ap_cache_request_is_conditional(r)) {
info = &(cache->handle->cache_obj->info);
/* fudge response into a conditional */
if (info && info->etag) {
/* if we have a cached etag */
apr_table_set(r->headers_in, "If-None-Match", info->etag);
}
else if (info && info->lastmods) {
/* if we have a cached IMS */
apr_table_set(r->headers_in, "If-Modified-Since",
info->lastmods);
}
}
/* Add cache_conditional_filter to see if we can salvage
* later.
*/
ap_add_output_filter_handle(cache_conditional_filter_handle,
NULL, r, r->connection);
return DECLINED;
}
/* fresh data available */
info = &(cache->handle->cache_obj->info);
if (info && info->lastmod) {
ap_update_mtime(r, info->lastmod);
}
rv = ap_meets_conditions(r);
if (rv != OK) {
/* Return cached status. */
return rv;
}
/* If we're a lookup, we can exit now instead of serving the content. */
if (lookup) {
return OK;
}
/* Serve up the content */
/* We are in the quick handler hook, which means that no output
* filters have been set. So lets run the insert_filter hook.
*/
ap_run_insert_filter(r);
ap_add_output_filter_handle(cache_out_filter_handle, NULL,
r, r->connection);
/* kick off the filter stack */
out = apr_brigade_create(r->pool, r->connection->bucket_alloc);
rv = ap_pass_brigade(r->output_filters, out);
if (rv != APR_SUCCESS) {
ap_log_error(APLOG_MARK, APLOG_ERR, rv, r->server,
"cache: error returned while trying to return %s "
"cached data",
cache->type);
return rv;
}
return OK;
}
Re: [PATCH] mod_cache fixes: #4
Posted by Bill Stoddard <bi...@wstoddard.com>.
Justin Erenkrantz wrote:
> --On Sunday, August 1, 2004 11:25 AM -0400 Bill Stoddard
> <bi...@wstoddard.com> wrote:
>
>> Too many changes in one patch. Break this up into multiple consumable
>> in 15
>> minute patches and I'll review them.
>
>
> (This is probably the largest and most complicated one. At the bottom,
> I've also pasted the current quick_handler function as I have it in my
> tree.)
>
+1, nice cleanup. I had second thoughts about removing the MAX_URL_LENGTH check, but what the heck, whack it.
Remove the #define from mod_cache.h.
Bill