View | Details | Raw Unified | Return to bug 25201
Collapse All | Expand All

(-)docs/manual/mod/mod_cache.xml (+38 lines)
Lines 314-317 Link Here
314
</usage>
314
</usage>
315
</directivesynopsis>
315
</directivesynopsis>
316
316
317
<directivesynopsis>
318
<name>CachePurgeMethod</name>
319
<description>Name of HTTP method used which may be used to remove
320
single entries in the cache.</description>
321
<syntax>CachePurgeMethod <var>MethodName</var></syntax>
322
<default>CachePurgeMethod PURGE</default>
323
<contextlist><context>server config</context><context>virtual host</context>
324
</contextlist>
325
326
<usage>
327
    <p>Generally a resource which has been stored in the cache will be
328
    removed and replaced by new resource data whenever the cache decides
329
    to do so. There are on the other situations, where some process, for
330
    example a web server in fron of which a caching reverse proxy is placed,
331
    knows before hand that some resource has changed. In such situations
332
    that other process might wish to inform the caching proxy to remove
333
    the stale data from the cache regardless of any other information.</p>
334
335
    <p>This kind of administration of the cache contents is made possible
336
    through the use of cache purge method. The cache handler will intercept
337
    a request with the hereby configured method and try to remove the
338
    cache entry indicated by the request. In case of success, that is the
339
    cache entry was present and has been removed, the server response
340
    with a OK status (200). If the no cache entry was present for the
341
    indicated resource, the cache handler sends a Not Found (404)
342
    response.</p>
343
    
344
    <p>The cache handler completely ignores any incoming request body and
345
    does not send back a response body. Request headers are only respected
346
    as far as they are needed to identify the cache entry for the
347
    resource.</p>
348
349
    <example>
350
      CachePurgeMethod PURGE_CACHE
351
    </example>
352
</usage>
353
</directivesynopsis>
354
317
</modulesynopsis>
355
</modulesynopsis>
(-)modules/experimental/cache_storage.c (-4 / +4 lines)
Lines 76-82 Link Here
76
 * delete all URL entities from the cache
76
 * delete all URL entities from the cache
77
 *
77
 *
78
 */
78
 */
79
int cache_remove_url(request_rec *r, const char *types, char *url)
79
int cache_remove_url(cache_handle_t *h, request_rec *r, const char *types, char *url)
80
{
80
{
81
    const char *next = types;
81
    const char *next = types;
82
    const char *type;
82
    const char *type;
Lines 91-97 Link Here
91
    /* for each specified cache type, delete the URL */
91
    /* for each specified cache type, delete the URL */
92
    while(next) {
92
    while(next) {
93
        type = ap_cache_tokstr(r->pool, next, &next);
93
        type = ap_cache_tokstr(r->pool, next, &next);
94
        cache_run_remove_url(type, key);
94
        cache_run_remove_url(h, r, type, key);
95
    }
95
    }
96
    return OK;
96
    return OK;
97
}
97
}
Lines 312-318 Link Here
312
                                      const char *urlkey),(h,r,type,urlkey),
312
                                      const char *urlkey),(h,r,type,urlkey),
313
                                      DECLINED)
313
                                      DECLINED)
314
APR_IMPLEMENT_EXTERNAL_HOOK_RUN_ALL(cache, CACHE, int, remove_url, 
314
APR_IMPLEMENT_EXTERNAL_HOOK_RUN_ALL(cache, CACHE, int, remove_url, 
315
                                    (const char *type, const char *urlkey),
315
                                    (cache_handle_t *h, request_rec *r, const char *type, const char *urlkey),
316
                                    (type,urlkey),OK,DECLINED)
316
                                    (h,r,type,urlkey),OK,DECLINED)
317
317
318
318
(-)modules/experimental/mod_cache.c (-5 / +150 lines)
Lines 71-78 Link Here
71
 */
71
 */
72
static ap_filter_rec_t *cache_in_filter_handle;
72
static ap_filter_rec_t *cache_in_filter_handle;
73
static ap_filter_rec_t *cache_out_filter_handle;
73
static ap_filter_rec_t *cache_out_filter_handle;
74
static ap_filter_rec_t *cache_out_purge_handle;
74
static ap_filter_rec_t *cache_conditional_filter_handle;
75
static ap_filter_rec_t *cache_conditional_filter_handle;
75
76
77
/* Forward declarations */
78
static int cache_purge(request_rec *r, cache_server_conf *conf, cache_request_rec *cache, char *url);
79
76
/*
80
/*
77
 * CACHE handler
81
 * CACHE handler
78
 * -------------
82
 * -------------
Lines 104-111 Link Here
104
    conf = (cache_server_conf *) ap_get_module_config(r->server->module_config,
108
    conf = (cache_server_conf *) ap_get_module_config(r->server->module_config,
105
                                                      &cache_module);
109
                                                      &cache_module);
106
110
107
    /* we don't handle anything but GET */
111
    /* we don't handle anything but GET and cache purge method */
108
    if (r->method_number != M_GET) {
112
    if (r->method_number != M_GET && r->method_number != conf->method) {    
109
        return DECLINED;
113
        return DECLINED;
110
    }
114
    }
111
115
Lines 169-175 Link Here
169
        if (ap_cache_liststr(NULL, cc_in, "no-store", NULL) ||
173
        if (ap_cache_liststr(NULL, cc_in, "no-store", NULL) ||
170
            ap_cache_liststr(NULL, pragma, "no-cache", NULL) || (auth != NULL)) {
174
            ap_cache_liststr(NULL, pragma, "no-cache", NULL) || (auth != NULL)) {
171
            /* delete the previously cached file */
175
            /* delete the previously cached file */
172
            cache_remove_url(r, cache->types, url);
176
            cache_remove_url(cache->handle, r, cache->types, url);
173
177
174
            ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
178
            ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
175
                         "cache: no-store forbids caching of %s", url);
179
                         "cache: no-store forbids caching of %s", url);
Lines 180-185 Link Here
180
    /*
184
    /*
181
     * Try to serve this request from the cache.
185
     * Try to serve this request from the cache.
182
     *
186
     *
187
     * If cache purge method
188
     *   purge cache entry
183
     * If no existing cache file
189
     * If no existing cache file
184
     *   add cache_in filter
190
     *   add cache_in filter
185
     * If stale cache file
191
     * If stale cache file
Lines 194-200 Link Here
194
     */
200
     */
195
201
196
    rv = cache_select_url(r, cache->types, url);
202
    rv = cache_select_url(r, cache->types, url);
197
    if (DECLINED == rv) {
203
    if (r->method_number == conf->method && (DECLINED == rv || OK == rv)) {
204
        cache_request_rec *purge_cache = (OK == rv) ? cache : NULL;
205
        return cache_purge(r, conf, purge_cache, url);
206
    }
207
    else if (DECLINED == rv) {
198
        if (!lookup) {
208
        if (!lookup) {
199
            /* no existing cache file */
209
            /* no existing cache file */
200
            ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
210
            ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
Lines 591-597 Link Here
591
         * BillS Asks.. Why do we need to make this call to remove_url?
601
         * BillS Asks.. Why do we need to make this call to remove_url?
592
         * leave it in for now..
602
         * leave it in for now..
593
         */
603
         */
594
        cache_remove_url(r, cache->types, url);
604
        cache_remove_url(cache->handle, r, cache->types, url);
595
605
596
        /* remove this filter from the chain */
606
        /* remove this filter from the chain */
597
        ap_remove_output_filter(f);
607
        ap_remove_output_filter(f);
Lines 775-780 Link Here
775
    return ap_pass_brigade(f->next, in);
785
    return ap_pass_brigade(f->next, in);
776
}
786
}
777
787
788
/*
789
 * CACHE_PURGE filter
790
 * ------------------
791
 *
792
 * Deliver cache purge response up the stack.
793
 */
794
static int cache_out_purge(ap_filter_t *f, apr_bucket_brigade *bb)
795
{
796
    request_rec *r = f->r;
797
    cache_request_rec *cache;
798
799
    cache = (cache_request_rec *) ap_get_module_config(r->request_config,
800
                                                       &cache_module);
801
802
    if (!cache) {
803
        /* user likely configured CACHE_PURGE manually; they should use mod_cache
804
         * configuration to do that */
805
        ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server,
806
                     "CACHE_PURGE enabled unexpectedly");
807
        ap_remove_output_filter(f);
808
        return ap_pass_brigade(f->next, bb);
809
    }
810
811
    ap_log_error(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, r->server,
812
                 "cache_out_purge: running CACHE_PURGE filter");
813
814
    /* Would set status code, but has already been done in cache_purge */
815
    
816
    /* Remove as many headers as possible .... */
817
    apr_table_clear(r->headers_out);
818
    apr_table_clear(r->err_headers_out);
819
820
    /* at least force Content-Length to be zero, we do not have anything */
821
    apr_table_set(r->headers_out, "Content-Length", "0");
822
823
    /* This filter is done once it has served up its content */
824
    ap_remove_output_filter(f);
825
826
    ap_log_error(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, r->server,
827
                 "cache: sending reply to purging %s from cache",
828
                 r->uri);
829
    return ap_pass_brigade(f->next, bb);
830
}
831
832
/*
833
 * Helper method to remove the cache entry from the storage
834
 * and redirect request handling to the cache_out_purge method.
835
 *
836
 * If cache
837
 *     cache contains data, which is removed
838
 *     set HTTP response status OK/200
839
 * Else
840
 *     cache does not contain data
841
 *     set HTTP response status NOT_FOUND/404
842
 */
843
static int cache_purge(request_rec *r, cache_server_conf *conf, cache_request_rec *cache, char *url)
844
{
845
    conn_rec *c = r->connection;
846
    apr_bucket_brigade *out;
847
    int rv;
848
849
    if (cache) {
850
        ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
851
                     "cache: Remove entity url=%s for types=%s",
852
                     url, cache->types);
853
854
        rv = cache_remove_url(cache->handle, r, cache->types, url);
855
        ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
856
                     "cache: cache_remove_url rv=%d",
857
                     rv);
858
        r->status = HTTP_OK;
859
    }
860
    else {
861
        ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
862
                     "cache: Entity url=%s not in cache",
863
                     url);
864
        r->status = HTTP_NOT_FOUND;
865
    }
866
867
868
    /* the following is duplicate from cache_url_handler, I assume
869
     * this code is correct...
870
     */
871
     
872
    /* We are in the quick handler hook, which means that no output
873
     * filters have been set. So lets run the insert_filter hook.
874
     */
875
    ap_run_insert_filter(r);
876
    ap_add_output_filter_handle(cache_out_purge_handle, NULL,
877
                                r, r->connection);
878
879
    /* kick off the filter stack */
880
    out = apr_brigade_create(r->pool, c->bucket_alloc);
881
    if (APR_SUCCESS != (rv = ap_pass_brigade(r->output_filters, out))) {
882
        ap_log_error(APLOG_MARK, APLOG_ERR, rv, r->server,
883
                     "cache: error returned while trying to purge cache entry "
884
                     "for url=%s",
885
                     url);
886
        return rv;
887
    }
888
889
    return OK;
890
}
891
778
/* -------------------------------------------------------------- */
892
/* -------------------------------------------------------------- */
779
/* Setup configurable data */
893
/* Setup configurable data */
780
894
Lines 798-803 Link Here
798
    /* default percentage to force cache completion */
912
    /* default percentage to force cache completion */
799
    ps->complete = DEFAULT_CACHE_COMPLETION;
913
    ps->complete = DEFAULT_CACHE_COMPLETION;
800
    ps->complete_set = 0;
914
    ps->complete_set = 0;
915
    /* default purge method name to remove cache entry */
916
    ps->method = ap_method_register(p, DEFAULT_PURGE_METHOD);
917
    ps->method_set = 0;
801
    ps->no_last_mod_ignore_set = 0;
918
    ps->no_last_mod_ignore_set = 0;
802
    ps->no_last_mod_ignore = 0;
919
    ps->no_last_mod_ignore = 0;
803
    ps->ignorecachecontrol = 0;
920
    ps->ignorecachecontrol = 0;
Lines 829-834 Link Here
829
    /* default percentage to force cache completion */
946
    /* default percentage to force cache completion */
830
    ps->complete =
947
    ps->complete =
831
        (overrides->complete_set == 0) ? base->complete : overrides->complete;
948
        (overrides->complete_set == 0) ? base->complete : overrides->complete;
949
    /* default purge method name to remove cache entry */
950
    ps->method =
951
        (overrides->method_set == 0) ? base->method : overrides->method;
832
952
833
    ps->no_last_mod_ignore =
953
    ps->no_last_mod_ignore =
834
        (overrides->no_last_mod_ignore_set == 0)
954
        (overrides->no_last_mod_ignore_set == 0)
Lines 957-962 Link Here
957
    return NULL;
1077
    return NULL;
958
}
1078
}
959
1079
1080
static const char *set_cache_purge_method(cmd_parms *parms, void *dummy,
1081
                                          const char *arg)
1082
{
1083
    cache_server_conf *conf;
1084
    int val;
1085
1086
    conf =
1087
        (cache_server_conf *)ap_get_module_config(parms->server->module_config,
1088
                                                  &cache_module);
1089
    int method = ap_method_register(parms->pool, arg);
1090
    if (method == M_INVALID) {
1091
        return "CachePurgeMethod cannot be registered and used";
1092
    }
1093
    conf->method = method;
1094
    conf->method_set = 1;
1095
    return NULL;
1096
}
1097
960
static int cache_post_config(apr_pool_t *p, apr_pool_t *plog,
1098
static int cache_post_config(apr_pool_t *p, apr_pool_t *plog,
961
                             apr_pool_t *ptemp, server_rec *s)
1099
                             apr_pool_t *ptemp, server_rec *s)
962
{
1100
{
Lines 1003-1008 Link Here
1003
    AP_INIT_TAKE1("CacheForceCompletion", set_cache_complete, NULL, RSRC_CONF,
1141
    AP_INIT_TAKE1("CacheForceCompletion", set_cache_complete, NULL, RSRC_CONF,
1004
                  "Percentage of download to arrive for the cache to force "
1142
                  "Percentage of download to arrive for the cache to force "
1005
                  "complete transfer"),
1143
                  "complete transfer"),
1144
    AP_INIT_TAKE1("CachePurgeMethod", set_cache_purge_method, NULL, RSRC_CONF,
1145
                  "Name of HTTP method used to purge a cache entry"),
1006
    {NULL}
1146
    {NULL}
1007
};
1147
};
1008
1148
Lines 1036-1041 Link Here
1036
                                  cache_conditional_filter, 
1176
                                  cache_conditional_filter, 
1037
                                  NULL,
1177
                                  NULL,
1038
                                  AP_FTYPE_CONTENT_SET);
1178
                                  AP_FTYPE_CONTENT_SET);
1179
    cache_out_purge_handle =
1180
        ap_register_output_filter("CACHE_PURGE",
1181
                                  cache_out_purge,
1182
                                  NULL,
1183
                                  AP_FTYPE_CONTENT_SET-1);
1039
    ap_hook_post_config(cache_post_config, NULL, NULL, APR_HOOK_REALLY_FIRST);
1184
    ap_hook_post_config(cache_post_config, NULL, NULL, APR_HOOK_REALLY_FIRST);
1040
}
1185
}
1041
1186
(-)modules/experimental/mod_cache.h (-2 / +6 lines)
Lines 130-135 Link Here
130
#define DEFAULT_CACHE_MAXEXPIRE MSEC_ONE_DAY
130
#define DEFAULT_CACHE_MAXEXPIRE MSEC_ONE_DAY
131
#define DEFAULT_CACHE_EXPIRE    MSEC_ONE_HR
131
#define DEFAULT_CACHE_EXPIRE    MSEC_ONE_HR
132
#define DEFAULT_CACHE_LMFACTOR  (0.1)
132
#define DEFAULT_CACHE_LMFACTOR  (0.1)
133
#define DEFAULT_PURGE_METHOD ("PURGE")
133
134
134
/* Create a set of PROXY_DECLARE(type), PROXY_DECLARE_NONSTD(type) and 
135
/* Create a set of PROXY_DECLARE(type), PROXY_DECLARE_NONSTD(type) and 
135
 * PROXY_DECLARE_DATA with appropriate export and import tags for the platform
136
 * PROXY_DECLARE_DATA with appropriate export and import tags for the platform
Lines 179-184 Link Here
179
    /** ignore client's requests for uncached responses */
180
    /** ignore client's requests for uncached responses */
180
    int ignorecachecontrol;
181
    int ignorecachecontrol;
181
    int ignorecachecontrol_set;
182
    int ignorecachecontrol_set;
183
    /* purge method */
184
    int method;
185
    int method_set;
182
} cache_server_conf;
186
} cache_server_conf;
183
187
184
/* cache info information */
188
/* cache info information */
Lines 284-290 Link Here
284
/**
288
/**
285
 * cache_storage.c
289
 * cache_storage.c
286
 */
290
 */
287
int cache_remove_url(request_rec *r, const char *types, char *url);
291
int cache_remove_url(cache_handle_t *h, request_rec *r, const char *types, char *url);
288
int cache_create_entity(request_rec *r, const char *types, char *url, apr_off_t size);
292
int cache_create_entity(request_rec *r, const char *types, char *url, apr_off_t size);
289
int cache_remove_entity(request_rec *r, const char *types, cache_handle_t *h);
293
int cache_remove_entity(request_rec *r, const char *types, cache_handle_t *h);
290
int cache_select_url(request_rec *r, const char *types, char *url);
294
int cache_select_url(request_rec *r, const char *types, char *url);
Lines 332-338 Link Here
332
                          (cache_handle_t *h, request_rec *r, const char *type,
336
                          (cache_handle_t *h, request_rec *r, const char *type,
333
                           const char *urlkey))
337
                           const char *urlkey))
334
APR_DECLARE_EXTERNAL_HOOK(cache, CACHE, int, remove_url, 
338
APR_DECLARE_EXTERNAL_HOOK(cache, CACHE, int, remove_url, 
335
                          (const char *type, const char *urlkey))
339
                          (cache_handle_t *h, request_rec *r, const char *type, const char *urlkey))
336
340
337
341
338
342
(-)modules/experimental/mod_disk_cache.c (-1 / +60 lines)
Lines 469-474 Link Here
469
    return OK;
469
    return OK;
470
}
470
}
471
471
472
/*
473
 * Removes the cache data addressed by the cache handle
474
 */
475
static int remove_url(cache_handle_t *h, request_rec *r, const char *type, const char *key)
476
{
477
    cache_object_t *obj;
478
    disk_cache_object_t *dobj;
479
480
    /* Look up entity keyed to 'url' */
481
    if (strcasecmp(type, "disk")) {
482
        ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
483
                     "disk_cache: Incorrect cache type for key=%s",
484
                     key);
485
        return DECLINED;
486
    }
487
488
    /* Check whether we have a cache handle at all */
489
    if (!h) {
490
        ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
491
                     "disk_cache: No cache handle for key=%s",
492
                     key);
493
        return DECLINED;
494
    }
495
      
496
    /* Need the cache object, fail if not present */
497
    obj = h->cache_obj;
498
    if (!obj) {
499
        ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
500
                     "disk_cache: No cache object in cache handle "
501
                     "for key=%s",
502
                     key);
503
        return DECLINED;
504
    }
505
506
    /* Now I need the disk cache object, fail if not present */
507
    dobj = (disk_cache_object_t *) obj->vobj;
508
    if (!dobj) {
509
        ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
510
                     "disk_cache: No disk cache object in cache "
511
                     "handle for key=%s",
512
                     key);
513
        return DECLINED;
514
    }
515
516
    /* So we continue to remove the header and data files */
517
    ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
518
                 "disk_cache: Removing files data=%s, headers=%s",
519
                 dobj->datafile, dobj->hdrsfile);
520
521
    /* simply remove the files,
522
     * should probably check and guard ???
523
     */
524
    apr_file_remove(dobj->datafile, r->pool);
525
    apr_file_remove(dobj->hdrsfile, r->pool);
526
527
    /*assume everything is just fine */
528
    return OK;
529
}
530
472
static int remove_entity(cache_handle_t *h) 
531
static int remove_entity(cache_handle_t *h) 
473
{
532
{
474
    /* Null out the cache object pointer so next time we start from scratch  */
533
    /* Null out the cache object pointer so next time we start from scratch  */
Lines 884-890 Link Here
884
    /* cache initializer */
943
    /* cache initializer */
885
    cache_hook_create_entity(create_entity, NULL, NULL, APR_HOOK_MIDDLE);
944
    cache_hook_create_entity(create_entity, NULL, NULL, APR_HOOK_MIDDLE);
886
    cache_hook_open_entity(open_entity,  NULL, NULL, APR_HOOK_MIDDLE);
945
    cache_hook_open_entity(open_entity,  NULL, NULL, APR_HOOK_MIDDLE);
887
/*    cache_hook_remove_entity(remove_entity, NULL, NULL, APR_HOOK_MIDDLE); */
946
    cache_hook_remove_url(remove_url, NULL, NULL, APR_HOOK_MIDDLE);
888
}
947
}
889
948
890
module AP_MODULE_DECLARE_DATA disk_cache_module = {
949
module AP_MODULE_DECLARE_DATA disk_cache_module = {
(-)modules/experimental/mod_mem_cache.c (-1 / +1 lines)
Lines 719-725 Link Here
719
    return APR_SUCCESS;
719
    return APR_SUCCESS;
720
}
720
}
721
/* Define request processing hook handlers */
721
/* Define request processing hook handlers */
722
static int remove_url(const char *type, const char *key) 
722
static int remove_url(cache_handle_t *h, request_rec *r, const char *type, const char *key) 
723
{
723
{
724
    cache_object_t *obj;
724
    cache_object_t *obj;
725
725

Return to bug 25201