Move parts of cache_save_filter() to a smaller check_cacheable_request() function that is easier to read and understand. Also, a useless assignment is removed.
Index: modules/cache/mod_cache.c =================================================================== --- modules/cache/mod_cache.c.orig +++ modules/cache/mod_cache.c @@ -313,65 +313,11 @@ * Finally, pass the data to the next filter (the network or whatever) */ -static int cache_save_filter(ap_filter_t *f, apr_bucket_brigade *in) +static const char* check_cacheable_request(request_rec *r, + cache_request_rec *cache, cache_server_conf *conf) { - int rv = !OK; - int date_in_errhdr = 0; - request_rec *r = f->r; - cache_request_rec *cache; - cache_server_conf *conf; - const char *cc_out, *cl; - const char *exps, *lastmods, *dates, *etag; - apr_time_t exp, date, lastmod, now; - apr_off_t size; - cache_info *info = NULL; - char *reason; - apr_pool_t *p; - - conf = (cache_server_conf *) ap_get_module_config(r->server->module_config, - &cache_module); - - /* Setup cache_request_rec */ - cache = (cache_request_rec *) ap_get_module_config(r->request_config, - &cache_module); - if (!cache) { - /* user likely configured CACHE_SAVE manually; they should really use - * mod_cache configuration to do that - */ - cache = apr_pcalloc(r->pool, sizeof(cache_request_rec)); - ap_set_module_config(r->request_config, &cache_module, cache); - } - - reason = NULL; - p = r->pool; - /* - * Pass Data to Cache - * ------------------ - * This section passes the brigades into the cache modules, but only - * if the setup section (see below) is complete. - */ - if (cache->block_response) { - /* We've already sent down the response and EOS. So, ignore - * whatever comes now. - */ - return APR_SUCCESS; - } - - /* have we already run the cachability check and set up the - * cached file handle? - */ - if (cache->in_checked) { - /* pass the brigades into the cache, then pass them - * up the filter stack - */ - rv = cache->provider->store_body(cache->handle, r, in); - if (rv != APR_SUCCESS) { - ap_log_error(APLOG_MARK, APLOG_DEBUG, rv, r->server, - "cache: Cache provider's store_body failed!"); - ap_remove_output_filter(f); - } - return ap_pass_brigade(f->next, in); - } + apr_time_t exp, lastmod; + const char *exps, *lastmods, *etag, *cc_out, *reason = NULL; /* * Setup Data in Cache @@ -439,11 +385,11 @@ * We include 304 Not Modified here too as this is the origin server * telling us to serve the cached copy. */ - reason = apr_psprintf(p, "Response status %d", r->status); + reason = apr_psprintf(r->pool, "Response status %d", r->status); } else if (exps != NULL && exp == APR_DATE_BAD) { /* if a broken Expires header is present, don't cache it */ - reason = apr_pstrcat(p, "Broken expires header: ", exps, NULL); + reason = apr_pstrcat(r->pool, "Broken expires header: ", exps, NULL); } else if (exp != APR_DATE_BAD && exp < r->request_time) { @@ -522,20 +468,16 @@ reason = "r->no_cache present"; } - if (reason) { - ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, - "cache: %s not cached. Reason: %s", r->unparsed_uri, - reason); + cache->exp = exp; + cache->lastmod = lastmod; - /* remove this filter from the chain */ - ap_remove_output_filter(f); - - /* ship the data up the stack */ - return ap_pass_brigade(f->next, in); - } + return reason; +} - /* Make it so that we don't execute this path again. */ - cache->in_checked = 1; +static apr_off_t request_cl(request_rec *r, apr_bucket_brigade *in) +{ + const char *cl; + apr_off_t size; /* Set the content length if known. */ @@ -580,48 +522,18 @@ } } - /* It's safe to cache the response. - * - * There are two possiblities at this point: - * - cache->handle == NULL. In this case there is no previously - * cached entity anywhere on the system. We must create a brand - * new entity and store the response in it. - * - cache->stale_handle != NULL. In this case there is a stale - * entity in the system which needs to be replaced by new - * content (unless the result was 304 Not Modified, which means - * the cached entity is actually fresh, and we should update - * the headers). - */ - - /* Did we have a stale cache entry that really is stale? */ - if (cache->stale_handle) { - if (r->status == HTTP_NOT_MODIFIED) { - /* Oh, hey. It isn't that stale! Yay! */ - cache->handle = cache->stale_handle; - info = &cache->handle->cache_obj->info; - rv = OK; - } - else { - /* Oh, well. Toss it. */ - cache->provider->remove_entity(cache->stale_handle); - /* Treat the request as if it wasn't conditional. */ - cache->stale_handle = NULL; - } - } + return size; +} - /* no cache handle, create a new entity */ - if (!cache->handle) { - rv = cache_create_entity(r, size); - info = apr_pcalloc(r->pool, sizeof(cache_info)); - /* We only set info->status upon the initial creation. */ - info->status = r->status; - } +static void prepare_cacheable_request(request_rec *r, cache_request_rec *cache, + cache_info *info, cache_server_conf *conf) +{ + const char *dates; + int date_in_errhdr = 0; + apr_time_t exp, lastmod, now, date; - if (rv != OK) { - /* Caching layer declined the opportunity to cache the response */ - ap_remove_output_filter(f); - return ap_pass_brigade(f->next, in); - } + exp = cache->exp; + lastmod = cache->lastmod; ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, "cache: Caching url: %s", r->unparsed_uri); @@ -690,7 +602,6 @@ if (lastmod != APR_DATE_BAD && lastmod > date) { /* if it's in the future, then replace by date */ lastmod = date; - lastmods = dates; ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, "cache: Last modified is in the future, " @@ -729,7 +640,129 @@ apr_table_set(r->headers_out, "Expires", expire_hdr); } } + info->expire = exp; +} + +static int cache_save_filter(ap_filter_t *f, apr_bucket_brigade *in) +{ + int rv = !OK; + request_rec *r = f->r; + cache_request_rec *cache; + cache_server_conf *conf; + apr_off_t size; + cache_info *info = NULL; + const char *reason; + apr_pool_t *p; + + conf = (cache_server_conf *) ap_get_module_config(r->server->module_config, + &cache_module); + + /* Setup cache_request_rec */ + cache = (cache_request_rec *) ap_get_module_config(r->request_config, + &cache_module); + if (!cache) { + /* user likely configured CACHE_SAVE manually; they should really use + * mod_cache configuration to do that + */ + cache = apr_pcalloc(r->pool, sizeof(cache_request_rec)); + ap_set_module_config(r->request_config, &cache_module, cache); + } + + p = r->pool; + + /* + * Pass Data to Cache + * ------------------ + * This section passes the brigades into the cache modules, but only + * if the setup section (see below) is complete. + */ + if (cache->block_response) { + /* We've already sent down the response and EOS. So, ignore + * whatever comes now. + */ + return APR_SUCCESS; + } + + /* have we already run the cachability check and set up the + * cached file handle? + */ + if (cache->in_checked) { + /* pass the brigades into the cache, then pass them + * up the filter stack + */ + rv = cache->provider->store_body(cache->handle, r, in); + if (rv != APR_SUCCESS) { + ap_log_error(APLOG_MARK, APLOG_DEBUG, rv, r->server, + "cache: Cache provider's store_body failed!"); + ap_remove_output_filter(f); + } + return ap_pass_brigade(f->next, in); + } + + reason = check_cacheable_request(r, cache, conf); + + if (reason) { + ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, + "cache: %s not cached. Reason: %s", r->unparsed_uri, + reason); + + /* remove this filter from the chain */ + ap_remove_output_filter(f); + + /* ship the data up the stack */ + return ap_pass_brigade(f->next, in); + } + + /* Make it so that we don't execute this path again. */ + cache->in_checked = 1; + + size = request_cl(r, in); + + /* It's safe to cache the response. + * + * There are two possiblities at this point: + * - cache->handle == NULL. In this case there is no previously + * cached entity anywhere on the system. We must create a brand + * new entity and store the response in it. + * - cache->stale_handle != NULL. In this case there is a stale + * entity in the system which needs to be replaced by new + * content (unless the result was 304 Not Modified, which means + * the cached entity is actually fresh, and we should update + * the headers). + */ + + /* Did we have a stale cache entry that really is stale? */ + if (cache->stale_handle) { + if (r->status == HTTP_NOT_MODIFIED) { + /* Oh, hey. It isn't that stale! Yay! */ + cache->handle = cache->stale_handle; + info = &cache->handle->cache_obj->info; + rv = OK; + } + else { + /* Oh, well. Toss it. */ + cache->provider->remove_entity(cache->stale_handle); + /* Treat the request as if it wasn't conditional. */ + cache->stale_handle = NULL; + } + } + + /* no cache handle, create a new entity */ + if (!cache->handle) { + rv = cache_create_entity(r, size); + info = apr_pcalloc(r->pool, sizeof(cache_info)); + /* We only set info->status upon the initial creation. */ + info->status = r->status; + } + + if (rv != OK) { + /* Caching layer declined the opportunity to cache the response */ + ap_remove_output_filter(f); + return ap_pass_brigade(f->next, in); + } + + prepare_cacheable_request(r, cache, info, conf); /* We found a stale entry which wasn't really stale. */ if (cache->stale_handle) { --