1
0
mirror of https://github.com/apache/httpd.git synced 2025-07-30 20:03:10 +03:00

mod_cache: Make sure Vary processing handles multivalued Vary headers and

multivalued headers referred to via Vary.


git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1478748 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Graham Leggett
2013-05-03 12:19:26 +00:00
parent f18afbfba1
commit 0ef0994152
4 changed files with 24 additions and 16 deletions

View File

@ -1,6 +1,9 @@
-*- coding: utf-8 -*- -*- coding: utf-8 -*-
Changes with Apache 2.5.0 Changes with Apache 2.5.0
*) mod_cache: Make sure Vary processing handles multivalued Vary headers and
multivalued headers referred to via Vary. [Graham Leggett]
*) mod_cache: When serving from cache, only the last header of a multivalued *) mod_cache: When serving from cache, only the last header of a multivalued
header was taken into account. Fixed. [Graham Leggett] header was taken into account. Fixed. [Graham Leggett]

View File

@ -220,6 +220,7 @@ int cache_select(cache_request_rec *cache, request_rec *r)
case OK: { case OK: {
char *vary = NULL; char *vary = NULL;
int fresh, mismatch = 0; int fresh, mismatch = 0;
char *last = NULL;
if (list->provider->recall_headers(h, r) != APR_SUCCESS) { if (list->provider->recall_headers(h, r) != APR_SUCCESS) {
/* try again with next cache type */ /* try again with next cache type */
@ -245,25 +246,19 @@ int cache_select(cache_request_rec *cache, request_rec *r)
* *
* RFC2616 13.6 and 14.44 describe the Vary mechanism. * RFC2616 13.6 and 14.44 describe the Vary mechanism.
*/ */
vary = apr_pstrdup(r->pool, apr_table_get(h->resp_hdrs, "Vary")); vary = cache_strqtok(
while (vary && *vary) { apr_pstrdup(r->pool,
char *name = vary; cache_table_getm(r->pool, h->resp_hdrs, "Vary")),
CACHE_SEPARATOR, &last);
while (vary) {
const char *h1, *h2; const char *h1, *h2;
/* isolate header name */
while (*vary && !apr_isspace(*vary) && (*vary != ','))
++vary;
while (apr_isspace(*vary) || (*vary == ',')) {
*vary = '\0';
++vary;
}
/* /*
* is this header in the request and the header in the cached * is this header in the request and the header in the cached
* request identical? If not, we give up and do a straight get * request identical? If not, we give up and do a straight get
*/ */
h1 = apr_table_get(r->headers_in, name); h1 = cache_table_getm(r->pool, r->headers_in, vary);
h2 = apr_table_get(h->req_hdrs, name); h2 = cache_table_getm(r->pool, h->req_hdrs, vary);
if (h1 == h2) { if (h1 == h2) {
/* both headers NULL, so a match - do nothing */ /* both headers NULL, so a match - do nothing */
} }
@ -277,6 +272,7 @@ int cache_select(cache_request_rec *cache, request_rec *r)
mismatch = 1; mismatch = 1;
break; break;
} }
vary = cache_strqtok(NULL, CACHE_SEPARATOR, &last);
} }
/* no vary match, try next provider */ /* no vary match, try next provider */

View File

@ -27,8 +27,6 @@ extern APR_OPTIONAL_FN_TYPE(ap_cache_generate_key) *cache_generate_key;
extern module AP_MODULE_DECLARE_DATA cache_module; extern module AP_MODULE_DECLARE_DATA cache_module;
#define CACHE_SEPARATOR ", "
/* Determine if "url" matches the hostname, scheme and port and path /* Determine if "url" matches the hostname, scheme and port and path
* in "filter". All but the path comparisons are case-insensitive. * in "filter". All but the path comparisons are case-insensitive.
*/ */
@ -862,7 +860,7 @@ CACHE_DECLARE(char *)ap_cache_generate_name(apr_pool_t *p, int dirlevels,
* String tokenizer that ignores separator characters within quoted strings * String tokenizer that ignores separator characters within quoted strings
* and escaped characters, as per RFC2616 section 2.2. * and escaped characters, as per RFC2616 section 2.2.
*/ */
static char *cache_strqtok(char *str, const char *sep, char **last) char *cache_strqtok(char *str, const char *sep, char **last)
{ {
char *token; char *token;
int quoted = 0; int quoted = 0;
@ -871,6 +869,10 @@ static char *cache_strqtok(char *str, const char *sep, char **last)
str = *last; /* start where we left off */ str = *last; /* start where we left off */
} }
if (!str) { /* no more tokens */
return NULL;
}
/* skip characters in sep (will terminate at '\0') */ /* skip characters in sep (will terminate at '\0') */
while (*str && ap_strchr_c(sep, *str)) { while (*str && ap_strchr_c(sep, *str)) {
++str; ++str;

View File

@ -99,6 +99,7 @@ extern "C" {
#define CACHE_LOCKNAME_KEY "mod_cache-lockname" #define CACHE_LOCKNAME_KEY "mod_cache-lockname"
#define CACHE_LOCKFILE_KEY "mod_cache-lockfile" #define CACHE_LOCKFILE_KEY "mod_cache-lockfile"
#define CACHE_CTX_KEY "mod_cache-ctx" #define CACHE_CTX_KEY "mod_cache-ctx"
#define CACHE_SEPARATOR ", "
/** /**
* cache_util.c * cache_util.c
@ -305,6 +306,12 @@ cache_provider_list *cache_get_providers(request_rec *r,
const char *cache_table_getm(apr_pool_t *p, const apr_table_t *t, const char *cache_table_getm(apr_pool_t *p, const apr_table_t *t,
const char *key); const char *key);
/**
* String tokenizer that ignores separator characters within quoted strings
* and escaped characters, as per RFC2616 section 2.2.
*/
char *cache_strqtok(char *str, const char *sep, char **last);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif