Index: modules/cache/mod_cache.c
===================================================================
--- modules/cache/mod_cache.c	(revision 661288)
+++ modules/cache/mod_cache.c	(working copy)
@@ -30,7 +30,11 @@
 static ap_filter_rec_t *cache_out_filter_handle;
 static ap_filter_rec_t *cache_out_subreq_filter_handle;
 static ap_filter_rec_t *cache_remove_url_filter_handle;
+static ap_filter_rec_t *cache_purge_url_filter_handle;
 
+/* The method number for the non-standard HTTP "PURGE" method */
+static int purge_method;
+
 /*
  * CACHE handler
  * -------------
@@ -57,8 +61,8 @@
     ap_filter_t *next;
     ap_filter_rec_t *cache_out_handle;
 
-    /* Delay initialization until we know we are handling a GET */
-    if (r->method_number != M_GET) {
+    /* Delay initialization until we know we are handling a GET or a PURGE */
+    if (r->method_number != M_GET && r->method_number != purge_method) {
         return DECLINED;
     }
 
@@ -93,7 +97,7 @@
     /* First things first - does the request allow us to return
      * cached information at all? If not, just decline the request.
      */
-    if (auth) {
+    if (auth && r->method_number == M_GET) {
         return DECLINED;
     }
 
@@ -212,13 +216,18 @@
      * the correct filter by checking if we are a subrequest
      * or not.
      */
-    if (r->main) {
+
+    /* Purge the content if that's what we've been asked to do */
+    if (r->method_number == purge_method) {
+        cache_out_handle = cache_purge_url_filter_handle;
+    }
+    else if (r->main) {
         cache_out_handle = cache_out_subreq_filter_handle;
     }
     else {
         cache_out_handle = cache_out_filter_handle;
     }
-    ap_add_output_filter_handle(cache_out_handle, NULL, r, r->connection);
+    ap_add_output_filter_handle(cache_out_handle, cache, r, r->connection);
 
     /*
      * Remove all filters that are before the cache_out filter. This ensures
@@ -892,6 +901,24 @@
     return ap_pass_brigade(f->next, in);
 }
 
+/*
+ * CACHE_PURGE_URL filter
+ * ---------------
+ *
+ * This filter gets added when we intercept a non-standard PURGE method request.
+ */
+static int cache_purge_url_filter(ap_filter_t *f, apr_bucket_brigade *in)
+{ 
+    apr_bucket *b;
+    char buf[] = "<html><body><h1>Purged!</h1></body></html>";
+    
+    b = apr_bucket_heap_create(buf, sizeof(buf), NULL, f->r->connection->bucket_alloc);
+    APR_BRIGADE_INSERT_TAIL(in, b);
+    
+    /* Remove the url */
+    return cache_remove_url_filter(f, in);
+}
+
 /* -------------------------------------------------------------- */
 /* Setup configurable data */
 
@@ -1192,6 +1219,10 @@
     if (!cache_generate_key) {
         cache_generate_key = cache_generate_key_default;
     }
+
+    /* Register ourselves as a handler for the "PURGE" method. */
+    purge_method = ap_method_register(p, "PURGE");
+
     return OK;
 }
 
@@ -1309,6 +1340,15 @@
                                   cache_remove_url_filter,
                                   NULL,
                                   AP_FTYPE_PROTOCOL);
+
+    /* CACHE_PURGE_URL
+     */
+    cache_purge_url_filter_handle =
+        ap_register_output_filter("CACHE_PURGE_URL",
+                                  cache_purge_url_filter,
+                                  NULL,
+                                  AP_FTYPE_CONTENT_SET+1);
+
     ap_hook_post_config(cache_post_config, NULL, NULL, APR_HOOK_REALLY_FIRST);
 }
 
