⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mod_cache.c

📁 Apache官方在今天放出产品系列2.2的最新版本2.2.11的源码包 最流行的HTTP服务器软件之一
💻 C
📖 第 1 页 / 共 4 页
字号:
    cache_info *info = NULL;    char *reason;    apr_pool_t *p;    conf = (cache_server_conf *) ap_get_module_config(r->server->module_config,                                                      &cache_module);    /* Setup cache_request_rec */    cache = (cache_request_rec *) ap_get_module_config(r->request_config,                                                       &cache_module);    if (!cache) {        /* user likely configured CACHE_SAVE manually; they should really use         * mod_cache configuration to do that         */        cache = apr_pcalloc(r->pool, sizeof(cache_request_rec));        ap_set_module_config(r->request_config, &cache_module, cache);    }    reason = NULL;    p = r->pool;    /*     * Pass Data to Cache     * ------------------     * This section passes the brigades into the cache modules, but only     * if the setup section (see below) is complete.     */    if (cache->block_response) {        /* We've already sent down the response and EOS.  So, ignore         * whatever comes now.         */        return APR_SUCCESS;    }    /* have we already run the cachability check and set up the     * cached file handle?     */    if (cache->in_checked) {        /* pass the brigades into the cache, then pass them         * up the filter stack         */        rv = cache->provider->store_body(cache->handle, r, in);        if (rv != APR_SUCCESS) {            ap_log_error(APLOG_MARK, APLOG_DEBUG, rv, r->server,                         "cache: Cache provider's store_body failed!");            ap_remove_output_filter(f);        }        return ap_pass_brigade(f->next, in);    }    /*     * Setup Data in Cache     * -------------------     * This section opens the cache entity and sets various caching     * parameters, and decides whether this URL should be cached at     * all. This section is* run before the above section.     */    /* read expiry date; if a bad date, then leave it so the client can     * read it     */    exps = apr_table_get(r->err_headers_out, "Expires");    if (exps == NULL) {        exps = apr_table_get(r->headers_out, "Expires");    }    if (exps != NULL) {        if (APR_DATE_BAD == (exp = apr_date_parse_http(exps))) {            exps = NULL;        }    }    else {        exp = APR_DATE_BAD;    }    /* read the last-modified date; if the date is bad, then delete it */    lastmods = apr_table_get(r->err_headers_out, "Last-Modified");    if (lastmods == NULL) {        lastmods = apr_table_get(r->headers_out, "Last-Modified");    }    if (lastmods != NULL) {        lastmod = apr_date_parse_http(lastmods);        if (lastmod == APR_DATE_BAD) {            lastmods = NULL;        }    }    else {        lastmod = APR_DATE_BAD;    }    /* read the etag and cache-control from the entity */    etag = apr_table_get(r->err_headers_out, "Etag");    if (etag == NULL) {        etag = apr_table_get(r->headers_out, "Etag");    }    cc_out = apr_table_get(r->err_headers_out, "Cache-Control");    if (cc_out == NULL) {        cc_out = apr_table_get(r->headers_out, "Cache-Control");    }    /*     * what responses should we not cache?     *     * At this point we decide based on the response headers whether it     * is appropriate _NOT_ to cache the data from the server. There are     * a whole lot of conditions that prevent us from caching this data.     * They are tested here one by one to be clear and unambiguous.     */    if (r->status != HTTP_OK && r->status != HTTP_NON_AUTHORITATIVE        && r->status != HTTP_MULTIPLE_CHOICES        && r->status != HTTP_MOVED_PERMANENTLY        && r->status != HTTP_NOT_MODIFIED) {        /* RFC2616 13.4 we are allowed to cache 200, 203, 206, 300, 301 or 410         * We don't cache 206, because we don't (yet) cache partial responses.         * We include 304 Not Modified here too as this is the origin server         * telling us to serve the cached copy.         */        reason = apr_psprintf(p, "Response status %d", r->status);    }    else if (exps != NULL && exp == APR_DATE_BAD) {        /* if a broken Expires header is present, don't cache it */        reason = apr_pstrcat(p, "Broken expires header: ", exps, NULL);    }    else if (exp != APR_DATE_BAD && exp < r->request_time)    {        /* if a Expires header is in the past, don't cache it */        reason = "Expires header already expired, not cacheable";    }    else if (!conf->ignorequerystring && r->parsed_uri.query && exps == NULL &&             !ap_cache_liststr(NULL, cc_out, "max-age", NULL)) {        /* if a query string is present but no explicit expiration time,         * don't cache it (RFC 2616/13.9 & 13.2.1)         */        reason = "Query string present but no explicit expiration time";    }    else if (r->status == HTTP_NOT_MODIFIED &&             !cache->handle && !cache->stale_handle) {        /* if the server said 304 Not Modified but we have no cache         * file - pass this untouched to the user agent, it's not for us.         */        reason = "HTTP Status 304 Not Modified";    }    else if (r->status == HTTP_OK && lastmods == NULL && etag == NULL             && (exps == NULL) && (conf->no_last_mod_ignore ==0)) {        /* 200 OK response from HTTP/1.0 and up without Last-Modified,         * Etag, or Expires headers.         */        /* Note: mod-include clears last_modified/expires/etags - this         * is why we have an optional function for a key-gen ;-)         */        reason = "No Last-Modified, Etag, or Expires headers";    }    else if (r->header_only && !cache->stale_handle) {        /* Forbid HEAD requests unless we have it cached already */        reason = "HTTP HEAD request";    }    else if (!conf->store_nostore &&             ap_cache_liststr(NULL, cc_out, "no-store", NULL)) {        /* RFC2616 14.9.2 Cache-Control: no-store response         * indicating do not cache, or stop now if you are         * trying to cache it.         */        /* FIXME: The Cache-Control: no-store could have come in on a 304,         * FIXME: while the original request wasn't conditional.  IOW, we         * FIXME:  made the the request conditional earlier to revalidate         * FIXME: our cached response.         */        reason = "Cache-Control: no-store present";    }    else if (!conf->store_private &&             ap_cache_liststr(NULL, cc_out, "private", NULL)) {        /* RFC2616 14.9.1 Cache-Control: private response         * this object is marked for this user's eyes only. Behave         * as a tunnel.         */        /* FIXME: See above (no-store) */        reason = "Cache-Control: private present";    }    else if (apr_table_get(r->headers_in, "Authorization") != NULL             && !(ap_cache_liststr(NULL, cc_out, "s-maxage", NULL)                  || ap_cache_liststr(NULL, cc_out, "must-revalidate", NULL)                  || ap_cache_liststr(NULL, cc_out, "public", NULL))) {        /* RFC2616 14.8 Authorisation:         * if authorisation is included in the request, we don't cache,         * but we can cache if the following exceptions are true:         * 1) If Cache-Control: s-maxage is included         * 2) If Cache-Control: must-revalidate is included         * 3) If Cache-Control: public is included         */        reason = "Authorization required";    }    else if (ap_cache_liststr(NULL,                              apr_table_get(r->headers_out, "Vary"),                              "*", NULL)) {        reason = "Vary header contains '*'";    }    else if (r->no_cache) {        /* or we've been asked not to cache it above */        reason = "r->no_cache present";    }    if (reason) {        ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,                     "cache: %s not cached. Reason: %s", r->unparsed_uri,                     reason);        /* remove this filter from the chain */        ap_remove_output_filter(f);        /* ship the data up the stack */        return ap_pass_brigade(f->next, in);    }    /* Make it so that we don't execute this path again. */    cache->in_checked = 1;    /* Set the content length if known.     */    cl = apr_table_get(r->err_headers_out, "Content-Length");    if (cl == NULL) {        cl = apr_table_get(r->headers_out, "Content-Length");    }    if (cl) {        char *errp;        if (apr_strtoff(&size, cl, &errp, 10) || *errp || size < 0) {            cl = NULL; /* parse error, see next 'if' block */        }    }    if (!cl) {        /* if we don't get the content-length, see if we have all the         * buckets and use their length to calculate the size         */        apr_bucket *e;        int all_buckets_here=0;        int unresolved_length = 0;        size=0;        for (e = APR_BRIGADE_FIRST(in);             e != APR_BRIGADE_SENTINEL(in);             e = APR_BUCKET_NEXT(e))        {            if (APR_BUCKET_IS_EOS(e)) {                all_buckets_here=1;                break;            }            if (APR_BUCKET_IS_FLUSH(e)) {                unresolved_length = 1;                continue;            }            if (e->length == (apr_size_t)-1) {                break;            }            size += e->length;        }        if (!all_buckets_here) {            size = -1;        }    }    /* It's safe to cache the response.     *     * There are two possiblities at this point:     * - cache->handle == NULL. In this case there is no previously     * cached entity anywhere on the system. We must create a brand     * new entity and store the response in it.     * - cache->stale_handle != NULL. In this case there is a stale     * entity in the system which needs to be replaced by new     * content (unless the result was 304 Not Modified, which means     * the cached entity is actually fresh, and we should update     * the headers).     */    /* Did we have a stale cache entry that really is stale?     *     * Note that for HEAD requests, we won't get the body, so for a stale     * HEAD request, we don't remove the entity - instead we let the     * CACHE_REMOVE_URL filter remove the stale item from the cache.     */    if (cache->stale_handle) {        if (r->status == HTTP_NOT_MODIFIED) {            /* Oh, hey.  It isn't that stale!  Yay! */            cache->handle = cache->stale_handle;            info = &cache->handle->cache_obj->info;            rv = OK;        }        else if (!r->header_only) {            /* Oh, well.  Toss it. */            cache->provider->remove_entity(cache->stale_handle);            /* Treat the request as if it wasn't conditional. */            cache->stale_handle = NULL;            /*             * Restore the original request headers as they may be needed             * by further output filters like the byterange filter to make             * the correct decisions.             */            r->headers_in = cache->stale_headers;        }    }    /* no cache handle, create a new entity only for non-HEAD requests */    if (!cache->handle && !r->header_only) {        rv = cache_create_entity(r, size);        info = apr_pcalloc(r->pool, sizeof(cache_info));        /* We only set info->status upon the initial creation. */        info->status = r->status;    }    if (rv != OK) {        /* Caching layer declined the opportunity to cache the response */        ap_remove_output_filter(f);        return ap_pass_brigade(f->next, in);    }    ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,                 "cache: Caching url: %s", r->unparsed_uri);    /* We are actually caching this response. So it does not     * make sense to remove this entity any more.     */    ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,                 "cache: Removing CACHE_REMOVE_URL filter.");    ap_remove_output_filter(cache->remove_url_filter);    /*     * We now want to update the cache file header information with     * the new date, last modified, expire and content length and write     * it away to our cache file. First, we determine these values from     * the response, using heuristics if appropriate.     *

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -