Признать протокол HTTP 304 работник службы / принеси()
Я создаю Service worker, который всегда отвечает данными из кэша, а затем в фоновом режиме отправляет запрос на сервер. Если сервер отвечает HTTP 304 - not modified
все в порядке, если сервер отвечает HTTP 200
, это означает, что данные были изменены и новый файл помещен в кэш, также пользователь уведомляется и просит обновить страницу.
Я использую not-modified-since
/ last-modified
заголовки, чтобы убедиться, что клиент получает самую последнюю версию. Когда запрос отправляется через fetch()
запрос передает HTTP-кэш по пути в сеть - также ответ передает http-кэш, когда он поступает на клиент. Проблема заключается в том, что когда ответ имеет статус 304
- не изменен, кэш HTTP отвечает работнику службы с кэшированной версией и заменяет статус на 200
(как описано в спецификации fetch - HTTP-network-or-cache-fetch). В сервисном работнике нет возможности узнать, был ли изначально отправлен ответ 200
сервер (пользователь должен быть обновлен) или он был отправлен кэшем и сервер первоначально ответил 304
(самая последняя версия уже загружена).
Существует флагрежима кэширования , который может быть установлен в no-cache
, но это обходит HTTP-кэш также при отправке запроса на сервер, что означает, что заголовок if-modified-since
не установлен и сервер не имеет возможности узнать, какая версия у клиента. Также этот флаг поддерживается только firefox nightly right сейчас.
Я думаю, что лучшее решение-это установить пользовательский заголовок HTTP, такой как x-was-modified
, когда сервер отвечает 200
. Этот пользовательский заголовок доступен в Service worker и может использоваться для определения того, был ли ресурс обновлен или нет, даже если кэш HTTP заменяет состояние 304
на 200
.
- Является ли это законным решением / обходным путем? Существуют ли какие-либо предлагаемые подходы к решению этой проблемы?
- должен ли я вообще полагаться на заголовки HTTP, которые должны обрабатывать http-кэширования при реализации кэша работник сервиса? Или мне лучше использовать обычай
x-if-modified-since
/x-last-modified
заголовки и использовать indexedDB для хранения информации о клиенте и добавлять ее к каждому запросу? - Почему
fetch()
даже заменяет код304
на200
, если в кэше есть последняя версия?
1 ответ:
Вы не можете полагаться на код состояния (304 против 200), чтобы определить, изменилось ли что-то. Что делать, если какая-то другая часть вашего кода запрашивает тот же ресурс, обновляя таким образом кэш браузера?
Вместо этого просто сравните заголовок ответаLast-Modified
с тем, что вы отправили вIf-Modified-Since
, или с тем, что вы в последний раз видели вLast-Modified
. Если значения не совпадают, значит, что-то изменилось.Для большей точности (если данные могут изменяться несколько раз за 1 секунду), рассмотрите возможность использования
ETag
вместо этого изLast-Modified
.Потому что обычно люди просто хотят получить свежий контент, независимо от того, откуда он берется. Ответ 304 интересен только тем, кто реализует свои собственные HTTP-кэши.Почему
fetch()
даже заменяет код304
на200
, Если в кэше есть последняя версия?