]> git.ipfire.org Git - thirdparty/apache/httpd.git/commitdiff
Merge r1496711, r1597533, r1649491, r1665216, r1756553, r1756631, r1726675, r1718496...
authorJim Jagielski <jim@apache.org>
Fri, 2 Dec 2016 11:42:13 +0000 (11:42 +0000)
committerJim Jagielski <jim@apache.org>
Fri, 2 Dec 2016 11:42:13 +0000 (11:42 +0000)
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 <paravoid debian.org>, 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

CHANGES
STATUS
modules/cache/cache_storage.c
modules/cache/cache_util.c
modules/cache/cache_util.h
modules/cache/mod_cache.c
modules/cache/mod_cache_disk.c
modules/cache/mod_file_cache.c
modules/cache/mod_socache_memcache.c

diff --git a/CHANGES b/CHANGES
index 0f4e175b81ad306fb1df5e71fedb4d0456345db5..0feceb7509aba03114ea51ffe0054f84cf422ab3 100644 (file)
--- 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 <paravoid debian.org>, 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 d0d91b1c46c6652946a4025951b990a57c1b0ed0..dcd3489fe602d01a29d7c837537d6bd3a9c46fd3 100644 (file)
--- 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
index 59d12aca15f64bcf676228b3f585e2fed423e4f4..1a75cc1d814e3b895f27e1dda09ed9f8e9c3c6e9 100644 (file)
@@ -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;
         }
index 1d65d3f7f8ceba0d32c6ec22c89c19f6843fefaf..096058308e037fa8f92be1ed31acdfa971383ae7 100644 (file)
@@ -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);
index 397efb90db7be3dedae6b2e877e802908783cbf0..6b0174c7bde1b07622b37f54f125cd9b98291084 100644 (file)
@@ -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
index f2779d6a9deb968a09252b172260b82dc3899ea0..b857e2ea0959972474faddcb440f07824e85598c 100644 (file)
@@ -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);
     }
 
index 14dee81ff72a827405489ce60ebc141dcf50929a..52d5dba0b12e05a9c311b0cfd736aa46248abaa1 100644 (file)
@@ -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);
 
index 97de196b6b40e39bec79a3b1f429ec913cc0d107..4199361861495d1e0ee62f861b63e94fdc0cd36d 100644 (file)
@@ -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;
     }
 
index e1fb2357bc94973725f92cf5d57e0d5ab9389718..86577a9f7b1a01e3fab763e855f659a1ba996b9b 100644 (file)
@@ -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)