Service Worker API
About
Сервис-воркер это файл JavaScript, который регистрируется на конкретном источнике (веб-сайте или части сайта на конкретном домене) при обращении браузером. После регистрации, он может управлять страницами на этом источнике. Воркер находится между загруженной страницей и сетевым соединением, перехватывая сетевые запросы источника.
Когда worker перехватывает запрос, он может делать многие вещи (смотри идеи для использования сервис-воркеров), но классический пример это сохранение сетевых ответов и затем доступ к ним при запросе, вместо запросов по сети. В результате, это позволяет сделать веб-сайт полностью работающим в офлайне.
Service worker фактически выполняет роль прокси-сервера, находящегося между веб-приложением и браузером, а также сетью (если доступна). Он позволяет (кроме прочего) описывать корректное поведение веб-приложения в режиме офлайн, перехватывать запросы сети и принимать соответствующие меры, основываясь на доступности сети, и обновлять данные, находящиеся на сервере при доступе к нему. Также они имеют доступ к push-уведомлениям и API для фоновой синхронизации.
Service worker запускается в контексте worker'ов, поэтому он не имеет доступа к DOM и работает в потоке отдельном от основного потока JavaScript, управляющего вашим приложением, а следовательно — не блокирует его. Он призван быть полностью асинхронным; как следствие, синхронные API, такие как XHR и localStorage, в Service Worker'е использовать нельзя.
Пример сервис воркер
Первое,что мы делаем, это проверка на то, что serviceWorker
доступен в объекте Navigator
. Если этот так, тогда мы знаем, что как минимум, базовые функции сервис-воркера доступны. Внутри проверки мы используем метод ServiceWorkerContainer.register()
для регистрации сервис-воркера, находящегося в файле sw.js
на текущем источнике, таким образом, он может управлять страницами в текущей или внутренних директориях. Когда Promise выполнится, сервис-воркер считается зарегистрированным.
Примечание: Путь к файлу sw.js
указан относительно корня сайта, а не JavaScript файла, содержащего основной код.
Устанавливаем сервис воркер
В следующий раз, когда страница с сервис-воркером будет запрошена (например когда страница будет перезагружена), сервис-воркер запустится на этой странице и начнет контролировать её. Когда это произойдет, событие install
будет вызвано в сервис-воркере; вы можете написать код внутри сервис-воркера, который будет вызван в процессе установки.
Давайте взглянем на файл сервис-воркера sw.js. Вы можете видеть, что слушатель события install
зарегистрирован на self
. Ключевое слово self
это способ ссылки на глобальную область видимости сервис-воркера из файла с сервис-воркером.
Внутри обработчика install
мы используем метод ExtendableEvent.waitUntil()
, доступном в объекте события, чтобы сигнализировать, что работа продолжается, и браузер не должен завершать установку, пока все задачи внутри блока не будут выполнены.
Здесь мы видим Cache API в действии. Мы используем метод CacheStorage.open()
для открытия нового объекта кэша, в котором ответы могут быть сохранены (похоже на объект хранилища IndexedDB). Обещание выполнится с объектом Cache
, представляющим собой кэш video-store
. Затем мы используем метод Cache.addAll()
для получения ресурсов и добавления ответов в кэш.
Отвечаем на последующие запросы
Когда сервис-воркер зарегистрирован и установлен на странице HTML и сопутствующие ресурсы добавлены в кэш, все практически готово. Нужно сделать еще одну вещь - написать код для ответа на дальнейшие сетевые запросы.
Мы добавим еще один слушатель к сервис-воркеру в глобальной области видимости, который запускает функцию-обработчик при событии fetch
. Это происходит всякий раз, когда браузер делает запрос ресурса в директорию, где зарегистрирован сервис-воркер.
Внутри обработчика, мы сначала выводим в консоль URL запрашиваемого ресурса. Затем отдаем особый ответ на запрос, используя метод FetchEvent.respondWith()
.
Внутри блока мы используем CacheStorage.match()
чтобы проверить, можно ли найти соответствующий запрос (т.е. совпадение по URL) в кэше. Обещание возвращает найденный ответ или undefined
, если ничего не нашлось.
Если совпадение нашлось, то просто возвращаем его как особый ответ. В противном случае, используем fetch() для запроса ресурса из сети.
Security
Attack
Загружаем наш html с js с регистрацией сервис воркера (если есть возможность — в корень)
Добавляем eventListener на fetch с отправкой нам уведомления
Обращаемся к html -> видим в консоли, зарегистрирован ли service worker (можно проверить в about:debugging#workers)
Далее, можем перехватывать и менять запросы и ответы к серверу
Поидее, можем таким манипулировать через stored xss (или заманивая пользователей на наш html загруженный)
Defence
Content-Disposition: attachment
дополнительная директория : https://example.com/subdir_y3ugbdcy2yfg8efjdnms/uploaded_files.html
Другие ваврианты использования Service Workers
Last updated