Quick Handler (2.0)
int module_quick_handler(request_rec *r, int lookup_uri)
This function is intended to
provide
content from a URI-based cache. If lookup_uri
is
set, then it should simply return OK
if the URI
exists, but not provide the content.
The only example of this in 2.0 is in an experimental module, mod_cache.c, as shown in Example 21-13.
Example 21-13. mod_cache.c
static int cache_url_handler(request_rec *r, int lookup) { apr_status_t rv; const char *cc_in, *pragma, *auth; apr_uri_t uri = r->parsed_uri; char *url = r->unparsed_uri; apr_size_t urllen; char *path = uri.path; const char *types; cache_info *info = NULL; cache_request_rec *cache; cache_server_conf *conf = (cache_server_conf *) ap_get_module_config(r->server->module_config, &cache_module); if (r->method_number != M_GET) return DECLINED; if (!(types = ap_cache_get_cachetype(r, conf, path))) { return DECLINED; } ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r->server, "cache: URL %s is being handled by %s", path, types); urllen = strlen(url); if (urllen > MAX_URL_LENGTH) { ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r->server, "cache: URL exceeds length threshold: %s", url); return DECLINED; } if (url[urllen-1] == '/') { return DECLINED; } cache = (cache_request_rec *) ap_get_module_config(r->request_config, &cache_module); if (!cache) { cache = ap_pcalloc(r->pool, sizeof(cache_request_rec)); ap_set_module_config(r->request_config, &cache_module, cache); } cache->types = types; cc_in = apr_table_get(r->headers_in, "Cache-Control"); pragma = apr_table_get(r->headers_in, "Pragma"); auth = apr_table_get(r->headers_in, "Authorization"); if (conf->ignorecachecontrol_set == 1 && conf->ignorecachecontrol == 1 && auth == NULL) { ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r->server, "incoming request is asking for a uncached version of %s, but we know better and are ignoring it", url); } else { if (ap_cache_liststr(cc_in, "no-store", NULL) || ap_cache_liststr(pragma, "no-cache", NULL) || (auth != NULL)) { /* delete the previously cached file */ cache_remove_url(r, cache->types, url); ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r->server, "cache: no-store forbids caching of %s", url); return DECLINED; } } rv = cache_select_url(r, cache->types, url); if (DECLINED == rv) { if (!lookup) { ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r->server, "cache: no cache - add cache_in filter and DECLINE"); ap_add_output_filter("CACHE_IN", NULL, r, r->connection); } return DECLINED; } else if (OK == rv) { if (cache->fresh) { apr_bucket_brigade *out; conn_rec *c = r->connection; if (lookup) { return OK; } ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r->server, "cache: fresh cache - add cache_out filter and " "handle request"); ap_run_insert_filter(r); ap_add_output_filter("CACHE_OUT", NULL, r, r->connection); out = apr_brigade_create(r->pool, c->bucket_alloc); if (APR_SUCCESS != (rv = ap_pass_brigade(r->output_filters, out))) { ap_log_error(APLOG_MARK, APLOG_ERR, rv, r->server, "cache: error returned while trying to return %s " "cached data", cache->type); return rv; } return OK; } else { if (lookup) { return DECLINED; } ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r->server, "cache: stale cache - test conditional"); if (ap_cache_request_is_conditional(r)) { ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r->server, "cache: conditional - add cache_in filter and " "DECLINE"); ap_add_output_filter("CACHE_IN", NULL, r, r->connection); return DECLINED; } else { if (info && info->etag) { ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r->server, "cache: nonconditional - fudge conditional " "by etag"); apr_table_set(r->headers_in, "If-None-Match", info->etag); } else if (info && info->lastmods) { ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r->server, "cache: nonconditional - fudge conditional " "by lastmod"); apr_table_set(r->headers_in, "If-Modified-Since", info->lastmods); } else { ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r->server, "cache: nonconditional - no cached " "etag/lastmods - add cache_in and DECLINE"); ap_add_output_filter("CACHE_IN", NULL, r, r->connection); return DECLINED; } ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r->server, "cache: nonconditional - add cache_conditional and" " DECLINE"); ap_add_output_filter("CACHE_CONDITIONAL", NULL, r, r->connection); return DECLINED; } } } else { ap_log_error(APLOG_MARK, APLOG_ERR, rv, r->server, "cache: error returned while checking for cached file by " "%s cache", cache->type); return DECLINED; } }
This is quite complex, but interesting — note the use of filters both to fill the cache and to generate the cached content for cache hits.