cache_storage.c revision 19e0a36b37350fbab6519834ef0e44e9eb62bf24
3802a3d3d7af51ddff31943d5514382f01265770Lennart Poettering/* Licensed to the Apache Software Foundation (ASF) under one or more
12b42c76672a66c2d4ea7212c14f8f1b5a62b78dTom Gundersen * contributor license agreements. See the NOTICE file distributed with
c91faef3b3facfdf13282aee957af25dd555890bLennart Poettering * this work for additional information regarding copyright ownership.
c91faef3b3facfdf13282aee957af25dd555890bLennart Poettering * The ASF licenses this file to You under the Apache License, Version 2.0
c91faef3b3facfdf13282aee957af25dd555890bLennart Poettering * (the "License"); you may not use this file except in compliance with
c91faef3b3facfdf13282aee957af25dd555890bLennart Poettering * the License. You may obtain a copy of the License at
c91faef3b3facfdf13282aee957af25dd555890bLennart Poettering * http://www.apache.org/licenses/LICENSE-2.0
5430f7f2bc7330f3088b894166bf3524a067e3d8Lennart Poettering * Unless required by applicable law or agreed to in writing, software
c91faef3b3facfdf13282aee957af25dd555890bLennart Poettering * distributed under the License is distributed on an "AS IS" BASIS,
c91faef3b3facfdf13282aee957af25dd555890bLennart Poettering * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
c91faef3b3facfdf13282aee957af25dd555890bLennart Poettering * See the License for the specific language governing permissions and
c91faef3b3facfdf13282aee957af25dd555890bLennart Poettering * limitations under the License.
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmekextern APR_OPTIONAL_FN_TYPE(ap_cache_generate_key) *cache_generate_key;
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmekextern module AP_MODULE_DECLARE_DATA cache_module;
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek/* -------------------------------------------------------------- */
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek * delete all URL entities from the cache
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmekint cache_remove_url(cache_request_rec *cache, apr_pool_t *p)
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek /* Remove the stale cache entry if present. If not, we're
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek * being called from outside of a request; remove the
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek * non-stale handle.
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek h = cache->stale_handle ? cache->stale_handle : cache->handle;
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, NULL,
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek "cache: Removing url %s from the cache", h->cache_obj->key);
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek /* for each specified cache type, delete the URL */
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek list->provider->remove_url(h, p);
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek * create a new URL entity in the cache
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek * It is possible to store more than once entity per URL. This
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek * function will always create a new entity, regardless of whether
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek * other entities already exist for the same URL.
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek * The size of the entity is provided so that a cache module can
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek * decide whether or not it wants to cache this particular entity.
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek * If the size is unknown, a size of -1 should be set.
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmekint cache_create_entity(cache_request_rec *cache, request_rec *r,
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek apr_off_t size, apr_bucket_brigade *in)
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek cache_handle_t *h = apr_pcalloc(r->pool, sizeof(cache_handle_t));
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek /* This should never happen */
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek ap_log_error(APLOG_MARK, APLOG_ERR, APR_EGENERAL, r->server,
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek "cache: No cache request information available for key"
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek rv = cache_generate_key(r, r->pool, &cache->key);
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek /* for each specified cache type, delete the URL */
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek switch (rv = list->provider->create_entity(h, r, cache->key, size, in)) {
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek cache->provider = list->provider;
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek cache->provider_name = list->provider_name;
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmekstatic int set_cookie_doo_doo(void *v, const char *key, const char *val)
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek * Take headers from the cache, and overlap them over the existing response
9407bc2d03b6405754807b6f38c8ca95b4fc1f40Zbigniew Jędrzejewski-Szmekvoid cache_accept_headers(cache_handle_t *h, request_rec *r,
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek apr_table_t *cookie_table, *hdr_copy;
71418295125c542d3edd1e7251bb0701ef1af89bZbigniew Jędrzejewski-Szmek v = apr_table_get(h->resp_hdrs, "Content-Type");
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek apr_table_unset(h->resp_hdrs, "Content-Type");
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek * Also unset possible Content-Type headers in r->headers_out and
71418295125c542d3edd1e7251bb0701ef1af89bZbigniew Jędrzejewski-Szmek * r->err_headers_out as they may be different to what we have received
71418295125c542d3edd1e7251bb0701ef1af89bZbigniew Jędrzejewski-Szmek * from the cache.
71418295125c542d3edd1e7251bb0701ef1af89bZbigniew Jędrzejewski-Szmek * Actually they are not needed as r->content_type set by
9407bc2d03b6405754807b6f38c8ca95b4fc1f40Zbigniew Jędrzejewski-Szmek * ap_set_content_type above will be used in the store_headers functions
9407bc2d03b6405754807b6f38c8ca95b4fc1f40Zbigniew Jędrzejewski-Szmek * of the storage providers as a fallback and the HTTP_HEADER filter
b938cb902c3b5bca807a94b277672c64d6767886Jan Engelhardt * does overwrite the Content-Type header with r->content_type anyway.
9407bc2d03b6405754807b6f38c8ca95b4fc1f40Zbigniew Jędrzejewski-Szmek apr_table_unset(r->headers_out, "Content-Type");
9407bc2d03b6405754807b6f38c8ca95b4fc1f40Zbigniew Jędrzejewski-Szmek apr_table_unset(r->err_headers_out, "Content-Type");
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek /* If the cache gave us a Last-Modified header, we can't just
9407bc2d03b6405754807b6f38c8ca95b4fc1f40Zbigniew Jędrzejewski-Szmek * pass it on blindly because of restrictions on future values.
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek v = apr_table_get(h->resp_hdrs, "Last-Modified");
9407bc2d03b6405754807b6f38c8ca95b4fc1f40Zbigniew Jędrzejewski-Szmek ap_update_mtime(r, apr_date_parse_http(v));
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek apr_table_unset(h->resp_hdrs, "Last-Modified");
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek /* The HTTP specification says that it is legal to merge duplicate
7284335adbb8cb2bc9c11f9e102906da1bf71145Zbigniew Jędrzejewski-Szmek * headers into one. Some browsers that support Cookies don't like
7284335adbb8cb2bc9c11f9e102906da1bf71145Zbigniew Jędrzejewski-Szmek * merged headers and prefer that each Set-Cookie header is sent
7284335adbb8cb2bc9c11f9e102906da1bf71145Zbigniew Jędrzejewski-Szmek * separately. Lets humour those browsers by not merging.
9407bc2d03b6405754807b6f38c8ca95b4fc1f40Zbigniew Jędrzejewski-Szmek * Oh what a pain it is.
9407bc2d03b6405754807b6f38c8ca95b4fc1f40Zbigniew Jędrzejewski-Szmek apr_table_do(set_cookie_doo_doo, cookie_table, r->err_headers_out,
9407bc2d03b6405754807b6f38c8ca95b4fc1f40Zbigniew Jędrzejewski-Szmek apr_table_do(set_cookie_doo_doo, cookie_table, h->resp_hdrs,
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek apr_table_unset(r->err_headers_out, "Set-Cookie");
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek apr_table_unset(h->resp_hdrs, "Set-Cookie");
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek hdr_copy = apr_table_copy(r->pool, h->resp_hdrs);
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek apr_table_overlap(hdr_copy, r->headers_out, APR_OVERLAP_TABLES_SET);
3ba3a79df4ae094d1008c04a9af8d1ff970124c4Zbigniew Jędrzejewski-Szmek apr_table_overlap(r->headers_out, h->resp_hdrs, APR_OVERLAP_TABLES_SET);
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek if (!apr_is_empty_table(cookie_table)) {
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek r->err_headers_out = apr_table_overlay(r->pool, r->err_headers_out,
cache_handle_t *h;
if (!cache) {
return DECLINED;
return DECLINED;
return DECLINED;
while (list) {
case OK: {
++vary;
++vary;
r->server,
if (mismatch) {
if (!fresh) {
r->headers_in);
if (etag) {
if (lastmod) {
lastmod);
return DECLINED;
int irv;
cache_accept_headers(h, r, 0);
return OK;
case DECLINED: {
return rv;
return HTTP_GATEWAY_TIME_OUT;
return DECLINED;
const char **key)
if (*key) {
return APR_SUCCESS;
&cache_module);
if (!hostname) {
* scheme for this request. As r->parsed_uri.scheme is not set if this
char **identifier;
int len;
char *param;
if (querystring) {
char *complete;
if (param) {
param++;
if (param) {
char *amp;
if (*querystring) {
return APR_SUCCESS;