Истекает заголовки при тестировании в Chrome
Очень запутался насчет заголовка "Expires" здесь! Иногда это работает, как ожидалось, а иногда нет.
Я использую следующий код, чтобы установить мои заголовки срока действия. Обратите внимание, что это делается с ASP.NET в настраиваемом атрибуте MVC - это не очень важно здесь - но объясняет, где 'filterContext'
идет от.
HttpCachePolicyBase cache = filterContext.HttpContext.Response.Cache;
TimeSpan cacheDuration = TimeSpan.FromSeconds(Duration);
// my own custom header so we know what time it was
filterContext.HttpContext.Response.AddHeader("CurrentTime", DateTime.Now.ToString());
cache.SetCacheability(HttpCacheability.Public);
cache.SetExpires(DateTime.Now.Add(cacheDuration));
cache.SetMaxAge(cacheDuration);
cache.AppendCacheExtension("must-revalidate, proxy-revalidate");
Это иногда дает мне такие заголовки:
Cache-Control: public, must-revalidate, proxy-revalidate, max-age=413
Date: Wed, 18 Feb 2009 05:24:19 GMT
Expires: Wed, 18 Feb 2009 05:21:12 GMT
CurrentTime: 2/17/2009 9:21:12 PM
Иногда так:
Cache-Control: public, must-revalidate, proxy-revalidate, max-age=600
Date: Wed, 18 Feb 2009 05:27:55 GMT
Expires: Wed, 18 Feb 2009 05:27:55 GMT
CurrentTime: 2/17/2009 9:27:55 PM
Я запускаю все через Fiddler и наблюдаю, когда что-то запрашивается повторно и когда оно поступает из кеша браузера.
Теперь странно то, что в IE кэширование всегда работает как положено. Ссылка на мой метод действия ASP.NET MVC появляется в Fiddler, а затем, когда я снова нажимаю на эту же ссылку, она поступает из кэша.
Однако в Chrome это иногда будет, а иногда не будет приходить из кеша! Под кешем я не имею в виду дополнительный HTTP-запрос.
Например, такая ссылка:
http://ipv4.fiddler:62669/gallery/mainimage/2
придет из кеша в IE, но вернется с 200 в хроме. Тогда иногда в Chrome это происходит из кеша. Я попытался очистить кеш браузера и повторил попытку - каждый раз один и тот же результат.
Chrome пытается сделать что-то "умное" и просто с треском проваливается - или мне нужен дополнительный заголовок?
Что мне интересно, так это то, что мой Expires
Дата заголовка никогда не бывает в будущем. если я посмотрю на заголовки Google для их размещенного файла jQuery, я увижу, что заголовки выглядят следующим образом (срок действия истекает здесь в 2010 году - через год).
Cache-Control: public, max-age=31536000
Date: Wed, 18 Feb 2009 05:44:53 GMT
Expires: Thu, 18 Feb 2010 05:44:53 GMT
Не должно быть, Истекает на самом деле в будущем?
Согласно спецификации HTTP:
Если ответ включает в себя как заголовок Expires, так и директиву max-age, директива max-age переопределяет заголовок Expires, даже если заголовок Expires является более ограничительным. Это правило позволяет исходному серверу предоставлять для данного ответа более длительное время истечения для кэша HTTP/1.1 (или более поздней), чем для кэша HTTP/1.0. Это может быть полезно, если некоторые кэши HTTP/1.0 неправильно рассчитывают возраст или время истечения, возможно, из-за десинхронизированных часов.
Поэтому кажется, что Chrome должен соблюдать директиву max-age, даже если "Expires" совпадает с текущим временем, но, похоже, он этого не делает.
2 ответа
Я нашел следующее в исходном коде ASP.NET MVC:
public virtual void RenderView(ViewContext viewContext) {
// TODO: Remove this hack. Without it, the browser appears to always load cached output
viewContext.HttpContext.Response.Cache.SetExpires(DateTime.Now);
ViewUserControlContainerPage containerPage = new ViewUserControlContainerPage(this);
// Tracing requires Page IDs to be unique.
ID = Guid.NewGuid().ToString();
RenderViewAndRestoreContentType(containerPage, viewContext);
}
Так что это объясняет, почему мой Expires
заголовок всегда является текущим временем. Однако я действительно не думаю, что это то, что запускает Chrome, потому что я создал простейшую страницу, как показано ниже, и Chrome все еще довольно счастливо возвращался на сервер и давал мне 200
public partial class test : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
TimeSpan cacheDuration = TimeSpan.FromSeconds(33);
var cache = Response.Cache;
cache.SetCacheability(HttpCacheability.Public);
cache.SetExpires(DateTime.Now.Add(cacheDuration));
cache.SetMaxAge(cacheDuration);
cache.AppendCacheExtension("must-revalidate, proxy-revalidate");
}
}
Я в значительной степени пришел к выводу, что это Chrome делает что-то действительно дурацкое с кэшированием.
Я упростил его до минимально возможного уровня - получения jQuery с сервера Google.
Я набрал:
http://ajax.googleapis.com/ajax/libs/jquery/1.3.1/jquery.min.js
в Chrome, и Фиддлер выдал следующий 200 запрос:
Requests started at: 22:58:00:7756
Responses completed at: 22:58:03:5020
Total Sequence time: 00:00:02.7263880
DNS Lookup time: 531ms
TCP/IP Connect time: 63ms
RESPONSE CODES
--------------
HTTP/200: 1
Заголовки были следующими (обратите внимание, что срок действия истекает через 1 год после сегодняшнего дня):
Cache-Control: public, max-age=31536000
Date: Wed, 18 Feb 2009 06:58:01 GMT
Expires: Thu, 18 Feb 2010 06:58:01 GMT
Vary: Accept-Encoding
а затем я подождал несколько секунд и нажал Enter - на той же вкладке. Скрипач придумал ДРУГОЙ **200* запрос:
Requests started at: 22:58:09:2516
Responses completed at: 22:58:12:3999
Total Sequence time: 00:00:03.1482360
RESPONSE CODES
--------------
HTTP/200: 1
И заголовки были:
Cache-Control: public, max-age=31536000
Date: Wed, 18 Feb 2009 06:58:09 GMT
Expires: Thu, 18 Feb 2010 06:58:09 GMT
Vary: Accept-Encoding
Очевидно, это не то, что я ожидал.
Да - Accept-Encoding был одинаковым для обоих запросов.
Да - третий запрос дал мне 304
Это была новая версия Chrome, на которой я никогда не занимался разработкой, и на которой я только что впервые установил Fiddler.
Я не могу ждать, пока кто-нибудь объяснит мне это. Сейчас я сдаюсь - я думаю, что мой код кэширования и истечения срока действия в порядке. Кроме того, ASP.NET MVC, кажется, заставляет Expires быть текущим временем. Это, очевидно, не является фактором в моем примере Google.
Я думаю, что Chrome слишком умный, и это должно быть ошибкой - я нахожусь на версии 1.0.154.48.