httpd-cvs mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From minf...@apache.org
Subject svn commit: r1023360 - in /httpd/httpd/trunk: include/ap_mmn.h modules/cache/cache_storage.c modules/cache/cache_util.c modules/cache/cache_util.h modules/cache/mod_cache.h
Date Sat, 16 Oct 2010 19:30:08 GMT
Author: minfrin
Date: Sat Oct 16 19:30:08 2010
New Revision: 1023360

URL: http://svn.apache.org/viewvc?rev=1023360&view=rev
Log:
Begin the process of optimising the parsing of Cache-Control headers. Parse
the incoming Cache-Control and Pragma headers once, instead of on each test.

Modified:
    httpd/httpd/trunk/include/ap_mmn.h
    httpd/httpd/trunk/modules/cache/cache_storage.c
    httpd/httpd/trunk/modules/cache/cache_util.c
    httpd/httpd/trunk/modules/cache/cache_util.h
    httpd/httpd/trunk/modules/cache/mod_cache.h

Modified: httpd/httpd/trunk/include/ap_mmn.h
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/include/ap_mmn.h?rev=1023360&r1=1023359&r2=1023360&view=diff
==============================================================================
--- httpd/httpd/trunk/include/ap_mmn.h (original)
+++ httpd/httpd/trunk/include/ap_mmn.h Sat Oct 16 19:30:08 2010
@@ -274,12 +274,13 @@
  *                         Make root parameter of ap_expr_eval() const.
  * 20100923.3 (2.3.9-dev)  Add "last" member to ap_directive_t
  * 20101012.0 (2.3.9-dev)  Add header to cache_status hook.
+ * 20101016.0 (2.3.9-dev)  Remove ap_cache_check_allowed().
  */
 
 #define MODULE_MAGIC_COOKIE 0x41503234UL /* "AP24" */
 
 #ifndef MODULE_MAGIC_NUMBER_MAJOR
-#define MODULE_MAGIC_NUMBER_MAJOR 20101012
+#define MODULE_MAGIC_NUMBER_MAJOR 20101016
 #endif
 #define MODULE_MAGIC_NUMBER_MINOR 0                     /* 0...n */
 

Modified: httpd/httpd/trunk/modules/cache/cache_storage.c
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/cache/cache_storage.c?rev=1023360&r1=1023359&r2=1023360&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/cache/cache_storage.c (original)
+++ httpd/httpd/trunk/modules/cache/cache_storage.c Sat Oct 16 19:30:08 2010
@@ -216,7 +216,7 @@ int cache_select(cache_request_rec *cach
         }
     }
 
-    if (!ap_cache_check_allowed(r)) {
+    if (!ap_cache_check_allowed(cache, r)) {
         return DECLINED;
     }
 

Modified: httpd/httpd/trunk/modules/cache/cache_util.c
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/cache/cache_util.c?rev=1023360&r1=1023359&r2=1023360&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/cache/cache_util.c (original)
+++ httpd/httpd/trunk/modules/cache/cache_util.c Sat Oct 16 19:30:08 2010
@@ -383,7 +383,7 @@ apr_status_t cache_remove_lock(cache_ser
     return apr_file_remove(lockname, r->pool);
 }
 
-CACHE_DECLARE(int) ap_cache_check_allowed(request_rec *r) {
+CACHE_DECLARE(int) ap_cache_check_allowed(cache_request_rec *cache, request_rec *r) {
     const char *cc_req;
     const char *pragma;
     cache_server_conf *conf =
@@ -409,8 +409,9 @@ CACHE_DECLARE(int) ap_cache_check_allowe
     cc_req = apr_table_get(r->headers_in, "Cache-Control");
     pragma = apr_table_get(r->headers_in, "Pragma");
 
-    if (ap_cache_liststr(NULL, pragma, "no-cache", NULL)
-        || ap_cache_liststr(NULL, cc_req, "no-cache", NULL)) {
+    ap_cache_control(r, &cache->control_in, cc_req, pragma, r->headers_in);
+
+    if (cache->control_in.no_cache) {
 
         if (!conf->ignorecachecontrol) {
             return 0;
@@ -423,7 +424,7 @@ CACHE_DECLARE(int) ap_cache_check_allowe
         }
     }
 
-    if (ap_cache_liststr(NULL, cc_req, "no-store", NULL)) {
+    if (cache->control_in.no_store) {
 
         if (!conf->ignorecachecontrol) {
             /* We're not allowed to serve a cached copy */
@@ -1012,3 +1013,168 @@ CACHE_DECLARE(apr_table_t *)ap_cache_cac
 
     return headers_out;
 }
+
+/**
+ * Parse the Cache-Control and Pragma headers in one go, marking
+ * which tokens appear within the header. Populate the structure
+ * passed in.
+ */
+int ap_cache_control(request_rec *r, cache_control_t *cc,
+        const char *cc_header, const char *pragma_header, apr_table_t *headers)
+{
+    char *last;
+
+    if (cc->parsed) {
+        return cc->cache_control || cc->pragma;
+    }
+
+    cc->parsed = 1;
+    cc->max_age_value = -1;
+    cc->max_stale_value = -1;
+    cc->min_fresh_value = -1;
+    cc->s_maxage_value = -1;
+
+    if (pragma_header) {
+        char *header = apr_pstrdup(r->pool, pragma_header);
+        const char *token = apr_strtok(header, ", ", &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")) {
+                cc->no_cache = 1;
+            }
+            token = apr_strtok(NULL, ", ", &last);
+        }
+        cc->pragma = 1;
+    }
+
+    if (cc_header) {
+        char *header = apr_pstrdup(r->pool, cc_header);
+        const char *token = apr_strtok(header, ", ", &last);
+        while (token) {
+            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 (token[8] == '=') {
+                        if (apr_table_get(headers, token + 9)) {
+                            cc->no_cache_header = 1;
+                        }
+                    }
+                    else if (!token[8]) {
+                        cc->no_cache = 1;
+                    }
+                    break;
+                }
+                else if (!strcasecmp(token, "no-store")) {
+                    cc->no_store = 1;
+                }
+                else if (!strcasecmp(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 (token[7] == '=') {
+                        cc->max_age = 1;
+                        cc->max_age_value = atoi(token + 8);
+                    }
+                    break;
+                }
+                else if (!strncasecmp(token, "max-stale", 9)) {
+                    if (token[9] == '=') {
+                        cc->max_stale = 1;
+                        cc->max_stale_value = atoi(token + 10);
+                    }
+                    else if (!token[10]) {
+                        cc->max_stale = 1;
+                        cc->max_stale_value = -1;
+                    }
+                    break;
+                }
+                else if (!strncasecmp(token, "min-fresh", 9)) {
+                    if (token[9] == '=') {
+                        cc->min_fresh = 1;
+                        cc->min_fresh_value = atoi(token + 10);
+                    }
+                    break;
+                }
+                else if (!strcasecmp(token, "must-revalidate")) {
+                    cc->must_revalidate = 1;
+                }
+                break;
+            }
+            case 'o':
+            case 'O': {
+                if (!strcasecmp(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")) {
+                    cc->public = 1;
+                }
+                else if (!strncasecmp(token, "private", 7)) {
+                    if (token[7] == '=') {
+                        if (apr_table_get(headers, token + 8)) {
+                            cc->private_header = 1;
+                        }
+                    }
+                    else if (!token[7]) {
+                        cc->private = 1;
+                    }
+                    break;
+                }
+                else if (!strcasecmp(token, "proxy-revalidate")) {
+                    cc->proxy_revalidate = 1;
+                }
+                break;
+            }
+            case 's':
+            case 'S': {
+                if (!strncasecmp(token, "s-maxage", 8)) {
+                    if (token[8] == '=') {
+                        cc->s_maxage = 1;
+                        cc->s_maxage_value = atoi(token + 9);
+                    }
+                    break;
+                }
+                break;
+            }
+            }
+            token = apr_strtok(NULL, ", ", &last);
+        }
+        cc->cache_control = 1;
+    }
+
+    return (cc_header != NULL || pragma_header != NULL);
+}

Modified: httpd/httpd/trunk/modules/cache/cache_util.h
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/cache/cache_util.h?rev=1023360&r1=1023359&r2=1023360&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/cache/cache_util.h (original)
+++ httpd/httpd/trunk/modules/cache/cache_util.h Sat Oct 16 19:30:08 2010
@@ -190,6 +190,31 @@ typedef struct {
     int stale_on_error_set;
 } cache_dir_conf;
 
+/* a cache control header breakdown */
+typedef struct {
+    unsigned int parsed:1;
+    unsigned int cache_control:1;
+    unsigned int pragma:1;
+    unsigned int no_cache:1;
+    unsigned int no_cache_header:1; /* no cache by header match */
+    unsigned int no_store:1;
+    unsigned int max_age:1;
+    unsigned int max_stale:1;
+    unsigned int min_fresh:1;
+    unsigned int no_transform:1;
+    unsigned int only_if_cached:1;
+    unsigned int public:1;
+    unsigned int private:1;
+    unsigned int private_header:1; /* private by header match */
+    unsigned int must_revalidate:1;
+    unsigned int proxy_revalidate:1;
+    unsigned int s_maxage:1;
+    int max_age_value; /* if positive, then set */
+    int max_stale_value; /* if positive, then set */
+    int min_fresh_value; /* if positive, then set */
+    int s_maxage_value; /* if positive, then set */
+} cache_control_t;
+
 /* A linked-list of authn providers. */
 typedef struct cache_provider_list cache_provider_list;
 
@@ -222,9 +247,27 @@ typedef struct {
                                          */
     apr_off_t size;                     /* the content length from the headers, or -1 */
     apr_bucket_brigade *out;            /* brigade to reuse for upstream responses */
+    cache_control_t control_in;         /* cache control incoming */
 } cache_request_rec;
 
 /**
+ * Parse the Cache-Control and Pragma headers in one go, marking
+ * which tokens appear within the header. Populate the structure
+ * passed in.
+ */
+int ap_cache_control(request_rec *r, cache_control_t *cc, const char *cc_header,
+        const char *pragma_header, apr_table_t *headers);
+
+/**
+ * Check the whether the request allows a cached object to be served as per RFC2616
+ * section 14.9.4 (Cache Revalidation and Reload Controls)
+ * @param h cache_handle_t
+ * @param r request_rec
+ * @return 0 ==> cache object may not be served, 1 ==> cache object may be served
+ */
+CACHE_DECLARE(int) ap_cache_check_allowed(cache_request_rec *cache, request_rec *r);
+
+/**
  * Check the freshness of the cache object per RFC2616 section 13.2 (Expiration Model)
  * @param h cache_handle_t
  * @param r request_rec

Modified: httpd/httpd/trunk/modules/cache/mod_cache.h
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/cache/mod_cache.h?rev=1023360&r1=1023359&r2=1023360&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/cache/mod_cache.h (original)
+++ httpd/httpd/trunk/modules/cache/mod_cache.h Sat Oct 16 19:30:08 2010
@@ -124,15 +124,6 @@ typedef enum {
 CACHE_DECLARE(apr_time_t) ap_cache_current_age(cache_info *info, const apr_time_t age_value,
                                                apr_time_t now);
 
-/**
- * Check the whether the request allows a cached object to be served as per RFC2616
- * section 14.9.4 (Cache Revalidation and Reload Controls)
- * @param h cache_handle_t
- * @param r request_rec
- * @return 0 ==> cache object may not be served, 1 ==> cache object may be served
- */
-CACHE_DECLARE(int) ap_cache_check_allowed(request_rec *r);
-
 CACHE_DECLARE(apr_time_t) ap_cache_hex2usec(const char *x);
 CACHE_DECLARE(void) ap_cache_usec2hex(apr_time_t j, char *y);
 CACHE_DECLARE(char *) ap_cache_generate_name(apr_pool_t *p, int dirlevels,



Mime
View raw message