]> granicus.if.org Git - apache/blob - modules/cache/mod_cache.c
Both lastmod and lastmods resolve to 0 when unset, but only lastmods is a
[apache] / modules / cache / mod_cache.c
1 /* Licensed to the Apache Software Foundation (ASF) under one or more
2  * contributor license agreements.  See the NOTICE file distributed with
3  * this work for additional information regarding copyright ownership.
4  * The ASF licenses this file to You under the Apache License, Version 2.0
5  * (the "License"); you may not use this file except in compliance with
6  * the License.  You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include "mod_cache.h"
18
19 #include "cache_storage.h"
20 #include "cache_util.h"
21
22 module AP_MODULE_DECLARE_DATA cache_module;
23 APR_OPTIONAL_FN_TYPE(ap_cache_generate_key) *cache_generate_key;
24
25 /* -------------------------------------------------------------- */
26
27
28 /* Handles for cache filters, resolved at startup to eliminate
29  * a name-to-function mapping on each request
30  */
31 static ap_filter_rec_t *cache_filter_handle;
32 static ap_filter_rec_t *cache_save_filter_handle;
33 static ap_filter_rec_t *cache_save_subreq_filter_handle;
34 static ap_filter_rec_t *cache_out_filter_handle;
35 static ap_filter_rec_t *cache_out_subreq_filter_handle;
36 static ap_filter_rec_t *cache_remove_url_filter_handle;
37
38 /*
39  * CACHE handler
40  * -------------
41  *
42  * Can we deliver this request from the cache?
43  * If yes:
44  *   deliver the content by installing the CACHE_OUT filter.
45  * If no:
46  *   check whether we're allowed to try cache it
47  *   If yes:
48  *     add CACHE_SAVE filter
49  *   If No:
50  *     oh well.
51  *
52  * By default, the cache handler runs in the quick handler, bypassing
53  * virtually all server processing and offering the cache its optimal
54  * performance. In this mode, the cache bolts onto the front of the
55  * server, and behaves as a discrete RFC2616 caching proxy
56  * implementation.
57  *
58  * Under certain circumstances, an admin might want to run the cache as
59  * a normal handler instead of a quick handler, allowing the cache to
60  * run after the authorisation hooks, or by allowing fine control over
61  * the placement of the cache in the filter chain. This option comes at
62  * a performance penalty, and should only be used to achieve specific
63  * caching goals where the admin understands what they are doing.
64  */
65
66 static int cache_quick_handler(request_rec *r, int lookup)
67 {
68     apr_status_t rv;
69     const char *auth;
70     cache_provider_list *providers;
71     cache_request_rec *cache;
72     apr_bucket_brigade *out;
73     apr_bucket *e;
74     ap_filter_t *next;
75     ap_filter_rec_t *cache_out_handle;
76     cache_server_conf *conf;
77
78     conf = (cache_server_conf *) ap_get_module_config(r->server->module_config,
79                                                       &cache_module);
80
81     /* only run if the quick handler is enabled */
82     if (!conf->quick) {
83         return DECLINED;
84     }
85
86     /*
87      * Which cache module (if any) should handle this request?
88      */
89     if (!(providers = cache_get_providers(r, conf, r->parsed_uri))) {
90         return DECLINED;
91     }
92
93     /* make space for the per request config */
94     cache = apr_pcalloc(r->pool, sizeof(cache_request_rec));
95     cache->size = -1;
96     cache->out = apr_brigade_create(r->pool, r->connection->bucket_alloc);
97
98     /* save away the possible providers */
99     cache->providers = providers;
100
101     /*
102      * Are we allowed to serve cached info at all?
103      */
104
105     /* find certain cache controlling headers */
106     auth = apr_table_get(r->headers_in, "Authorization");
107
108     /* First things first - does the request allow us to return
109      * cached information at all? If not, just decline the request.
110      */
111     if (auth) {
112         return DECLINED;
113     }
114
115     /* Are we something other than GET or HEAD? If so, invalidate
116      * the cached entities.
117      */
118     if (r->method_number != M_GET) {
119
120         ap_log_rerror(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, r,
121                 "Invalidating all cached entities in response to '%s' request for %s",
122                 r->method, r->uri);
123
124         cache_invalidate(cache, r);
125
126         /* we've got a cache invalidate! tell everyone who cares */
127         cache_run_cache_status(cache->handle, r, r->headers_out,
128                 AP_CACHE_INVALIDATE, apr_psprintf(r->pool,
129                         "cache invalidated by %s", r->method));
130
131         return DECLINED;
132     }
133
134     /*
135      * Try to serve this request from the cache.
136      *
137      * If no existing cache file (DECLINED)
138      *   add cache_save filter
139      * If cached file (OK)
140      *   clear filter stack
141      *   add cache_out filter
142      *   return OK
143      */
144     rv = cache_select(cache, r);
145     if (rv != OK) {
146         if (rv == DECLINED) {
147             if (!lookup) {
148
149                 /* try to obtain a cache lock at this point. if we succeed,
150                  * we are the first to try and cache this url. if we fail,
151                  * it means someone else is already trying to cache this
152                  * url, and we should just let the request through to the
153                  * backend without any attempt to cache. this stops
154                  * duplicated simultaneous attempts to cache an entity.
155                  */
156                 rv = cache_try_lock(conf, cache, r);
157                 if (APR_SUCCESS == rv) {
158
159                     /*
160                      * Add cache_save filter to cache this request. Choose
161                      * the correct filter by checking if we are a subrequest
162                      * or not.
163                      */
164                     if (r->main) {
165                         ap_log_rerror(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS,
166                                 r, "Adding CACHE_SAVE_SUBREQ filter for %s",
167                                 r->uri);
168                         cache->save_filter = ap_add_output_filter_handle(
169                                 cache_save_subreq_filter_handle, cache, r,
170                                 r->connection);
171                     }
172                     else {
173                         ap_log_rerror(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS,
174                                 r, "Adding CACHE_SAVE filter for %s",
175                                 r->uri);
176                         cache->save_filter = ap_add_output_filter_handle(
177                                 cache_save_filter_handle, cache, r,
178                                 r->connection);
179                     }
180
181                     apr_pool_userdata_setn(cache, CACHE_CTX_KEY, NULL, r->pool);
182
183                     ap_log_rerror(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, r,
184                             "Adding CACHE_REMOVE_URL filter for %s",
185                             r->uri);
186
187                     /* Add cache_remove_url filter to this request to remove a
188                      * stale cache entry if needed. Also put the current cache
189                      * request rec in the filter context, as the request that
190                      * is available later during running the filter may be
191                      * different due to an internal redirect.
192                      */
193                     cache->remove_url_filter = ap_add_output_filter_handle(
194                             cache_remove_url_filter_handle, cache, r,
195                             r->connection);
196
197                 }
198                 else {
199                     ap_log_rerror(APLOG_MARK, APLOG_DEBUG, rv,
200                             r, "Cache locked for url, not caching "
201                             "response: %s", r->uri);
202                 }
203             }
204             else {
205                 if (cache->stale_headers) {
206                     ap_log_rerror(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS,
207                             r, "Restoring request headers for %s",
208                             r->uri);
209
210                     r->headers_in = cache->stale_headers;
211                 }
212             }
213         }
214         else {
215             /* error */
216             return rv;
217         }
218         return DECLINED;
219     }
220
221     /* we've got a cache hit! tell everyone who cares */
222     cache_run_cache_status(cache->handle, r, r->headers_out, AP_CACHE_HIT,
223             "cache hit");
224
225     /* if we are a lookup, we are exiting soon one way or another; Restore
226      * the headers. */
227     if (lookup) {
228         if (cache->stale_headers) {
229             ap_log_rerror(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, r,
230                     "Restoring request headers.");
231             r->headers_in = cache->stale_headers;
232         }
233     }
234
235     rv = ap_meets_conditions(r);
236     if (rv != OK) {
237         /* If we are a lookup, we have to return DECLINED as we have no
238          * way of knowing if we will be able to serve the content.
239          */
240         if (lookup) {
241             return DECLINED;
242         }
243
244         /* Return cached status. */
245         return rv;
246     }
247
248     /* If we're a lookup, we can exit now instead of serving the content. */
249     if (lookup) {
250         return OK;
251     }
252
253     /* Serve up the content */
254
255     /* We are in the quick handler hook, which means that no output
256      * filters have been set. So lets run the insert_filter hook.
257      */
258     ap_run_insert_filter(r);
259
260     /*
261      * Add cache_out filter to serve this request. Choose
262      * the correct filter by checking if we are a subrequest
263      * or not.
264      */
265     if (r->main) {
266         cache_out_handle = cache_out_subreq_filter_handle;
267     }
268     else {
269         cache_out_handle = cache_out_filter_handle;
270     }
271     ap_add_output_filter_handle(cache_out_handle, cache, r, r->connection);
272
273     /*
274      * Remove all filters that are before the cache_out filter. This ensures
275      * that we kick off the filter stack with our cache_out filter being the
276      * first in the chain. This make sense because we want to restore things
277      * in the same manner as we saved them.
278      * There may be filters before our cache_out filter, because
279      *
280      * 1. We call ap_set_content_type during cache_select. This causes
281      *    Content-Type specific filters to be added.
282      * 2. We call the insert_filter hook. This causes filters e.g. like
283      *    the ones set with SetOutputFilter to be added.
284      */
285     next = r->output_filters;
286     while (next && (next->frec != cache_out_handle)) {
287         ap_remove_output_filter(next);
288         next = next->next;
289     }
290
291     /* kick off the filter stack */
292     out = apr_brigade_create(r->pool, r->connection->bucket_alloc);
293     e = apr_bucket_eos_create(out->bucket_alloc);
294     APR_BRIGADE_INSERT_TAIL(out, e);
295     rv = ap_pass_brigade(r->output_filters, out);
296     if (rv != APR_SUCCESS) {
297         if (rv != AP_FILTER_ERROR) {
298             /* no way to know what type of error occurred */
299             ap_log_rerror(APLOG_MARK, APLOG_DEBUG, rv, r,
300                           "cache_quick_handler(%s): ap_pass_brigade returned %i",
301                           cache->provider_name, rv);
302             return HTTP_INTERNAL_SERVER_ERROR;
303         }
304         return rv;
305     }
306
307     return OK;
308 }
309
310 /**
311  * If the two filter handles are present within the filter chain, replace
312  * the last instance of the first filter with the last instance of the
313  * second filter, and return true. If the second filter is not present at
314  * all, the first filter is removed, and false is returned. If neither
315  * filter is present, false is returned and this function does nothing.
316  * If a stop filter is specified, processing will stop once this filter is
317  * reached.
318  */
319 static int cache_replace_filter(ap_filter_t *next, ap_filter_rec_t *from,
320         ap_filter_rec_t *to, ap_filter_rec_t *stop) {
321     ap_filter_t *ffrom = NULL, *fto = NULL;
322     while (next && next->frec != stop) {
323         if (next->frec == from && !next->ctx) {
324             ffrom = next;
325         }
326         if (next->frec == to && !next->ctx) {
327             fto = next;
328         }
329         next = next->next;
330     }
331     if (ffrom && fto) {
332         ffrom->frec = fto->frec;
333         ffrom->ctx = fto->ctx;
334         ap_remove_output_filter(fto);
335         return 1;
336     }
337     if (ffrom) {
338         ap_remove_output_filter(ffrom);
339     }
340     return 0;
341 }
342
343 /**
344  * Find the given filter, and return it if found, or NULL otherwise.
345  */
346 static ap_filter_t *cache_get_filter(ap_filter_t *next, ap_filter_rec_t *rec) {
347     while (next) {
348         if (next->frec == rec && next->ctx) {
349             break;
350         }
351         next = next->next;
352     }
353     return next;
354 }
355
356 /**
357  * The cache handler is functionally similar to the cache_quick_hander,
358  * however a number of steps that are required by the quick handler are
359  * not required here, as the normal httpd processing has already handled
360  * these steps.
361  */
362 static int cache_handler(request_rec *r)
363 {
364     apr_status_t rv;
365     cache_provider_list *providers;
366     cache_request_rec *cache;
367     apr_bucket_brigade *out;
368     apr_bucket *e;
369     ap_filter_t *next;
370     ap_filter_rec_t *cache_out_handle;
371     ap_filter_rec_t *cache_save_handle;
372     cache_server_conf *conf;
373
374     conf = (cache_server_conf *) ap_get_module_config(r->server->module_config,
375                                                       &cache_module);
376
377     /* only run if the quick handler is disabled */
378     if (conf->quick) {
379         return DECLINED;
380     }
381
382     /*
383      * Which cache module (if any) should handle this request?
384      */
385     if (!(providers = cache_get_providers(r, conf, r->parsed_uri))) {
386         return DECLINED;
387     }
388
389     /* make space for the per request config */
390     cache = apr_pcalloc(r->pool, sizeof(cache_request_rec));
391     cache->size = -1;
392     cache->out = apr_brigade_create(r->pool, r->connection->bucket_alloc);
393
394     /* save away the possible providers */
395     cache->providers = providers;
396
397     /* Are we something other than GET or HEAD? If so, invalidate
398      * the cached entities.
399      */
400     if (r->method_number != M_GET) {
401
402         ap_log_rerror(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, r,
403                 "Invalidating all cached entities in response to '%s' request for %s",
404                 r->method, r->uri);
405
406         cache_invalidate(cache, r);
407
408         /* we've got a cache invalidate! tell everyone who cares */
409         cache_run_cache_status(cache->handle, r, r->headers_out,
410                 AP_CACHE_INVALIDATE, apr_psprintf(r->pool,
411                         "cache invalidated by %s", r->method));
412
413         return DECLINED;
414
415     }
416
417     /*
418      * Try to serve this request from the cache.
419      *
420      * If no existing cache file (DECLINED)
421      *   add cache_save filter
422      * If cached file (OK)
423      *   clear filter stack
424      *   add cache_out filter
425      *   return OK
426      */
427     rv = cache_select(cache, r);
428     if (rv != OK) {
429         if (rv == DECLINED) {
430
431             /* try to obtain a cache lock at this point. if we succeed,
432              * we are the first to try and cache this url. if we fail,
433              * it means someone else is already trying to cache this
434              * url, and we should just let the request through to the
435              * backend without any attempt to cache. this stops
436              * duplicated simultaneous attempts to cache an entity.
437              */
438             rv = cache_try_lock(conf, cache, r);
439             if (APR_SUCCESS == rv) {
440
441                 /*
442                  * Add cache_save filter to cache this request. Choose
443                  * the correct filter by checking if we are a subrequest
444                  * or not.
445                  */
446                 if (r->main) {
447                     ap_log_rerror(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS,
448                             r, "Adding CACHE_SAVE_SUBREQ filter for %s",
449                             r->uri);
450                     cache_save_handle = cache_save_subreq_filter_handle;
451                 }
452                 else {
453                     ap_log_rerror(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS,
454                             r, "Adding CACHE_SAVE filter for %s",
455                             r->uri);
456                     cache_save_handle = cache_save_filter_handle;
457                 }
458                 ap_add_output_filter_handle(cache_save_handle, cache, r,
459                         r->connection);
460
461                 /*
462                  * Did the user indicate the precise location of the
463                  * CACHE_SAVE filter by inserting the CACHE filter as a
464                  * marker?
465                  *
466                  * If so, we get cunning and replace CACHE with the
467                  * CACHE_SAVE filter. This has the effect of inserting
468                  * the CACHE_SAVE filter at the precise location where
469                  * the admin wants to cache the content. All filters that
470                  * lie before and after the original location of the CACHE
471                  * filter will remain in place.
472                  */
473                 if (cache_replace_filter(r->output_filters,
474                         cache_filter_handle, cache_save_handle,
475                         ap_get_input_filter_handle("SUBREQ_CORE"))) {
476                     ap_log_rerror(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS,
477                             r, "Replacing CACHE with CACHE_SAVE "
478                             "filter for %s", r->uri);
479                 }
480
481                 /* save away the save filter stack */
482                 cache->save_filter = cache_get_filter(r->output_filters,
483                         cache_save_filter_handle);
484
485                 apr_pool_userdata_setn(cache, CACHE_CTX_KEY, NULL, r->pool);
486
487                 ap_log_rerror(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, r,
488                         "Adding CACHE_REMOVE_URL filter for %s",
489                         r->uri);
490
491                 /* Add cache_remove_url filter to this request to remove a
492                  * stale cache entry if needed. Also put the current cache
493                  * request rec in the filter context, as the request that
494                  * is available later during running the filter may be
495                  * different due to an internal redirect.
496                  */
497                 cache->remove_url_filter
498                         = ap_add_output_filter_handle(
499                                 cache_remove_url_filter_handle, cache, r,
500                                 r->connection);
501
502             }
503             else {
504                 ap_log_rerror(APLOG_MARK, APLOG_DEBUG, rv,
505                         r, "Cache locked for url, not caching "
506                         "response: %s", r->uri);
507             }
508         }
509         else {
510             /* error */
511             return rv;
512         }
513         return DECLINED;
514     }
515
516     /* we've got a cache hit! tell everyone who cares */
517     cache_run_cache_status(cache->handle, r, r->headers_out, AP_CACHE_HIT,
518             "cache hit");
519
520     rv = ap_meets_conditions(r);
521     if (rv != OK) {
522         return rv;
523     }
524
525     /* Serve up the content */
526
527     /*
528      * Add cache_out filter to serve this request. Choose
529      * the correct filter by checking if we are a subrequest
530      * or not.
531      */
532     if (r->main) {
533         cache_out_handle = cache_out_subreq_filter_handle;
534     }
535     else {
536         cache_out_handle = cache_out_filter_handle;
537     }
538     ap_add_output_filter_handle(cache_out_handle, cache, r, r->connection);
539
540     /*
541      * Did the user indicate the precise location of the CACHE_OUT filter by
542      * inserting the CACHE filter as a marker?
543      *
544      * If so, we get cunning and replace CACHE with the CACHE_OUT filters.
545      * This has the effect of inserting the CACHE_OUT filter at the precise
546      * location where the admin wants to cache the content. All filters that
547      * lie *after* the original location of the CACHE filter will remain in
548      * place.
549      */
550     if (cache_replace_filter(r->output_filters, cache_filter_handle,
551             cache_out_handle, ap_get_input_filter_handle("SUBREQ_CORE"))) {
552         ap_log_rerror(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS,
553                 r, "Replacing CACHE with CACHE_OUT filter for %s",
554                 r->uri);
555     }
556
557     /*
558      * Remove all filters that are before the cache_out filter. This ensures
559      * that we kick off the filter stack with our cache_out filter being the
560      * first in the chain. This make sense because we want to restore things
561      * in the same manner as we saved them.
562      * There may be filters before our cache_out filter, because
563      *
564      * 1. We call ap_set_content_type during cache_select. This causes
565      *    Content-Type specific filters to be added.
566      * 2. We call the insert_filter hook. This causes filters e.g. like
567      *    the ones set with SetOutputFilter to be added.
568      */
569     next = r->output_filters;
570     while (next && (next->frec != cache_out_handle)) {
571         ap_remove_output_filter(next);
572         next = next->next;
573     }
574
575     /* kick off the filter stack */
576     out = apr_brigade_create(r->pool, r->connection->bucket_alloc);
577     e = apr_bucket_eos_create(out->bucket_alloc);
578     APR_BRIGADE_INSERT_TAIL(out, e);
579     rv = ap_pass_brigade(r->output_filters, out);
580     if (rv != APR_SUCCESS) {
581         if (rv != AP_FILTER_ERROR) {
582             /* no way to know what type of error occurred */
583             ap_log_rerror(APLOG_MARK, APLOG_DEBUG, rv, r,
584                           "cache_handler(%s): ap_pass_brigade returned %i",
585                           cache->provider_name, rv);
586             return HTTP_INTERNAL_SERVER_ERROR;
587         }
588         return rv;
589     }
590
591     return OK;
592 }
593
594 /*
595  * CACHE_OUT filter
596  * ----------------
597  *
598  * Deliver cached content (headers and body) up the stack.
599  */
600 static int cache_out_filter(ap_filter_t *f, apr_bucket_brigade *in)
601 {
602     request_rec *r = f->r;
603     apr_bucket *e;
604     cache_request_rec *cache = (cache_request_rec *)f->ctx;
605
606     if (!cache) {
607         /* user likely configured CACHE_OUT manually; they should use mod_cache
608          * configuration to do that */
609         ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
610                 "CACHE/CACHE_OUT filter enabled while caching is disabled, ignoring");
611         ap_remove_output_filter(f);
612         return ap_pass_brigade(f->next, in);
613     }
614
615     ap_log_rerror(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, r,
616             "cache: running CACHE_OUT filter");
617
618     /* clean out any previous response up to EOS, if any */
619     for (e = APR_BRIGADE_FIRST(in);
620          e != APR_BRIGADE_SENTINEL(in);
621          e = APR_BUCKET_NEXT(e))
622     {
623         if (APR_BUCKET_IS_EOS(e)) {
624             apr_bucket_brigade *bb = apr_brigade_create(r->pool,
625                     r->connection->bucket_alloc);
626
627             /* restore status of cached response */
628             r->status = cache->handle->cache_obj->info.status;
629
630             /* recall_headers() was called in cache_select() */
631             cache->provider->recall_body(cache->handle, r->pool, bb);
632             APR_BRIGADE_PREPEND(in, bb);
633
634             /* This filter is done once it has served up its content */
635             ap_remove_output_filter(f);
636
637             ap_log_rerror(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, r,
638                     "cache: serving %s", r->uri);
639             return ap_pass_brigade(f->next, in);
640
641         }
642         apr_bucket_delete(e);
643     }
644
645     return APR_SUCCESS;
646 }
647
648 /*
649  * Having jumped through all the hoops and decided to cache the
650  * response, call store_body() for each brigade, handling the
651  * case where the provider can't swallow the full brigade. In this
652  * case, we write the brigade we were passed out downstream, and
653  * loop around to try and cache some more until the in brigade is
654  * completely empty. As soon as the out brigade contains eos, call
655  * commit_entity() to finalise the cached element.
656  */
657 static int cache_save_store(ap_filter_t *f, apr_bucket_brigade *in,
658         cache_server_conf *conf, cache_request_rec *cache)
659 {
660     int rv = APR_SUCCESS;
661     apr_bucket *e;
662
663     /* pass the brigade in into the cache provider, which is then
664      * expected to move cached buckets to the out brigade, for us
665      * to pass up the filter stack. repeat until in is empty, or
666      * we fail.
667      */
668     while (APR_SUCCESS == rv && !APR_BRIGADE_EMPTY(in)) {
669
670         rv = cache->provider->store_body(cache->handle, f->r, in, cache->out);
671         if (rv != APR_SUCCESS) {
672             ap_log_rerror(APLOG_MARK, APLOG_DEBUG, rv, f->r,
673                     "cache: Cache provider's store_body failed!");
674             ap_remove_output_filter(f);
675
676             /* give someone else the chance to cache the file */
677             cache_remove_lock(conf, cache, f->r, NULL);
678
679             /* give up trying to cache, just step out the way */
680             APR_BRIGADE_PREPEND(in, cache->out);
681             return ap_pass_brigade(f->next, in);
682
683         }
684
685         /* does the out brigade contain eos? if so, we're done, commit! */
686         for (e = APR_BRIGADE_FIRST(cache->out);
687              e != APR_BRIGADE_SENTINEL(cache->out);
688              e = APR_BUCKET_NEXT(e))
689         {
690             if (APR_BUCKET_IS_EOS(e)) {
691                 rv = cache->provider->commit_entity(cache->handle, f->r);
692                 break;
693             }
694         }
695
696         /* conditionally remove the lock as soon as we see the eos bucket */
697         cache_remove_lock(conf, cache, f->r, cache->out);
698
699         if (APR_BRIGADE_EMPTY(cache->out)) {
700             if (APR_BRIGADE_EMPTY(in)) {
701                 /* cache provider wants more data before passing the brigade
702                  * upstream, oblige the provider by leaving to fetch more.
703                  */
704                 break;
705             }
706             else {
707                 /* oops, no data out, but not all data read in either, be
708                  * safe and stand down to prevent a spin.
709                  */
710                 ap_log_rerror(APLOG_MARK, APLOG_WARNING, rv, f->r,
711                         "cache: Cache provider's store_body returned an "
712                         "empty brigade, but didn't consume all of the"
713                         "input brigade, standing down to prevent a spin");
714                 ap_remove_output_filter(f);
715
716                 /* give someone else the chance to cache the file */
717                 cache_remove_lock(conf, cache, f->r, NULL);
718
719                 return ap_pass_brigade(f->next, in);
720             }
721         }
722
723         rv = ap_pass_brigade(f->next, cache->out);
724     }
725
726     return rv;
727 }
728
729 /*
730  * CACHE_SAVE filter
731  * ---------------
732  *
733  * Decide whether or not this content should be cached.
734  * If we decide no it should not:
735  *   remove the filter from the chain
736  * If we decide yes it should:
737  *   Have we already started saving the response?
738  *      If we have started, pass the data to the storage manager via store_body
739  *      Otherwise:
740  *        Check to see if we *can* save this particular response.
741  *        If we can, call cache_create_entity() and save the headers and body
742  *   Finally, pass the data to the next filter (the network or whatever)
743  *
744  * After the various failure cases, the cache lock is proactively removed, so
745  * that another request is given the opportunity to attempt to cache without
746  * waiting for a potentially slow client to acknowledge the failure.
747  */
748
749 static int cache_save_filter(ap_filter_t *f, apr_bucket_brigade *in)
750 {
751     int rv = !OK;
752     request_rec *r = f->r;
753     cache_request_rec *cache = (cache_request_rec *)f->ctx;
754     cache_server_conf *conf;
755     cache_dir_conf *dconf;
756     cache_control_t control;
757     const char *cc_out, *cl, *pragma;
758     const char *exps, *lastmods, *dates, *etag;
759     apr_time_t exp, date, lastmod, now;
760     apr_off_t size = -1;
761     cache_info *info = NULL;
762     char *reason;
763     apr_pool_t *p;
764     apr_bucket *e;
765     apr_table_t *headers;
766
767     conf = (cache_server_conf *) ap_get_module_config(r->server->module_config,
768                                                       &cache_module);
769
770     /* Setup cache_request_rec */
771     if (!cache) {
772         /* user likely configured CACHE_SAVE manually; they should really use
773          * mod_cache configuration to do that
774          */
775         ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
776                 "CACHE/CACHE_SAVE filter enabled while caching is disabled, ignoring");
777         ap_remove_output_filter(f);
778         return ap_pass_brigade(f->next, in);
779     }
780
781     reason = NULL;
782     p = r->pool;
783     /*
784      * Pass Data to Cache
785      * ------------------
786      * This section passes the brigades into the cache modules, but only
787      * if the setup section (see below) is complete.
788      */
789     if (cache->block_response) {
790         /* We've already sent down the response and EOS.  So, ignore
791          * whatever comes now.
792          */
793         return APR_SUCCESS;
794     }
795
796     /* have we already run the cacheability check and set up the
797      * cached file handle?
798      */
799     if (cache->in_checked) {
800         return cache_save_store(f, in, conf, cache);
801     }
802
803     /*
804      * Setup Data in Cache
805      * -------------------
806      * This section opens the cache entity and sets various caching
807      * parameters, and decides whether this URL should be cached at
808      * all. This section is* run before the above section.
809      */
810
811     dconf = ap_get_module_config(r->per_dir_config, &cache_module);
812
813     /* RFC2616 13.8 Errors or Incomplete Response Cache Behavior:
814      * If a cache receives a 5xx response while attempting to revalidate an
815      * entry, it MAY either forward this response to the requesting client,
816      * or act as if the server failed to respond. In the latter case, it MAY
817      * return a previously received response unless the cached entry
818      * includes the "must-revalidate" cache-control directive (see section
819      * 14.9).
820      *
821      * This covers the case where an error was generated behind us, for example
822      * by a backend server via mod_proxy.
823      */
824     if (dconf->stale_on_error && r->status >= HTTP_INTERNAL_SERVER_ERROR) {
825
826         ap_remove_output_filter(cache->remove_url_filter);
827
828         if (cache->stale_handle
829                 && !cache->stale_handle->cache_obj->info.control.must_revalidate
830                 && !cache->stale_handle->cache_obj->info.control.proxy_revalidate) {
831             const char *warn_head;
832
833             /* morph the current save filter into the out filter, and serve from
834              * cache.
835              */
836             cache->handle = cache->stale_handle;
837             if (r->main) {
838                 f->frec = cache_out_subreq_filter_handle;
839             }
840             else {
841                 f->frec = cache_out_filter_handle;
842             }
843
844             r->headers_out = cache->stale_handle->resp_hdrs;
845
846             /* add a revalidation warning */
847             warn_head = apr_table_get(r->err_headers_out, "Warning");
848             if ((warn_head == NULL) || ((warn_head != NULL)
849                     && (ap_strstr_c(warn_head, "111") == NULL))) {
850                 apr_table_mergen(r->err_headers_out, "Warning",
851                         "111 Revalidation failed");
852             }
853
854             cache_run_cache_status(cache->handle, r, r->headers_out, AP_CACHE_HIT,
855                     apr_psprintf(r->pool,
856                             "cache hit: %d status; stale content returned",
857                             r->status));
858
859             /* give someone else the chance to cache the file */
860             cache_remove_lock(conf, cache, f->r, NULL);
861
862             /* pass brigade to our morphed out filter */
863             return ap_pass_brigade(f, in);
864         }
865     }
866
867     /* read expiry date; if a bad date, then leave it so the client can
868      * read it
869      */
870     exps = apr_table_get(r->err_headers_out, "Expires");
871     if (exps == NULL) {
872         exps = apr_table_get(r->headers_out, "Expires");
873     }
874     if (exps != NULL) {
875         exp = apr_date_parse_http(exps);
876     }
877     else {
878         exp = APR_DATE_BAD;
879     }
880
881     /* read the last-modified date; if the date is bad, then delete it */
882     lastmods = apr_table_get(r->err_headers_out, "Last-Modified");
883     if (lastmods == NULL) {
884         lastmods = apr_table_get(r->headers_out, "Last-Modified");
885     }
886     if (lastmods != NULL) {
887         lastmod = apr_date_parse_http(lastmods);
888         if (lastmod == APR_DATE_BAD) {
889             lastmods = NULL;
890         }
891     }
892     else {
893         lastmod = APR_DATE_BAD;
894     }
895
896     /* read the etag and cache-control from the entity */
897     etag = apr_table_get(r->err_headers_out, "Etag");
898     if (etag == NULL) {
899         etag = apr_table_get(r->headers_out, "Etag");
900     }
901     cc_out = apr_table_get(r->err_headers_out, "Cache-Control");
902     pragma = apr_table_get(r->err_headers_out, "Pragma");
903     headers = r->err_headers_out;
904     if (!cc_out && !pragma) {
905         cc_out = apr_table_get(r->headers_out, "Cache-Control");
906         pragma = apr_table_get(r->headers_out, "Pragma");
907         headers = r->headers_out;
908     }
909
910     /* Have we received a 304 response without any headers at all? Fall back to
911      * the original headers in the original cached request.
912      */
913     if (r->status == HTTP_NOT_MODIFIED && cache->stale_handle && !cc_out
914             && !pragma) {
915         cc_out = apr_table_get(cache->stale_handle->resp_hdrs, "Cache-Control");
916         pragma = apr_table_get(cache->stale_handle->resp_hdrs, "Pragma");
917     }
918
919     /* Parse the cache control header */
920     memset(&control, 0, sizeof(cache_control_t));
921     ap_cache_control(r, &control, cc_out, pragma, headers);
922
923     /*
924      * what responses should we not cache?
925      *
926      * At this point we decide based on the response headers whether it
927      * is appropriate _NOT_ to cache the data from the server. There are
928      * a whole lot of conditions that prevent us from caching this data.
929      * They are tested here one by one to be clear and unambiguous.
930      */
931     if (r->status != HTTP_OK && r->status != HTTP_NON_AUTHORITATIVE
932         && r->status != HTTP_PARTIAL_CONTENT
933         && r->status != HTTP_MULTIPLE_CHOICES
934         && r->status != HTTP_MOVED_PERMANENTLY
935         && r->status != HTTP_NOT_MODIFIED) {
936         /* RFC2616 13.4 we are allowed to cache 200, 203, 206, 300, 301 or 410
937          * We allow the caching of 206, but a cache implementation might choose
938          * to decline to cache a 206 if it doesn't know how to.
939          * We include 304 Not Modified here too as this is the origin server
940          * telling us to serve the cached copy.
941          */
942         if (exps != NULL || cc_out != NULL) {
943             /* We are also allowed to cache any response given that it has a
944              * valid Expires or Cache Control header. If we find a either of
945              * those here,  we pass request through the rest of the tests. From
946              * the RFC:
947              *
948              * A response received with any other status code (e.g. status
949              * codes 302 and 307) MUST NOT be returned in a reply to a
950              * subsequent request unless there are cache-control directives or
951              * another header(s) that explicitly allow it. For example, these
952              * include the following: an Expires header (section 14.21); a
953              * "max-age", "s-maxage",  "must-revalidate", "proxy-revalidate",
954              * "public" or "private" cache-control directive (section 14.9).
955              */
956         }
957         else {
958             reason = apr_psprintf(p, "Response status %d", r->status);
959         }
960     }
961
962     if (reason) {
963         /* noop */
964     }
965     else if (exps != NULL && exp == APR_DATE_BAD) {
966         /* if a broken Expires header is present, don't cache it */
967         reason = apr_pstrcat(p, "Broken expires header: ", exps, NULL);
968     }
969     else if (!dconf->store_expired && exp != APR_DATE_BAD
970             && exp < r->request_time) {
971         /* if a Expires header is in the past, don't cache it */
972         reason = "Expires header already expired; not cacheable";
973     }
974     else if (!dconf->store_expired && (control.must_revalidate
975             || control.proxy_revalidate) && (!control.s_maxage_value
976             || (!control.s_maxage && !control.max_age_value)) && lastmods
977             == NULL && etag == NULL) {
978         /* if we're already stale, but can never revalidate, don't cache it */
979         reason
980                 = "s-maxage or max-age zero and no Last-Modified or Etag; not cacheable";
981     }
982     else if (!conf->ignorequerystring && r->parsed_uri.query && exps == NULL
983             && !control.max_age && !control.s_maxage) {
984         /* if a query string is present but no explicit expiration time,
985          * don't cache it (RFC 2616/13.9 & 13.2.1)
986          */
987         reason = "Query string present but no explicit expiration time";
988     }
989     else if (r->status == HTTP_NOT_MODIFIED &&
990              !cache->handle && !cache->stale_handle) {
991         /* if the server said 304 Not Modified but we have no cache
992          * file - pass this untouched to the user agent, it's not for us.
993          */
994         reason = "HTTP Status 304 Not Modified";
995     }
996     else if (r->status == HTTP_OK && lastmods == NULL && etag == NULL && (exps
997             == NULL) && (dconf->no_last_mod_ignore == 0) && !control.max_age
998             && !control.s_maxage) {
999         /* 200 OK response from HTTP/1.0 and up without Last-Modified,
1000          * Etag, Expires, Cache-Control:max-age, or Cache-Control:s-maxage
1001          * headers.
1002          */
1003         /* Note: mod-include clears last_modified/expires/etags - this
1004          * is why we have an optional function for a key-gen ;-)
1005          */
1006         reason = "No Last-Modified; Etag; Expires; Cache-Control:max-age or Cache-Control:s-maxage headers";
1007     }
1008     else if (!dconf->store_nostore && control.no_store) {
1009         /* RFC2616 14.9.2 Cache-Control: no-store response
1010          * indicating do not cache, or stop now if you are
1011          * trying to cache it.
1012          */
1013         reason = "Cache-Control: no-store present";
1014     }
1015     else if (!dconf->store_private && control.private) {
1016         /* RFC2616 14.9.1 Cache-Control: private response
1017          * this object is marked for this user's eyes only. Behave
1018          * as a tunnel.
1019          */
1020         reason = "Cache-Control: private present";
1021     }
1022     else if (apr_table_get(r->headers_in, "Authorization")
1023             && !(control.s_maxage || control.must_revalidate
1024                     || control.proxy_revalidate || control.public)) {
1025         /* RFC2616 14.8 Authorisation:
1026          * if authorisation is included in the request, we don't cache,
1027          * but we can cache if the following exceptions are true:
1028          * 1) If Cache-Control: s-maxage is included
1029          * 2) If Cache-Control: must-revalidate is included
1030          * 3) If Cache-Control: public is included
1031          */
1032         reason = "Authorization required";
1033     }
1034     else if (ap_cache_liststr(NULL,
1035                               apr_table_get(r->headers_out, "Vary"),
1036                               "*", NULL)) {
1037         reason = "Vary header contains '*'";
1038     }
1039     else if (apr_table_get(r->subprocess_env, "no-cache") != NULL) {
1040         reason = "environment variable 'no-cache' is set";
1041     }
1042     else if (r->no_cache) {
1043         /* or we've been asked not to cache it above */
1044         reason = "r->no_cache present";
1045     }
1046
1047     /* Hold the phone. Some servers might allow us to cache a 2xx, but
1048      * then make their 304 responses non cacheable. This leaves us in a
1049      * sticky position. If the 304 is in answer to our own conditional
1050      * request, we cannot send this 304 back to the client because the
1051      * client isn't expecting it. Instead, our only option is to respect
1052      * the answer to the question we asked (has it changed, answer was
1053      * no) and return the cached item to the client, and then respect
1054      * the uncacheable nature of this 304 by allowing the remove_url
1055      * filter to kick in and remove the cached entity.
1056      */
1057     if (reason && r->status == HTTP_NOT_MODIFIED &&
1058              cache->stale_handle) {
1059         apr_bucket_brigade *bb;
1060         apr_bucket *bkt;
1061         int status;
1062
1063         cache->handle = cache->stale_handle;
1064         info = &cache->handle->cache_obj->info;
1065
1066         /* Load in the saved status and clear the status line. */
1067         r->status = info->status;
1068         r->status_line = NULL;
1069
1070         bb = apr_brigade_create(r->pool, r->connection->bucket_alloc);
1071
1072         r->headers_in = cache->stale_headers;
1073         status = ap_meets_conditions(r);
1074         if (status != OK) {
1075             r->status = status;
1076
1077             bkt = apr_bucket_flush_create(bb->bucket_alloc);
1078             APR_BRIGADE_INSERT_TAIL(bb, bkt);
1079         }
1080         else {
1081             cache->provider->recall_body(cache->handle, r->pool, bb);
1082
1083             bkt = apr_bucket_eos_create(bb->bucket_alloc);
1084             APR_BRIGADE_INSERT_TAIL(bb, bkt);
1085         }
1086
1087         cache->block_response = 1;
1088
1089         /* we've got a cache conditional hit! tell anyone who cares */
1090         cache_run_cache_status(
1091                 cache->handle,
1092                 r,
1093                 r->headers_out,
1094                 AP_CACHE_REVALIDATE,
1095                 apr_psprintf(
1096                         r->pool,
1097                         "conditional cache hit: 304 was uncacheable though (%s); entity removed",
1098                         reason));
1099
1100         /* let someone else attempt to cache */
1101         cache_remove_lock(conf, cache, r, NULL);
1102
1103         return ap_pass_brigade(f->next, bb);
1104     }
1105
1106     if (reason) {
1107         ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
1108                 "cache: %s not cached. Reason: %s", r->unparsed_uri,
1109                 reason);
1110
1111         /* we've got a cache miss! tell anyone who cares */
1112         cache_run_cache_status(cache->handle, r, r->headers_out, AP_CACHE_MISS,
1113                 reason);
1114
1115         /* remove this filter from the chain */
1116         ap_remove_output_filter(f);
1117
1118         /* remove the lock file unconditionally */
1119         cache_remove_lock(conf, cache, r, NULL);
1120
1121         /* ship the data up the stack */
1122         return ap_pass_brigade(f->next, in);
1123     }
1124
1125     /* Make it so that we don't execute this path again. */
1126     cache->in_checked = 1;
1127
1128     /* Set the content length if known.
1129      */
1130     cl = apr_table_get(r->err_headers_out, "Content-Length");
1131     if (cl == NULL) {
1132         cl = apr_table_get(r->headers_out, "Content-Length");
1133     }
1134     if (cl) {
1135         char *errp;
1136         if (apr_strtoff(&size, cl, &errp, 10) || *errp || size < 0) {
1137             cl = NULL; /* parse error, see next 'if' block */
1138         }
1139     }
1140
1141     if (!cl) {
1142         /* if we don't get the content-length, see if we have all the
1143          * buckets and use their length to calculate the size
1144          */
1145         int all_buckets_here=0;
1146         size=0;
1147         for (e = APR_BRIGADE_FIRST(in);
1148              e != APR_BRIGADE_SENTINEL(in);
1149              e = APR_BUCKET_NEXT(e))
1150         {
1151             if (APR_BUCKET_IS_EOS(e)) {
1152                 all_buckets_here=1;
1153                 break;
1154             }
1155             if (APR_BUCKET_IS_FLUSH(e)) {
1156                 continue;
1157             }
1158             if (e->length == (apr_size_t)-1) {
1159                 break;
1160             }
1161             size += e->length;
1162         }
1163         if (!all_buckets_here) {
1164             size = -1;
1165         }
1166     }
1167
1168     /* remember content length to check response size against later */
1169     cache->size = size;
1170
1171     /* It's safe to cache the response.
1172      *
1173      * There are two possiblities at this point:
1174      * - cache->handle == NULL. In this case there is no previously
1175      * cached entity anywhere on the system. We must create a brand
1176      * new entity and store the response in it.
1177      * - cache->stale_handle != NULL. In this case there is a stale
1178      * entity in the system which needs to be replaced by new
1179      * content (unless the result was 304 Not Modified, which means
1180      * the cached entity is actually fresh, and we should update
1181      * the headers).
1182      */
1183
1184     /* Did we have a stale cache entry that really is stale?
1185      */
1186     if (cache->stale_handle) {
1187         if (r->status == HTTP_NOT_MODIFIED) {
1188             /* Oh, hey.  It isn't that stale!  Yay! */
1189             cache->handle = cache->stale_handle;
1190             info = &cache->handle->cache_obj->info;
1191             rv = OK;
1192         }
1193         else {
1194             /* Oh, well.  Toss it. */
1195             cache->provider->remove_entity(cache->stale_handle);
1196             /* Treat the request as if it wasn't conditional. */
1197             cache->stale_handle = NULL;
1198             /*
1199              * Restore the original request headers as they may be needed
1200              * by further output filters like the byterange filter to make
1201              * the correct decisions.
1202              */
1203             r->headers_in = cache->stale_headers;
1204         }
1205     }
1206
1207     /* no cache handle, create a new entity */
1208     if (!cache->handle) {
1209         rv = cache_create_entity(cache, r, size, in);
1210         info = apr_pcalloc(r->pool, sizeof(cache_info));
1211         /* We only set info->status upon the initial creation. */
1212         info->status = r->status;
1213     }
1214
1215     if (rv != OK) {
1216         /* we've got a cache miss! tell anyone who cares */
1217         cache_run_cache_status(cache->handle, r, r->headers_out, AP_CACHE_MISS,
1218                 "cache miss: create_entity failed");
1219
1220         /* Caching layer declined the opportunity to cache the response */
1221         ap_remove_output_filter(f);
1222         cache_remove_lock(conf, cache, r, NULL);
1223         return ap_pass_brigade(f->next, in);
1224     }
1225
1226     ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
1227             "cache: Caching url: %s", r->unparsed_uri);
1228
1229     /* We are actually caching this response. So it does not
1230      * make sense to remove this entity any more.
1231      */
1232     ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
1233             "cache: Removing CACHE_REMOVE_URL filter.");
1234     ap_remove_output_filter(cache->remove_url_filter);
1235
1236     /*
1237      * We now want to update the cache file header information with
1238      * the new date, last modified, expire and content length and write
1239      * it away to our cache file. First, we determine these values from
1240      * the response, using heuristics if appropriate.
1241      *
1242      * In addition, we make HTTP/1.1 age calculations and write them away
1243      * too.
1244      */
1245
1246     /* store away the previously parsed cache control headers */
1247     memcpy(&info->control, &control, sizeof(cache_control_t));
1248
1249     /* Read the date. Generate one if one is not supplied */
1250     dates = apr_table_get(r->err_headers_out, "Date");
1251     if (dates == NULL) {
1252         dates = apr_table_get(r->headers_out, "Date");
1253     }
1254     if (dates != NULL) {
1255         info->date = apr_date_parse_http(dates);
1256     }
1257     else {
1258         info->date = APR_DATE_BAD;
1259     }
1260
1261     now = apr_time_now();
1262     if (info->date == APR_DATE_BAD) {  /* No, or bad date */
1263         /* no date header (or bad header)! */
1264         info->date = now;
1265     }
1266     date = info->date;
1267
1268     /* set response_time for HTTP/1.1 age calculations */
1269     info->response_time = now;
1270
1271     /* get the request time */
1272     info->request_time = r->request_time;
1273
1274     /* check last-modified date */
1275     if (lastmod != APR_DATE_BAD && lastmod > date) {
1276         /* if it's in the future, then replace by date */
1277         lastmod = date;
1278         lastmods = dates;
1279         ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0,
1280                 r, "cache: Last modified is in the future, "
1281                 "replacing with now");
1282     }
1283
1284     /* if no expiry date then
1285      *   if Cache-Control: max-age
1286      *      expiry date = date + max-age
1287      *   else if lastmod
1288      *      expiry date = date + min((date - lastmod) * factor, maxexpire)
1289      *   else
1290      *      expire date = date + defaultexpire
1291      */
1292     if (exp == APR_DATE_BAD) {
1293
1294         if (control.max_age) {
1295             apr_int64_t x;
1296
1297             errno = 0;
1298             x = control.max_age_value;
1299             if (errno) {
1300                 x = dconf->defex;
1301             }
1302             else {
1303                 x = x * MSEC_ONE_SEC;
1304             }
1305             if (x < dconf->minex) {
1306                 x = dconf->minex;
1307             }
1308             if (x > dconf->maxex) {
1309                 x = dconf->maxex;
1310             }
1311             exp = date + x;
1312         }
1313         else if ((lastmod != APR_DATE_BAD) && (lastmod < date)) {
1314             /* if lastmod == date then you get 0*conf->factor which results in
1315              * an expiration time of now. This causes some problems with
1316              * freshness calculations, so we choose the else path...
1317              */
1318             apr_time_t x = (apr_time_t) ((date - lastmod) * dconf->factor);
1319
1320             if (x < dconf->minex) {
1321                 x = dconf->minex;
1322             }
1323             if (x > dconf->maxex) {
1324                 x = dconf->maxex;
1325             }
1326             exp = date + x;
1327         }
1328         else {
1329             exp = date + dconf->defex;
1330         }
1331     }
1332     info->expire = exp;
1333
1334     /* We found a stale entry which wasn't really stale. */
1335     if (cache->stale_handle) {
1336         /* Load in the saved status and clear the status line. */
1337         r->status = info->status;
1338         r->status_line = NULL;
1339
1340         /* RFC 2616 10.3.5 states that entity headers are not supposed
1341          * to be in the 304 response.  Therefore, we need to combine the
1342          * response headers with the cached headers *before* we update
1343          * the cached headers.
1344          *
1345          * However, before doing that, we need to first merge in
1346          * err_headers_out and we also need to strip any hop-by-hop
1347          * headers that might have snuck in.
1348          */
1349         r->headers_out = ap_cache_cacheable_headers_out(r);
1350
1351         /* Merge in our cached headers.  However, keep any updated values. */
1352         cache_accept_headers(cache->handle, r, 1);
1353     }
1354
1355     /* Write away header information to cache. It is possible that we are
1356      * trying to update headers for an entity which has already been cached.
1357      *
1358      * This may fail, due to an unwritable cache area. E.g. filesystem full,
1359      * permissions problems or a read-only (re)mount. This must be handled
1360      * later.
1361      */
1362     rv = cache->provider->store_headers(cache->handle, r, info);
1363
1364     /* Did we just update the cached headers on a revalidated response?
1365      *
1366      * If so, we can now decide what to serve to the client.  This is done in
1367      * the same way as with a regular response, but conditions are now checked
1368      * against the cached or merged response headers.
1369      */
1370     if (cache->stale_handle) {
1371         apr_bucket_brigade *bb;
1372         apr_bucket *bkt;
1373         int status;
1374
1375         /* We're just saving response headers, so we are done. Commit
1376          * the response at this point, unless there was a previous error.
1377          */
1378         if (rv == APR_SUCCESS) {
1379             rv = cache->provider->commit_entity(cache->handle, r);
1380         }
1381
1382         bb = apr_brigade_create(r->pool, r->connection->bucket_alloc);
1383
1384         /* Restore the original request headers and see if we need to
1385          * return anything else than the cached response (ie. the original
1386          * request was conditional).
1387          */
1388         r->headers_in = cache->stale_headers;
1389         status = ap_meets_conditions(r);
1390         if (status != OK) {
1391             r->status = status;
1392
1393             bkt = apr_bucket_flush_create(bb->bucket_alloc);
1394             APR_BRIGADE_INSERT_TAIL(bb, bkt);
1395         }
1396         else {
1397             cache->provider->recall_body(cache->handle, r->pool, bb);
1398
1399             bkt = apr_bucket_eos_create(bb->bucket_alloc);
1400             APR_BRIGADE_INSERT_TAIL(bb, bkt);
1401         }
1402
1403         cache->block_response = 1;
1404
1405         /* Before returning we need to handle the possible case of an
1406          * unwritable cache. Rather than leaving the entity in the cache
1407          * and having it constantly re-validated, now that we have recalled
1408          * the body it is safe to try and remove the url from the cache.
1409          */
1410         if (rv != APR_SUCCESS) {
1411             ap_log_rerror(APLOG_MARK, APLOG_DEBUG, rv, r,
1412                     "cache: updating headers with store_headers failed. "
1413                     "Removing cached url.");
1414
1415             rv = cache->provider->remove_url(cache->stale_handle, r);
1416             if (rv != OK) {
1417                 /* Probably a mod_cache_disk cache area has been (re)mounted
1418                  * read-only, or that there is a permissions problem.
1419                  */
1420                 ap_log_rerror(APLOG_MARK, APLOG_DEBUG, rv, r,
1421                         "cache: attempt to remove url from cache unsuccessful.");
1422             }
1423
1424             /* we've got a cache conditional hit! tell anyone who cares */
1425             cache_run_cache_status(cache->handle, r, r->headers_out,
1426                     AP_CACHE_REVALIDATE,
1427                     "conditional cache hit: entity refresh failed");
1428
1429         }
1430         else {
1431
1432             /* we've got a cache conditional hit! tell anyone who cares */
1433             cache_run_cache_status(cache->handle, r, r->headers_out,
1434                     AP_CACHE_REVALIDATE,
1435                     "conditional cache hit: entity refreshed");
1436
1437         }
1438
1439         /* let someone else attempt to cache */
1440         cache_remove_lock(conf, cache, r, NULL);
1441
1442         return ap_pass_brigade(f->next, bb);
1443     }
1444
1445     if (rv != APR_SUCCESS) {
1446         ap_log_rerror(APLOG_MARK, APLOG_DEBUG, rv, r,
1447                 "cache: store_headers failed");
1448
1449         /* we've got a cache miss! tell anyone who cares */
1450         cache_run_cache_status(cache->handle, r, r->headers_out, AP_CACHE_MISS,
1451                 "cache miss: store_headers failed");
1452
1453         ap_remove_output_filter(f);
1454         cache_remove_lock(conf, cache, r, NULL);
1455         return ap_pass_brigade(f->next, in);
1456     }
1457
1458     /* we've got a cache miss! tell anyone who cares */
1459     cache_run_cache_status(cache->handle, r, r->headers_out, AP_CACHE_MISS,
1460             "cache miss: attempting entity save");
1461
1462     return cache_save_store(f, in, conf, cache);
1463 }
1464
1465 /*
1466  * CACHE_REMOVE_URL filter
1467  * -----------------------
1468  *
1469  * This filter gets added in the quick handler every time the CACHE_SAVE filter
1470  * gets inserted. Its purpose is to remove a confirmed stale cache entry from
1471  * the cache.
1472  *
1473  * CACHE_REMOVE_URL has to be a protocol filter to ensure that is run even if
1474  * the response is a canned error message, which removes the content filters
1475  * and thus the CACHE_SAVE filter from the chain.
1476  *
1477  * CACHE_REMOVE_URL expects cache request rec within its context because the
1478  * request this filter runs on can be different from the one whose cache entry
1479  * should be removed, due to internal redirects.
1480  *
1481  * Note that CACHE_SAVE_URL (as a content-set filter, hence run before the
1482  * protocol filters) will remove this filter if it decides to cache the file.
1483  * Therefore, if this filter is left in, it must mean we need to toss any
1484  * existing files.
1485  */
1486 static int cache_remove_url_filter(ap_filter_t *f, apr_bucket_brigade *in)
1487 {
1488     request_rec *r = f->r;
1489     cache_request_rec *cache;
1490
1491     /* Setup cache_request_rec */
1492     cache = (cache_request_rec *) f->ctx;
1493
1494     if (!cache) {
1495         /* user likely configured CACHE_REMOVE_URL manually; they should really
1496          * use mod_cache configuration to do that. So:
1497          * 1. Remove ourselves
1498          * 2. Do nothing and bail out
1499          */
1500         ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
1501                 "cache: CACHE_REMOVE_URL enabled unexpectedly");
1502         ap_remove_output_filter(f);
1503         return ap_pass_brigade(f->next, in);
1504     }
1505
1506     /* Now remove this cache entry from the cache */
1507     cache_remove_url(cache, r);
1508
1509     /* remove ourselves */
1510     ap_remove_output_filter(f);
1511     return ap_pass_brigade(f->next, in);
1512 }
1513
1514 /*
1515  * CACHE filter
1516  * ------------
1517  *
1518  * This filter can be optionally inserted into the filter chain by the admin as
1519  * a marker representing the precise location within the filter chain where
1520  * caching is to be performed.
1521  *
1522  * When the filter chain is set up in the non-quick version of the URL handler,
1523  * the CACHE filter is replaced by the CACHE_OUT or CACHE_SAVE filter,
1524  * effectively inserting the caching filters at the point indicated by the
1525  * admin. The CACHE filter is then removed.
1526  *
1527  * This allows caching to be performed before the content is passed to the
1528  * INCLUDES filter, or to a filter that might perform transformations unique
1529  * to the specific request and that would otherwise be non-cacheable.
1530  */
1531 static int cache_filter(ap_filter_t *f, apr_bucket_brigade *in)
1532 {
1533     /* we are just a marker, so let's just remove ourselves */
1534     ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, f->r,
1535             "cache: CACHE filter was added twice, or was added in quick "
1536             "handler mode and will be ignored.");
1537     ap_remove_output_filter(f);
1538     return ap_pass_brigade(f->next, in);
1539 }
1540
1541 /**
1542  * If configured, add the status of the caching attempt to the subprocess
1543  * environment, and if configured, to headers in the response.
1544  *
1545  * The status is saved below the broad category of the status (hit, miss,
1546  * revalidate), as well as a single cache-status key. This can be used for
1547  * conditional logging.
1548  *
1549  * The status is optionally saved to an X-Cache header, and the detail of
1550  * why a particular cache entry was cached (or not cached) is optionally
1551  * saved to an X-Cache-Detail header. This extra detail is useful for
1552  * service developers who may need to know whether their Cache-Control headers
1553  * are working correctly.
1554  */
1555 static int cache_status(cache_handle_t *h, request_rec *r,
1556         apr_table_t *headers, ap_cache_status_e status, const char *reason)
1557 {
1558     cache_server_conf
1559             *conf =
1560                     (cache_server_conf *) ap_get_module_config(r->server->module_config,
1561                             &cache_module);
1562
1563     cache_dir_conf *dconf = ap_get_module_config(r->per_dir_config, &cache_module);
1564     int x_cache = 0, x_cache_detail = 0;
1565
1566     switch (status) {
1567     case AP_CACHE_HIT: {
1568         apr_table_setn(r->subprocess_env, AP_CACHE_HIT_ENV, reason);
1569         break;
1570     }
1571     case AP_CACHE_REVALIDATE: {
1572         apr_table_setn(r->subprocess_env, AP_CACHE_REVALIDATE_ENV, reason);
1573         break;
1574     }
1575     case AP_CACHE_MISS: {
1576         apr_table_setn(r->subprocess_env, AP_CACHE_MISS_ENV, reason);
1577         break;
1578     }
1579     case AP_CACHE_INVALIDATE: {
1580         apr_table_setn(r->subprocess_env, AP_CACHE_INVALIDATE_ENV, reason);
1581         break;
1582     }
1583     }
1584
1585     apr_table_setn(r->subprocess_env, AP_CACHE_STATUS_ENV, reason);
1586
1587     if (dconf && dconf->x_cache_set) {
1588         x_cache = dconf->x_cache;
1589     }
1590     else {
1591         x_cache = conf->x_cache;
1592     }
1593     if (x_cache) {
1594         apr_table_setn(headers, "X-Cache", apr_psprintf(r->pool, "%s from %s",
1595                 status == AP_CACHE_HIT ? "HIT"
1596                         : status == AP_CACHE_REVALIDATE ? "REVALIDATE" : status
1597                                 == AP_CACHE_INVALIDATE ? "INVALIDATE" : "MISS",
1598                 r->server->server_hostname));
1599     }
1600
1601     if (dconf && dconf->x_cache_detail_set) {
1602         x_cache_detail = dconf->x_cache_detail;
1603     }
1604     else {
1605         x_cache_detail = conf->x_cache_detail;
1606     }
1607     if (x_cache_detail) {
1608         apr_table_setn(headers, "X-Cache-Detail", apr_psprintf(r->pool,
1609                 "\"%s\" from %s", reason, r->server->server_hostname));
1610     }
1611
1612     return OK;
1613 }
1614
1615 /**
1616  * If an error has occurred, but we have a stale cached entry, restore the
1617  * filter stack from the save filter onwards. The canned error message will
1618  * be discarded in the process, and replaced with the cached response.
1619  */
1620 static void cache_insert_error_filter(request_rec *r)
1621 {
1622     void *dummy;
1623     cache_dir_conf *dconf;
1624
1625     /* ignore everything except for 5xx errors */
1626     if (r->status < HTTP_INTERNAL_SERVER_ERROR) {
1627         return;
1628     }
1629
1630     dconf = ap_get_module_config(r->per_dir_config, &cache_module);
1631
1632     if (!dconf->stale_on_error) {
1633         return;
1634     }
1635
1636     /* RFC2616 13.8 Errors or Incomplete Response Cache Behavior:
1637      * If a cache receives a 5xx response while attempting to revalidate an
1638      * entry, it MAY either forward this response to the requesting client,
1639      * or act as if the server failed to respond. In the latter case, it MAY
1640      * return a previously received response unless the cached entry
1641      * includes the "must-revalidate" cache-control directive (see section
1642      * 14.9).
1643      *
1644      * This covers the case where the error was generated by our server via
1645      * ap_die().
1646      */
1647     apr_pool_userdata_get(&dummy, CACHE_CTX_KEY, r->pool);
1648     if (dummy) {
1649         cache_request_rec *cache = (cache_request_rec *) dummy;
1650
1651         ap_remove_output_filter(cache->remove_url_filter);
1652
1653         if (cache->stale_handle && cache->save_filter
1654                 && !cache->stale_handle->cache_obj->info.control.must_revalidate
1655                 && !cache->stale_handle->cache_obj->info.control.proxy_revalidate) {
1656             const char *warn_head;
1657             cache_server_conf
1658                     *conf =
1659                             (cache_server_conf *) ap_get_module_config(r->server->module_config,
1660                                     &cache_module);
1661
1662             /* morph the current save filter into the out filter, and serve from
1663              * cache.
1664              */
1665             cache->handle = cache->stale_handle;
1666             if (r->main) {
1667                 cache->save_filter->frec = cache_out_subreq_filter_handle;
1668             }
1669             else {
1670                 cache->save_filter->frec = cache_out_filter_handle;
1671             }
1672
1673             r->output_filters = cache->save_filter;
1674
1675             r->err_headers_out = cache->stale_handle->resp_hdrs;
1676
1677             /* add a revalidation warning */
1678             warn_head = apr_table_get(r->err_headers_out, "Warning");
1679             if ((warn_head == NULL) || ((warn_head != NULL)
1680                     && (ap_strstr_c(warn_head, "111") == NULL))) {
1681                 apr_table_mergen(r->err_headers_out, "Warning",
1682                         "111 Revalidation failed");
1683             }
1684
1685             cache_run_cache_status(
1686                     cache->handle,
1687                     r,
1688                     r->err_headers_out,
1689                     AP_CACHE_HIT,
1690                     apr_psprintf(
1691                             r->pool,
1692                             "cache hit: %d status; stale content returned",
1693                             r->status));
1694
1695             /* give someone else the chance to cache the file */
1696             cache_remove_lock(conf, cache, r, NULL);
1697
1698         }
1699     }
1700
1701     return;
1702 }
1703
1704 /* -------------------------------------------------------------- */
1705 /* Setup configurable data */
1706
1707 static void *create_dir_config(apr_pool_t *p, char *dummy)
1708 {
1709     cache_dir_conf *dconf = apr_pcalloc(p, sizeof(cache_dir_conf));
1710
1711     dconf->no_last_mod_ignore = 0;
1712     dconf->store_expired = 0;
1713     dconf->store_private = 0;
1714     dconf->store_nostore = 0;
1715
1716     /* maximum time to cache a document */
1717     dconf->maxex = DEFAULT_CACHE_MAXEXPIRE;
1718     dconf->minex = DEFAULT_CACHE_MINEXPIRE;
1719     /* default time to cache a document */
1720     dconf->defex = DEFAULT_CACHE_EXPIRE;
1721
1722     /* factor used to estimate Expires date from LastModified date */
1723     dconf->factor = DEFAULT_CACHE_LMFACTOR;
1724
1725     dconf->x_cache = DEFAULT_X_CACHE;
1726     dconf->x_cache_detail = DEFAULT_X_CACHE_DETAIL;
1727
1728     dconf->stale_on_error = DEFAULT_CACHE_STALE_ON_ERROR;
1729
1730     /* array of providers for this URL space */
1731     dconf->cacheenable = apr_array_make(p, 10, sizeof(struct cache_enable));
1732
1733     return dconf;
1734 }
1735
1736 static void *merge_dir_config(apr_pool_t *p, void *basev, void *addv) {
1737     cache_dir_conf *new = (cache_dir_conf *) apr_pcalloc(p, sizeof(cache_dir_conf));
1738     cache_dir_conf *add = (cache_dir_conf *) addv;
1739     cache_dir_conf *base = (cache_dir_conf *) basev;
1740
1741     new->no_last_mod_ignore = (add->no_last_mod_ignore_set == 0) ? base->no_last_mod_ignore : add->no_last_mod_ignore;
1742     new->no_last_mod_ignore_set = add->no_last_mod_ignore_set || base->no_last_mod_ignore_set;
1743
1744     new->store_expired = (add->store_expired_set == 0) ? base->store_expired : add->store_expired;
1745     new->store_expired_set = add->store_expired_set || base->store_expired_set;
1746     new->store_private = (add->store_private_set == 0) ? base->store_private : add->store_private;
1747     new->store_private_set = add->store_private_set || base->store_private_set;
1748     new->store_nostore = (add->store_nostore_set == 0) ? base->store_nostore : add->store_nostore;
1749     new->store_nostore_set = add->store_nostore_set || base->store_nostore_set;
1750
1751     /* maximum time to cache a document */
1752     new->maxex = (add->maxex_set == 0) ? base->maxex : add->maxex;
1753     new->maxex_set = add->maxex_set || base->maxex_set;
1754     new->minex = (add->minex_set == 0) ? base->minex : add->minex;
1755     new->minex_set = add->minex_set || base->minex_set;
1756
1757     /* default time to cache a document */
1758     new->defex = (add->defex_set == 0) ? base->defex : add->defex;
1759     new->defex_set = add->defex_set || base->defex_set;
1760
1761     /* factor used to estimate Expires date from LastModified date */
1762     new->factor = (add->factor_set == 0) ? base->factor : add->factor;
1763     new->factor_set = add->factor_set || base->factor_set;
1764
1765     new->x_cache = (add->x_cache_set == 0) ? base->x_cache : add->x_cache;
1766     new->x_cache_set = add->x_cache_set || base->x_cache_set;
1767     new->x_cache_detail = (add->x_cache_detail_set == 0) ? base->x_cache_detail
1768             : add->x_cache_detail;
1769     new->x_cache_detail_set = add->x_cache_detail_set
1770             || base->x_cache_detail_set;
1771
1772     new->stale_on_error = (add->stale_on_error_set == 0) ? base->stale_on_error
1773             : add->stale_on_error;
1774     new->stale_on_error_set = add->stale_on_error_set
1775             || base->stale_on_error_set;
1776
1777     new->cacheenable = add->enable_set ? apr_array_append(p, base->cacheenable,
1778             add->cacheenable) : base->cacheenable;
1779     new->enable_set = add->enable_set || base->enable_set;
1780     new->disable = (add->disable_set == 0) ? base->disable : add->disable;
1781     new->disable_set = add->disable_set || base->disable_set;
1782
1783     return new;
1784 }
1785
1786 static void * create_cache_config(apr_pool_t *p, server_rec *s)
1787 {
1788     const char *tmppath;
1789     cache_server_conf *ps = apr_pcalloc(p, sizeof(cache_server_conf));
1790
1791     /* array of URL prefixes for which caching is enabled */
1792     ps->cacheenable = apr_array_make(p, 10, sizeof(struct cache_enable));
1793     /* array of URL prefixes for which caching is disabled */
1794     ps->cachedisable = apr_array_make(p, 10, sizeof(struct cache_disable));
1795     ps->ignorecachecontrol = 0;
1796     ps->ignorecachecontrol_set = 0;
1797     /* array of headers that should not be stored in cache */
1798     ps->ignore_headers = apr_array_make(p, 10, sizeof(char *));
1799     ps->ignore_headers_set = CACHE_IGNORE_HEADERS_UNSET;
1800     /* flag indicating that query-string should be ignored when caching */
1801     ps->ignorequerystring = 0;
1802     ps->ignorequerystring_set = 0;
1803     /* by default, run in the quick handler */
1804     ps->quick = 1;
1805     ps->quick_set = 0;
1806     /* array of identifiers that should not be used for key calculation */
1807     ps->ignore_session_id = apr_array_make(p, 10, sizeof(char *));
1808     ps->ignore_session_id_set = CACHE_IGNORE_SESSION_ID_UNSET;
1809     ps->lock = 0; /* thundering herd lock defaults to off */
1810     ps->lock_set = 0;
1811     apr_temp_dir_get(&tmppath, p);
1812     if (tmppath) {
1813         ps->lockpath = apr_pstrcat(p, tmppath, DEFAULT_CACHE_LOCKPATH, NULL);
1814     }
1815     ps->lockmaxage = apr_time_from_sec(DEFAULT_CACHE_MAXAGE);
1816     ps->x_cache = DEFAULT_X_CACHE;
1817     ps->x_cache_detail = DEFAULT_X_CACHE_DETAIL;
1818     return ps;
1819 }
1820
1821 static void * merge_cache_config(apr_pool_t *p, void *basev, void *overridesv)
1822 {
1823     cache_server_conf *ps = apr_pcalloc(p, sizeof(cache_server_conf));
1824     cache_server_conf *base = (cache_server_conf *) basev;
1825     cache_server_conf *overrides = (cache_server_conf *) overridesv;
1826
1827     /* array of URL prefixes for which caching is disabled */
1828     ps->cachedisable = apr_array_append(p,
1829                                         base->cachedisable,
1830                                         overrides->cachedisable);
1831     /* array of URL prefixes for which caching is enabled */
1832     ps->cacheenable = apr_array_append(p,
1833                                        base->cacheenable,
1834                                        overrides->cacheenable);
1835
1836     ps->ignorecachecontrol  =
1837         (overrides->ignorecachecontrol_set == 0)
1838         ? base->ignorecachecontrol
1839         : overrides->ignorecachecontrol;
1840     ps->ignore_headers =
1841         (overrides->ignore_headers_set == CACHE_IGNORE_HEADERS_UNSET)
1842         ? base->ignore_headers
1843         : overrides->ignore_headers;
1844     ps->ignorequerystring =
1845         (overrides->ignorequerystring_set == 0)
1846         ? base->ignorequerystring
1847         : overrides->ignorequerystring;
1848     ps->ignore_session_id =
1849         (overrides->ignore_session_id_set == CACHE_IGNORE_SESSION_ID_UNSET)
1850         ? base->ignore_session_id
1851         : overrides->ignore_session_id;
1852     ps->lock =
1853         (overrides->lock_set == 0)
1854         ? base->lock
1855         : overrides->lock;
1856     ps->lockpath =
1857         (overrides->lockpath_set == 0)
1858         ? base->lockpath
1859         : overrides->lockpath;
1860     ps->lockmaxage =
1861         (overrides->lockmaxage_set == 0)
1862         ? base->lockmaxage
1863         : overrides->lockmaxage;
1864     ps->quick =
1865         (overrides->quick_set == 0)
1866         ? base->quick
1867         : overrides->quick;
1868     ps->x_cache =
1869         (overrides->x_cache_set == 0)
1870         ? base->x_cache
1871         : overrides->x_cache;
1872     ps->x_cache_detail =
1873         (overrides->x_cache_detail_set == 0)
1874         ? base->x_cache_detail
1875         : overrides->x_cache_detail;
1876     ps->base_uri =
1877         (overrides->base_uri_set == 0)
1878         ? base->base_uri
1879         : overrides->base_uri;
1880     return ps;
1881 }
1882
1883 static const char *set_cache_quick_handler(cmd_parms *parms, void *dummy,
1884                                            int flag)
1885 {
1886     cache_server_conf *conf;
1887
1888     conf =
1889         (cache_server_conf *)ap_get_module_config(parms->server->module_config
1890 ,
1891                                                   &cache_module);
1892     conf->quick = flag;
1893     conf->quick_set = 1;
1894     return NULL;
1895
1896 }
1897
1898 static const char *set_cache_ignore_no_last_mod(cmd_parms *parms, void *dummy,
1899                                                 int flag)
1900 {
1901     cache_dir_conf *dconf = (cache_dir_conf *)dummy;
1902
1903     dconf->no_last_mod_ignore = flag;
1904     dconf->no_last_mod_ignore_set = 1;
1905     return NULL;
1906
1907 }
1908
1909 static const char *set_cache_ignore_cachecontrol(cmd_parms *parms,
1910                                                  void *dummy, int flag)
1911 {
1912     cache_server_conf *conf;
1913
1914     conf =
1915         (cache_server_conf *)ap_get_module_config(parms->server->module_config,
1916                                                   &cache_module);
1917     conf->ignorecachecontrol = flag;
1918     conf->ignorecachecontrol_set = 1;
1919     return NULL;
1920 }
1921
1922 static const char *set_cache_store_expired(cmd_parms *parms, void *dummy,
1923                                            int flag)
1924 {
1925     cache_dir_conf *dconf = (cache_dir_conf *)dummy;
1926
1927     dconf->store_expired = flag;
1928     dconf->store_expired_set = 1;
1929     return NULL;
1930 }
1931
1932 static const char *set_cache_store_private(cmd_parms *parms, void *dummy,
1933                                            int flag)
1934 {
1935     cache_dir_conf *dconf = (cache_dir_conf *)dummy;
1936
1937     dconf->store_private = flag;
1938     dconf->store_private_set = 1;
1939     return NULL;
1940 }
1941
1942 static const char *set_cache_store_nostore(cmd_parms *parms, void *dummy,
1943                                            int flag)
1944 {
1945     cache_dir_conf *dconf = (cache_dir_conf *)dummy;
1946
1947     dconf->store_nostore = flag;
1948     dconf->store_nostore_set = 1;
1949     return NULL;
1950 }
1951
1952 static const char *add_ignore_header(cmd_parms *parms, void *dummy,
1953                                      const char *header)
1954 {
1955     cache_server_conf *conf;
1956     char **new;
1957
1958     conf =
1959         (cache_server_conf *)ap_get_module_config(parms->server->module_config,
1960                                                   &cache_module);
1961     if (!strcasecmp(header, "None")) {
1962         /* if header None is listed clear array */
1963         conf->ignore_headers->nelts = 0;
1964     }
1965     else {
1966         if ((conf->ignore_headers_set == CACHE_IGNORE_HEADERS_UNSET) ||
1967             (conf->ignore_headers->nelts)) {
1968             /* Only add header if no "None" has been found in header list
1969              * so far.
1970              * (When 'None' is passed, IGNORE_HEADERS_SET && nelts == 0.)
1971              */
1972             new = (char **)apr_array_push(conf->ignore_headers);
1973             (*new) = (char *)header;
1974         }
1975     }
1976     conf->ignore_headers_set = CACHE_IGNORE_HEADERS_SET;
1977     return NULL;
1978 }
1979
1980 static const char *add_ignore_session_id(cmd_parms *parms, void *dummy,
1981                                          const char *identifier)
1982 {
1983     cache_server_conf *conf;
1984     char **new;
1985
1986     conf =
1987         (cache_server_conf *)ap_get_module_config(parms->server->module_config,
1988                                                   &cache_module);
1989     if (!strcasecmp(identifier, "None")) {
1990         /* if identifier None is listed clear array */
1991         conf->ignore_session_id->nelts = 0;
1992     }
1993     else {
1994         if ((conf->ignore_session_id_set == CACHE_IGNORE_SESSION_ID_UNSET) ||
1995             (conf->ignore_session_id->nelts)) {
1996             /*
1997              * Only add identifier if no "None" has been found in identifier
1998              * list so far.
1999              */
2000             new = (char **)apr_array_push(conf->ignore_session_id);
2001             (*new) = (char *)identifier;
2002         }
2003     }
2004     conf->ignore_session_id_set = CACHE_IGNORE_SESSION_ID_SET;
2005     return NULL;
2006 }
2007
2008 static const char *add_cache_enable(cmd_parms *parms, void *dummy,
2009                                     const char *type,
2010                                     const char *url)
2011 {
2012     cache_dir_conf *dconf = (cache_dir_conf *)dummy;
2013     cache_server_conf *conf;
2014     struct cache_enable *new;
2015
2016     const char *err = ap_check_cmd_context(parms,
2017                                            NOT_IN_DIRECTORY|NOT_IN_LIMIT|NOT_IN_FILES);
2018     if (err != NULL) {
2019         return err;
2020     }
2021
2022     if (*type == '/') {
2023         return apr_psprintf(parms->pool,
2024           "provider (%s) starts with a '/'.  Are url and provider switched?",
2025           type);
2026     }
2027
2028     if (!url) {
2029         url = parms->path;
2030     }
2031     if (!url) {
2032         return apr_psprintf(parms->pool,
2033           "CacheEnable provider (%s) is missing an URL.", type);
2034     }
2035     if (parms->path && strncmp(parms->path, url, strlen(parms->path))) {
2036         return "When in a Location, CacheEnable must specify a path or an URL below "
2037         "that location.";
2038     }
2039
2040     conf =
2041         (cache_server_conf *)ap_get_module_config(parms->server->module_config,
2042                                                   &cache_module);
2043
2044     if (parms->path) {
2045         new = apr_array_push(dconf->cacheenable);
2046         dconf->enable_set = 1;
2047     }
2048     else {
2049         new = apr_array_push(conf->cacheenable);
2050     }
2051
2052     new->type = type;
2053     if (apr_uri_parse(parms->pool, url, &(new->url))) {
2054         return NULL;
2055     }
2056     if (new->url.path) {
2057         new->pathlen = strlen(new->url.path);
2058     } else {
2059         new->pathlen = 1;
2060         new->url.path = "/";
2061     }
2062     return NULL;
2063 }
2064
2065 static const char *add_cache_disable(cmd_parms *parms, void *dummy,
2066                                      const char *url)
2067 {
2068     cache_dir_conf *dconf = (cache_dir_conf *)dummy;
2069     cache_server_conf *conf;
2070     struct cache_disable *new;
2071
2072     const char *err = ap_check_cmd_context(parms,
2073                                            NOT_IN_DIRECTORY|NOT_IN_LIMIT|NOT_IN_FILES);
2074     if (err != NULL) {
2075         return err;
2076     }
2077
2078     if (parms->path && !strcmp(url, "on")) {
2079         url = parms->path;
2080     }
2081     if (url[0] != '/' && !ap_strchr_c(url, ':')) {
2082         return "CacheDisable must specify a path or an URL, or when in a Location, "
2083             "the word 'on'.";
2084     }
2085
2086     if (parms->path && strncmp(parms->path, url, strlen(parms->path))) {
2087         return "When in a Location, CacheDisable must specify a path or an URL below "
2088         "that location.";
2089     }
2090
2091     conf =
2092         (cache_server_conf *)ap_get_module_config(parms->server->module_config,
2093                                                   &cache_module);
2094
2095     if (parms->path) {
2096         dconf->disable = 1;
2097         dconf->disable_set = 1;
2098         return NULL;
2099     }
2100
2101     new = apr_array_push(conf->cachedisable);
2102     if (apr_uri_parse(parms->pool, url, &(new->url))) {
2103         return NULL;
2104     }
2105     if (new->url.path) {
2106         new->pathlen = strlen(new->url.path);
2107     } else {
2108         new->pathlen = 1;
2109         new->url.path = "/";
2110     }
2111     return NULL;
2112 }
2113
2114 static const char *set_cache_maxex(cmd_parms *parms, void *dummy,
2115                                    const char *arg)
2116 {
2117     cache_dir_conf *dconf = (cache_dir_conf *)dummy;
2118
2119     dconf->maxex = (apr_time_t) (atol(arg) * MSEC_ONE_SEC);
2120     dconf->maxex_set = 1;
2121     return NULL;
2122 }
2123
2124 static const char *set_cache_minex(cmd_parms *parms, void *dummy,
2125                                    const char *arg)
2126 {
2127     cache_dir_conf *dconf = (cache_dir_conf *)dummy;
2128
2129     dconf->minex = (apr_time_t) (atol(arg) * MSEC_ONE_SEC);
2130     dconf->minex_set = 1;
2131     return NULL;
2132 }
2133
2134 static const char *set_cache_defex(cmd_parms *parms, void *dummy,
2135                                    const char *arg)
2136 {
2137     cache_dir_conf *dconf = (cache_dir_conf *)dummy;
2138
2139     dconf->defex = (apr_time_t) (atol(arg) * MSEC_ONE_SEC);
2140     dconf->defex_set = 1;
2141     return NULL;
2142 }
2143
2144 static const char *set_cache_factor(cmd_parms *parms, void *dummy,
2145                                     const char *arg)
2146 {
2147     cache_dir_conf *dconf = (cache_dir_conf *)dummy;
2148     double val;
2149
2150     if (sscanf(arg, "%lg", &val) != 1) {
2151         return "CacheLastModifiedFactor value must be a float";
2152     }
2153     dconf->factor = val;
2154     dconf->factor_set = 1;
2155     return NULL;
2156 }
2157
2158 static const char *set_cache_ignore_querystring(cmd_parms *parms, void *dummy,
2159                                                 int flag)
2160 {
2161     cache_server_conf *conf;
2162
2163     conf =
2164         (cache_server_conf *)ap_get_module_config(parms->server->module_config,
2165                                                   &cache_module);
2166     conf->ignorequerystring = flag;
2167     conf->ignorequerystring_set = 1;
2168     return NULL;
2169 }
2170
2171 static const char *set_cache_lock(cmd_parms *parms, void *dummy,
2172                                                 int flag)
2173 {
2174     cache_server_conf *conf;
2175
2176     conf =
2177         (cache_server_conf *)ap_get_module_config(parms->server->module_config,
2178                                                   &cache_module);
2179     conf->lock = flag;
2180     conf->lock_set = 1;
2181     return NULL;
2182 }
2183
2184 static const char *set_cache_lock_path(cmd_parms *parms, void *dummy,
2185                                     const char *arg)
2186 {
2187     cache_server_conf *conf;
2188
2189     conf =
2190         (cache_server_conf *)ap_get_module_config(parms->server->module_config,
2191                                                   &cache_module);
2192
2193     conf->lockpath = ap_server_root_relative(parms->pool, arg);
2194     if (!conf->lockpath) {
2195         return apr_pstrcat(parms->pool, "Invalid CacheLockPath path ",
2196                            arg, NULL);
2197     }
2198     conf->lockpath_set = 1;
2199     return NULL;
2200 }
2201
2202 static const char *set_cache_lock_maxage(cmd_parms *parms, void *dummy,
2203                                     const char *arg)
2204 {
2205     cache_server_conf *conf;
2206     apr_int64_t seconds;
2207
2208     conf =
2209         (cache_server_conf *)ap_get_module_config(parms->server->module_config,
2210                                                   &cache_module);
2211     seconds = apr_atoi64(arg);
2212     if (seconds <= 0) {
2213         return "CacheLockMaxAge value must be a non-zero positive integer";
2214     }
2215     conf->lockmaxage = apr_time_from_sec(seconds);
2216     conf->lockmaxage_set = 1;
2217     return NULL;
2218 }
2219
2220 static const char *set_cache_x_cache(cmd_parms *parms, void *dummy, int flag)
2221 {
2222
2223     if (parms->path) {
2224         cache_dir_conf *dconf = (cache_dir_conf *)dummy;
2225
2226         dconf->x_cache = flag;
2227         dconf->x_cache_set = 1;
2228
2229     }
2230     else {
2231         cache_server_conf *conf =
2232             (cache_server_conf *)ap_get_module_config(parms->server->module_config,
2233                                                       &cache_module);
2234
2235         conf->x_cache = flag;
2236         conf->x_cache_set = 1;
2237
2238     }
2239
2240     return NULL;
2241 }
2242
2243 static const char *set_cache_x_cache_detail(cmd_parms *parms, void *dummy, int flag)
2244 {
2245
2246     if (parms->path) {
2247         cache_dir_conf *dconf = (cache_dir_conf *)dummy;
2248
2249         dconf->x_cache_detail = flag;
2250         dconf->x_cache_detail_set = 1;
2251
2252     }
2253     else {
2254         cache_server_conf *conf =
2255             (cache_server_conf *)ap_get_module_config(parms->server->module_config,
2256                                                       &cache_module);
2257
2258         conf->x_cache_detail = flag;
2259         conf->x_cache_detail_set = 1;
2260
2261     }
2262
2263     return NULL;
2264 }
2265
2266 static const char *set_cache_key_base_url(cmd_parms *parms, void *dummy,
2267         const char *arg)
2268 {
2269     cache_server_conf *conf;
2270     apr_status_t rv;
2271
2272     conf =
2273         (cache_server_conf *)ap_get_module_config(parms->server->module_config,
2274                                                   &cache_module);
2275     conf->base_uri = apr_pcalloc(parms->pool, sizeof(apr_uri_t));
2276     rv = apr_uri_parse(parms->pool, arg, conf->base_uri);
2277     if (rv != APR_SUCCESS) {
2278         return apr_psprintf(parms->pool, "Could not parse '%s' as an URL.", arg);
2279     }
2280     else if (!conf->base_uri->scheme && !conf->base_uri->hostname &&
2281             !conf->base_uri->port_str) {
2282         return apr_psprintf(parms->pool, "URL '%s' must contain at least one of a scheme, a hostname or a port.", arg);
2283     }
2284     conf->base_uri_set = 1;
2285     return NULL;
2286 }
2287
2288 static const char *set_cache_stale_on_error(cmd_parms *parms, void *dummy,
2289         int flag)
2290 {
2291     cache_dir_conf *dconf = (cache_dir_conf *)dummy;
2292
2293     dconf->stale_on_error = flag;
2294     dconf->stale_on_error_set = 1;
2295     return NULL;
2296 }
2297
2298 static int cache_post_config(apr_pool_t *p, apr_pool_t *plog,
2299                              apr_pool_t *ptemp, server_rec *s)
2300 {
2301     /* This is the means by which unusual (non-unix) os's may find alternate
2302      * means to run a given command (e.g. shebang/registry parsing on Win32)
2303      */
2304     cache_generate_key = APR_RETRIEVE_OPTIONAL_FN(ap_cache_generate_key);
2305     if (!cache_generate_key) {
2306         cache_generate_key = cache_generate_key_default;
2307     }
2308     return OK;
2309 }
2310
2311
2312 static const command_rec cache_cmds[] =
2313 {
2314     /* XXX
2315      * Consider a new config directive that enables loading specific cache
2316      * implememtations (like mod_cache_mem, mod_cache_file, etc.).
2317      * Rather than using a LoadModule directive, admin would use something
2318      * like CacheModule  mem_cache_module | file_cache_module, etc,
2319      * which would cause the approprpriate cache module to be loaded.
2320      * This is more intuitive that requiring a LoadModule directive.
2321      */
2322
2323     AP_INIT_TAKE12("CacheEnable", add_cache_enable, NULL, RSRC_CONF|ACCESS_CONF,
2324                    "A cache type and partial URL prefix below which "
2325                    "caching is enabled"),
2326     AP_INIT_TAKE1("CacheDisable", add_cache_disable, NULL, RSRC_CONF|ACCESS_CONF,
2327                   "A partial URL prefix below which caching is disabled"),
2328     AP_INIT_TAKE1("CacheMaxExpire", set_cache_maxex, NULL, RSRC_CONF|ACCESS_CONF,
2329                   "The maximum time in seconds to cache a document"),
2330     AP_INIT_TAKE1("CacheMinExpire", set_cache_minex, NULL, RSRC_CONF|ACCESS_CONF,
2331                   "The minimum time in seconds to cache a document"),
2332     AP_INIT_TAKE1("CacheDefaultExpire", set_cache_defex, NULL, RSRC_CONF|ACCESS_CONF,
2333                   "The default time in seconds to cache a document"),
2334     AP_INIT_FLAG("CacheQuickHandler", set_cache_quick_handler, NULL,
2335                  RSRC_CONF,
2336                  "Run the cache in the quick handler, default on"),
2337     AP_INIT_FLAG("CacheIgnoreNoLastMod", set_cache_ignore_no_last_mod, NULL,
2338                  RSRC_CONF|ACCESS_CONF,
2339                  "Ignore Responses where there is no Last Modified Header"),
2340     AP_INIT_FLAG("CacheIgnoreCacheControl", set_cache_ignore_cachecontrol,
2341                  NULL, RSRC_CONF,
2342                  "Ignore requests from the client for uncached content"),
2343     AP_INIT_FLAG("CacheStoreExpired", set_cache_store_expired,
2344                  NULL, RSRC_CONF|ACCESS_CONF,
2345                  "Ignore expiration dates when populating cache, resulting in "
2346                  "an If-Modified-Since request to the backend on retrieval"),
2347     AP_INIT_FLAG("CacheStorePrivate", set_cache_store_private,
2348                  NULL, RSRC_CONF|ACCESS_CONF,
2349                  "Ignore 'Cache-Control: private' and store private content"),
2350     AP_INIT_FLAG("CacheStoreNoStore", set_cache_store_nostore,
2351                  NULL, RSRC_CONF|ACCESS_CONF,
2352                  "Ignore 'Cache-Control: no-store' and store sensitive content"),
2353     AP_INIT_ITERATE("CacheIgnoreHeaders", add_ignore_header, NULL, RSRC_CONF,
2354                     "A space separated list of headers that should not be "
2355                     "stored by the cache"),
2356     AP_INIT_FLAG("CacheIgnoreQueryString", set_cache_ignore_querystring,
2357                  NULL, RSRC_CONF,
2358                  "Ignore query-string when caching"),
2359     AP_INIT_ITERATE("CacheIgnoreURLSessionIdentifiers", add_ignore_session_id,
2360                     NULL, RSRC_CONF, "A space separated list of session "
2361                     "identifiers that should be ignored for creating the key "
2362                     "of the cached entity."),
2363     AP_INIT_TAKE1("CacheLastModifiedFactor", set_cache_factor, NULL, RSRC_CONF|ACCESS_CONF,
2364                   "The factor used to estimate Expires date from "
2365                   "LastModified date"),
2366     AP_INIT_FLAG("CacheLock", set_cache_lock,
2367                  NULL, RSRC_CONF,
2368                  "Enable or disable the thundering herd lock."),
2369     AP_INIT_TAKE1("CacheLockPath", set_cache_lock_path, NULL, RSRC_CONF,
2370                   "The thundering herd lock path. Defaults to the '"
2371                   DEFAULT_CACHE_LOCKPATH "' directory in the system "
2372                   "temp directory."),
2373     AP_INIT_TAKE1("CacheLockMaxAge", set_cache_lock_maxage, NULL, RSRC_CONF,
2374                   "Maximum age of any thundering herd lock."),
2375     AP_INIT_FLAG("CacheHeader", set_cache_x_cache, NULL, RSRC_CONF | ACCESS_CONF,
2376                  "Add a X-Cache header to responses. Default is off."),
2377     AP_INIT_FLAG("CacheDetailHeader", set_cache_x_cache_detail, NULL,
2378                  RSRC_CONF | ACCESS_CONF,
2379                  "Add a X-Cache-Detail header to responses. Default is off."),
2380     AP_INIT_TAKE1("CacheKeyBaseURL", set_cache_key_base_url, NULL, RSRC_CONF,
2381                   "Override the base URL of reverse proxied cache keys."),
2382     AP_INIT_FLAG("CacheStaleOnError", set_cache_stale_on_error,
2383                  NULL, RSRC_CONF|ACCESS_CONF,
2384                  "Serve stale content on 5xx errors if present. Defaults to on."),
2385     {NULL}
2386 };
2387
2388 static void register_hooks(apr_pool_t *p)
2389 {
2390     /* cache initializer */
2391     /* cache quick handler */
2392     ap_hook_quick_handler(cache_quick_handler, NULL, NULL, APR_HOOK_FIRST);
2393     /* cache handler */
2394     ap_hook_handler(cache_handler, NULL, NULL, APR_HOOK_REALLY_FIRST);
2395     /* cache status */
2396     cache_hook_cache_status(cache_status, NULL, NULL, APR_HOOK_MIDDLE);
2397     /* cache error handler */
2398     ap_hook_insert_error_filter(cache_insert_error_filter, NULL, NULL, APR_HOOK_MIDDLE);
2399     /* cache filters
2400      * XXX The cache filters need to run right after the handlers and before
2401      * any other filters. Consider creating AP_FTYPE_CACHE for this purpose.
2402      *
2403      * Depending on the type of request (subrequest / main request) they
2404      * need to be run before AP_FTYPE_CONTENT_SET / after AP_FTYPE_CONTENT_SET
2405      * filters. Thus create two filter handles for each type:
2406      * cache_save_filter_handle / cache_out_filter_handle to be used by
2407      * main requests and
2408      * cache_save_subreq_filter_handle / cache_out_subreq_filter_handle
2409      * to be run by subrequest
2410      */
2411     /*
2412      * CACHE is placed into the filter chain at an admin specified location,
2413      * and when the cache_handler is run, the CACHE filter is swapped with
2414      * the CACHE_OUT filter, or CACHE_SAVE filter as appropriate. This has
2415      * the effect of offering optional fine control of where the cache is
2416      * inserted into the filter chain.
2417      */
2418     cache_filter_handle =
2419         ap_register_output_filter("CACHE",
2420                                   cache_filter,
2421                                   NULL,
2422                                   AP_FTYPE_RESOURCE);
2423     /*
2424      * CACHE_SAVE must go into the filter chain after a possible DEFLATE
2425      * filter to ensure that the compressed content is stored.
2426      * Incrementing filter type by 1 ensures this happens.
2427      */
2428     cache_save_filter_handle =
2429         ap_register_output_filter("CACHE_SAVE",
2430                                   cache_save_filter,
2431                                   NULL,
2432                                   AP_FTYPE_CONTENT_SET+1);
2433     /*
2434      * CACHE_SAVE_SUBREQ must go into the filter chain before SUBREQ_CORE to
2435      * handle subrequsts. Decrementing filter type by 1 ensures this
2436      * happens.
2437      */
2438     cache_save_subreq_filter_handle =
2439         ap_register_output_filter("CACHE_SAVE_SUBREQ",
2440                                   cache_save_filter,
2441                                   NULL,
2442                                   AP_FTYPE_CONTENT_SET-1);
2443     /*
2444      * CACHE_OUT must go into the filter chain after a possible DEFLATE
2445      * filter to ensure that already compressed cache objects do not
2446      * get compressed again. Incrementing filter type by 1 ensures
2447      * this happens.
2448      */
2449     cache_out_filter_handle =
2450         ap_register_output_filter("CACHE_OUT",
2451                                   cache_out_filter,
2452                                   NULL,
2453                                   AP_FTYPE_CONTENT_SET+1);
2454     /*
2455      * CACHE_OUT_SUBREQ must go into the filter chain before SUBREQ_CORE to
2456      * handle subrequsts. Decrementing filter type by 1 ensures this
2457      * happens.
2458      */
2459     cache_out_subreq_filter_handle =
2460         ap_register_output_filter("CACHE_OUT_SUBREQ",
2461                                   cache_out_filter,
2462                                   NULL,
2463                                   AP_FTYPE_CONTENT_SET-1);
2464     /* CACHE_REMOVE_URL has to be a protocol filter to ensure that is
2465      * run even if the response is a canned error message, which
2466      * removes the content filters.
2467      */
2468     cache_remove_url_filter_handle =
2469         ap_register_output_filter("CACHE_REMOVE_URL",
2470                                   cache_remove_url_filter,
2471                                   NULL,
2472                                   AP_FTYPE_PROTOCOL);
2473     ap_hook_post_config(cache_post_config, NULL, NULL, APR_HOOK_REALLY_FIRST);
2474 }
2475
2476 AP_DECLARE_MODULE(cache) =
2477 {
2478     STANDARD20_MODULE_STUFF,
2479     create_dir_config,      /* create per-directory config structure */
2480     merge_dir_config,       /* merge per-directory config structures */
2481     create_cache_config,    /* create per-server config structure */
2482     merge_cache_config,     /* merge per-server config structures */
2483     cache_cmds,             /* command apr_table_t */
2484     register_hooks
2485 };
2486
2487 APR_HOOK_STRUCT(
2488     APR_HOOK_LINK(cache_status)
2489 )
2490
2491 APR_IMPLEMENT_EXTERNAL_HOOK_RUN_ALL(cache, CACHE, int, cache_status,
2492         (cache_handle_t *h, request_rec *r,
2493                 apr_table_t *headers, ap_cache_status_e status,
2494                 const char *reason), (h, r, headers, status, reason),
2495         OK, DECLINED)