mod_disk_cache.c revision 524cd27a7865687dcc0e0010a3bbf1f438befb0f
842ae4bd224140319ae7feec1872b93dfd491143fielding/* ====================================================================
842ae4bd224140319ae7feec1872b93dfd491143fielding * The Apache Software License, Version 1.1
842ae4bd224140319ae7feec1872b93dfd491143fielding *
842ae4bd224140319ae7feec1872b93dfd491143fielding * Copyright (c) 2000 The Apache Software Foundation. All rights
842ae4bd224140319ae7feec1872b93dfd491143fielding * reserved.
842ae4bd224140319ae7feec1872b93dfd491143fielding *
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * Redistribution and use in source and binary forms, with or without
04891cf70e0bfc38bfb027541dc821f04c754ff7nd * modification, are permitted provided that the following conditions
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * are met:
04891cf70e0bfc38bfb027541dc821f04c754ff7nd *
04891cf70e0bfc38bfb027541dc821f04c754ff7nd * 1. Redistributions of source code must retain the above copyright
04891cf70e0bfc38bfb027541dc821f04c754ff7nd * notice, this list of conditions and the following disclaimer.
04891cf70e0bfc38bfb027541dc821f04c754ff7nd *
04891cf70e0bfc38bfb027541dc821f04c754ff7nd * 2. Redistributions in binary form must reproduce the above copyright
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * notice, this list of conditions and the following disclaimer in
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * the documentation and/or other materials provided with the
3568de757bac0b47256647504c186d17ca272f85rbb * distribution.
3568de757bac0b47256647504c186d17ca272f85rbb *
3568de757bac0b47256647504c186d17ca272f85rbb * 3. The end-user documentation included with the redistribution,
3568de757bac0b47256647504c186d17ca272f85rbb * if any, must include the following acknowledgment:
3568de757bac0b47256647504c186d17ca272f85rbb * "This product includes software developed by the
3568de757bac0b47256647504c186d17ca272f85rbb * Apache Software Foundation (http://www.apache.org/)."
3568de757bac0b47256647504c186d17ca272f85rbb * Alternately, this acknowledgment may appear in the software itself,
3568de757bac0b47256647504c186d17ca272f85rbb * if and wherever such third-party acknowledgments normally appear.
3568de757bac0b47256647504c186d17ca272f85rbb *
3568de757bac0b47256647504c186d17ca272f85rbb * 4. The names "Apache" and "Apache Software Foundation" must
3568de757bac0b47256647504c186d17ca272f85rbb * not be used to endorse or promote products derived from this
3568de757bac0b47256647504c186d17ca272f85rbb * software without prior written permission. For written
3568de757bac0b47256647504c186d17ca272f85rbb * permission, please contact apache@apache.org.
3568de757bac0b47256647504c186d17ca272f85rbb *
3568de757bac0b47256647504c186d17ca272f85rbb * 5. Products derived from this software may not be called "Apache",
3568de757bac0b47256647504c186d17ca272f85rbb * nor may "Apache" appear in their name, without prior written
3568de757bac0b47256647504c186d17ca272f85rbb * permission of the Apache Software Foundation.
3568de757bac0b47256647504c186d17ca272f85rbb *
3568de757bac0b47256647504c186d17ca272f85rbb * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
3568de757bac0b47256647504c186d17ca272f85rbb * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
3568de757bac0b47256647504c186d17ca272f85rbb * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
3568de757bac0b47256647504c186d17ca272f85rbb * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
3568de757bac0b47256647504c186d17ca272f85rbb * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
3568de757bac0b47256647504c186d17ca272f85rbb * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
3568de757bac0b47256647504c186d17ca272f85rbb * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
3568de757bac0b47256647504c186d17ca272f85rbb * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
3568de757bac0b47256647504c186d17ca272f85rbb * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
3568de757bac0b47256647504c186d17ca272f85rbb * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
3568de757bac0b47256647504c186d17ca272f85rbb * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3568de757bac0b47256647504c186d17ca272f85rbb * SUCH DAMAGE.
3568de757bac0b47256647504c186d17ca272f85rbb * ====================================================================
3568de757bac0b47256647504c186d17ca272f85rbb *
3568de757bac0b47256647504c186d17ca272f85rbb * This software consists of voluntary contributions made by many
3568de757bac0b47256647504c186d17ca272f85rbb * individuals on behalf of the Apache Software Foundation. For more
3568de757bac0b47256647504c186d17ca272f85rbb * information on the Apache Software Foundation, please see
3568de757bac0b47256647504c186d17ca272f85rbb * <http://www.apache.org/>.
3568de757bac0b47256647504c186d17ca272f85rbb *
3568de757bac0b47256647504c186d17ca272f85rbb * Portions of this software are based upon public domain software
3568de757bac0b47256647504c186d17ca272f85rbb * originally written at the National Center for Supercomputing Applications,
3568de757bac0b47256647504c186d17ca272f85rbb * University of Illinois, Urbana-Champaign.
3568de757bac0b47256647504c186d17ca272f85rbb */
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding#include "mod_cache.h"
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding#include "apr_file_io.h"
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding#include "apr_strings.h"
3568de757bac0b47256647504c186d17ca272f85rbb#include "http_config.h"
cd8f8c995d415473f3bfb0b329b2450f2a722c3atrawick#include "http_log.h"
3568de757bac0b47256647504c186d17ca272f85rbb#include "util_filter.h"
3568de757bac0b47256647504c186d17ca272f85rbb
3568de757bac0b47256647504c186d17ca272f85rbbmodule MODULE_VAR_EXPORT disk_cache_module;
3568de757bac0b47256647504c186d17ca272f85rbb
98fb535f829e2a95aabd82420931f476661fa8e3jortonstatic int disk_serve(request_rec *r)
db12cd62083041bf90945eeb90cc40fbd2340797trawick{
db12cd62083041bf90945eeb90cc40fbd2340797trawick ap_bucket *e;
db12cd62083041bf90945eeb90cc40fbd2340797trawick ap_bucket_brigade *bb = ap_brigade_create(r->pool);
333eac96e4fb7d6901cb75e6ca7bb22b2ccb84cetrawick const char *filename;
333eac96e4fb7d6901cb75e6ca7bb22b2ccb84cetrawick apr_file_t *fd = NULL;
3568de757bac0b47256647504c186d17ca272f85rbb apr_status_t rv;
3568de757bac0b47256647504c186d17ca272f85rbb ap_filter_t *f;
3568de757bac0b47256647504c186d17ca272f85rbb char str[256];
3568de757bac0b47256647504c186d17ca272f85rbb apr_off_t offset = 0;
3568de757bac0b47256647504c186d17ca272f85rbb
3568de757bac0b47256647504c186d17ca272f85rbb filename = ap_server_root_relative(r->pool,
3568de757bac0b47256647504c186d17ca272f85rbb apr_pstrcat(r->pool, "proxy", r->uri, NULL));
3568de757bac0b47256647504c186d17ca272f85rbb if ((rv = apr_open(&fd, filename, APR_READ,
3568de757bac0b47256647504c186d17ca272f85rbb APR_UREAD, r->connection->pool)) != APR_SUCCESS) {
3568de757bac0b47256647504c186d17ca272f85rbb return DECLINED;
3568de757bac0b47256647504c186d17ca272f85rbb }
3568de757bac0b47256647504c186d17ca272f85rbb
3568de757bac0b47256647504c186d17ca272f85rbb /* skip the cached headers. */
28c170ac8e99644de58cad454c6e0f9b4b359be6jerenkrantz do {
3568de757bac0b47256647504c186d17ca272f85rbb apr_fgets(str, 256, fd);
28c170ac8e99644de58cad454c6e0f9b4b359be6jerenkrantz offset += strlen(str);
28c170ac8e99644de58cad454c6e0f9b4b359be6jerenkrantz } while (strcmp(str, CRLF));
28c170ac8e99644de58cad454c6e0f9b4b359be6jerenkrantz
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding /* If we are serving from the cache, we don't want to try to cache it
28c170ac8e99644de58cad454c6e0f9b4b359be6jerenkrantz * again.
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding */
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding for ((f = r->output_filters); (f = f->next);) {
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding if (!strcmp(f->frec->name, "CACHE")) {
8f3ec4772d2aeb347cf40e87c77627bb784dd018rbb ap_remove_output_filter(f);
8f3ec4772d2aeb347cf40e87c77627bb784dd018rbb }
3d96ee83babeec32482c9082c9426340cee8c44dwrowe }
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding
b6e310e482c42cc323a28fa6fec653e11e0552e5jorton e = ap_bucket_create_file(fd, offset, r->finfo.size);
cd8f8c995d415473f3bfb0b329b2450f2a722c3atrawick
98fb535f829e2a95aabd82420931f476661fa8e3jorton AP_BRIGADE_INSERT_HEAD(bb, e);
f0e395a55abfcad3d2bd7c63470003b08a93d567nd e = ap_bucket_create_eos();
f0e395a55abfcad3d2bd7c63470003b08a93d567nd AP_BRIGADE_INSERT_TAIL(bb, e);
f0e395a55abfcad3d2bd7c63470003b08a93d567nd
f0e395a55abfcad3d2bd7c63470003b08a93d567nd ap_pass_brigade(r->output_filters, bb);
98fb535f829e2a95aabd82420931f476661fa8e3jorton return OK;
7cd5419264796cfeaf8215383cf0f89130a81fectrawick}
7cd5419264796cfeaf8215383cf0f89130a81fectrawick
7cd5419264796cfeaf8215383cf0f89130a81fectrawicktypedef struct cache_struct {
7cd5419264796cfeaf8215383cf0f89130a81fectrawick const char *filename;
7cd5419264796cfeaf8215383cf0f89130a81fectrawick apr_file_t *fd;
7cd5419264796cfeaf8215383cf0f89130a81fectrawick int state;
7cd5419264796cfeaf8215383cf0f89130a81fectrawick} cache_struct;
7cd5419264796cfeaf8215383cf0f89130a81fectrawick
3568de757bac0b47256647504c186d17ca272f85rbbstatic int disk_cache(request_rec *r, ap_bucket_brigade *bb, void **cf)
28c170ac8e99644de58cad454c6e0f9b4b359be6jerenkrantz{
3568de757bac0b47256647504c186d17ca272f85rbb cache_struct *ctx = *cf;
3568de757bac0b47256647504c186d17ca272f85rbb ap_bucket *e;
28c170ac8e99644de58cad454c6e0f9b4b359be6jerenkrantz
3568de757bac0b47256647504c186d17ca272f85rbb if (ctx == NULL) {
3568de757bac0b47256647504c186d17ca272f85rbb *cf = ctx = apr_pcalloc(r->pool, sizeof(*ctx));
3568de757bac0b47256647504c186d17ca272f85rbb }
3568de757bac0b47256647504c186d17ca272f85rbb if (ctx->filename == NULL) {
3568de757bac0b47256647504c186d17ca272f85rbb apr_status_t rv;
3568de757bac0b47256647504c186d17ca272f85rbb apr_make_dir(ap_server_root_relative(r->pool, "proxy"), APR_UREAD | APR_UWRITE | APR_UEXECUTE | APR_GREAD | APR_GWRITE, r->pool);
3568de757bac0b47256647504c186d17ca272f85rbb
3568de757bac0b47256647504c186d17ca272f85rbb /* currently, we are using the uri as the cache key. This is
3568de757bac0b47256647504c186d17ca272f85rbb * probably wrong, but it is much better than a hard-coded filename.
3568de757bac0b47256647504c186d17ca272f85rbb */
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding ctx->filename = ap_server_root_relative(r->pool,
3568de757bac0b47256647504c186d17ca272f85rbb apr_pstrcat(r->pool, "proxy", r->uri, NULL));
3568de757bac0b47256647504c186d17ca272f85rbb if ((rv = apr_open(&ctx->fd, ctx->filename,
3568de757bac0b47256647504c186d17ca272f85rbb APR_WRITE | APR_CREATE | APR_TRUNCATE | APR_BUFFERED,
3568de757bac0b47256647504c186d17ca272f85rbb APR_UREAD | APR_UWRITE, r->pool)) != APR_SUCCESS) {
3568de757bac0b47256647504c186d17ca272f85rbb ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,
3568de757bac0b47256647504c186d17ca272f85rbb "Could not create cache file");
41634f717c623556a16b27b25d7d909a66fe20f8wrowe *cf = NULL;
3568de757bac0b47256647504c186d17ca272f85rbb return DECLINED;
3568de757bac0b47256647504c186d17ca272f85rbb }
28c170ac8e99644de58cad454c6e0f9b4b359be6jerenkrantz }
3568de757bac0b47256647504c186d17ca272f85rbb AP_BRIGADE_FOREACH(e, bb) {
28c170ac8e99644de58cad454c6e0f9b4b359be6jerenkrantz const char *str;
3568de757bac0b47256647504c186d17ca272f85rbb apr_ssize_t length;
28c170ac8e99644de58cad454c6e0f9b4b359be6jerenkrantz
3568de757bac0b47256647504c186d17ca272f85rbb ap_bucket_read(e, &str, &length, 0);
28c170ac8e99644de58cad454c6e0f9b4b359be6jerenkrantz apr_write(ctx->fd, str, &length);
3568de757bac0b47256647504c186d17ca272f85rbb }
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding if (AP_BUCKET_IS_EOS(AP_BRIGADE_LAST(bb))) {
41634f717c623556a16b27b25d7d909a66fe20f8wrowe apr_close(ctx->fd);
3568de757bac0b47256647504c186d17ca272f85rbb }
3568de757bac0b47256647504c186d17ca272f85rbb return OK;
28c170ac8e99644de58cad454c6e0f9b4b359be6jerenkrantz}
3568de757bac0b47256647504c186d17ca272f85rbb
28c170ac8e99644de58cad454c6e0f9b4b359be6jerenkrantzstatic void disk_cache_register_hook(void)
3568de757bac0b47256647504c186d17ca272f85rbb{
28c170ac8e99644de58cad454c6e0f9b4b359be6jerenkrantz ap_hook_store_cache(disk_cache, NULL, NULL, AP_HOOK_MIDDLE);
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding ap_hook_serve_cache(disk_serve, NULL, NULL, AP_HOOK_MIDDLE);
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding}
28c170ac8e99644de58cad454c6e0f9b4b359be6jerenkrantz
3568de757bac0b47256647504c186d17ca272f85rbbmodule MODULE_VAR_EXPORT disk_cache_module = {
fc1efab92032301e317f07e1b3a00082d9d71f3frbb STANDARD20_MODULE_STUFF,
28c170ac8e99644de58cad454c6e0f9b4b359be6jerenkrantz NULL, /* create per-directory config structure */
24b534291150023e6b68eca89ddd33e475ccddc0wrowe NULL, /* merge per-directory config structures */
3568de757bac0b47256647504c186d17ca272f85rbb NULL, /* create per-server config structure */
24b534291150023e6b68eca89ddd33e475ccddc0wrowe NULL, /* merge per-server config structures */
3568de757bac0b47256647504c186d17ca272f85rbb NULL, /* command apr_table_t */
24b534291150023e6b68eca89ddd33e475ccddc0wrowe disk_cache_register_hook /* register hooks */
24b534291150023e6b68eca89ddd33e475ccddc0wrowe};
28c170ac8e99644de58cad454c6e0f9b4b359be6jerenkrantz