Сведения о вопросе

Holish

16:03, 1st July, 2020

Теги

Как узнать, когда отправить 304 не измененный ответ

Просмотров: 537   Ответов: 5

Я пишу метод обработки ресурсов, где я контролирую доступ к различным файлам, и я хотел бы иметь возможность использовать кэш браузера. Мой вопрос двоякий:

  1. Какие окончательные заголовки HTTP мне нужно проверить, чтобы точно знать, должен ли я отправить ответ 304, и что я ищу, когда я их проверяю?

  2. Кроме того, есть ли какие-либо заголовки, которые мне нужно отправить, когда я изначально отправляю файл (например, 'Last-Modified') в качестве ответа 200?

Некоторые psuedo-код, вероятно, будет наиболее полезным ответом.


А как насчет заголовка cache-control? Могут ли различные возможные значения этого влиять на то, что вы отправляете клиенту (а именно max-age), или следует выполнять только if-modified-since?



  Сведения об ответе

VCe znayu

18:03, 1st July, 2020

Вот как я это реализовал. Код работает уже чуть больше года и с несколькими браузерами, поэтому я думаю, что он довольно надежен. Это основано на RFC 2616 и наблюдении за тем, что и когда отправляли различные браузеры.

Вот вам и псевдокод:

server_etag = gen_etag_for_this_file(myfile)
etag_from_browser = get_header("Etag")

if etag_from_browser does not exist:
    etag_from_browser = get_header("If-None-Match")
if the browser has quoted the etag:
    strip the quotes (e.g. "foo" --> foo)

set server_etag into http header

if etag_from_browser matches server_etag
    send 304 return code to browser

Вот фрагмент моей серверной логики, которая обрабатывает это.

/* the client should set either Etag or If-None-Match */
/* some clients quote the parm, strip quotes if so    */
mketag(etag, &sb);

etagin = apr_table_get(r->headers_in, "Etag");
if (etagin == NULL)
    etagin = apr_table_get(r->headers_in, "If-None-Match");
if (etag != NULL && etag[0] == '"') {
    int sl; 
    sl = strlen(etag);
    memmove(etag, etag+1, sl+1);
    etag[sl-2] = 0;
    logit(2,"etag=:%s:",etag);
}   
... 
apr_table_add(r->headers_out, "ETag", etag);
... 
if (etagin != NULL && strcmp(etagin, etag) == 0) {
    /* if the etag matches, we return a 304 */
    rc = HTTP_NOT_MODIFIED;
}   

Если вам нужна помощь с etag поколением, напишите еще один вопрос, и я найду какой-нибудь код, который тоже это делает. HTH!


  Сведения об ответе

$DOLLAR

18:03, 1st July, 2020

Ответ 304 Not Modified может быть получен из запроса GET или HEAD с заголовком If-Modified-Since ("IMS") или If-Not-Match ("INM").

Чтобы решить, что делать при получении этих заголовков, представьте, что вы обрабатываете запрос GET без этих условных заголовков. Определите, какие значения ваших заголовков ETag и Last-Modified будут в этом ответе, и используйте их для принятия решения. Надеюсь, вы построили свою систему таким образом, что определение этого менее затратно, чем построение полного ответа.

Если существует INM и значение этого заголовка совпадает со значением, которое вы разместили бы в ETag, то ответьте 304.

Если есть IMS и значение даты в этом заголовке позже, чем то, которое вы разместили бы в последнем измененном, то ответьте 304.

В противном случае действуйте так, как будто запрос не содержит этих заголовков.

Для наименее трудоемкого подхода к части 2 Вашего вопроса выясните, какие из заголовков (Expires, ETag и Last-Modified) вы можете легко и правильно создать в своем веб-приложении.

Для предлагаемого материала для чтения:

http://www.w3.org/Protocols/rfc2616/rfc2616.html

http://www.mnot.net/cache_docs/


  Сведения об ответе

+-*/

18:03, 1st July, 2020

Вы должны отправить сообщение 304, если клиент явно заявил, что у него уже есть страница в кэше. Это называется условным GET, который должен включать заголовок if-modified-since в запросе.

В основном, этот заголовок запроса содержит дату, с которой клиент утверждает, что у него есть кэшированная копия. Вы должны проверить, изменилось ли содержимое после этой даты, и отправить запрос, если нет.

Смотрите http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.25 для соответствующего раздела в RFC.


  Сведения об ответе

SILA

18:03, 1st July, 2020

Мы также обрабатываем кэшированные, но защищенные ресурсы.  Если вы отправляете / генерируете заголовок ETAg (который RFC 2616 раздел 13.3 рекомендует вам SHOULD), то клиент MUST использует его в условном запросе (обычно в заголовке If-None-Match - HTTP_IF_NONE_MATCH).  Если вы отправляете последний измененный заголовок (снова вы SHOULD), то вы должны проверить If-Modified-Since - HTTP_IF_MODIFIED_SINCE - заголовок.  Если вы отправите оба, то клиент SHOULD отправит оба, но он MUST отправит ETag.  Также обратите внимание, что validtion просто определяется как проверка условных заголовков на строгое равенство с теми, которые вы бы отправили.  Кроме того, только сильный валидатор (например, ETag) будет использоваться для ранжированных запросов (где запрашивается только часть ресурса).

На практике, поскольку ресурсы, которые мы защищаем, довольно статичны, и время задержки в одну секунду является приемлемым, мы делаем следующее:

  1.  Проверьте, имеет ли пользователь право доступа к запрошенному ресурсу

         Если это не так, перенаправьте их или отправьте ответ 4xx по мере необходимости.  Мы сгенерируем 404 ответа на запросы, которые выглядят как попытки взлома или вопиющие попытки выполнить завершающий запуск системы безопасности.

  2.  Сравните заголовок If-Modified-Since с последним измененным заголовком, который мы бы отправили (см. ниже) для строгого равенства

         Если они совпадают, отправьте 304 не измененных ответа и завершите обработку страницы

  3.  Создайте последний измененный заголовок, используя время изменения запрошенного ресурса

        Посмотрите формат даты HTTP в RFC 2616

  4.  Отправьте заголовок и содержимое ресурса вместе с соответствующим типом содержимого

Мы решили отказаться от заголовка ETag, так как он является излишним для наших целей.  Я полагаю, что мы могли бы также просто использовать метку времени даты как ETag.  Если мы перейдем к истинной системе ETag, мы, вероятно, будем хранить вычисленные хэши для ресурсов и использовать их как ETags.

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


  Сведения об ответе

$DOLLAR

18:03, 1st July, 2020

что касается управления кэшем:

Вам не нужно беспокоиться о контроле кэша при подаче, кроме установки его на разумное значение. Это в основном говорит браузеру и другим нижестоящим сущностям (таким как прокси) максимальное время, которое должно пройти до истечения времени ожидания кэша.


Ответить на вопрос

Чтобы ответить на вопрос вам нужно войти в систему или зарегистрироваться