From: Jim Jagielski Date: Fri, 2 Dec 2016 11:42:13 +0000 (+0000) Subject: Merge r1496711, r1597533, r1649491, r1665216, r1756553, r1756631, r1726675, r1718496... X-Git-Tag: 2.4.24~89 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=21efb981a27c694d3453355632b3afbd40001cfb;p=thirdparty%2Fapache%2Fhttpd.git Merge r1496711, r1597533, r1649491, r1665216, r1756553, r1756631, r1726675, r1718496, r1718476, r1747469 from trunk: recognize the "default handler name" in r->handler, which is used when no SetHandler/AddHandler and no matching mimetype during type_checker. Submitted by: Eric Covener mod_cache: try to use the key of a possible open but stale cache entry if we have one in cache_try_lock(). PR 50317 Submitted by: Ruediger Pluem * modules/cache/mod_socache_memcache.c (socache_mc_store): Pass through expiration time. Submitted by: Faidon Liambotis , jorton * mod_cache: Preserve the Content-Type in case of 304 response. 304 does not contain Content-Type and mod_mime regenerates the Content-Type based on the r->filename. This later leads to original Content-Type to be lost (overwriten by whatever mod_mime generates). mod_cache: Use the actual URI path and query-string for identifying the cached entity (key), such that rewrites are taken into account when running afterwards (CacheQuickHandler off). PR 21935. mod_cache: follow up to r1756553: log the real/actual cached URI (debug). better s-maxage support + *) mod_cache: Consider Cache-Control: s-maxage in expiration + calculations. [Eric Covener] + + *) mod_cache: Allow caching of responses with an Expires header + in the past that also has Cache-Control: max-age or s-maxage. + PR55156. [Eric Covener] remove dead code leftover from r1023387. Prior to this revision, there was an apr_atoi64 in this context. Now, ap_cache_control() sets control.max_age (which is checked here) when the maxage value was parsed OK. duplicate debug-level AH00764 in the just-validated path. Rename ap_casecmpstr[n]() to ap_cstr_casecmp[n](), update with APR doxygen Submitted by: jkaluza, jorton, jkaluza, ylavic, ylavic, covener, covener, covener, wrowe Reviewed/backported by: jim git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.4.x@1772331 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/CHANGES b/CHANGES index 0f4e175b81a..0feceb7509a 100644 --- a/CHANGES +++ b/CHANGES @@ -2,6 +2,13 @@ Changes with Apache 2.4.24 + *) mod_socache_memcache: Pass expiration time through to memcached. + [Faidon Liambotis , Joe Orton] + + *) mod_cache: Use the actual URI path and query-string for identifying the + cached entity (key), such that rewrites are taken into account when + running afterwards (CacheQuickHandler off). PR 21935. [Yann Ylavic] + *) mod_http2: new directive 'H2EarlyHints' to enable sending of HTTP status 103 interim responses. Disabled by default. [Stefan Eissing] diff --git a/STATUS b/STATUS index d0d91b1c46c..dcd3489fe60 100644 --- a/STATUS +++ b/STATUS @@ -117,27 +117,6 @@ RELEASE SHOWSTOPPERS: PATCHES ACCEPTED TO BACKPORT FROM TRUNK: [ start all new proposals below, under PATCHES PROPOSED. ] - *) mod_cache: Bring up-to-date w/ trunk. - trunk patch: - try to use the key of a possible open but stale cache entry (PR 50317) - http://svn.apache.org/r1597533 - socache_mc_store: Pass through expiration time. - http://svn.apache.org/r1649491 - Preserve the Content-Type in case of 304 response - http://svn.apache.org/r1665216 - Use the actual URI path and query-string (PR 21935) - http://svn.apache.org/r1756553 - http://svn.apache.org/r1756631 - better s-maxage support - http://svn.apache.org/r1726675 - http://svn.apache.org/r1718496 - http://svn.apache.org/r1718476 - Rename ap_casecmpstr[n]() to ap_cstr_casecmp[n](), update with APR doxygen - http://svn.apache.org/r1747469 - 2.4.x patch: http://home.apache.org/~jim/patches/httpd-2.4-cache.patch.txt - +1: jim, ylavic, wrowe - ylavic: r1756553 and r1649491 have a CHANGES entry. - *) ap_reclaim_child_processes(): Implement terminate immediately trunk patches: https://svn.apache.org/r1757061 diff --git a/modules/cache/cache_storage.c b/modules/cache/cache_storage.c index 59d12aca15f..1a75cc1d814 100644 --- a/modules/cache/cache_storage.c +++ b/modules/cache/cache_storage.c @@ -115,7 +115,7 @@ int cache_create_entity(cache_request_rec *cache, request_rec *r, static int filter_header_do(void *v, const char *key, const char *val) { - if ((*key == 'W' || *key == 'w') && !strcasecmp(key, "Warning") + if ((*key == 'W' || *key == 'w') && !ap_cstr_casecmp(key, "Warning") && *val == '1') { /* any stored Warning headers with warn-code 1xx (see section * 14.46) MUST be deleted from the cache entry and the forwarded @@ -129,7 +129,7 @@ static int filter_header_do(void *v, const char *key, const char *val) } static int remove_header_do(void *v, const char *key, const char *val) { - if ((*key == 'W' || *key == 'w') && !strcasecmp(key, "Warning")) { + if ((*key == 'W' || *key == 'w') && !ap_cstr_casecmp(key, "Warning")) { /* any stored Warning headers with warn-code 2xx MUST be retained * in the cache entry and the forwarded response. */ @@ -427,7 +427,9 @@ int cache_select(cache_request_rec *cache, request_rec *r) } static apr_status_t cache_canonicalise_key(request_rec *r, apr_pool_t* p, - const char *uri, apr_uri_t *parsed_uri, const char **key) + const char *uri, const char *query, + apr_uri_t *parsed_uri, + const char **key) { cache_server_conf *conf; char *port_str, *hn, *lcs; @@ -563,7 +565,7 @@ static apr_status_t cache_canonicalise_key(request_rec *r, apr_pool_t* p, * if needed. */ path = uri; - querystring = parsed_uri->query; + querystring = apr_pstrdup(p, query ? query : parsed_uri->query); if (conf->ignore_session_id->nelts) { int i; char **identifier; @@ -588,7 +590,7 @@ static apr_status_t cache_canonicalise_key(request_rec *r, apr_pool_t* p, /* * Check if the identifier is in the querystring and cut it out. */ - if (querystring) { + if (querystring && *querystring) { /* * First check if the identifier is at the beginning of the * querystring and followed by a '=' @@ -605,7 +607,7 @@ static apr_status_t cache_canonicalise_key(request_rec *r, apr_pool_t* p, * identifier with a '&' and append a '=' */ complete = apr_pstrcat(p, "&", *identifier, "=", NULL); - param = strstr(querystring, complete); + param = ap_strstr_c(querystring, complete); /* If we found something we are sitting on the '&' */ if (param) { param++; @@ -669,7 +671,11 @@ static apr_status_t cache_canonicalise_key(request_rec *r, apr_pool_t* p, apr_status_t cache_generate_key_default(request_rec *r, apr_pool_t* p, const char **key) { - return cache_canonicalise_key(r, p, r->uri, &r->parsed_uri, key); + /* We want the actual query-string, which may differ from + * r->parsed_uri.query (immutable), so use "" (not NULL). + */ + const char *args = r->args ? r->args : ""; + return cache_canonicalise_key(r, p, r->uri, args, &r->parsed_uri, key); } /* @@ -709,12 +715,13 @@ int cache_invalidate(cache_request_rec *cache, request_rec *r) location = apr_table_get(r->headers_out, "Location"); if (location) { - if (APR_SUCCESS != apr_uri_parse(r->pool, location, &location_uri) - || APR_SUCCESS - != cache_canonicalise_key(r, r->pool, location, - &location_uri, &location_key) - || !(r->parsed_uri.hostname && location_uri.hostname - && !strcmp(r->parsed_uri.hostname, + if (apr_uri_parse(r->pool, location, &location_uri) + || cache_canonicalise_key(r, r->pool, + location, NULL, + &location_uri, &location_key) + || !(r->parsed_uri.hostname + && location_uri.hostname + && !strcmp(r->parsed_uri.hostname, location_uri.hostname))) { location_key = NULL; } @@ -722,14 +729,15 @@ int cache_invalidate(cache_request_rec *cache, request_rec *r) content_location = apr_table_get(r->headers_out, "Content-Location"); if (content_location) { - if (APR_SUCCESS - != apr_uri_parse(r->pool, content_location, - &content_location_uri) - || APR_SUCCESS - != cache_canonicalise_key(r, r->pool, content_location, - &content_location_uri, &content_location_key) - || !(r->parsed_uri.hostname && content_location_uri.hostname - && !strcmp(r->parsed_uri.hostname, + if (apr_uri_parse(r->pool, content_location, + &content_location_uri) + || cache_canonicalise_key(r, r->pool, + content_location, NULL, + &content_location_uri, + &content_location_key) + || !(r->parsed_uri.hostname + && content_location_uri.hostname + && !strcmp(r->parsed_uri.hostname, content_location_uri.hostname))) { content_location_key = NULL; } diff --git a/modules/cache/cache_util.c b/modules/cache/cache_util.c index 1d65d3f7f8c..096058308e0 100644 --- a/modules/cache/cache_util.c +++ b/modules/cache/cache_util.c @@ -31,8 +31,9 @@ extern module AP_MODULE_DECLARE_DATA cache_module; * in "filter". All but the path comparisons are case-insensitive. */ static int uri_meets_conditions(const apr_uri_t *filter, const int pathlen, - const apr_uri_t *url) + request_rec *r) { + const apr_uri_t *url = &r->parsed_uri; /* Scheme, hostname port and local part. The filter URI and the * URI we test may have the following shapes: @@ -55,7 +56,7 @@ static int uri_meets_conditions(const apr_uri_t *filter, const int pathlen, } else { /* The URI scheme must be present and identical except for case. */ - if (!url->scheme || strcasecmp(filter->scheme, url->scheme)) { + if (!url->scheme || ap_cstr_casecmp(filter->scheme, url->scheme)) { return 0; } @@ -113,7 +114,7 @@ static int uri_meets_conditions(const apr_uri_t *filter, const int pathlen, /* For HTTP caching purposes, an empty (NULL) path is equivalent to * a single "/" path. RFCs 3986/2396 */ - if (!url->path) { + if (!r->uri) { if (*filter->path == '/' && pathlen == 1) { return 1; } @@ -125,7 +126,7 @@ static int uri_meets_conditions(const apr_uri_t *filter, const int pathlen, /* Url has met all of the filter conditions so far, determine * if the paths match. */ - return !strncmp(filter->path, url->path, pathlen); + return !strncmp(filter->path, r->uri, pathlen); } static cache_provider_list *get_provider(request_rec *r, struct cache_enable *ent, @@ -167,8 +168,7 @@ static cache_provider_list *get_provider(request_rec *r, struct cache_enable *en } cache_provider_list *cache_get_providers(request_rec *r, - cache_server_conf *conf, - apr_uri_t uri) + cache_server_conf *conf) { cache_dir_conf *dconf = ap_get_module_config(r->per_dir_config, &cache_module); cache_provider_list *providers = NULL; @@ -183,7 +183,7 @@ cache_provider_list *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 (uri_meets_conditions(&ent[i].url, ent[i].pathlen, &uri)) { + if (uri_meets_conditions(&ent[i].url, ent[i].pathlen, r)) { /* Stop searching now. */ return NULL; } @@ -200,7 +200,7 @@ cache_provider_list *cache_get_providers(request_rec *r, for (i = 0; i < conf->cacheenable->nelts; i++) { struct cache_enable *ent = (struct cache_enable *)conf->cacheenable->elts; - if (uri_meets_conditions(&ent[i].url, ent[i].pathlen, &uri)) { + if (uri_meets_conditions(&ent[i].url, ent[i].pathlen, r)) { providers = get_provider(r, &ent[i], providers); } } @@ -284,7 +284,25 @@ apr_status_t cache_try_lock(cache_server_conf *conf, cache_request_rec *cache, /* create the key if it doesn't exist */ if (!cache->key) { - cache_generate_key(r, r->pool, &cache->key); + cache_handle_t *h; + /* + * Try to use the key of a possible open but stale cache + * entry if we have one. + */ + if (cache->handle != NULL) { + h = cache->handle; + } + else { + h = cache->stale_handle; + } + if ((h != NULL) && + (h->cache_obj != NULL) && + (h->cache_obj->key != NULL)) { + cache->key = apr_pstrdup(r->pool, h->cache_obj->key); + } + else { + cache_generate_key(r, r->pool, &cache->key); + } } /* create a hashed filename from the key, and save it for later */ @@ -315,7 +333,7 @@ apr_status_t cache_try_lock(cache_server_conf *conf, cache_request_rec *cache, status = apr_stat(&finfo, lockname, APR_FINFO_MTIME | APR_FINFO_NLINK, r->pool); if (!(APR_STATUS_IS_ENOENT(status)) && APR_SUCCESS != status) { - ap_log_rerror(APLOG_MARK, APLOG_ERR, APR_EEXIST, r, APLOGNO(00779) + ap_log_rerror(APLOG_MARK, APLOG_ERR, status, r, APLOGNO(00779) "Could not stat a cache lock file: %s", lockname); return status; @@ -981,12 +999,7 @@ int ap_cache_control(request_rec *r, cache_control_t *cc, char *header = apr_pstrdup(r->pool, pragma_header); const char *token = cache_strqtok(header, CACHE_SEPARATOR, &last); while (token) { - /* handle most common quickest case... */ - if (!strcmp(token, "no-cache")) { - cc->no_cache = 1; - } - /* ...then try slowest case */ - else if (!strcasecmp(token, "no-cache")) { + if (!ap_cstr_casecmp(token, "no-cache")) { cc->no_cache = 1; } token = cache_strqtok(NULL, CACHE_SEPARATOR, &last); @@ -1003,52 +1016,36 @@ int ap_cache_control(request_rec *r, cache_control_t *cc, switch (token[0]) { case 'n': case 'N': { - /* handle most common quickest cases... */ - if (!strcmp(token, "no-cache")) { - cc->no_cache = 1; - } - else if (!strcmp(token, "no-store")) { - cc->no_store = 1; - } - /* ...then try slowest cases */ - else if (!strncasecmp(token, "no-cache", 8)) { + if (!ap_cstr_casecmpn(token, "no-cache", 8)) { if (token[8] == '=') { cc->no_cache_header = 1; } else if (!token[8]) { cc->no_cache = 1; } - break; } - else if (!strcasecmp(token, "no-store")) { + else if (!ap_cstr_casecmp(token, "no-store")) { cc->no_store = 1; } - else if (!strcasecmp(token, "no-transform")) { + else if (!ap_cstr_casecmp(token, "no-transform")) { cc->no_transform = 1; } break; } case 'm': case 'M': { - /* handle most common quickest cases... */ - if (!strcmp(token, "max-age=0")) { - cc->max_age = 1; - cc->max_age_value = 0; - } - else if (!strcmp(token, "must-revalidate")) { - cc->must_revalidate = 1; - } - /* ...then try slowest cases */ - else if (!strncasecmp(token, "max-age", 7)) { + if (!ap_cstr_casecmpn(token, "max-age", 7)) { if (token[7] == '=' && !apr_strtoff(&offt, token + 8, &endp, 10) && endp > token + 8 && !*endp) { cc->max_age = 1; cc->max_age_value = offt; } - break; } - else if (!strncasecmp(token, "max-stale", 9)) { + else if (!ap_cstr_casecmp(token, "must-revalidate")) { + cc->must_revalidate = 1; + } + else if (!ap_cstr_casecmpn(token, "max-stale", 9)) { if (token[9] == '=' && !apr_strtoff(&offt, token + 10, &endp, 10) && endp > token + 10 && !*endp) { @@ -1059,63 +1056,51 @@ int ap_cache_control(request_rec *r, cache_control_t *cc, cc->max_stale = 1; cc->max_stale_value = -1; } - break; } - else if (!strncasecmp(token, "min-fresh", 9)) { + else if (!ap_cstr_casecmpn(token, "min-fresh", 9)) { if (token[9] == '=' && !apr_strtoff(&offt, token + 10, &endp, 10) && endp > token + 10 && !*endp) { cc->min_fresh = 1; cc->min_fresh_value = offt; } - break; - } - else if (!strcasecmp(token, "must-revalidate")) { - cc->must_revalidate = 1; } break; } case 'o': case 'O': { - if (!strcasecmp(token, "only-if-cached")) { + if (!ap_cstr_casecmp(token, "only-if-cached")) { cc->only_if_cached = 1; } break; } case 'p': case 'P': { - /* handle most common quickest cases... */ - if (!strcmp(token, "private")) { - cc->private = 1; - } - /* ...then try slowest cases */ - else if (!strcasecmp(token, "public")) { + if (!ap_cstr_casecmp(token, "public")) { cc->public = 1; } - else if (!strncasecmp(token, "private", 7)) { + else if (!ap_cstr_casecmpn(token, "private", 7)) { if (token[7] == '=') { cc->private_header = 1; } else if (!token[7]) { cc->private = 1; } - break; } - else if (!strcasecmp(token, "proxy-revalidate")) { + else if (!ap_cstr_casecmp(token, "proxy-revalidate")) { cc->proxy_revalidate = 1; } break; } case 's': case 'S': { - if (!strncasecmp(token, "s-maxage", 8)) { + if (!ap_cstr_casecmpn(token, "s-maxage", 8)) { if (token[8] == '=' && !apr_strtoff(&offt, token + 9, &endp, 10) && endp > token + 9 && !*endp) { cc->s_maxage = 1; cc->s_maxage_value = offt; } - break; } break; } @@ -1145,8 +1130,7 @@ static int cache_control_remove(request_rec *r, const char *cc_header, switch (token[0]) { case 'n': case 'N': { - if (!strncmp(token, "no-cache", 8) - || !strncasecmp(token, "no-cache", 8)) { + if (!ap_cstr_casecmpn(token, "no-cache", 8)) { if (token[8] == '=') { const char *header = cache_strqtok(token + 9, CACHE_SEPARATOR "\"", &slast); @@ -1163,8 +1147,7 @@ static int cache_control_remove(request_rec *r, const char *cc_header, } case 'p': case 'P': { - if (!strncmp(token, "private", 7) - || !strncasecmp(token, "private", 7)) { + if (!ap_cstr_casecmpn(token, "private", 7)) { if (token[7] == '=') { const char *header = cache_strqtok(token + 8, CACHE_SEPARATOR "\"", &slast); diff --git a/modules/cache/cache_util.h b/modules/cache/cache_util.h index 397efb90db7..6b0174c7bde 100644 --- a/modules/cache/cache_util.h +++ b/modules/cache/cache_util.h @@ -300,7 +300,7 @@ apr_status_t cache_remove_lock(cache_server_conf *conf, cache_request_rec *cache, request_rec *r, apr_bucket_brigade *bb); cache_provider_list *cache_get_providers(request_rec *r, - cache_server_conf *conf, apr_uri_t uri); + cache_server_conf *conf); /** * Get a value from a table, where the table may contain multiple diff --git a/modules/cache/mod_cache.c b/modules/cache/mod_cache.c index f2779d6a9de..b857e2ea095 100644 --- a/modules/cache/mod_cache.c +++ b/modules/cache/mod_cache.c @@ -103,7 +103,7 @@ static int cache_quick_handler(request_rec *r, int lookup) /* * Which cache module (if any) should handle this request? */ - if (!(providers = cache_get_providers(r, conf, r->parsed_uri))) { + if (!(providers = cache_get_providers(r, conf))) { return DECLINED; } @@ -413,7 +413,7 @@ static int cache_handler(request_rec *r) /* * Which cache module (if any) should handle this request? */ - if (!(providers = cache_get_providers(r, conf, r->parsed_uri))) { + if (!(providers = cache_get_providers(r, conf))) { return DECLINED; } @@ -973,12 +973,20 @@ static apr_status_t cache_save_filter(ap_filter_t *f, apr_bucket_brigade *in) /* Have we received a 304 response without any headers at all? Fall back to * the original headers in the original cached request. */ - if (r->status == HTTP_NOT_MODIFIED && cache->stale_handle && !cc_out - && !pragma) { - cc_out = cache_table_getm(r->pool, cache->stale_handle->resp_hdrs, - "Cache-Control"); - pragma = cache_table_getm(r->pool, cache->stale_handle->resp_hdrs, - "Pragma"); + if (r->status == HTTP_NOT_MODIFIED && cache->stale_handle) { + if (!cc_out && !pragma) { + cc_out = cache_table_getm(r->pool, cache->stale_handle->resp_hdrs, + "Cache-Control"); + pragma = cache_table_getm(r->pool, cache->stale_handle->resp_hdrs, + "Pragma"); + } + + /* 304 does not contain Content-Type and mod_mime regenerates the + * Content-Type based on the r->filename. This would lead to original + * Content-Type to be lost (overwriten by whatever mod_mime generates). + * We preserves the original Content-Type here. */ + ap_set_content_type(r, apr_table_get( + cache->stale_handle->resp_hdrs, "Content-Type")); } /* Parse the cache control header */ @@ -1017,6 +1025,8 @@ static apr_status_t cache_save_filter(ap_filter_t *f, apr_bucket_brigade *in) * include the following: an Expires header (section 14.21); a * "max-age", "s-maxage", "must-revalidate", "proxy-revalidate", * "public" or "private" cache-control directive (section 14.9). + * + * FIXME: Wrong if cc_out has just an extension we don't know about */ } else { @@ -1031,9 +1041,12 @@ static apr_status_t cache_save_filter(ap_filter_t *f, apr_bucket_brigade *in) /* if a broken Expires header is present, don't cache it */ reason = apr_pstrcat(p, "Broken expires header: ", exps, NULL); } - else if (!dconf->store_expired && exp != APR_DATE_BAD + else if (!control.s_maxage && !control.max_age + && !dconf->store_expired && exp != APR_DATE_BAD && exp < r->request_time) { - /* if a Expires header is in the past, don't cache it */ + /* if a Expires header is in the past, don't cache it + * Unless CC: s-maxage or max-age is present + */ reason = "Expires header already expired; not cacheable"; } else if (!dconf->store_expired && (control.must_revalidate @@ -1177,8 +1190,8 @@ static apr_status_t cache_save_filter(ap_filter_t *f, apr_bucket_brigade *in) ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, APLOGNO(02473) "cache: %s responded with an uncacheable 304, " - "retrying the request. Reason: %s", - r->unparsed_uri, reason); + "retrying the request %s. Reason: %s", + cache->key, r->unparsed_uri, reason); /* we've got a cache conditional miss! tell anyone who cares */ cache_run_cache_status(cache->handle, r, r->headers_out, AP_CACHE_MISS, @@ -1212,8 +1225,8 @@ static apr_status_t cache_save_filter(ap_filter_t *f, apr_bucket_brigade *in) if (reason) { ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(00768) - "cache: %s not cached. Reason: %s", r->unparsed_uri, - reason); + "cache: %s not cached for request %s. Reason: %s", + cache->key, r->unparsed_uri, reason); /* we've got a cache miss! tell anyone who cares */ cache_run_cache_status(cache->handle, r, r->headers_out, AP_CACHE_MISS, @@ -1331,7 +1344,8 @@ static apr_status_t cache_save_filter(ap_filter_t *f, apr_bucket_brigade *in) } ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(00769) - "cache: Caching url: %s", r->unparsed_uri); + "cache: Caching url %s for request %s", + cache->key, r->unparsed_uri); /* We are actually caching this response. So it does not * make sense to remove this entity any more. @@ -1387,7 +1401,26 @@ static apr_status_t cache_save_filter(ap_filter_t *f, apr_bucket_brigade *in) "replacing with now"); } + + /* CC has priority over Expires. */ + if (control.s_maxage || control.max_age) { + apr_int64_t x; + + x = control.s_maxage ? control.s_maxage_value : control.max_age_value; + x = x * MSEC_ONE_SEC; + + if (x < dconf->minex) { + x = dconf->minex; + } + if (x > dconf->maxex) { + x = dconf->maxex; + } + exp = date + x; + } + /* if no expiry date then + * if Cache-Control: s-maxage + * expiry date = date + smaxage * if Cache-Control: max-age * expiry date = date + max-age * else if lastmod @@ -1395,28 +1428,9 @@ static apr_status_t cache_save_filter(ap_filter_t *f, apr_bucket_brigade *in) * else * expire date = date + defaultexpire */ - if (exp == APR_DATE_BAD) { - - if (control.max_age) { - apr_int64_t x; - errno = 0; - x = control.max_age_value; - if (errno) { - x = dconf->defex; - } - else { - x = x * MSEC_ONE_SEC; - } - if (x < dconf->minex) { - x = dconf->minex; - } - if (x > dconf->maxex) { - x = dconf->maxex; - } - exp = date + x; - } - else if ((lastmod != APR_DATE_BAD) && (lastmod < date)) { + if (exp == APR_DATE_BAD) { + if ((lastmod != APR_DATE_BAD) && (lastmod < date)) { /* if lastmod == date then you get 0*conf->factor which results in * an expiration time of now. This causes some problems with * freshness calculations, so we choose the else path... @@ -1558,6 +1572,9 @@ static apr_status_t cache_save_filter(ap_filter_t *f, apr_bucket_brigade *in) /* let someone else attempt to cache */ cache_remove_lock(conf, cache, r, NULL); + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, r, APLOGNO(02971) + "cache: serving %s (revalidated)", r->uri); + return ap_pass_brigade(f->next, bb); } diff --git a/modules/cache/mod_cache_disk.c b/modules/cache/mod_cache_disk.c index 14dee81ff72..52d5dba0b12 100644 --- a/modules/cache/mod_cache_disk.c +++ b/modules/cache/mod_cache_disk.c @@ -786,7 +786,7 @@ static apr_status_t read_table(cache_handle_t *handle, request_rec *r, /* ### What about APR_EOF? */ rv = apr_file_gets(w, MAX_STRING_LEN - 1, file); if (rv != APR_SUCCESS) { - ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(00717) + ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(00717) "Premature end of cache headers."); return rv; } @@ -865,6 +865,7 @@ static apr_status_t read_table(cache_handle_t *handle, request_rec *r, static apr_status_t recall_headers(cache_handle_t *h, request_rec *r) { disk_cache_object_t *dobj = (disk_cache_object_t *) h->cache_obj->vobj; + apr_status_t rv; /* This case should not happen... */ if (!dobj->hdrs.fd) { @@ -877,8 +878,18 @@ static apr_status_t recall_headers(cache_handle_t *h, request_rec *r) h->resp_hdrs = apr_table_make(r->pool, 20); /* Call routine to read the header lines/status line */ - read_table(h, r, h->resp_hdrs, dobj->hdrs.fd); - read_table(h, r, h->req_hdrs, dobj->hdrs.fd); + rv = read_table(h, r, h->resp_hdrs, dobj->hdrs.fd); + if (rv != APR_SUCCESS) { + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(02987) + "Error reading response headers from %s for %s", + dobj->hdrs.file, dobj->name); + } + rv = read_table(h, r, h->req_hdrs, dobj->hdrs.fd); + if (rv != APR_SUCCESS) { + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(02988) + "Error reading request headers from %s for %s", + dobj->hdrs.file, dobj->name); + } apr_file_close(dobj->hdrs.fd); diff --git a/modules/cache/mod_file_cache.c b/modules/cache/mod_file_cache.c index 97de196b6b4..41993618614 100644 --- a/modules/cache/mod_file_cache.c +++ b/modules/cache/mod_file_cache.c @@ -312,10 +312,10 @@ static int file_cache_handler(request_rec *r) int errstatus; int rc = OK; - /* XXX: not sure if this is right yet - * see comment in http_core.c:default_handler + /* Bail out if r->handler isn't the default value, and doesn't look like a Content-Type + * XXX: Even though we made the user explicitly list each path to cache? */ - if (ap_strcmp_match(r->handler, "*/*")) { + if (ap_strcmp_match(r->handler, "*/*") && !AP_IS_DEFAULT_HANDLER_NAME(r->handler)) { return DECLINED; } diff --git a/modules/cache/mod_socache_memcache.c b/modules/cache/mod_socache_memcache.c index e1fb2357bc9..86577a9f7b1 100644 --- a/modules/cache/mod_socache_memcache.c +++ b/modules/cache/mod_socache_memcache.c @@ -214,8 +214,14 @@ static apr_status_t socache_mc_store(ap_socache_instance_t *ctx, server_rec *s, return APR_EINVAL; } - /* In APR-util - unclear what 'timeout' is, as it was not implemented */ - rv = apr_memcache_set(ctx->mc, buf, (char*)ucaData, nData, 0, 0); + /* memcache needs time in seconds till expiry; fail if this is not + * positive *before* casting to unsigned (apr_uint32_t). */ + expiry -= apr_time_now(); + if (apr_time_sec(expiry) <= 0) { + return APR_EINVAL; + } + rv = apr_memcache_set(ctx->mc, buf, (char*)ucaData, nData, + apr_time_sec(expiry), 0); if (rv != APR_SUCCESS) { ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s, APLOGNO(00790)