public static void ReplaceOrUpdateCacheHeaders(HttpRequestCacheValidator ctx, HttpWebResponse resp) {
/*
In other words, the set of end-to-end headers received in the
incoming response overrides all corresponding end-to-end headers
stored with the cache entry (except for stored Warning headers with
warn-code 1xx, which are deleted even if not overridden).
This rule does not allow an origin server to use
a 304 (Not Modified) or a 206 (Partial Content) response to
entirely delete a header that it had provided with a previous
response.
*/
if (ctx.CacheHeaders == null || (resp.StatusCode != HttpStatusCode.NotModified && resp.StatusCode != HttpStatusCode.PartialContent))
{
// existing context is dropped
ctx.CacheHeaders = new WebHeaderCollection();
}
// Here we preserve Request headers that are present in the response Vary header
string[] respVary = resp.Headers.GetValues(HttpKnownHeaderNames.Vary);
if (respVary != null) {
ArrayList varyValues = new ArrayList();
HttpRequestCacheValidator.ParseHeaderValues(respVary,
HttpRequestCacheValidator.ParseValuesCallback,
varyValues);
if (varyValues.Count != 0 && ((string)(varyValues[0]))[0] != '*') {
// we got some request headers to save
if(Logging.On)Logging.PrintInfo(Logging.RequestCache, SR.GetString(SR.net_log_cache_saving_request_headers, resp.Headers[HttpKnownHeaderNames.Vary]));
if (ctx.SystemMeta == null) {
ctx.SystemMeta = new NameValueCollection(varyValues.Count+1, CaseInsensitiveAscii.StaticInstance);
}
for (int i = 0; i < varyValues.Count; ++i) {
string headerValue = ctx.Request.Headers[(string)varyValues[i]];
ctx.SystemMeta[(string)varyValues[i]] = headerValue;
}
}
}
/*
- Hop-by-hop headers, which are meaningful only for a single
transport-level connection, and are not stored by caches or
forwarded by proxies.
The following HTTP/1.1 headers are hop-by-hop headers:
- Connection
- Keep-Alive
- Proxy-Authenticate
- Proxy-Authorization
- TE
- Trailers
- Transfer-Encoding
- Upgrade
*/
// We add or Replace headers from the live response
for (int i = 0; i < ctx.Response.Headers.Count; ++i) {
string key = ctx.Response.Headers.GetKey(i);
if (AsciiLettersNoCaseEqual(key, HttpKnownHeaderNames.Connection) ||
AsciiLettersNoCaseEqual(key, HttpKnownHeaderNames.KeepAlive) ||
AsciiLettersNoCaseEqual(key, HttpKnownHeaderNames.ProxyAuthenticate) ||
AsciiLettersNoCaseEqual(key, HttpKnownHeaderNames.ProxyAuthorization) ||
AsciiLettersNoCaseEqual(key, HttpKnownHeaderNames.TE) ||
AsciiLettersNoCaseEqual(key, HttpKnownHeaderNames.TransferEncoding) ||
AsciiLettersNoCaseEqual(key, HttpKnownHeaderNames.Trailer) ||
AsciiLettersNoCaseEqual(key, HttpKnownHeaderNames.Upgrade))
{
continue;
}
if (resp.StatusCode == HttpStatusCode.NotModified && AsciiLettersNoCaseEqual(key, HttpKnownHeaderNames.ContentLength)) {
continue;
}
ctx.CacheHeaders.ChangeInternal(key, ctx.Response.Headers[i]);
}
}
//