0e3136
diff --git a/modules/cache/cache_util.h b/modules/cache/cache_util.h
0e3136
index 6b92151..4c42a8e 100644
0e3136
--- a/modules/cache/cache_util.h
0e3136
+++ b/modules/cache/cache_util.h
0e3136
@@ -195,6 +195,9 @@ typedef struct {
0e3136
     unsigned int store_nostore_set:1;
0e3136
     unsigned int enable_set:1;
0e3136
     unsigned int disable_set:1;
0e3136
+    /* treat maxex as hard limit */
0e3136
+    unsigned int hardmaxex:1;
0e3136
+    unsigned int hardmaxex_set:1;
0e3136
 } cache_dir_conf;
0e3136
 
0e3136
 /* A linked-list of authn providers. */
0e3136
diff --git a/modules/cache/mod_cache.c b/modules/cache/mod_cache.c
0e3136
index 3b9aa4f..8268503 100644
0e3136
--- a/modules/cache/mod_cache.c
0e3136
+++ b/modules/cache/mod_cache.c
0e3136
@@ -1455,6 +1455,11 @@ static apr_status_t cache_save_filter(ap_filter_t *f, apr_bucket_brigade *in)
0e3136
             exp = date + dconf->defex;
0e3136
         }
0e3136
     }
0e3136
+    /* else, forcibly cap the expiry date if required */
0e3136
+    else if (dconf->hardmaxex && (date + dconf->maxex) < exp) {
0e3136
+        exp = date + dconf->maxex;
0e3136
+    }        
0e3136
+
0e3136
     info->expire = exp;
0e3136
 
0e3136
     /* We found a stale entry which wasn't really stale. */
0e3136
@@ -1954,7 +1959,9 @@ static void *create_dir_config(apr_pool_t *p, char *dummy)
0e3136
 
0e3136
     /* array of providers for this URL space */
0e3136
     dconf->cacheenable = apr_array_make(p, 10, sizeof(struct cache_enable));
0e3136
-
0e3136
+    /* flag; treat maxex as hard limit */
0e3136
+    dconf->hardmaxex = 0;
0e3136
+    dconf->hardmaxex_set = 0;
0e3136
     return dconf;
0e3136
 }
0e3136
 
0e3136
@@ -2004,7 +2011,10 @@ static void *merge_dir_config(apr_pool_t *p, void *basev, void *addv) {
0e3136
     new->enable_set = add->enable_set || base->enable_set;
0e3136
     new->disable = (add->disable_set == 0) ? base->disable : add->disable;
0e3136
     new->disable_set = add->disable_set || base->disable_set;
0e3136
-
0e3136
+    new->hardmaxex = 
0e3136
+        (add->hardmaxex_set == 0)
0e3136
+        ? base->hardmaxex
0e3136
+        : add->hardmaxex;
0e3136
     return new;
0e3136
 }
0e3136
 
0e3136
@@ -2332,12 +2342,18 @@ static const char *add_cache_disable(cmd_parms *parms, void *dummy,
0e3136
 }
0e3136
 
0e3136
 static const char *set_cache_maxex(cmd_parms *parms, void *dummy,
0e3136
-                                   const char *arg)
0e3136
+                                   const char *arg, const char *hard)
0e3136
 {
0e3136
     cache_dir_conf *dconf = (cache_dir_conf *)dummy;
0e3136
 
0e3136
     dconf->maxex = (apr_time_t) (atol(arg) * MSEC_ONE_SEC);
0e3136
     dconf->maxex_set = 1;
0e3136
+    
0e3136
+    if (hard && strcasecmp(hard, "hard") == 0) {
0e3136
+        dconf->hardmaxex = 1;
0e3136
+        dconf->hardmaxex_set = 1;
0e3136
+    }
0e3136
+
0e3136
     return NULL;
0e3136
 }
0e3136
 
0e3136
@@ -2545,7 +2561,7 @@ static const command_rec cache_cmds[] =
0e3136
                    "caching is enabled"),
0e3136
     AP_INIT_TAKE1("CacheDisable", add_cache_disable, NULL, RSRC_CONF|ACCESS_CONF,
0e3136
                   "A partial URL prefix below which caching is disabled"),
0e3136
-    AP_INIT_TAKE1("CacheMaxExpire", set_cache_maxex, NULL, RSRC_CONF|ACCESS_CONF,
0e3136
+    AP_INIT_TAKE12("CacheMaxExpire", set_cache_maxex, NULL, RSRC_CONF|ACCESS_CONF,
0e3136
                   "The maximum time in seconds to cache a document"),
0e3136
     AP_INIT_TAKE1("CacheMinExpire", set_cache_minex, NULL, RSRC_CONF|ACCESS_CONF,
0e3136
                   "The minimum time in seconds to cache a document"),