Какие ограничения применяются к непрозрачным ответам?

86

Непрозрачные ответы определяются как часть Fetch API и представляют результат запроса к удаленному источнику, когда CORS не включен.

Какие практические ограничения и «подводные камни» существуют относительно того, как можно использовать непрозрачные ответы как из JavaScript, так и в качестве ресурсов на странице?

Джефф Посник
источник

Ответы:

125

Доступ к заголовкам / телу непрозрачных ответов

Наиболее простое ограничение вокруг непрозрачных ответов является то , что вы не можете получить значимую информацию обратно от большинства свойств этого Responseкласса, как headers, или вызывать различные методы , которые составляют Bodyинтерфейс, как json()и text(). Это соответствует природе непрозрачного ответа в виде черного ящика.

Использование непрозрачных ответов в качестве ресурсов на странице

Непрозрачные ответы могут использоваться в качестве ресурса на веб-странице всякий раз, когда браузер позволяет использовать ресурсы перекрестного происхождения, отличные от CORS. Вот подмножество элементов, для которых допустимы ресурсы перекрестного происхождения, отличные от CORS, и, следовательно, непрозрачные ответы, адаптированные из документации Mozilla Developer Network :

  • <script>
  • <link rel="stylesheet">
  • <img>, <video>И<audio>
  • <object> а также <embed>
  • <iframe>

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

Как правило, чтобы определить, можно ли использовать непрозрачный ответ в качестве определенного типа ресурса на странице, проверьте соответствующую спецификацию. Например, спецификация HTML объясняет, что для <script>элементов могут использоваться ответы, не относящиеся к CORS (т.е. непрозрачные) , хотя и с некоторыми ограничениями для предотвращения утечки информации об ошибках.

Непрозрачные ответы и API хранилища кэша

Одна из «ловушек», с которой разработчик может столкнуться с непрозрачными ответами, связана с их использованием с API Cache Storage . Уместны две части справочной информации:

  • statusСвойство непрозрачной ответа всегда устанавливается0 , независимо от того, удалось ли первоначальный запрос или не удалось.
  • Оба метода add()/ API кэш-хранилища addAll()будут отклонены, если ответы, полученные в результате любого из запросов, имеют код состояния, который не находится в диапазоне 2XX .

Из этих двух пунктов следует, что если запрос, выполняемый как часть вызова add()/, addAll()дает непрозрачный ответ, он не будет добавлен в кеш.

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

const request = new Request('https://third-party-no-cors.com/', {mode: 'no-cors'});
// Assume `cache` is an open instance of the Cache class.
fetch(request).then(response => cache.put(request, response));

Непрозрачные ответы и API navigator.storage

Чтобы избежать утечки междоменной информации, к размеру непрозрачного ответа, используемого для расчета пределов квоты хранилища (т.е. генерируется ли QuotaExceededисключение), и сообщается navigator.storageAPI, добавлены значительные отступы .

Детали этого заполнения варьируются от браузера к браузеру, но для Google Chrome это означает, что минимальный размер, который любой кешированный непрозрачный ответ вносит в общее использование хранилища, составляет примерно 7 мегабайт . Вы должны помнить об этом при определении количества непрозрачных ответов, которые вы хотите кэшировать, поскольку вы можете легко превысить ограничения квоты хранилища намного раньше, чем вы ожидали бы в противном случае, исходя из фактического размера непрозрачных ресурсов.

Джефф Посник
источник
1
На самом деле он не занимает столько места в физической памяти устройства. Это просто значение, которое используется в расчетах квоты.
Джефф Посник
1
Ваш ответ даже упомянут в руководстве по Workbox здесь: developers.google.com/web/tools/workbox/guides/…
Дима Сливин
14
Верно, но я написал это руководство по Workbox :-)
Джефф Посник
1
Делает ли это использование CDN образов в сочетании с таким кешем плохим дизайном? (Потеря выделенного пространства) Можно ли кэшировать файл, полученный из нашего основного домена, и раскрыть его с помощью ссылки (ключа) CDN? Например, могу ли я отправить сетевой запрос, cdn.x.com/test.jpgа запросы кеша перейти в основной домен www.x.com/test.jpg.
cglacet
1
Я нашел уловку вокруг этой проблемы, я понятия не имею, достойное ли это решение, но я в основном заставляю своего сервисного работника делать вид, что это CDN. Я добавляю относительные URL-адреса домена в кеш (например, /test.jpgзатем для каждого запроса на выборку cdn.x.com/test.jpgя изменяю URL-адрес с исходным доменом (URL-адрес становится www.x.com/test.jpg), я использую что-то вроде этого:. const cacheUrl = (url.hostname == 'cdn.x.com')? new URL(event.target.location.origin + url.pathname): url;Затем я запрашиваю кеш с этим новым URL-адресом caches.match(cacheUrl), который кажется чтобы работать нормально. Есть хоть какой-нибудь об этом подходе?
cglacet