internal static TriState ValidateCacheByVaryHeader(HttpRequestCacheValidator ctx) {
string[] cacheVary = ctx.CacheHeaders.GetValues(HttpKnownHeaderNames.Vary);
if (cacheVary == null) {
return TriState.Unknown;
}
ArrayList varyValues = new ArrayList();
HttpRequestCacheValidator.ParseHeaderValues(cacheVary,
HttpRequestCacheValidator.ParseValuesCallback,
varyValues);
if (varyValues.Count == 0) {
if(Logging.On)Logging.PrintWarning(Logging.RequestCache, SR.GetString(SR.net_log_cache_vary_header_empty));
return TriState.Invalid;
}
if (((string)(varyValues[0]))[0] == '*') {
if(Logging.On)Logging.PrintInfo(Logging.RequestCache, SR.GetString(SR.net_log_cache_vary_header_contains_asterisks));
return TriState.Invalid;
}
if (ctx.SystemMeta == null || ctx.SystemMeta.Count == 0) {
// We keep there previous request headers
if(Logging.On)Logging.PrintWarning(Logging.RequestCache, SR.GetString(SR.net_log_cache_no_headers_in_metadata));
return TriState.Invalid;
}
/*
A Vary field value consisting of a list of field-names signals that
the representation selected for the response is based on a selection
algorithm which considers ONLY the listed request-header field values
in selecting the most appropriate representation. A cache MAY assume
that the same selection will be made for future requests with the
same values for the listed field names, for the duration of time for
which the response is fresh.
*/
for (int i = 0; i < varyValues.Count; ++i) {
string[] requestValues = ctx.Request.Headers.GetValues((string)varyValues[i]);
ArrayList requestFields = new ArrayList();
if (requestValues != null) {
HttpRequestCacheValidator.ParseHeaderValues(requestValues,
HttpRequestCacheValidator.ParseValuesCallback,
requestFields);
}
string[] cacheValues = ctx.SystemMeta.GetValues((string)varyValues[i]);
ArrayList cacheFields = new ArrayList();
if (cacheValues != null) {
HttpRequestCacheValidator.ParseHeaderValues(cacheValues,
HttpRequestCacheValidator.ParseValuesCallback,
cacheFields);
}
if (requestFields.Count != cacheFields.Count) {
if(Logging.On)Logging.PrintInfo(Logging.RequestCache, SR.GetString(SR.net_log_cache_vary_header_mismatched_count, (string)varyValues[i]));
return TriState.Invalid;
}
// NB: fields order is significant as per RFC.
for (int j = 0; j < cacheFields.Count; ++j) {
if (!AsciiLettersNoCaseEqual((string)cacheFields[j], (string)requestFields[j])) {
if(Logging.On)Logging.PrintInfo(Logging.RequestCache, SR.GetString(SR.net_log_cache_vary_header_mismatched_field, (string)varyValues[i], (string)cacheFields[j], (string)requestFields[j]));
return TriState.Invalid;
}
}
}
if(Logging.On)Logging.PrintInfo(Logging.RequestCache, SR.GetString(SR.net_log_cache_vary_header_match));
// The Vary header is in cache and all headers values referenced to are equal to those in the Request.
return TriState.Valid;
}