Заголовки для предотвращения запросов 304 / If-Modified-Since / HEAD

31

Какие заголовки я должен отправлять для полной остановки всех запросов к серверу после того, как содержимое было кэшировано?

У нас есть сервер с очень высокой задержкой (Sigh, VMWare), поэтому даже отправка HEADзапроса на сервер занимает + 40 мс.

В настоящее время это отправляемые / получаемые заголовки;

Первый запрос

Клиент отправляет;

GET http://dugong:8080/Rvi24mYJkxFRGNzq73PPvgWGh1j/IMG_2071.jpg HTTP/1.1
Host: dugong:8080
User-Agent: Mozilla/5.0 (Windows NT 5.1; rv:9.0) Gecko/20100101 Firefox/9.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip, deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Pragma: no-cache, no-cache, no-cache
Cache-Control: no-cache, no-cache, no-cache

Сервер отвечает;

HTTP/1.1 200 OK
Server: nginx/1.0.11
Date: Wed, 01 Feb 2012 14:51:51 GMT
Content-Type: text/plain
Vary: Accept-Encoding
Last-Modified: Tue, 31 Jan 2012 10:45:11 GMT
Content-Length: 14
Expires: Thu, 31 Jan 2013 14:51:51 GMT
Cache-Control: max-age=31536000

Таким образом , он посылает Cache-Controlи Expiresнабор заголовков 365 дней в будущем. К сожалению, при втором обновлении он снова запрашивает объект с If-Modified-Sinceзаголовком.

Второй запрос

GET http://dugong:8080/Rvi24mYJkxFRGNzq73PPvgWGh1j/IMG_2071.jpg HTTP/1.1
Host: dugong:8080
User-Agent: Mozilla/5.0 (Windows NT 5.1; rv:9.0) Gecko/20100101 Firefox/9.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip, deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
If-Modified-Since: Tue, 31 Jan 2012 10:45:11 GMT
Cache-Control: max-age=0

Отклик;

HTTP/1.1 304 Not Modified
Server: nginx/1.0.11
Date: Wed, 01 Feb 2012 14:58:00 GMT
Vary: Accept-Encoding
Expires: Thu, 31 Jan 2013 14:58:00 GMT
Cache-Control: max-age=31536000

К сожалению, из-за глупо устаревшего программного обеспечения прокси мы не можем использовать Keep-Aliveили ставить какие-либо другие серверы / прокси перед приложением. Мы также не можем улучшить производительность сервера и уменьшить задержки в сети. Я пытался выяснить, какие заголовки мы можем отправить, чтобы избавиться от 301 запроса. Я пытался использовать ETag, но это не имеет значения, он все еще отправляет If-modified-sinceзаголовок. Я также попытался удалить Last-Modifiedзаголовок, но это просто вызывает стандартный запрос GET без кэширования (проверил логи, сервер все еще получает запросы).

Клиенты - это смесь Firefox (в основном), IE 7, 8 и (некоторые) 9, Chrome и Safari, но такое поведение, похоже, проявляется во всех протестированных браузерах.

TL; DR;

Ужасная сеть, какие заголовки я должен отправлять, чтобы сказать клиентам никогда не отправлять If-modified-sinceзапросы на сервер для проверки их кэша и сохранять содержимое в кэше до тех пор, пока Expiresзаголовок не будет встречен?

Я, наверное, упускаю что-то очевидное, но все, что я пытаюсь, похоже, дает те же результаты.

У нас есть сервер NGINX, расположенный напротив нашего сервера приложений, поэтому я могу добавлять / удалять любые заголовки по своему усмотрению. Наш прокси не поддерживает Keep-Alive и не может улучшить производительность сети. Из-за ужасного дизайна программного обеспечения веб-приложение загружает +100 ресурсов на каждую загрузку страницы (да, корпоративное программное обеспечение отстает) с задержкой ~ 40-50 мс на объект.

мазаться
источник
1
Хм, это странно. Отправка заголовков Expires и max age должна предотвратить дальнейшие запросы изображения. Изменить: кстати, какова сделка с отправкой JPG как text/plain?
DisgruntledGoat
1
@DisgruntledGoat Ааа, вы сделали предположение, что файл .jpg на самом деле является изображением, а не текстовым документом. Добро пожаловать в мой мир =) (На самом деле это текстовый файл, который содержит «Hello World» для моего тестирования, программа просто переименовывает все файлы последовательно IMG_xxxx.jpg независимо от типа. Круто, да?)
Smudge
что вы использовали для установки заголовков HTTP-запроса?
Барлоп

Ответы:

25

Вы не можете реально контролировать, какие заголовки пользовательские агенты решат вам отправить. Если рассматриваемый файл находится в кеше браузера, и он решает, что нужно проверить новую версию, тогда он будет. Согласно этой статье , вот ситуации, которые браузеры будут запрашивать, используя If-Modified-Since:

  • Кэшированная запись не имеет срока действия, и к контенту обращаются впервые в сеансе браузера
  • Кэшированная запись имеет срок действия, но срок его действия истек
  • Пользователь запросил обновление страницы, нажав кнопку «Обновить» или нажав клавишу F5.

Поэтому, если вы перезагружаете страницу для проверки вашего кэширования, она не будет работать, так как браузер повторно запросит изображения. Попробуйте щелкнуть ссылку, затем другую ссылку на первую страницу. Если ваши пользователи регулярно перезагружают страницы, вам может потребоваться переосмыслить структуру вашего сайта / приложения, чтобы предотвратить это.

Одна вещь , которая может помочь в добавлении «общественность» в заголовок управления кэшем, то есть Cache-Control: public, max-age=31536000. Недавно я также узнал, что срок действия более одного года недействителен. Поскольку срок действия истекает ровно через год, возможно, его снижение на несколько дней или недель обеспечит сохранение файла в кэше браузера и его удаление.

DisgruntledGoat
источник
Интересно, я уменьшу срок действия до 60 дней и добавлю публичный флаг, и посмотрю, что произойдет. Похоже, это происходит при щелчках по ссылкам, а не по F5 (согласно Firebug и журналам сервера)
Smudge
Технически, спецификация HTTP / 1.1 говорит только о том, что «серверам НЕ СЛЕДУЕТ отправлять даты Expires более чем на один год в будущем» (предположительно, потому что это до смехотворно долгого времени до истечения срока действия) и что «приблизительно один год» в будущем является подходящим сроком действия. время для отправки контента, срок действия которого не ожидается.
Ильмари Каронен
1
Немного поигравшись, я пришел к выводу, что истечение 365 дней не влияет на наших клиентов, однако я остановил его, чтобы быть в безопасности, кажется, это Cache-Control: public,...был ключ к этой конкретной ситуации.
Пятно
Вы имеете в виду, что в "публичном" заголовке исправлены ненужные обходы? Я попробовал, но безуспешно ...
phtrivier
2
Если из моего ответа непонятно, перезагрузка страницы в вашем браузере снова запросит файлы . Просто нажмите на ссылку, чтобы открыть страницу, и браузер использует свой кеш.
Рассерженная шлюха
3

У меня была та же самая проблема, и Запросы определенно поражают сервер для того, чтобы он ответил со 304статусом - я посылаю 304 через некоторый C # и наверняка он попадает на сервер ..

Я только Cache-Control: privateустановил. Нет max-ageи нет. ExpiresОн действовал как ожидалось; поразить сервер с тем, If-Modified-Sinceгде я проверяю значение по сравнению с тем, что я ожидаю, и доставить 304с пустым телом ответа - иначе 200и заполнить тело ответа.

Установка Expiresзаголовка дала желаемые результаты, 200 - (from cache)на клиенте не было HTTP-запросов на сервере.

Но .. Я обнаружил, что установка ОБА max-age= & Expiresможет привести к тому, что браузеры не будут отправлять If-Modified-Sinceзаголовок И вообще не кэшировать, если значения не совпадают .

Что нужно знать, если у вас есть проблемы с кэшированием и вы используете разные заголовки в комбинации.

Эндрю Скотт
источник
1

Немного не по теме, но, возможно, полезно. Еще одним улучшением ваших запросов к кешированному контенту является кеширование в sessionStorage, чтобы вам не нужно было просить сервер проверить кеш и получить 304. Посмотрите, например, google, откройте консоль и напишите sessionStorage. Вы увидите, что они кешируют CSS или DOM с помощью sessionStorage. ofc, вы не можете использовать это в старых браузерах IE.

Пабло Эсторнут
источник
0

Просмотрите исходный код и убедитесь, что нет META REFRESH для перехода на другую страницу. Вместо этого используйте что-то вроде sendRedirect. На моей установке META REFRESH выдает 304 в IE, но не в Chrome. sendRedirect не производит это ни на одном браузере.

<meta http-equiv="refresh" content="0;URL='nextpage'" />    

против

<% response.sendRedirect("nextpage") %>
Ричард Сандос
источник