]> git.ipfire.org Git - thirdparty/apache/httpd.git/commitdiff
Backporting the following fix from 2.1-dev:
authorPaul J. Reder <rederpj@apache.org>
Wed, 10 Dec 2003 16:48:46 +0000 (16:48 +0000)
committerPaul J. Reder <rederpj@apache.org>
Wed, 10 Dec 2003 16:48:46 +0000 (16:48 +0000)
  *) Modified the cache code to be header-location agnostic. Also
     fixed a number of other cache code bugs related to PR 15852.
     Includes a patch submitted by Sushma Rai <rsushma novell.com>.
     This fixes mod_mem_cache but not mod_disk_cache yet so I'm not
     closing the PR since that is what they are using.
     Reviewed by: Fielding, Trawick

git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/APACHE_2_0_BRANCH@102015 13f79535-47bb-0310-9956-ffa450edef68

CHANGES
STATUS
modules/experimental/cache_storage.c
modules/experimental/cache_util.c
modules/experimental/mod_cache.c
modules/experimental/mod_cache.h
modules/experimental/mod_disk_cache.c
modules/experimental/mod_mem_cache.c

diff --git a/CHANGES b/CHANGES
index e08975eda753ed12d5a8b1383229890f6c224b77..44e04c4b692ccc423512453226c443c4540e8390 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,5 +1,11 @@
 Changes with Apache 2.0.49
 
+  *) Modified the cache code to be header-location agnostic. Also
+     fixed a number of other cache code bugs related to PR 15852.
+     Includes a patch submitted by Sushma Rai <rsushma novell.com>.
+     This fixes mod_mem_cache but not mod_disk_cache yet so I'm not
+     closing the PR since that is what they are using. [Paul J. Reder]
+
   *) complain via error_log when mod_include's INCLUDES filter is
      enabled, but the relevant Options flag allowing the filter to run
      for the specific resource wasn't set, so that the filter won't
diff --git a/STATUS b/STATUS
index 32461a8de7b9c0ad124a6a1ac64fe55a7b23b4ff..a5f903f21935c892a606425b83f94c7872814b89 100644 (file)
--- a/STATUS
+++ b/STATUS
@@ -1,5 +1,5 @@
 APACHE 2.0 STATUS:                                              -*-text-*-
-Last modified at [$Date: 2003/12/10 08:50:10 $]
+Last modified at [$Date: 2003/12/10 16:48:45 $]
 
 Release:
 
@@ -107,19 +107,6 @@ PATCHES TO BACKPORT FROM 2.1
       http://cvs.apache.org/viewcvs.cgi/httpd-2.0/modules/mappers/config9.m4.diff?r1=1.17&r2=1.18
       +1: kess, trawick, nd, erikabele
 
-    * Modifies the cache code to be header-location agnostic. Also
-      fixes a number of other cache code bugs related to PR 15852
-      (an RFC 2616 violation).
-      http://cvs.apache.org/viewcvs.cgi/httpd-2.0/modules/experimental/cache_storage.c.diff?r1=1.28&r2=1.29
-      http://cvs.apache.org/viewcvs.cgi/httpd-2.0/modules/experimental/cache_storage.c.diff?r1=1.29&r2=1.30
-      http://cvs.apache.org/viewcvs.cgi/httpd-2.0/modules/experimental/cache_util.c.diff?r1=1.27&r2=1.28
-      http://cvs.apache.org/viewcvs.cgi/httpd-2.0/modules/experimental/mod_cache.c.diff?r1=1.74&r2=1.75
-      http://cvs.apache.org/viewcvs.cgi/httpd-2.0/modules/experimental/mod_cache.c.diff?r1=1.75&r2=1.76
-      http://cvs.apache.org/viewcvs.cgi/httpd-2.0/modules/experimental/mod_cache.h.diff?r1=1.39&r2=1.40
-      http://cvs.apache.org/viewcvs.cgi/httpd-2.0/modules/experimental/mod_disk_cache.c.diff?r1=1.46&r2=1.47
-      http://cvs.apache.org/viewcvs.cgi/httpd-2.0/modules/experimental/mod_mem_cache.c.diff?r1=1.93&r2=1.94
-      +1: rederpj, fielding, trawick
-
     * Replace some of the mutex locking in the worker MPM with
       atomic operations for higher concurrency.
       server/mpm/worker/fdqueue.c 1.24, 1.25
index 7a549683cbcd1851086c777d586c459d8d23eb42..3e5c83faae5c266a0ace735d88f8465e1be6b9df 100644 (file)
@@ -187,6 +187,7 @@ int cache_select_url(request_rec *r, const char *types, char *url)
         switch ((rv = cache_run_open_entity(h, r, type, key))) {
         case OK: {
             char *vary = NULL;
+            const char *varyhdr = NULL;
             if (cache_read_entity_headers(h, r) != APR_SUCCESS) {
                 /* TODO: Handle this error */
                 return DECLINED;
@@ -209,7 +210,10 @@ int cache_select_url(request_rec *r, const char *types, char *url)
              * 
              * RFC2616 13.6 and 14.44 describe the Vary mechanism.
              */
-            vary = apr_pstrdup(r->pool, apr_table_get(r->headers_out, "Vary"));
+            if ((varyhdr = apr_table_get(r->err_headers_out, "Vary")) == NULL) {
+                varyhdr = apr_table_get(r->headers_out, "Vary");
+            }
+            vary = apr_pstrdup(r->pool, varyhdr);
             while (vary && *vary) {
                 char *name = vary;
                 const char *h1, *h2;
index 066c02658b2aacdd25dd39464900ae8637358e97..e97413f3165666cdad5abe13cd8867c031c81e93 100644 (file)
@@ -143,13 +143,16 @@ CACHE_DECLARE(const char *)ap_cache_get_cachetype(request_rec *r,
 CACHE_DECLARE(apr_int64_t) ap_cache_current_age(cache_info *info, const apr_time_t age_value,
                                                 apr_time_t now)
 {
-    apr_time_t apparent_age, corrected_received_age, response_delay, corrected_initial_age,
-           resident_time, current_age;
+    apr_time_t apparent_age, corrected_received_age, response_delay,
+               corrected_initial_age, resident_time, current_age,
+               age_value_usec;
+
+    age_value_usec = apr_time_from_sec(age_value);
 
     /* Perform an HTTP/1.1 age calculation. (RFC2616 13.2.3) */
 
     apparent_age = MAX(0, info->response_time - info->date);
-    corrected_received_age = MAX(apparent_age, age_value);
+    corrected_received_age = MAX(apparent_age, age_value_usec);
     response_delay = info->response_time - info->request_time;
     corrected_initial_age = corrected_received_age + response_delay;
     resident_time = now - info->response_time;
@@ -165,6 +168,7 @@ CACHE_DECLARE(int) ap_cache_check_freshness(cache_request_rec *cache,
     int age_in_errhdr = 0;
     const char *cc_cresp, *cc_ceresp, *cc_req;
     const char *agestr = NULL;
+    const char *expstr = NULL;
     char *val;
     apr_time_t age_c = 0;
     cache_info *info = &(cache->handle->cache_obj->info);
@@ -213,6 +217,10 @@ CACHE_DECLARE(int) ap_cache_check_freshness(cache_request_rec *cache,
         age_in_errhdr = 1;
     }
 
+    if (!(expstr = apr_table_get(r->err_headers_out, "Expires"))) {
+        expstr = apr_table_get(r->headers_out, "Expires");
+    }
+
     /* calculate age of object */
     age = ap_cache_current_age(info, age_c, r->request_time);
 
@@ -277,12 +285,25 @@ CACHE_DECLARE(int) ap_cache_check_freshness(cache_request_rec *cache,
                                        "proxy-revalidate", NULL)))) {
         maxstale = 0;
     }
+
     /* handle expiration */
     if (((smaxage != -1) && (age < (smaxage - minfresh))) ||
         ((maxage != -1) && (age < (maxage + maxstale - minfresh))) ||
         ((smaxage == -1) && (maxage == -1) &&
          (info->expire != APR_DATE_BAD) &&
          (age < (apr_time_sec(info->expire - info->date) + maxstale - minfresh)))) {
+        const char *warn_head;
+        apr_table_t *head_ptr;
+
+        warn_head = apr_table_get(r->headers_out, "Warning");
+        if (warn_head != NULL) {
+            head_ptr = r->headers_out;
+        }
+        else {
+            warn_head = apr_table_get(r->err_headers_out, "Warning");
+            head_ptr = r->err_headers_out;
+        }
+
         /* it's fresh darlings... */
         /* set age header on response */
         if (age_in_errhdr) {
@@ -299,7 +320,27 @@ CACHE_DECLARE(int) ap_cache_check_freshness(cache_request_rec *cache,
               ((maxage != -1) && age < maxage) ||
               (info->expire != APR_DATE_BAD && (info->expire - info->date) > age))) {
             /* make sure we don't stomp on a previous warning */
-            apr_table_merge(r->headers_out, "Warning", "110 Response is stale");
+            if ((warn_head == NULL) ||
+                ((warn_head != NULL) && (ap_strstr_c(warn_head, "110") == NULL))) {
+                apr_table_merge(head_ptr, "Warning", "110 Response is stale");
+            }
+        }
+        /* 
+         * If none of Expires, Cache-Control: max-age, or Cache-Control: 
+         * s-maxage appears in the response, and the respose header age 
+         * calculated is more than 24 hours add the warning 113 
+         */
+        if ((maxage_cresp == -1) && (smaxage == -1) &&
+            (expstr == NULL) && (age > 86400)) {
+
+            /* Make sure we don't stomp on a previous warning, and don't dup
+             * a 113 marning that is already present. Also, make sure to add
+             * the new warning to the correct *headers_out location.
+             */
+            if ((warn_head == NULL) ||
+                ((warn_head != NULL) && (ap_strstr_c(warn_head, "113") == NULL))) {
+                apr_table_merge(head_ptr, "Warning", "113 Heuristic expiration");
+            }
         }
         return 1;    /* Cache object is fresh (enough) */
     }
@@ -496,17 +537,18 @@ CACHE_DECLARE(char *)generate_name(apr_pool_t *p, int dirlevels, int dirlength,
     return apr_pstrdup(p, hashfile);
 }
 
-/* Create a new table consisting of those elements from a request_rec's
- * headers_out that are allowed to be stored in a cache.
+/* Create a new table consisting of those elements from an input
+ * headers table that are allowed to be stored in a cache.
  */
-CACHE_DECLARE(apr_table_t *)ap_cache_cacheable_hdrs_out(request_rec *r)
+CACHE_DECLARE(apr_table_t *)ap_cache_cacheable_hdrs_out(apr_pool_t *pool,
+                                                        apr_table_t *t)
 {
-    /* Make a copy of the response headers, and remove from
+    /* Make a copy of the headers, and remove from
      * the copy any hop-by-hop headers, as defined in Section
      * 13.5.1 of RFC 2616
      */
     apr_table_t *headers_out;
-    headers_out = apr_table_copy(r->pool, r->headers_out);
+    headers_out = apr_table_copy(pool, t);
     apr_table_unset(headers_out, "Connection");
     apr_table_unset(headers_out, "Keep-Alive");
     apr_table_unset(headers_out, "Proxy-Authenticate");
index d32d7f3e69c8e84b93b530fe54a822f3997f5215..95929628a9091eca4fecdfcb997e17c67694f4b3 100644 (file)
@@ -250,7 +250,9 @@ static int cache_url_handler(request_rec *r, int lookup)
             return OK;
         }
         else {
-           r->err_headers_out = apr_table_make(r->pool, 3);
+            if (!r->err_headers_out) {
+                r->err_headers_out = apr_table_make(r->pool, 3);
+            }
             /* stale data available */
             if (lookup) {
                 return DECLINED;
@@ -272,6 +274,16 @@ static int cache_url_handler(request_rec *r, int lookup)
             }
             /* 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, 
@@ -415,6 +427,7 @@ static int cache_conditional_filter(ap_filter_t *f, apr_bucket_brigade *in)
 static int cache_in_filter(ap_filter_t *f, apr_bucket_brigade *in)
 {
     int rv;
+    int date_in_errhdr = 0;
     request_rec *r = f->r;
     cache_request_rec *cache;
     cache_server_conf *conf;
@@ -478,7 +491,10 @@ static int cache_in_filter(ap_filter_t *f, apr_bucket_brigade *in)
     /* read expiry date; if a bad date, then leave it so the client can
      * read it 
      */
-    exps = apr_table_get(r->headers_out, "Expires");
+    exps = apr_table_get(r->err_headers_out, "Expires");
+    if (exps == NULL) {
+        exps = apr_table_get(r->headers_out, "Expires");
+    }
     if (exps != NULL) {
         if (APR_DATE_BAD == (exp = apr_date_parse_http(exps))) {
             exps = NULL;
@@ -489,7 +505,10 @@ static int cache_in_filter(ap_filter_t *f, apr_bucket_brigade *in)
     }
 
     /* read the last-modified date; if the date is bad, then delete it */
-    lastmods = apr_table_get(r->headers_out, "Last-Modified");
+    lastmods = apr_table_get(r->err_headers_out, "Last-Modified");
+    if (lastmods ==NULL) {
+        lastmods = apr_table_get(r->headers_out, "Last-Modified");
+    }
     if (lastmods != NULL) {
         if (APR_DATE_BAD == (lastmod = apr_date_parse_http(lastmods))) {
             lastmods = NULL;
@@ -501,8 +520,14 @@ static int cache_in_filter(ap_filter_t *f, apr_bucket_brigade *in)
 
     conf = (cache_server_conf *) ap_get_module_config(r->server->module_config, &cache_module);
     /* read the etag and cache-control from the entity */
-    etag = apr_table_get(r->headers_out, "Etag");
-    cc_out = apr_table_get(r->headers_out, "Cache-Control");
+    etag = apr_table_get(r->err_headers_out, "Etag");
+    if (etag == NULL) {
+        etag = apr_table_get(r->headers_out, "Etag");
+    }
+    cc_out = apr_table_get(r->err_headers_out, "Cache-Control");
+    if (cc_out == NULL) {
+        cc_out = apr_table_get(r->headers_out, "Cache-Control");
+    }
 
     /*
      * what responses should we not cache?
@@ -603,7 +628,10 @@ static int cache_in_filter(ap_filter_t *f, apr_bucket_brigade *in)
 
     /* Set the content length if known. 
      */
-    cl = apr_table_get(r->headers_out, "Content-Length");
+    cl = apr_table_get(r->err_headers_out, "Content-Length");
+    if (cl == NULL) {
+        cl = apr_table_get(r->headers_out, "Content-Length");
+    }
     if (cl) {
         size = apr_atoi64(cl);
     }
@@ -652,7 +680,7 @@ static int cache_in_filter(ap_filter_t *f, apr_bucket_brigade *in)
     }
     /* pre-existing cache handle and 304, make entity fresh */
     else if (r->status == HTTP_NOT_MODIFIED) {
-        /* update headers */
+        /* update headers: TODO */
 
         /* remove this filter ??? */
 
@@ -689,7 +717,13 @@ static int cache_in_filter(ap_filter_t *f, apr_bucket_brigade *in)
      */
 
     /* Read the date. Generate one if one is not supplied */
-    dates = apr_table_get(r->headers_out, "Date");
+    dates = apr_table_get(r->err_headers_out, "Date");
+    if (dates != NULL) {
+        date_in_errhdr = 1;
+    }
+    else {
+        dates = apr_table_get(r->headers_out, "Date");
+    }
     if (dates != NULL) {
         info->date = apr_date_parse_http(dates);
     }
@@ -700,10 +734,13 @@ static int cache_in_filter(ap_filter_t *f, apr_bucket_brigade *in)
     now = apr_time_now();
     if (info->date == APR_DATE_BAD) {  /* No, or bad date */
         char *dates;
-        /* no date header! */
+        /* no date header (or bad header)! */
         /* add one; N.B. use the time _now_ rather than when we were checking
          * the cache 
          */
+        if (date_in_errhdr == 1) {
+            apr_table_unset(r->err_headers_out, "Date");
+        }
         date = now;
         dates = apr_pcalloc(r->pool, MAX_STRING_LEN);
         apr_rfc822_date(dates, now);
@@ -736,9 +773,9 @@ static int cache_in_filter(ap_filter_t *f, apr_bucket_brigade *in)
 
     /* if no expiry date then
      *   if lastmod
-     *      expiry date = now + min((date - lastmod) * factor, maxexpire)
+     *      expiry date = date + min((date - lastmod) * factor, maxexpire)
      *   else
-     *      expire date = now + defaultexpire
+     *      expire date = date + defaultexpire
      */
     if (exp == APR_DATE_BAD) {
         /* if lastmod == date then you get 0*conf->factor which results in
@@ -747,18 +784,21 @@ static int cache_in_filter(ap_filter_t *f, apr_bucket_brigade *in)
          */
         if ((lastmod != APR_DATE_BAD) && (lastmod < date)) {
             apr_time_t x = (apr_time_t) ((date - lastmod) * conf->factor);
+
             if (x > conf->maxex) {
                 x = conf->maxex;
             }
-            exp = now + x;
+            exp = date + x;
         }
         else {
-            exp = now + conf->defex;
+            exp = date + conf->defex;
         }
     }
     info->expire = exp;
 
     info->content_type = apr_pstrdup(r->pool, r->content_type);
+    info->etag = apr_pstrdup(r->pool, etag);
+    info->lastmods = apr_pstrdup(r->pool, lastmods);
     info->filename = apr_pstrdup(r->pool, r->filename );
 
     /*
index e0d824c77d0d50a6e728d218565ffddb46d03a59..1a76564fd139353c967b4720a69fe04166505809 100644 (file)
@@ -279,7 +279,7 @@ CACHE_DECLARE(const char *)ap_cache_tokstr(apr_pool_t *p, const char *list, cons
 /* Create a new table consisting of those elements from a request_rec's
  * headers_out that are allowed to be stored in a cache
  */
-CACHE_DECLARE(apr_table_t *)ap_cache_cacheable_hdrs_out(request_rec *r);
+CACHE_DECLARE(apr_table_t *)ap_cache_cacheable_hdrs_out(apr_pool_t *pool, apr_table_t *t);
 
 /**
  * cache_storage.c
index 82c3ad883ea7c51401d6017fbad89fcf5f20bed6..ab2a4ab5ae4f5964674d0a6d66e46df44b6a1a5d 100644 (file)
@@ -603,7 +603,7 @@ static apr_status_t write_headers(cache_handle_t *h, request_rec *r, cache_info
 
         if (r->headers_out) {
             int i;
-            apr_table_t* headers_out = ap_cache_cacheable_hdrs_out(r);
+            apr_table_t* headers_out = ap_cache_cacheable_hdrs_out(r->pool, r->headers_out);
             apr_table_entry_t *elts = (apr_table_entry_t *) apr_table_elts(headers_out)->elts;
             for (i = 0; i < apr_table_elts(headers_out)->nelts; ++i) {
                 if (elts[i].key != NULL) {
index ad515be57dbc029a9c8a767342d00ae8c76223b3..c6398259f40ad887cde6293f77cc6c33f9b60702 100644 (file)
@@ -86,10 +86,12 @@ typedef struct {
 typedef struct mem_cache_object {
     cache_type_e type;
     apr_ssize_t num_header_out;
+    apr_ssize_t num_err_header_out;
     apr_ssize_t num_subprocess_env;
     apr_ssize_t num_notes;
     apr_ssize_t num_req_hdrs;
     cache_header_tbl_t *header_out;
+    cache_header_tbl_t *err_header_out;
     cache_header_tbl_t *subprocess_env;
     cache_header_tbl_t *notes;
     cache_header_tbl_t *req_hdrs; /* for Vary negotiation */
@@ -303,6 +305,11 @@ static void cleanup_cache_object(cache_object_t *obj)
                 free(mobj->header_out[0].hdr);
             free(mobj->header_out);
         }
+        if (mobj->err_header_out) {
+            if (mobj->err_header_out[0].hdr) 
+                free(mobj->err_header_out[0].hdr);
+            free(mobj->err_header_out);
+        }
         if (mobj->subprocess_env) {
             if (mobj->subprocess_env[0].hdr) 
                 free(mobj->subprocess_env[0].hdr);
@@ -782,6 +789,7 @@ static apr_status_t read_headers(cache_handle_t *h, request_rec *r)
  
     h->req_hdrs = apr_table_make(r->pool, mobj->num_req_hdrs);
     r->headers_out = apr_table_make(r->pool, mobj->num_header_out);
+    r->err_headers_out = apr_table_make(r->pool, mobj->num_err_header_out);
     r->subprocess_env = apr_table_make(r->pool, mobj->num_subprocess_env);
     r->notes = apr_table_make(r->pool, mobj->num_notes);
 
@@ -791,6 +799,9 @@ static apr_status_t read_headers(cache_handle_t *h, request_rec *r)
     rc = unserialize_table( mobj->header_out,
                             mobj->num_header_out, 
                             r->headers_out);
+    rc = unserialize_table( mobj->err_header_out,
+                            mobj->num_err_header_out, 
+                            r->err_headers_out);
     rc = unserialize_table( mobj->subprocess_env, 
                             mobj->num_subprocess_env, 
                             r->subprocess_env);
@@ -852,7 +863,13 @@ static apr_status_t write_headers(cache_handle_t *h, request_rec *r, cache_info
     /* Precompute how much storage we need to hold the headers */
     rc = serialize_table(&mobj->header_out, 
                          &mobj->num_header_out, 
-                         ap_cache_cacheable_hdrs_out(r));   
+                         ap_cache_cacheable_hdrs_out(r->pool, r->headers_out));   
+    if (rc != APR_SUCCESS) {
+        return rc;
+    }
+    rc = serialize_table(&mobj->err_header_out, 
+                         &mobj->num_err_header_out, 
+                         ap_cache_cacheable_hdrs_out(r->pool, r->err_headers_out));   
     if (rc != APR_SUCCESS) {
         return rc;
     }
@@ -892,6 +909,22 @@ static apr_status_t write_headers(cache_handle_t *h, request_rec *r, cache_info
         }
         memcpy(obj->info.content_type, info->content_type, len);
     }
+    if (info->etag) {
+        apr_size_t len = strlen(info->etag) + 1;
+        obj->info.etag = (char*) malloc(len);
+        if (!obj->info.etag) {
+            return APR_ENOMEM;
+        }
+        memcpy(obj->info.etag, info->etag, len);
+    }
+    if (info->lastmods) {
+        apr_size_t len = strlen(info->lastmods) + 1;
+        obj->info.lastmods = (char*) malloc(len);
+        if (!obj->info.lastmods) {
+            return APR_ENOMEM;
+        }
+        memcpy(obj->info.lastmods, info->lastmods, len);
+    }
     if ( info->filename) {
         apr_size_t len = strlen(info->filename) + 1;
         obj->info.filename = (char*) malloc(len);