Move parts of cache_select() to a smaller cache_check_request()
function that is easier to read and understand.
Index: trunk/modules/cache/cache_storage.c
===================================================================
--- trunk.orig/modules/cache/cache_storage.c
+++ trunk/modules/cache/cache_storage.c
@@ -169,6 +169,115 @@ CACHE_DECLARE(void) ap_cache_accept_head
}
}
+static int cache_check_request(cache_handle_t *h, request_rec *r,
+ cache_request_rec *cache,
+ cache_provider_list *list)
+{
+ int fresh;
+ char *vary = NULL;
+
+ /*
+ * Check Content-Negotiation - Vary
+ *
+ * At this point we need to make sure that the object we found in
+ * the cache is the same object that would be delivered to the
+ * client, when the effects of content negotiation are taken into
+ * effect.
+ *
+ * In plain english, we want to make sure that a language-negotiated
+ * document in one language is not given to a client asking for a
+ * language negotiated document in a different language by mistake.
+ *
+ * This code makes the assumption that the storage manager will
+ * cache the req_hdrs if the response contains a Vary
+ * header.
+ *
+ * RFC2616 13.6 and 14.44 describe the Vary mechanism.
+ */
+ vary = apr_pstrdup(r->pool, apr_table_get(h->resp_hdrs, "Vary"));
+ while (vary && *vary) {
+ char *name = vary;
+ const char *h1, *h2;
+
+ /* isolate header name */
+ while (*vary && !apr_isspace(*vary) && (*vary != ','))
+ ++vary;
+ while (*vary && (apr_isspace(*vary) || (*vary == ','))) {
+ *vary = '\0';
+ ++vary;
+ }
+
+ /*
+ * is this header in the request and the header in the cached
+ * request identical? If not, we give up and do a straight get
+ */
+ h1 = apr_table_get(r->headers_in, name);
+ h2 = apr_table_get(h->req_hdrs, name);
+ if (h1 == h2) {
+ /* both headers NULL, so a match - do nothing */
+ }
+ else if (h1 && h2 && !strcmp(h1, h2)) {
+ /* both headers exist and are equal - do nothing */
+ }
+ else {
+ /* headers do not match, so Vary failed */
+ ap_log_error(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS,
+ r->server,
+ "cache_select_url(): Vary header mismatch.");
+ return DECLINED;
+ }
+ }
+
+ cache->provider = list->provider;
+ cache->provider_name = list->provider_name;
+
+ /* Is our cached response fresh enough? */
+ fresh = ap_cache_check_freshness(h, r);
+ if (!fresh) {
+ const char *etag, *lastmod;
+
+ ap_log_error(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, r->server,
+ "Cached response for %s isn't fresh. Adding/replacing "
+ "conditional request headers.", r->uri);
+
+ /* Make response into a conditional */
+ cache->stale_headers = apr_table_copy(r->pool,
+ r->headers_in);
+
+ /* We can only revalidate with our own conditionals: remove the
+ * conditions from the original request.
+ */
+ apr_table_unset(r->headers_in, "If-Match");
+ apr_table_unset(r->headers_in, "If-Modified-Since");
+ apr_table_unset(r->headers_in, "If-None-Match");
+ apr_table_unset(r->headers_in, "If-Range");
+ apr_table_unset(r->headers_in, "If-Unmodified-Since");
+
+ etag = apr_table_get(h->resp_hdrs, "ETag");
+ lastmod = apr_table_get(h->resp_hdrs, "Last-Modified");
+
+ if (etag || lastmod) {
+ /* If we have a cached etag and/or Last-Modified add in
+ * our own conditionals.
+ */
+
+ if (etag) {
+ apr_table_set(r->headers_in, "If-None-Match", etag);
+ }
+
+ if (lastmod) {
+ apr_table_set(r->headers_in, "If-Modified-Since",
+ lastmod);
+ }
+ cache->stale_handle = h;
+ }
+
+ return DECLINED;
+ }
+
+ return OK;
+}
+
/*
* select a specific URL entity in the cache
*
@@ -201,110 +310,13 @@ int cache_select(request_rec *r)
while (list) {
switch ((rv = list->provider->open_entity(h, r, key))) {
case OK: {
- char *vary = NULL;
- int fresh;
if (list->provider->recall_headers(h, r) != APR_SUCCESS) {
/* TODO: Handle this error */
return DECLINED;
}
- /*
- * Check Content-Negotiation - Vary
- *
- * At this point we need to make sure that the object we found in
- * the cache is the same object that would be delivered to the
- * client, when the effects of content negotiation are taken into
- * effect.
- *
- * In plain english, we want to make sure that a
language-negotiated
- * document in one language is not given to a client asking for a
- * language negotiated document in a different language by mistake.
- *
- * This code makes the assumption that the storage manager will
- * cache the req_hdrs if the response contains a Vary
- * header.
- *
- * RFC2616 13.6 and 14.44 describe the Vary mechanism.
- */
- vary = apr_pstrdup(r->pool, apr_table_get(h->resp_hdrs, "Vary"));
- while (vary && *vary) {
- char *name = vary;
- const char *h1, *h2;
-
- /* isolate header name */
- while (*vary && !apr_isspace(*vary) && (*vary != ','))
- ++vary;
- while (*vary && (apr_isspace(*vary) || (*vary == ','))) {
- *vary = '\0';
- ++vary;
- }
-
- /*
- * is this header in the request and the header in the cached
- * request identical? If not, we give up and do a straight get
- */
- h1 = apr_table_get(r->headers_in, name);
- h2 = apr_table_get(h->req_hdrs, name);
- if (h1 == h2) {
- /* both headers NULL, so a match - do nothing */
- }
- else if (h1 && h2 && !strcmp(h1, h2)) {
- /* both headers exist and are equal - do nothing */
- }
- else {
- /* headers do not match, so Vary failed */
- ap_log_error(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS,
- r->server,
- "cache_select_url(): Vary header mismatch.");
- return DECLINED;
- }
- }
-
- cache->provider = list->provider;
- cache->provider_name = list->provider_name;
-
- /* Is our cached response fresh enough? */
- fresh = ap_cache_check_freshness(h, r);
- if (!fresh) {
- const char *etag, *lastmod;
-
- ap_log_error(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, r->server,
- "Cached response for %s isn't fresh. Adding/replacing "
- "conditional request headers.", r->uri);
-
- /* Make response into a conditional */
- cache->stale_headers = apr_table_copy(r->pool,
- r->headers_in);
-
- /* We can only revalidate with our own conditionals: remove the
- * conditions from the original request.
- */
- apr_table_unset(r->headers_in, "If-Match");
- apr_table_unset(r->headers_in, "If-Modified-Since");
- apr_table_unset(r->headers_in, "If-None-Match");
- apr_table_unset(r->headers_in, "If-Range");
- apr_table_unset(r->headers_in, "If-Unmodified-Since");
-
- etag = apr_table_get(h->resp_hdrs, "ETag");
- lastmod = apr_table_get(h->resp_hdrs, "Last-Modified");
-
- if (etag || lastmod) {
- /* If we have a cached etag and/or Last-Modified add in
- * our own conditionals.
- */
-
- if (etag) {
- apr_table_set(r->headers_in, "If-None-Match", etag);
- }
-
- if (lastmod) {
- apr_table_set(r->headers_in, "If-Modified-Since",
- lastmod);
- }
- cache->stale_handle = h;
- }
-
+ if (cache_check_request(h, r, cache, list) != OK) {
return DECLINED;
}
--