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