Признать протокол 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 2

1 ответ:

Вы не можете полагаться на код состояния (304 против 200), чтобы определить, изменилось ли что-то. Что делать, если какая-то другая часть вашего кода запрашивает тот же ресурс, обновляя таким образом кэш браузера?

Вместо этого просто сравните заголовок ответа Last-Modified с тем, что вы отправили в If-Modified-Since, или с тем, что вы в последний раз видели в Last-Modified. Если значения не совпадают, значит, что-то изменилось.

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

Почему fetch() даже заменяет код 304 на 200, Если в кэше есть последняя версия?

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