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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 #include "mod_cache.h"
19 module AP_MODULE_DECLARE_DATA cache_module;
20 APR_OPTIONAL_FN_TYPE(ap_cache_generate_key) *cache_generate_key;
22 /* -------------------------------------------------------------- */
25 /* Handles for cache filters, resolved at startup to eliminate
26 * a name-to-function mapping on each request
28 static ap_filter_rec_t *cache_save_filter_handle;
29 static ap_filter_rec_t *cache_save_subreq_filter_handle;
30 static ap_filter_rec_t *cache_out_filter_handle;
31 static ap_filter_rec_t *cache_out_subreq_filter_handle;
32 static ap_filter_rec_t *cache_remove_url_filter_handle;
38 * Can we deliver this request from the cache?
40 * deliver the content by installing the CACHE_OUT filter.
42 * check whether we're allowed to try cache it
44 * add CACHE_SAVE filter
49 static int cache_url_handler(request_rec *r, int lookup)
53 cache_provider_list *providers;
54 cache_request_rec *cache;
55 cache_server_conf *conf;
56 apr_bucket_brigade *out;
58 ap_filter_rec_t *cache_out_handle;
60 /* Delay initialization until we know we are handling a GET */
61 if (r->method_number != M_GET) {
65 conf = (cache_server_conf *) ap_get_module_config(r->server->module_config,
69 * Which cache module (if any) should handle this request?
71 if (!(providers = ap_cache_get_providers(r, conf, r->parsed_uri))) {
75 /* make space for the per request config */
76 cache = (cache_request_rec *) ap_get_module_config(r->request_config,
79 cache = apr_pcalloc(r->pool, sizeof(cache_request_rec));
80 ap_set_module_config(r->request_config, &cache_module, cache);
83 /* save away the possible providers */
84 cache->providers = providers;
87 * Are we allowed to serve cached info at all?
90 /* find certain cache controlling headers */
91 auth = apr_table_get(r->headers_in, "Authorization");
93 /* First things first - does the request allow us to return
94 * cached information at all? If not, just decline the request.
101 * Try to serve this request from the cache.
103 * If no existing cache file (DECLINED)
104 * add cache_save filter
105 * If cached file (OK)
107 * add cache_out filter
110 rv = cache_select(r);
112 if (rv == DECLINED) {
116 * Add cache_save filter to cache this request. Choose
117 * the correct filter by checking if we are a subrequest
121 ap_log_error(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS,
123 "Adding CACHE_SAVE_SUBREQ filter for %s",
125 ap_add_output_filter_handle(cache_save_subreq_filter_handle,
126 NULL, r, r->connection);
129 ap_log_error(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS,
130 r->server, "Adding CACHE_SAVE filter for %s",
132 ap_add_output_filter_handle(cache_save_filter_handle,
133 NULL, r, r->connection);
136 ap_log_error(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, r->server,
137 "Adding CACHE_REMOVE_URL filter for %s",
140 /* Add cache_remove_url filter to this request to remove a
141 * stale cache entry if needed. Also put the current cache
142 * request rec in the filter context, as the request that
143 * is available later during running the filter maybe
144 * different due to an internal redirect.
146 cache->remove_url_filter =
147 ap_add_output_filter_handle(cache_remove_url_filter_handle,
148 cache, r, r->connection);
151 if (cache->stale_headers) {
152 ap_log_error(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS,
153 r->server, "Restoring request headers for %s",
156 r->headers_in = cache->stale_headers;
159 /* Delete our per-request configuration. */
160 ap_set_module_config(r->request_config, &cache_module, NULL);
165 ap_log_error(APLOG_MARK, APLOG_ERR, rv, r->server,
166 "cache: error returned while checking for cached "
167 "file by %s cache", cache->provider_name);
172 /* if we are a lookup, we are exiting soon one way or another; Restore
175 if (cache->stale_headers) {
176 ap_log_error(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, r->server,
177 "Restoring request headers.");
178 r->headers_in = cache->stale_headers;
181 /* Delete our per-request configuration. */
182 ap_set_module_config(r->request_config, &cache_module, NULL);
185 rv = ap_meets_conditions(r);
187 /* If we are a lookup, we have to return DECLINED as we have no
188 * way of knowing if we will be able to serve the content.
194 /* Return cached status. */
198 /* If we're a lookup, we can exit now instead of serving the content. */
203 /* Serve up the content */
205 /* We are in the quick handler hook, which means that no output
206 * filters have been set. So lets run the insert_filter hook.
208 ap_run_insert_filter(r);
211 * Add cache_out filter to serve this request. Choose
212 * the correct filter by checking if we are a subrequest
216 cache_out_handle = cache_out_subreq_filter_handle;
219 cache_out_handle = cache_out_filter_handle;
221 ap_add_output_filter_handle(cache_out_handle, NULL, r, r->connection);
224 * Remove all filters that are before the cache_out filter. This ensures
225 * that we kick off the filter stack with our cache_out filter being the
226 * first in the chain. This make sense because we want to restore things
227 * in the same manner as we saved them.
228 * There may be filters before our cache_out filter, because
230 * 1. We call ap_set_content_type during cache_select. This causes
231 * Content-Type specific filters to be added.
232 * 2. We call the insert_filter hook. This causes filters e.g. like
233 * the ones set with SetOutputFilter to be added.
235 next = r->output_filters;
236 while (next && (next->frec != cache_out_handle)) {
237 ap_remove_output_filter(next);
241 /* kick off the filter stack */
242 out = apr_brigade_create(r->pool, r->connection->bucket_alloc);
243 rv = ap_pass_brigade(r->output_filters, out);
244 if (rv != APR_SUCCESS) {
245 if (rv != AP_FILTER_ERROR) {
246 ap_log_error(APLOG_MARK, APLOG_ERR, rv, r->server,
247 "cache: error returned while trying to return %s "
249 cache->provider_name);
261 * Deliver cached content (headers and body) up the stack.
263 static int cache_out_filter(ap_filter_t *f, apr_bucket_brigade *bb)
265 request_rec *r = f->r;
266 cache_request_rec *cache;
268 cache = (cache_request_rec *) ap_get_module_config(r->request_config,
272 /* user likely configured CACHE_OUT manually; they should use mod_cache
273 * configuration to do that */
274 ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server,
275 "CACHE_OUT enabled unexpectedly");
276 ap_remove_output_filter(f);
277 return ap_pass_brigade(f->next, bb);
280 ap_log_error(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, r->server,
281 "cache: running CACHE_OUT filter");
283 /* restore status of cached response */
284 /* XXX: This exposes a bug in mem_cache, since it does not
285 * restore the status into it's handle. */
286 r->status = cache->handle->cache_obj->info.status;
288 /* recall_headers() was called in cache_select() */
289 cache->provider->recall_body(cache->handle, r->pool, bb);
291 /* This filter is done once it has served up its content */
292 ap_remove_output_filter(f);
294 ap_log_error(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, r->server,
295 "cache: serving %s", r->uri);
296 return ap_pass_brigade(f->next, bb);
304 * Decide whether or not this content should be cached.
305 * If we decide no it should not:
306 * remove the filter from the chain
307 * If we decide yes it should:
308 * Have we already started saving the response?
309 * If we have started, pass the data to the storage manager via store_body
311 * Check to see if we *can* save this particular response.
312 * If we can, call cache_create_entity() and save the headers and body
313 * Finally, pass the data to the next filter (the network or whatever)
316 static int cache_save_filter(ap_filter_t *f, apr_bucket_brigade *in)
319 request_rec *r = f->r;
320 cache_request_rec *cache;
321 cache_server_conf *conf;
322 const char *cc_out, *cl;
323 const char *exps, *lastmods, *dates, *etag;
324 apr_time_t exp, date, lastmod, now;
326 cache_info *info = NULL;
330 conf = (cache_server_conf *) ap_get_module_config(r->server->module_config,
333 /* Setup cache_request_rec */
334 cache = (cache_request_rec *) ap_get_module_config(r->request_config,
337 /* user likely configured CACHE_SAVE manually; they should really use
338 * mod_cache configuration to do that
340 cache = apr_pcalloc(r->pool, sizeof(cache_request_rec));
341 ap_set_module_config(r->request_config, &cache_module, cache);
349 * This section passes the brigades into the cache modules, but only
350 * if the setup section (see below) is complete.
352 if (cache->block_response) {
353 /* We've already sent down the response and EOS. So, ignore
354 * whatever comes now.
359 /* have we already run the cachability check and set up the
360 * cached file handle?
362 if (cache->in_checked) {
363 /* pass the brigades into the cache, then pass them
364 * up the filter stack
366 rv = cache->provider->store_body(cache->handle, r, in);
367 if (rv != APR_SUCCESS) {
368 ap_log_error(APLOG_MARK, APLOG_DEBUG, rv, r->server,
369 "cache: Cache provider's store_body failed!");
370 ap_remove_output_filter(f);
372 return ap_pass_brigade(f->next, in);
376 * Setup Data in Cache
377 * -------------------
378 * This section opens the cache entity and sets various caching
379 * parameters, and decides whether this URL should be cached at
380 * all. This section is* run before the above section.
383 /* read expiry date; if a bad date, then leave it so the client can
386 exps = apr_table_get(r->err_headers_out, "Expires");
388 exps = apr_table_get(r->headers_out, "Expires");
391 if (APR_DATE_BAD == (exp = apr_date_parse_http(exps))) {
399 /* read the last-modified date; if the date is bad, then delete it */
400 lastmods = apr_table_get(r->err_headers_out, "Last-Modified");
401 if (lastmods == NULL) {
402 lastmods = apr_table_get(r->headers_out, "Last-Modified");
404 if (lastmods != NULL) {
405 lastmod = apr_date_parse_http(lastmods);
406 if (lastmod == APR_DATE_BAD) {
411 lastmod = APR_DATE_BAD;
414 /* read the etag and cache-control from the entity */
415 etag = apr_table_get(r->err_headers_out, "Etag");
417 etag = apr_table_get(r->headers_out, "Etag");
419 cc_out = apr_table_get(r->err_headers_out, "Cache-Control");
420 if (cc_out == NULL) {
421 cc_out = apr_table_get(r->headers_out, "Cache-Control");
425 * what responses should we not cache?
427 * At this point we decide based on the response headers whether it
428 * is appropriate _NOT_ to cache the data from the server. There are
429 * a whole lot of conditions that prevent us from caching this data.
430 * They are tested here one by one to be clear and unambiguous.
432 if (r->status != HTTP_OK && r->status != HTTP_NON_AUTHORITATIVE
433 && r->status != HTTP_MULTIPLE_CHOICES
434 && r->status != HTTP_MOVED_PERMANENTLY
435 && r->status != HTTP_NOT_MODIFIED) {
436 /* RFC2616 13.4 we are allowed to cache 200, 203, 206, 300, 301 or 410
437 * We don't cache 206, because we don't (yet) cache partial responses.
438 * We include 304 Not Modified here too as this is the origin server
439 * telling us to serve the cached copy.
441 reason = apr_psprintf(p, "Response status %d", r->status);
443 else if (exps != NULL && exp == APR_DATE_BAD) {
444 /* if a broken Expires header is present, don't cache it */
445 reason = apr_pstrcat(p, "Broken expires header: ", exps, NULL);
447 else if (exp != APR_DATE_BAD && exp < r->request_time)
449 /* if a Expires header is in the past, don't cache it */
450 reason = "Expires header already expired, not cacheable";
452 else if (!conf->ignorequerystring && r->parsed_uri.query && exps == NULL &&
453 !ap_cache_liststr(NULL, cc_out, "max-age", NULL)) {
454 /* if a query string is present but no explicit expiration time,
455 * don't cache it (RFC 2616/13.9 & 13.2.1)
457 reason = "Query string present but no explicit expiration time";
459 else if (r->status == HTTP_NOT_MODIFIED &&
460 !cache->handle && !cache->stale_handle) {
461 /* if the server said 304 Not Modified but we have no cache
462 * file - pass this untouched to the user agent, it's not for us.
464 reason = "HTTP Status 304 Not Modified";
466 else if (r->status == HTTP_OK && lastmods == NULL && etag == NULL
467 && (exps == NULL) && (conf->no_last_mod_ignore ==0)) {
468 /* 200 OK response from HTTP/1.0 and up without Last-Modified,
469 * Etag, or Expires headers.
471 /* Note: mod-include clears last_modified/expires/etags - this
472 * is why we have an optional function for a key-gen ;-)
474 reason = "No Last-Modified, Etag, or Expires headers";
476 else if (r->header_only && !cache->stale_handle) {
477 /* Forbid HEAD requests unless we have it cached already */
478 reason = "HTTP HEAD request";
480 else if (!conf->store_nostore &&
481 ap_cache_liststr(NULL, cc_out, "no-store", NULL)) {
482 /* RFC2616 14.9.2 Cache-Control: no-store response
483 * indicating do not cache, or stop now if you are
484 * trying to cache it.
486 /* FIXME: The Cache-Control: no-store could have come in on a 304,
487 * FIXME: while the original request wasn't conditional. IOW, we
488 * FIXME: made the the request conditional earlier to revalidate
489 * FIXME: our cached response.
491 reason = "Cache-Control: no-store present";
493 else if (!conf->store_private &&
494 ap_cache_liststr(NULL, cc_out, "private", NULL)) {
495 /* RFC2616 14.9.1 Cache-Control: private response
496 * this object is marked for this user's eyes only. Behave
499 /* FIXME: See above (no-store) */
500 reason = "Cache-Control: private present";
502 else if (apr_table_get(r->headers_in, "Authorization") != NULL
503 && !(ap_cache_liststr(NULL, cc_out, "s-maxage", NULL)
504 || ap_cache_liststr(NULL, cc_out, "must-revalidate", NULL)
505 || ap_cache_liststr(NULL, cc_out, "public", NULL))) {
506 /* RFC2616 14.8 Authorisation:
507 * if authorisation is included in the request, we don't cache,
508 * but we can cache if the following exceptions are true:
509 * 1) If Cache-Control: s-maxage is included
510 * 2) If Cache-Control: must-revalidate is included
511 * 3) If Cache-Control: public is included
513 reason = "Authorization required";
515 else if (ap_cache_liststr(NULL,
516 apr_table_get(r->headers_out, "Vary"),
518 reason = "Vary header contains '*'";
520 else if (r->no_cache) {
521 /* or we've been asked not to cache it above */
522 reason = "r->no_cache present";
526 ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
527 "cache: %s not cached. Reason: %s", r->unparsed_uri,
530 /* remove this filter from the chain */
531 ap_remove_output_filter(f);
533 /* ship the data up the stack */
534 return ap_pass_brigade(f->next, in);
537 /* Make it so that we don't execute this path again. */
538 cache->in_checked = 1;
540 /* Set the content length if known.
542 cl = apr_table_get(r->err_headers_out, "Content-Length");
544 cl = apr_table_get(r->headers_out, "Content-Length");
548 if (apr_strtoff(&size, cl, &errp, 10) || *errp || size < 0) {
549 cl = NULL; /* parse error, see next 'if' block */
554 /* if we don't get the content-length, see if we have all the
555 * buckets and use their length to calculate the size
558 int all_buckets_here=0;
559 int unresolved_length = 0;
561 for (e = APR_BRIGADE_FIRST(in);
562 e != APR_BRIGADE_SENTINEL(in);
563 e = APR_BUCKET_NEXT(e))
565 if (APR_BUCKET_IS_EOS(e)) {
569 if (APR_BUCKET_IS_FLUSH(e)) {
570 unresolved_length = 1;
573 if (e->length == (apr_size_t)-1) {
578 if (!all_buckets_here) {
583 /* It's safe to cache the response.
585 * There are two possiblities at this point:
586 * - cache->handle == NULL. In this case there is no previously
587 * cached entity anywhere on the system. We must create a brand
588 * new entity and store the response in it.
589 * - cache->stale_handle != NULL. In this case there is a stale
590 * entity in the system which needs to be replaced by new
591 * content (unless the result was 304 Not Modified, which means
592 * the cached entity is actually fresh, and we should update
596 /* Did we have a stale cache entry that really is stale?
598 * Note that for HEAD requests, we won't get the body, so for a stale
599 * HEAD request, we don't remove the entity - instead we let the
600 * CACHE_REMOVE_URL filter remove the stale item from the cache.
602 if (cache->stale_handle) {
603 if (r->status == HTTP_NOT_MODIFIED) {
604 /* Oh, hey. It isn't that stale! Yay! */
605 cache->handle = cache->stale_handle;
606 info = &cache->handle->cache_obj->info;
609 else if (!r->header_only) {
610 /* Oh, well. Toss it. */
611 cache->provider->remove_entity(cache->stale_handle);
612 /* Treat the request as if it wasn't conditional. */
613 cache->stale_handle = NULL;
615 * Restore the original request headers as they may be needed
616 * by further output filters like the byterange filter to make
617 * the correct decisions.
619 r->headers_in = cache->stale_headers;
623 /* no cache handle, create a new entity only for non-HEAD requests */
624 if (!cache->handle && !r->header_only) {
625 rv = cache_create_entity(r, size);
626 info = apr_pcalloc(r->pool, sizeof(cache_info));
627 /* We only set info->status upon the initial creation. */
628 info->status = r->status;
632 /* Caching layer declined the opportunity to cache the response */
633 ap_remove_output_filter(f);
634 return ap_pass_brigade(f->next, in);
637 ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
638 "cache: Caching url: %s", r->unparsed_uri);
640 /* We are actually caching this response. So it does not
641 * make sense to remove this entity any more.
643 ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
644 "cache: Removing CACHE_REMOVE_URL filter.");
645 ap_remove_output_filter(cache->remove_url_filter);
648 * We now want to update the cache file header information with
649 * the new date, last modified, expire and content length and write
650 * it away to our cache file. First, we determine these values from
651 * the response, using heuristics if appropriate.
653 * In addition, we make HTTP/1.1 age calculations and write them away
657 /* Read the date. Generate one if one is not supplied */
658 dates = apr_table_get(r->err_headers_out, "Date");
660 dates = apr_table_get(r->headers_out, "Date");
663 info->date = apr_date_parse_http(dates);
666 info->date = APR_DATE_BAD;
669 now = apr_time_now();
670 if (info->date == APR_DATE_BAD) { /* No, or bad date */
671 /* no date header (or bad header)! */
676 /* set response_time for HTTP/1.1 age calculations */
677 info->response_time = now;
679 /* get the request time */
680 info->request_time = r->request_time;
682 /* check last-modified date */
683 if (lastmod != APR_DATE_BAD && lastmod > date) {
684 /* if it's in the future, then replace by date */
687 ap_log_error(APLOG_MARK, APLOG_DEBUG, 0,
689 "cache: Last modified is in the future, "
690 "replacing with now");
693 /* if no expiry date then
694 * if Cache-Control: max-age
695 * expiry date = date + max-age
697 * expiry date = date + min((date - lastmod) * factor, maxexpire)
699 * expire date = date + defaultexpire
701 if (exp == APR_DATE_BAD) {
704 if (ap_cache_liststr(r->pool, cc_out, "max-age", &max_age_val) &&
705 max_age_val != NULL) {
709 x = apr_atoi64(max_age_val);
714 x = x * MSEC_ONE_SEC;
716 if (x < conf->minex) {
719 if (x > conf->maxex) {
724 else if ((lastmod != APR_DATE_BAD) && (lastmod < date)) {
725 /* if lastmod == date then you get 0*conf->factor which results in
726 * an expiration time of now. This causes some problems with
727 * freshness calculations, so we choose the else path...
729 apr_time_t x = (apr_time_t) ((date - lastmod) * conf->factor);
731 if (x < conf->minex) {
734 if (x > conf->maxex) {
740 exp = date + conf->defex;
745 /* We found a stale entry which wasn't really stale. */
746 if (cache->stale_handle) {
747 /* Load in the saved status and clear the status line. */
748 r->status = info->status;
749 r->status_line = NULL;
751 /* RFC 2616 10.3.5 states that entity headers are not supposed
752 * to be in the 304 response. Therefore, we need to combine the
753 * response headers with the cached headers *before* we update
754 * the cached headers.
756 * However, before doing that, we need to first merge in
757 * err_headers_out and we also need to strip any hop-by-hop
758 * headers that might have snuck in.
760 r->headers_out = apr_table_overlay(r->pool, r->headers_out,
763 /* XXX check -- we're not patching up content-type - i.e. this
764 * propably should be ap_cache_cacheable_headers_out().
766 r->headers_out = ap_cache_cacheable_headers(r->pool, r->headers_out,
768 apr_table_clear(r->err_headers_out);
770 /* Merge in our cached headers. However, keep any updated values. */
771 ap_cache_accept_headers(cache->handle, r, 1);
774 /* Write away header information to cache. It is possible that we are
775 * trying to update headers for an entity which has already been cached.
777 * This may fail, due to an unwritable cache area. E.g. filesystem full,
778 * permissions problems or a read-only (re)mount. This must be handled
781 rv = cache->provider->store_headers(cache->handle, r, info);
783 /* Did we just update the cached headers on a revalidated response?
785 * If so, we can now decide what to serve to the client. This is done in
786 * the same way as with a regular response, but conditions are now checked
787 * against the cached or merged response headers.
789 if (cache->stale_handle) {
790 apr_bucket_brigade *bb;
794 bb = apr_brigade_create(r->pool, r->connection->bucket_alloc);
796 /* Restore the original request headers and see if we need to
797 * return anything else than the cached response (ie. the original
798 * request was conditional).
800 r->headers_in = cache->stale_headers;
801 status = ap_meets_conditions(r);
805 bkt = apr_bucket_flush_create(bb->bucket_alloc);
806 APR_BRIGADE_INSERT_TAIL(bb, bkt);
809 cache->provider->recall_body(cache->handle, r->pool, bb);
812 cache->block_response = 1;
814 /* Before returning we need to handle the possible case of an
815 * unwritable cache. Rather than leaving the entity in the cache
816 * and having it constantly re-validated, now that we have recalled
817 * the body it is safe to try and remove the url from the cache.
819 if (rv != APR_SUCCESS) {
820 ap_log_error(APLOG_MARK, APLOG_DEBUG, rv, r->server,
821 "cache: updating headers with store_headers failed. "
822 "Removing cached url.");
824 rv = cache->provider->remove_url(cache->stale_handle, r->pool);
826 /* Probably a mod_disk_cache cache area has been (re)mounted
827 * read-only, or that there is a permissions problem.
829 ap_log_error(APLOG_MARK, APLOG_DEBUG, rv, r->server,
830 "cache: attempt to remove url from cache unsuccessful.");
834 return ap_pass_brigade(f->next, bb);
837 if(rv != APR_SUCCESS) {
838 ap_log_error(APLOG_MARK, APLOG_DEBUG, rv, r->server,
839 "cache: store_headers failed");
840 ap_remove_output_filter(f);
842 return ap_pass_brigade(f->next, in);
845 rv = cache->provider->store_body(cache->handle, r, in);
846 if (rv != APR_SUCCESS) {
847 ap_log_error(APLOG_MARK, APLOG_DEBUG, rv, r->server,
848 "cache: store_body failed");
849 ap_remove_output_filter(f);
852 return ap_pass_brigade(f->next, in);
856 * CACHE_REMOVE_URL filter
859 * This filter gets added in the quick handler every time the CACHE_SAVE filter
860 * gets inserted. Its purpose is to remove a confirmed stale cache entry from
863 * CACHE_REMOVE_URL has to be a protocol filter to ensure that is run even if
864 * the response is a canned error message, which removes the content filters
865 * and thus the CACHE_SAVE filter from the chain.
867 * CACHE_REMOVE_URL expects cache request rec within its context because the
868 * request this filter runs on can be different from the one whose cache entry
869 * should be removed, due to internal redirects.
871 * Note that CACHE_SAVE_URL (as a content-set filter, hence run before the
872 * protocol filters) will remove this filter if it decides to cache the file.
873 * Therefore, if this filter is left in, it must mean we need to toss any
876 static int cache_remove_url_filter(ap_filter_t *f, apr_bucket_brigade *in)
878 request_rec *r = f->r;
879 cache_request_rec *cache;
881 /* Setup cache_request_rec */
882 cache = (cache_request_rec *) f->ctx;
885 /* user likely configured CACHE_REMOVE_URL manually; they should really
886 * use mod_cache configuration to do that. So:
887 * 1. Remove ourselves
888 * 2. Do nothing and bail out
890 ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
891 "cache: CACHE_REMOVE_URL enabled unexpectedly");
892 ap_remove_output_filter(f);
893 return ap_pass_brigade(f->next, in);
895 /* Now remove this cache entry from the cache */
896 cache_remove_url(cache, r->pool);
898 /* remove ourselves */
899 ap_remove_output_filter(f);
900 return ap_pass_brigade(f->next, in);
903 /* -------------------------------------------------------------- */
904 /* Setup configurable data */
906 static void * create_cache_config(apr_pool_t *p, server_rec *s)
908 cache_server_conf *ps = apr_pcalloc(p, sizeof(cache_server_conf));
910 /* array of URL prefixes for which caching is enabled */
911 ps->cacheenable = apr_array_make(p, 10, sizeof(struct cache_enable));
912 /* array of URL prefixes for which caching is disabled */
913 ps->cachedisable = apr_array_make(p, 10, sizeof(struct cache_disable));
914 /* maximum time to cache a document */
915 ps->maxex = DEFAULT_CACHE_MAXEXPIRE;
917 ps->minex = DEFAULT_CACHE_MINEXPIRE;
919 /* default time to cache a document */
920 ps->defex = DEFAULT_CACHE_EXPIRE;
922 /* factor used to estimate Expires date from LastModified date */
923 ps->factor = DEFAULT_CACHE_LMFACTOR;
925 ps->no_last_mod_ignore_set = 0;
926 ps->no_last_mod_ignore = 0;
927 ps->ignorecachecontrol = 0;
928 ps->ignorecachecontrol_set = 0;
929 ps->store_private = 0;
930 ps->store_private_set = 0;
931 ps->store_nostore = 0;
932 ps->store_nostore_set = 0;
933 /* array of headers that should not be stored in cache */
934 ps->ignore_headers = apr_array_make(p, 10, sizeof(char *));
935 ps->ignore_headers_set = CACHE_IGNORE_HEADERS_UNSET;
936 /* flag indicating that query-string should be ignored when caching */
937 ps->ignorequerystring = 0;
938 ps->ignorequerystring_set = 0;
942 static void * merge_cache_config(apr_pool_t *p, void *basev, void *overridesv)
944 cache_server_conf *ps = apr_pcalloc(p, sizeof(cache_server_conf));
945 cache_server_conf *base = (cache_server_conf *) basev;
946 cache_server_conf *overrides = (cache_server_conf *) overridesv;
948 /* array of URL prefixes for which caching is disabled */
949 ps->cachedisable = apr_array_append(p,
951 overrides->cachedisable);
952 /* array of URL prefixes for which caching is enabled */
953 ps->cacheenable = apr_array_append(p,
955 overrides->cacheenable);
956 /* maximum time to cache a document */
957 ps->maxex = (overrides->maxex_set == 0) ? base->maxex : overrides->maxex;
958 ps->minex = (overrides->minex_set == 0) ? base->minex : overrides->minex;
959 /* default time to cache a document */
960 ps->defex = (overrides->defex_set == 0) ? base->defex : overrides->defex;
961 /* factor used to estimate Expires date from LastModified date */
963 (overrides->factor_set == 0) ? base->factor : overrides->factor;
965 ps->no_last_mod_ignore =
966 (overrides->no_last_mod_ignore_set == 0)
967 ? base->no_last_mod_ignore
968 : overrides->no_last_mod_ignore;
969 ps->ignorecachecontrol =
970 (overrides->ignorecachecontrol_set == 0)
971 ? base->ignorecachecontrol
972 : overrides->ignorecachecontrol;
974 (overrides->store_private_set == 0)
975 ? base->store_private
976 : overrides->store_private;
978 (overrides->store_nostore_set == 0)
979 ? base->store_nostore
980 : overrides->store_nostore;
982 (overrides->ignore_headers_set == CACHE_IGNORE_HEADERS_UNSET)
983 ? base->ignore_headers
984 : overrides->ignore_headers;
985 ps->ignorequerystring =
986 (overrides->ignorequerystring_set == 0)
987 ? base->ignorequerystring
988 : overrides->ignorequerystring;
991 static const char *set_cache_ignore_no_last_mod(cmd_parms *parms, void *dummy,
994 cache_server_conf *conf;
997 (cache_server_conf *)ap_get_module_config(parms->server->module_config,
999 conf->no_last_mod_ignore = flag;
1000 conf->no_last_mod_ignore_set = 1;
1005 static const char *set_cache_ignore_cachecontrol(cmd_parms *parms,
1006 void *dummy, int flag)
1008 cache_server_conf *conf;
1011 (cache_server_conf *)ap_get_module_config(parms->server->module_config,
1013 conf->ignorecachecontrol = flag;
1014 conf->ignorecachecontrol_set = 1;
1018 static const char *set_cache_store_private(cmd_parms *parms, void *dummy,
1021 cache_server_conf *conf;
1024 (cache_server_conf *)ap_get_module_config(parms->server->module_config,
1026 conf->store_private = flag;
1027 conf->store_private_set = 1;
1031 static const char *set_cache_store_nostore(cmd_parms *parms, void *dummy,
1034 cache_server_conf *conf;
1037 (cache_server_conf *)ap_get_module_config(parms->server->module_config,
1039 conf->store_nostore = flag;
1040 conf->store_nostore_set = 1;
1044 static const char *add_ignore_header(cmd_parms *parms, void *dummy,
1047 cache_server_conf *conf;
1051 (cache_server_conf *)ap_get_module_config(parms->server->module_config,
1053 if (!strncasecmp(header, "None", 4)) {
1054 /* if header None is listed clear array */
1055 conf->ignore_headers->nelts = 0;
1058 if ((conf->ignore_headers_set == CACHE_IGNORE_HEADERS_UNSET) ||
1059 (conf->ignore_headers->nelts)) {
1060 /* Only add header if no "None" has been found in header list
1062 * (When 'None' is passed, IGNORE_HEADERS_SET && nelts == 0.)
1064 new = (char **)apr_array_push(conf->ignore_headers);
1065 (*new) = (char *)header;
1068 conf->ignore_headers_set = CACHE_IGNORE_HEADERS_SET;
1072 static const char *add_cache_enable(cmd_parms *parms, void *dummy,
1076 cache_server_conf *conf;
1077 struct cache_enable *new;
1080 return apr_psprintf(parms->pool,
1081 "provider (%s) starts with a '/'. Are url and provider switched?",
1086 (cache_server_conf *)ap_get_module_config(parms->server->module_config,
1088 new = apr_array_push(conf->cacheenable);
1090 if (apr_uri_parse(parms->pool, url, &(new->url))) {
1093 if (new->url.path) {
1094 new->pathlen = strlen(new->url.path);
1097 new->url.path = "/";
1102 static const char *add_cache_disable(cmd_parms *parms, void *dummy,
1105 cache_server_conf *conf;
1106 struct cache_disable *new;
1109 (cache_server_conf *)ap_get_module_config(parms->server->module_config,
1111 new = apr_array_push(conf->cachedisable);
1112 if (apr_uri_parse(parms->pool, url, &(new->url))) {
1115 if (new->url.path) {
1116 new->pathlen = strlen(new->url.path);
1119 new->url.path = "/";
1124 static const char *set_cache_maxex(cmd_parms *parms, void *dummy,
1127 cache_server_conf *conf;
1130 (cache_server_conf *)ap_get_module_config(parms->server->module_config,
1132 conf->maxex = (apr_time_t) (atol(arg) * MSEC_ONE_SEC);
1133 conf->maxex_set = 1;
1137 static const char *set_cache_minex(cmd_parms *parms, void *dummy,
1140 cache_server_conf *conf;
1143 (cache_server_conf *)ap_get_module_config(parms->server->module_config,
1145 conf->minex = (apr_time_t) (atol(arg) * MSEC_ONE_SEC);
1146 conf->minex_set = 1;
1150 static const char *set_cache_defex(cmd_parms *parms, void *dummy,
1153 cache_server_conf *conf;
1156 (cache_server_conf *)ap_get_module_config(parms->server->module_config,
1158 conf->defex = (apr_time_t) (atol(arg) * MSEC_ONE_SEC);
1159 conf->defex_set = 1;
1163 static const char *set_cache_factor(cmd_parms *parms, void *dummy,
1166 cache_server_conf *conf;
1170 (cache_server_conf *)ap_get_module_config(parms->server->module_config,
1172 if (sscanf(arg, "%lg", &val) != 1) {
1173 return "CacheLastModifiedFactor value must be a float";
1176 conf->factor_set = 1;
1180 static const char *set_cache_ignore_querystring(cmd_parms *parms, void *dummy,
1183 cache_server_conf *conf;
1186 (cache_server_conf *)ap_get_module_config(parms->server->module_config,
1188 conf->ignorequerystring = flag;
1189 conf->ignorequerystring_set = 1;
1193 static int cache_post_config(apr_pool_t *p, apr_pool_t *plog,
1194 apr_pool_t *ptemp, server_rec *s)
1196 /* This is the means by which unusual (non-unix) os's may find alternate
1197 * means to run a given command (e.g. shebang/registry parsing on Win32)
1199 cache_generate_key = APR_RETRIEVE_OPTIONAL_FN(ap_cache_generate_key);
1200 if (!cache_generate_key) {
1201 cache_generate_key = cache_generate_key_default;
1207 static const command_rec cache_cmds[] =
1210 * Consider a new config directive that enables loading specific cache
1211 * implememtations (like mod_cache_mem, mod_cache_file, etc.).
1212 * Rather than using a LoadModule directive, admin would use something
1213 * like CacheModule mem_cache_module | file_cache_module, etc,
1214 * which would cause the approprpriate cache module to be loaded.
1215 * This is more intuitive that requiring a LoadModule directive.
1218 AP_INIT_TAKE2("CacheEnable", add_cache_enable, NULL, RSRC_CONF,
1219 "A cache type and partial URL prefix below which "
1220 "caching is enabled"),
1221 AP_INIT_TAKE1("CacheDisable", add_cache_disable, NULL, RSRC_CONF,
1222 "A partial URL prefix below which caching is disabled"),
1223 AP_INIT_TAKE1("CacheMaxExpire", set_cache_maxex, NULL, RSRC_CONF,
1224 "The maximum time in seconds to cache a document"),
1225 AP_INIT_TAKE1("CacheMinExpire", set_cache_minex, NULL, RSRC_CONF,
1226 "The minimum time in seconds to cache a document"),
1227 AP_INIT_TAKE1("CacheDefaultExpire", set_cache_defex, NULL, RSRC_CONF,
1228 "The default time in seconds to cache a document"),
1229 AP_INIT_FLAG("CacheIgnoreNoLastMod", set_cache_ignore_no_last_mod, NULL,
1231 "Ignore Responses where there is no Last Modified Header"),
1232 AP_INIT_FLAG("CacheIgnoreCacheControl", set_cache_ignore_cachecontrol,
1234 "Ignore requests from the client for uncached content"),
1235 AP_INIT_FLAG("CacheStorePrivate", set_cache_store_private,
1237 "Ignore 'Cache-Control: private' and store private content"),
1238 AP_INIT_FLAG("CacheStoreNoStore", set_cache_store_nostore,
1240 "Ignore 'Cache-Control: no-store' and store sensitive content"),
1241 AP_INIT_ITERATE("CacheIgnoreHeaders", add_ignore_header, NULL, RSRC_CONF,
1242 "A space separated list of headers that should not be "
1243 "stored by the cache"),
1244 AP_INIT_FLAG("CacheIgnoreQueryString", set_cache_ignore_querystring,
1246 "Ignore query-string when caching"),
1247 AP_INIT_TAKE1("CacheLastModifiedFactor", set_cache_factor, NULL, RSRC_CONF,
1248 "The factor used to estimate Expires date from "
1249 "LastModified date"),
1253 static void register_hooks(apr_pool_t *p)
1255 /* cache initializer */
1257 ap_hook_quick_handler(cache_url_handler, NULL, NULL, APR_HOOK_FIRST);
1259 * XXX The cache filters need to run right after the handlers and before
1260 * any other filters. Consider creating AP_FTYPE_CACHE for this purpose.
1262 * Depending on the type of request (subrequest / main request) they
1263 * need to be run before AP_FTYPE_CONTENT_SET / after AP_FTYPE_CONTENT_SET
1264 * filters. Thus create two filter handles for each type:
1265 * cache_save_filter_handle / cache_out_filter_handle to be used by
1267 * cache_save_subreq_filter_handle / cache_out_subreq_filter_handle
1268 * to be run by subrequest
1271 * CACHE_SAVE must go into the filter chain after a possible DEFLATE
1272 * filter to ensure that the compressed content is stored.
1273 * Incrementing filter type by 1 ensures his happens.
1275 cache_save_filter_handle =
1276 ap_register_output_filter("CACHE_SAVE",
1279 AP_FTYPE_CONTENT_SET+1);
1281 * CACHE_SAVE_SUBREQ must go into the filter chain before SUBREQ_CORE to
1282 * handle subrequsts. Decrementing filter type by 1 ensures this
1285 cache_save_subreq_filter_handle =
1286 ap_register_output_filter("CACHE_SAVE_SUBREQ",
1289 AP_FTYPE_CONTENT_SET-1);
1291 * CACHE_OUT must go into the filter chain after a possible DEFLATE
1292 * filter to ensure that already compressed cache objects do not
1293 * get compressed again. Incrementing filter type by 1 ensures
1296 cache_out_filter_handle =
1297 ap_register_output_filter("CACHE_OUT",
1300 AP_FTYPE_CONTENT_SET+1);
1302 * CACHE_OUT_SUBREQ must go into the filter chain before SUBREQ_CORE to
1303 * handle subrequsts. Decrementing filter type by 1 ensures this
1306 cache_out_subreq_filter_handle =
1307 ap_register_output_filter("CACHE_OUT_SUBREQ",
1310 AP_FTYPE_CONTENT_SET-1);
1311 /* CACHE_REMOVE_URL has to be a protocol filter to ensure that is
1312 * run even if the response is a canned error message, which
1313 * removes the content filters.
1315 cache_remove_url_filter_handle =
1316 ap_register_output_filter("CACHE_REMOVE_URL",
1317 cache_remove_url_filter,
1320 ap_hook_post_config(cache_post_config, NULL, NULL, APR_HOOK_REALLY_FIRST);
1323 module AP_MODULE_DECLARE_DATA cache_module =
1325 STANDARD20_MODULE_STUFF,
1326 NULL, /* create per-directory config structure */
1327 NULL, /* merge per-directory config structures */
1328 create_cache_config, /* create per-server config structure */
1329 merge_cache_config, /* merge per-server config structures */
1330 cache_cmds, /* command apr_table_t */