Apache HTTPD
cache_storage.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
23
25
26extern module AP_MODULE_DECLARE_DATA cache_module;
27
28/* -------------------------------------------------------------- */
29
30/*
31 * delete all URL entities from the cache
32 *
33 */
35{
38
39 list = cache->providers;
40
41 /* Remove the stale cache entry if present. If not, we're
42 * being called from outside of a request; remove the
43 * non-stale handle.
44 */
45 h = cache->stale_handle ? cache->stale_handle : cache->handle;
46 if (!h) {
47 return OK;
48 }
50 "cache: Removing url %s from the cache", h->cache_obj->key);
51
52 /* for each specified cache type, delete the URL */
53 while (list) {
54 list->provider->remove_url(h, r);
55 list = list->next;
56 }
57 return OK;
58}
59
60
61/*
62 * create a new URL entity in the cache
63 *
64 * It is possible to store more than once entity per URL. This
65 * function will always create a new entity, regardless of whether
66 * other entities already exist for the same URL.
67 *
68 * The size of the entity is provided so that a cache module can
69 * decide whether or not it wants to cache this particular entity.
70 * If the size is unknown, a size of -1 should be set.
71 */
74{
77 apr_status_t rv;
78
79 if (!cache) {
80 /* This should never happen */
82 "cache: No cache request information available for key"
83 " generation");
84 return APR_EGENERAL;
85 }
86
87 if (!cache->key) {
88 rv = cache_generate_key(r, r->pool, &cache->key);
89 if (rv != APR_SUCCESS) {
90 return rv;
91 }
92 }
93
94 list = cache->providers;
95 /* for each specified cache type, delete the URL */
96 while (list) {
97 switch (rv = list->provider->create_entity(h, r, cache->key, size, in)) {
98 case OK: {
99 cache->handle = h;
100 cache->provider = list->provider;
101 cache->provider_name = list->provider_name;
102 return OK;
103 }
104 case DECLINED: {
105 list = list->next;
106 continue;
107 }
108 default: {
109 return rv;
110 }
111 }
112 }
113 return DECLINED;
114}
115
116static int filter_header_do(void *v, const char *key, const char *val)
117{
118 if ((*key == 'W' || *key == 'w') && !ap_cstr_casecmp(key, "Warning")
119 && *val == '1') {
120 /* any stored Warning headers with warn-code 1xx (see section
121 * 14.46) MUST be deleted from the cache entry and the forwarded
122 * response.
123 */
124 }
125 else {
127 }
128 return 1;
129}
130static int remove_header_do(void *v, const char *key, const char *val)
131{
132 if ((*key == 'W' || *key == 'w') && !ap_cstr_casecmp(key, "Warning")) {
133 /* any stored Warning headers with warn-code 2xx MUST be retained
134 * in the cache entry and the forwarded response.
135 */
136 }
137 else {
139 }
140 return 1;
141}
142static int add_header_do(void *v, const char *key, const char *val)
143{
145 return 1;
146}
147
162 apr_table_t *bottom, int revalidation)
163{
164 const char *v;
165
166 if (revalidation) {
169 }
170 else if (r->headers_out != bottom) {
171 r->headers_out = apr_table_copy(r->pool, bottom);
172 }
175
176 v = apr_table_get(r->headers_out, "Content-Type");
177 if (v) {
179 /*
180 * Also unset possible Content-Type headers in r->headers_out and
181 * r->err_headers_out as they may be different to what we have received
182 * from the cache.
183 * Actually they are not needed as r->content_type set by
184 * ap_set_content_type above will be used in the store_headers functions
185 * of the storage providers as a fallback and the HTTP_HEADER filter
186 * does overwrite the Content-Type header with r->content_type anyway.
187 */
188 apr_table_unset(r->headers_out, "Content-Type");
189 apr_table_unset(r->err_headers_out, "Content-Type");
190 }
191
192 /* If the cache gave us a Last-Modified header, we can't just
193 * pass it on blindly because of restrictions on future values.
194 */
195 v = apr_table_get(r->headers_out, "Last-Modified");
196 if (v) {
199 }
200
201}
202
203/*
204 * select a specific URL entity in the cache
205 *
206 * It is possible to store more than one entity per URL. Content
207 * negotiation is used to select an entity. Once an entity is
208 * selected, details of it are stored in the per request
209 * config to save time when serving the request later.
210 *
211 * This function returns OK if successful, DECLINED if no
212 * cached entity fits the bill.
213 */
215{
217 apr_status_t rv;
219
220 if (!cache) {
221 /* This should never happen */
223 "cache: No cache request information available for key"
224 " generation");
225 return DECLINED;
226 }
227
228 /* if no-cache, we can't serve from the cache, but we may store to the
229 * cache.
230 */
232 return DECLINED;
233 }
234
235 if (!cache->key) {
236 rv = cache_generate_key(r, r->pool, &cache->key);
237 if (rv != APR_SUCCESS) {
238 return DECLINED;
239 }
240 }
241
242 /* go through the cache types till we get a match */
243 h = apr_palloc(r->pool, sizeof(cache_handle_t));
244
245 list = cache->providers;
246
247 while (list) {
248 switch ((rv = list->provider->open_entity(h, r, cache->key))) {
249 case OK: {
250 char *vary = NULL;
251 int mismatch = 0;
252 char *last = NULL;
253
254 if (list->provider->recall_headers(h, r) != APR_SUCCESS) {
255 /* try again with next cache type */
256 list = list->next;
257 continue;
258 }
259
260 /*
261 * Check Content-Negotiation - Vary
262 *
263 * At this point we need to make sure that the object we found in
264 * the cache is the same object that would be delivered to the
265 * client, when the effects of content negotiation are taken into
266 * effect.
267 *
268 * In plain english, we want to make sure that a language-negotiated
269 * document in one language is not given to a client asking for a
270 * language negotiated document in a different language by mistake.
271 *
272 * This code makes the assumption that the storage manager will
273 * cache the req_hdrs if the response contains a Vary header.
274 *
275 * RFC2616 13.6 and 14.44 describe the Vary mechanism.
276 */
277 vary = cache_strqtok(
279 cache_table_getm(r->pool, h->resp_hdrs, "Vary")),
281 while (vary) {
282 const char *h1, *h2;
283
284 /*
285 * is this header in the request and the header in the cached
286 * request identical? If not, we give up and do a straight get
287 */
288 h1 = cache_table_getm(r->pool, r->headers_in, vary);
289 h2 = cache_table_getm(r->pool, h->req_hdrs, vary);
290 if (h1 == h2) {
291 /* both headers NULL, so a match - do nothing */
292 }
293 else if (h1 && h2 && !strcmp(h1, h2)) {
294 /* both headers exist and are equal - do nothing */
295 }
296 else {
297 /* headers do not match, so Vary failed */
299 r, APLOGNO(00694) "cache_select(): Vary header mismatch.");
300 mismatch = 1;
301 break;
302 }
304 }
305
306 /* no vary match, try next provider */
307 if (mismatch) {
308 /* try again with next cache type */
309 list = list->next;
310 continue;
311 }
312
313 cache->provider = list->provider;
314 cache->provider_name = list->provider_name;
315
316 /*
317 * RFC2616 13.3.4 Rules for When to Use Entity Tags and Last-Modified
318 * Dates: An HTTP/1.1 caching proxy, upon receiving a conditional request
319 * that includes both a Last-Modified date and one or more entity tags as
320 * cache validators, MUST NOT return a locally cached response to the
321 * client unless that cached response is consistent with all of the
322 * conditional header fields in the request.
323 */
325 || ap_condition_if_unmodified_since(r, h->resp_hdrs)
327 || ap_condition_if_none_match(r, h->resp_hdrs)
329 || ap_condition_if_modified_since(r, h->resp_hdrs)
331 || ap_condition_if_range(r, h->resp_hdrs) == AP_CONDITION_NOMATCH) {
332 mismatch = 1;
333 }
334
335 /* Is our cached response fresh enough? */
337 const char *etag, *lastmod;
338
339 /* Cache-Control: only-if-cached and revalidation required, try
340 * the next provider
341 */
342 if (cache->control_in.only_if_cached) {
343 /* try again with next cache type */
344 list = list->next;
345 continue;
346 }
347
348 /* set aside the stale entry for accessing later */
349 cache->stale_headers = apr_table_copy(r->pool,
350 r->headers_in);
351 cache->stale_handle = h;
352
353 /* if no existing conditionals, use conditionals of our own */
354 if (!mismatch) {
355
357 APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, r, APLOGNO(00695) "Cached response for %s isn't fresh. Adding "
358 "conditional request headers.", r->uri);
359
360 /* Remove existing conditionals that might conflict with ours */
361 apr_table_unset(r->headers_in, "If-Match");
362 apr_table_unset(r->headers_in, "If-Modified-Since");
363 apr_table_unset(r->headers_in, "If-None-Match");
364 apr_table_unset(r->headers_in, "If-Range");
365 apr_table_unset(r->headers_in, "If-Unmodified-Since");
366
367 etag = apr_table_get(h->resp_hdrs, "ETag");
368 lastmod = apr_table_get(h->resp_hdrs, "Last-Modified");
369
370 if (etag || lastmod) {
371 /* If we have a cached etag and/or Last-Modified add in
372 * our own conditionals.
373 */
374
375 if (etag) {
376 apr_table_set(r->headers_in, "If-None-Match", etag);
377 }
378
379 if (lastmod) {
380 apr_table_set(r->headers_in, "If-Modified-Since",
381 lastmod);
382 }
383
384 /*
385 * Do not do Range requests with our own conditionals: If
386 * we get 304 the Range does not matter and otherwise the
387 * entity changed and we want to have the complete entity
388 */
389 apr_table_unset(r->headers_in, "Range");
390
391 }
392
393 }
394
395 /* ready to revalidate, pretend we were never here */
396 return DECLINED;
397 }
398
399 /* Okay, this response looks okay. Merge in our stuff and go. */
400 cache_accept_headers(h, r, h->resp_hdrs, r->headers_out, 0);
401
402 cache->handle = h;
403 return OK;
404 }
405 case DECLINED: {
406 /* try again with next cache type */
407 list = list->next;
408 continue;
409 }
410 default: {
411 /* oo-er! an error */
412 return rv;
413 }
414 }
415 }
416
417 /* if Cache-Control: only-if-cached, and not cached, return 504 */
418 if (cache->control_in.only_if_cached) {
420 "cache: 'only-if-cached' requested and no cached entity, "
421 "returning 504 Gateway Timeout for: %s", r->uri);
423 }
424
425 return DECLINED;
426}
427
429 const char *path, const char *query,
430 apr_uri_t *parsed_uri,
431 const char **key)
432{
433 cache_server_conf *conf;
434 char *port_str, *hn, *lcs;
435 const char *hostname, *scheme;
436 int i;
437 const char *kpath;
438 const char *kquery;
439
440 if (*key) {
441 /*
442 * We have been here before during the processing of this request.
443 */
444 return APR_SUCCESS;
445 }
446
447 /*
448 * Get the module configuration. We need this for the CacheIgnoreQueryString
449 * option below.
450 */
452 &cache_module);
453
454 /*
455 * Use the canonical name to improve cache hit rate, but only if this is
456 * not a proxy request or if this is a reverse proxy request.
457 * We need to handle both cases in the same manner as for the reverse proxy
458 * case we have the following situation:
459 *
460 * If a cached entry is looked up by mod_cache's quick handler r->proxyreq
461 * is still unset in the reverse proxy case as it only gets set in the
462 * translate name hook (either by ProxyPass or mod_rewrite) which is run
463 * after the quick handler hook. This is different to the forward proxy
464 * case where it gets set before the quick handler is run (in the
465 * post_read_request hook).
466 * If a cache entry is created by the CACHE_SAVE filter we always have
467 * r->proxyreq set correctly.
468 * So we must ensure that in the reverse proxy case we use the same code
469 * path and using the canonical name seems to be the right thing to do
470 * in the reverse proxy case.
471 */
472 if (!r->proxyreq || (r->proxyreq == PROXYREQ_REVERSE)) {
473 if (conf->base_uri && conf->base_uri->hostname) {
474 hostname = conf->base_uri->hostname;
475 }
476 else {
477 /* Use _default_ as the hostname if none present, as in mod_vhost */
479 if (!hostname) {
480 hostname = "_default_";
481 }
482 }
483 }
484 else if (parsed_uri->hostname) {
485 /* Copy the parsed uri hostname */
486 hn = apr_pstrdup(p, parsed_uri->hostname);
488 /* const work-around */
489 hostname = hn;
490 }
491 else {
492 /* We are a proxied request, with no hostname. Unlikely
493 * to get very far - but just in case */
494 hostname = "_default_";
495 }
496
497 /*
498 * Copy the scheme, ensuring that it is lower case. If the parsed uri
499 * contains no string or if this is not a proxy request get the http
500 * scheme for this request. As r->parsed_uri.scheme is not set if this
501 * is a reverse proxy request, it is ensured that the cases
502 * "no proxy request" and "reverse proxy request" are handled in the same
503 * manner (see above why this is needed).
504 */
505 if (r->proxyreq && parsed_uri->scheme) {
506 /* Copy the scheme and lower-case it */
507 lcs = apr_pstrdup(p, parsed_uri->scheme);
509 /* const work-around */
510 scheme = lcs;
511 }
512 else {
513 if (conf->base_uri && conf->base_uri->scheme) {
514 scheme = conf->base_uri->scheme;
515 }
516 else {
517 scheme = ap_http_scheme(r);
518 }
519 }
520
521 /*
522 * If this is a proxy request, but not a reverse proxy request (see comment
523 * above why these cases must be handled in the same manner), copy the
524 * URI's port-string (which may be a service name). If the URI contains
525 * no port-string, use apr-util's notion of the default port for that
526 * scheme - if available. Otherwise use the port-number of the current
527 * server.
528 */
529 if (r->proxyreq && (r->proxyreq != PROXYREQ_REVERSE)) {
530 if (parsed_uri->port_str) {
531 port_str = apr_pcalloc(p, strlen(parsed_uri->port_str) + 2);
532 port_str[0] = ':';
533 for (i = 0; parsed_uri->port_str[i]; i++) {
534 port_str[i + 1] = apr_tolower(parsed_uri->port_str[i]);
535 }
536 }
537 else if (apr_uri_port_of_scheme(scheme)) {
538 port_str = apr_psprintf(p, ":%u", apr_uri_port_of_scheme(scheme));
539 }
540 else {
541 /* No port string given in the AbsoluteUri, and we have no
542 * idea what the default port for the scheme is. Leave it
543 * blank and live with the inefficiency of some extra cached
544 * entities.
545 */
546 port_str = "";
547 }
548 }
549 else {
550 if (conf->base_uri && conf->base_uri->port_str) {
551 port_str = apr_pstrcat(p, ":", conf->base_uri->port_str, NULL);
552 }
553 else if (conf->base_uri && conf->base_uri->hostname) {
554 port_str = "";
555 }
556 else {
557 /* Use the server port */
558 port_str = apr_psprintf(p, ":%u", ap_get_server_port(r));
559 }
560 }
561
562 /*
563 * Check if we need to ignore session identifiers in the URL and do so
564 * if needed.
565 */
566 kpath = path;
568 if (conf->ignore_session_id->nelts) {
569 int i;
570 char **identifier;
571
572 identifier = (char **) conf->ignore_session_id->elts;
573 for (i = 0; i < conf->ignore_session_id->nelts; i++, identifier++) {
574 int len;
575 const char *param;
576
577 len = strlen(*identifier);
578 /*
579 * Check that we have a parameter separator in the last segment
580 * of the path and that the parameter matches our identifier
581 */
582 if ((param = ap_strrchr_c(kpath, ';'))
583 && !strncmp(param + 1, *identifier, len)
584 && (*(param + len + 1) == '=')
585 && !ap_strchr_c(param + len + 2, '/')) {
587 continue;
588 }
589 /*
590 * Check if the identifier is in the query string and cut it out.
591 */
592 if (kquery && *kquery) {
593 /*
594 * First check if the identifier is at the beginning of the
595 * query string and followed by a '='
596 */
597 if (!strncmp(kquery, *identifier, len) && kquery[len] == '=') {
598 param = kquery;
599 }
600 else {
601 char *complete;
602
603 /*
604 * In order to avoid subkey matching (PR 48401) prepend
605 * identifier with a '&' and append a '='
606 */
607 complete = apr_pstrcat(p, "&", *identifier, "=", NULL);
608 param = ap_strstr_c(kquery, complete);
609 /* If we found something we are sitting on the '&' */
610 if (param) {
611 param++;
612 }
613 }
614 if (param) {
615 const char *amp;
616 char *dup = NULL;
617
618 if (kquery != param) {
620 kquery = dup;
621 }
622 else {
623 kquery = "";
624 }
625
626 if ((amp = ap_strchr_c(param + len + 1, '&'))) {
627 kquery = apr_pstrcat(p, kquery, amp + 1, NULL);
628 }
629 else {
630 /*
631 * If query string is not "", then we have the case
632 * that the identifier parameter we removed was the
633 * last one in the original query string. Hence we have
634 * a trailing '&' which needs to be removed.
635 */
636 if (dup) {
637 dup[strlen(dup) - 1] = '\0';
638 }
639 }
640 }
641 }
642 }
643 }
644
645 /* Key format is a URI, optionally without the query-string (NULL
646 * per above if conf->ignorequerystring)
647 */
648 *key = apr_pstrcat(p, scheme, "://", hostname, port_str,
649 kpath, "?", kquery, NULL);
650
651 /*
652 * Store the key in the request_config for the cache as r->parsed_uri
653 * might have changed in the time from our first visit here triggered by the
654 * quick handler and our possible second visit triggered by the CACHE_SAVE
655 * filter (e.g. r->parsed_uri got unescaped). In this case we would save the
656 * resource in the cache under a key where it is never found by the quick
657 * handler during following requests.
658 */
660 "cache: Key for entity %s?%s is %s", path, query, *key);
661
662 return APR_SUCCESS;
663}
664
666 const char **key)
667{
668 /* In early processing (quick-handler, forward proxy), we want the initial
669 * query-string from r->parsed_uri, since any change before CACHE_SAVE
670 * shouldn't modify the key. Otherwise we want the actual query-string.
671 */
672 const char *path = r->uri;
673 const char *query = r->args;
674 if (cache_use_early_url(r)) {
677 }
679}
680
681/*
682 * Invalidate a specific URL entity in all caches
683 *
684 * All cached entities for this URL are removed, usually in
685 * response to a POST/PUT or DELETE.
686 *
687 * This function returns OK if at least one entity was found and
688 * removed, and DECLINED if no cached entities were removed.
689 */
691{
697
698 const char *location, *location_key = NULL;
700
701 if (!cache) {
702 /* This should never happen */
704 APLOG_MARK, APLOG_ERR, APR_EGENERAL, r, APLOGNO(00697) "cache: No cache request information available for key"
705 " generation");
706 return DECLINED;
707 }
708
709 if (!cache->key) {
710 rv = cache_generate_key(r, r->pool, &cache->key);
711 if (rv != APR_SUCCESS) {
712 return DECLINED;
713 }
714 }
715
716 location = apr_table_get(r->headers_out, "Location");
717 if (location) {
718 if (apr_uri_parse(r->pool, location, &location_uri)
720 location_uri.path,
721 location_uri.query,
723 || !(r->parsed_uri.hostname
724 && location_uri.hostname
726 location_uri.hostname))) {
728 }
729 }
730
731 content_location = apr_table_get(r->headers_out, "Content-Location");
732 if (content_location) {
740 || !(r->parsed_uri.hostname
741 && content_location_uri.hostname
743 content_location_uri.hostname))) {
745 }
746 }
747
748 /* go through the cache types */
749 h = apr_palloc(r->pool, sizeof(cache_handle_t));
750
751 list = cache->providers;
752
753 while (list) {
754
755 /* invalidate the request uri */
756 rv = list->provider->open_entity(h, r, cache->key);
757 if (OK == rv) {
758 rv = list->provider->invalidate_entity(h, r);
759 status = OK;
760 }
762 APLOG_MARK, APLOG_DEBUG, rv, r, APLOGNO(02468) "cache: Attempted to invalidate cached entity with key: %s", cache->key);
763
764 /* invalidate the Location */
765 if (location_key) {
766 rv = list->provider->open_entity(h, r, location_key);
767 if (OK == rv) {
768 rv = list->provider->invalidate_entity(h, r);
769 status = OK;
770 }
772 APLOG_MARK, APLOG_DEBUG, rv, r, APLOGNO(02469) "cache: Attempted to invalidate cached entity with key: %s", location_key);
773 }
774
775 /* invalidate the Content-Location */
777 rv = list->provider->open_entity(h, r, content_location_key);
778 if (OK == rv) {
779 rv = list->provider->invalidate_entity(h, r);
780 status = OK;
781 }
783 APLOG_MARK, APLOG_DEBUG, rv, r, APLOGNO(02470) "cache: Attempted to invalidate cached entity with key: %s", content_location_key);
784 }
785
786 list = list->next;
787 }
788
789 return status;
790}
const char apr_size_t len
Definition ap_regex.h:187
static int filter_header_do(void *v, const char *key, const char *val)
static apr_status_t cache_canonicalise_key(request_rec *r, apr_pool_t *p, const char *path, const char *query, apr_uri_t *parsed_uri, const char **key)
static int remove_header_do(void *v, const char *key, const char *val)
apr_OFN_ap_cache_generate_key_t * cache_generate_key
Definition mod_cache.c:23
static int add_header_do(void *v, const char *key, const char *val)
Cache Storage Functions.
Cache Storage Functions.
#define APLOG_USE_MODULE(foo)
#define ap_get_module_config(v, m)
const char * hostname
request_rec int int apr_table_t const char * path
request_rec * r
#define ap_http_scheme(r)
Definition httpd.h:297
#define DECLINED
Definition httpd.h:457
#define OK
Definition httpd.h:456
apr_port_t ap_get_server_port(const request_rec *r)
Definition core.c:1199
const char * ap_get_server_name(request_rec *r)
Definition core.c:1145
#define APLOGNO(n)
Definition http_log.h:117
#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_DEBUG
Definition http_log.h:71
ap_condition_e ap_condition_if_modified_since(request_rec *r, apr_table_t *headers)
ap_condition_e ap_condition_if_range(request_rec *r, apr_table_t *headers)
ap_condition_e ap_condition_if_unmodified_since(request_rec *r, apr_table_t *headers)
void ap_set_last_modified(request_rec *r)
Definition protocol.c:2280
void ap_set_content_type(request_rec *r, const char *ct)
ap_condition_e ap_condition_if_match(request_rec *r, apr_table_t *headers)
ap_condition_e ap_condition_if_none_match(request_rec *r, apr_table_t *headers)
@ AP_CONDITION_NOMATCH
void ap_update_mtime(request_rec *r, apr_time_t dependency_mtime)
Definition request.c:2557
#define APR_EGENERAL
Definition apr_errno.h:313
apr_pool_t apr_dbd_t const char * query
Definition apr_dbd.h:396
#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)
char * cache_strqtok(char *str, const char *sep, char **last)
Definition cache_util.c:929
#define CACHE_SEPARATOR
Definition cache_util.h:102
int ap_cache_check_no_cache(cache_request_rec *cache, request_rec *r)
Definition cache_util.c:450
const char * cache_table_getm(apr_pool_t *p, const apr_table_t *t, const char *key)
int cache_check_freshness(cache_handle_t *h, cache_request_rec *cache, request_rec *r)
Definition cache_util.c:533
int cache_use_early_url(request_rec *r)
Definition cache_util.c:130
#define HTTP_GATEWAY_TIME_OUT
Definition httpd.h:539
int ap_cstr_casecmp(const char *s1, const char *s2)
Definition util.c:3542
#define ap_strrchr_c(s, c)
Definition httpd.h:2357
#define ap_strstr_c(s, c)
Definition httpd.h:2361
#define ap_strchr_c(s, c)
Definition httpd.h:2353
void ap_str_tolower(char *s)
Definition util.c:2410
#define PROXYREQ_REVERSE
Definition httpd.h:1135
apr_size_t size
apr_uint32_t val
Definition apr_atomic.h:66
const apr_array_header_t * list
Definition apr_cstr.h:105
#define apr_tolower(c)
Definition apr_lib.h:231
#define APR_SUCCESS
Definition apr_errno.h:225
int apr_status_t
Definition apr_errno.h:44
const char * key
const apr_hash_t * h
Definition apr_hash.h:97
const apr_hash_t * h1
Definition apr_hash.h:232
const apr_hash_t const apr_hash_t * h2
Definition apr_hash.h:233
#define apr_pcalloc(p, size)
Definition apr_pools.h:465
const char char ** last
apr_int32_t in
int int status
apr_pool_t * p
Definition md_event.c:32
Main include file for the Apache Transparent Cache.
struct param_s param
return NULL
Definition mod_so.c:359
int i
Definition mod_so.c:347
char * scheme
Definition apr_uri.h:87
char * path
Definition apr_uri.h:99
char * query
Definition apr_uri.h:101
char * hostname
Definition apr_uri.h:95
char * port_str
Definition apr_uri.h:97
apr_uri_t * base_uri
Definition cache_util.h:129
unsigned int ignorequerystring
Definition cache_util.h:133
apr_array_header_t * ignore_session_id
Definition cache_util.h:126
A structure that represents the current request.
Definition httpd.h:845
char * uri
Definition httpd.h:1016
apr_pool_t * pool
Definition httpd.h:847
apr_uri_t parsed_uri
Definition httpd.h:1092
int proxyreq
Definition httpd.h:873
apr_table_t * err_headers_out
Definition httpd.h:981
apr_table_t * headers_in
Definition httpd.h:976
server_rec * server
Definition httpd.h:851
char * args
Definition httpd.h:1026
apr_table_t * headers_out
Definition httpd.h:978
struct ap_conf_vector_t * module_config
Definition httpd.h:1341