http: условное получение не дает возможности обновить заголовки без повторной отправки тела - PullRequest
4 голосов
/ 08 декабря 2011

Я не знаю, является ли это ошибкой или функцией в спецификации http, или я не понимаю, все в порядке.

У меня есть ресурс, который меняется не чаще одного раза в неделю, в начале недели. Если он не изменился, то ресурс предыдущей недели остается в силе всю неделю.

(Для всех наших тестов мы изменили однонедельный период на пять минут, но я думаю, что наши наблюдения все еще действительны).

Сначала мы отправляем ресурс с заголовком Expires: next Monday. Целую неделю браузер извлекает из кеша. Если в понедельник у нас появился новый ресурс, он извлекается с новыми заголовками, и все в порядке.

Проблема возникает, когда ресурс не обновляется. В ответ на условное получение наше приложение (Java + Tomcat) отправляет новые заголовки с Expires: next Monday, но без тела. Но наш внешний сервер (apache) удаляет этот заголовок, потому что спецификация говорит, что вы не должны отправлять новые заголовки, если ресурс не изменился. Так что теперь навсегда (до тех пор, пока ресурс не изменится) браузер отправит условное получение, когда мы хотим, чтобы оно продолжало обслуживать прямо из кэша.

Существует ли специальный способ обновления заголовков без обновления тела? (или отправив его снова)

И подвопрос: как заставить apache проходить по заголовкам tomcat?

Ответы [ 4 ]

5 голосов
/ 11 декабря 2011

Просто заголовка Expires недостаточно. В соответствии с разделом 13.3.4 RFC 2616 сервер должен ответить двумя заголовками, Last-Modified и ETag, чтобы сделать условное GET правильное:

Другими словами, предпочтительным поведением для исходного сервера HTTP / 1.1 является отправка как тега сильной сущности, так и значения Last-Modified.

И если клиент совместим с HTTP / 1.1, он должен отправить If-Modified-Since. Затем сервер должен ответить следующим образом (цитата из предложения Роя Филдинга о добавлении условного запроса GET ):

  • Если ресурс недоступен (по какой-либо причине), то сервер должен вернуть сообщение 4XX, как это происходит сейчас.
  • Если ресурс больше не существует, сервер должен вернуть ответ 404 Not Found (т. Е. Такой же, как сейчас).
  • Если ресурс доступен, но его дата последнего изменения более ранняя (меньше) или равна пройденной дате, сервер должен вернуть сообщение 304 Not Modified (без тела).
  • Если ресурс доступен, и его последняя дата изменения более поздняя, ​​чем пройденная дата, сервер должен вернуть сообщение 200 OK (т. Е. Такое же, как сейчас) с телом.

Итак, я думаю, вам не нужно настраивать Apache и / или Tomcat так, как вы описали. Вы должны сделать ваше приложение совместимым с HTTP / 1.1.

0 голосов
/ 17 декабря 2011

Заголовок Expires в основном был устаревшим с HTTP 1.1;используйте Cache-Control: max-age вместо.

Убедитесь, что вы включаете Last-Modified.

Это необязательно, но вы также можете указать Cache-Control: must-revalidate, чтобы промежуточные прокси не доставлялипотенциально устаревшее содержимое.

Вам не нужно устанавливать ETag.

Пример запроса:

GET http://localhost/images/logo.png HTTP/1.1
Accept: image/png, image/svg+xml, image/*;q=0.8, */*;q=0.5
Referer: http://localhost/default.aspx
Accept-Language: en-US
User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0)
Accept-Encoding: gzip, deflate
Host: localhost
Connection: Keep-Alive

Ответ включает запрошенное содержимое:

HTTP/1.1 200 OK
Cache-Control: max-age=10
Content-Type: image/png
Last-Modified: Sat, 21 Feb 2009 11:28:18 GMT
Accept-Ranges: bytes
Date: Sun, 18 Dec 2011 05:48:34 GMT
Content-Length: 2245

Запросы, сделанные до 10-секундного тайм-аута, разрешаются из кэша без HTTP-запроса.По истечении времени ожидания:

GET http://localhost/images/logo.png HTTP/1.1
Accept: image/png, image/svg+xml, image/*;q=0.8, */*;q=0.5
Referer: http://localhost/default.aspx
Accept-Language: en-US
User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0)
Accept-Encoding: gzip, deflate
Connection: Keep-Alive
If-Modified-Since: Sat, 21 Feb 2009 11:28:18 GMT
Host: localhost

Ответ - это просто заголовки без содержимого:

HTTP/1.1 304 Not Modified
Cache-Control: max-age=10
Last-Modified: Sat, 21 Feb 2009 11:28:18 GMT
Accept-Ranges: bytes
Date: Sun, 18 Dec 2011 05:49:04 GMT

Последующие запросы снова разрешаются из кэша браузера до истечения указанного срока действия.

0 голосов
/ 16 декабря 2011

Одним из способов решения проблемы является использование отдельных URI для каждой недели. Канонический URL-адрес перенаправляет на соответствующий URL-адрес недели и инструктирует браузер кэшировать перенаправление на неделю. Кроме того, URL-адреса, содержащие дату, будут указывать браузеру на кеширование навсегда.

Канонический URL: / путь / к / ресурсу


Status Code : 301
Location : /path/to/resource/12-dec or /path/to/resource/19-dec
Expires : Next Monday

Неделя 1: / путь / к / ресурсу / 12 декабря


Status code : 200
Expires : Never

Неделя 2: / путь / к / ресурсу / 19 декабря


Status code : 200
Expires : Never

Когда срок действия кэша истекает в понедельник, вы просто отправляете ответ перенаправления. Вы либо отправляете URL-адрес за последние недели, либо за эти недели, но никогда не отправляете весь текст ответа.

При таком подходе вы устранили условные получения. Вы также сделали свои ресурсы «неизменяемыми - однажды опубликованными», и вы также получите версионные ресурсы.

Единственное предупреждение - перенаправления не кэшируются всеми браузерами, даже если спецификация http требует от них этого. В частности, IE8 и ниже не кэшируются. Подробнее см. в столбце «Перенаправление кеша браузера» в браузере .

.
0 голосов
/ 14 декабря 2011

Попробуйте отправить действительный HTTP-Дата для Истекает заголовок?

...