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