Как я могу сделать кэш браузера веб-ресурсом, у которого нет постоянного URL-адреса?

#web

#веб

Вопрос:

Проблема

Скажем, веб-странице необходимо загрузить несколько файлов ${some_id}.file . Но

  • Они размещены в облачной службе и должны быть загружены с другого домена, например https://some.cloud.com/${some_generated_token} , которые не являются постоянными URL-адресами.
  • Файлы могут быть частными для текущего пользователя, поэтому пользователи без разрешения не смогут получить URL-адрес загрузки.

Если интерфейс просто делает:

 fetch(`https://some.cloud.com/${some_generated_token}`)
  

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


Подход 1

Напишите мой собственный файловый сервер, чтобы интерфейс загружался с https://my-server.com/download/${some_id}.file него.

Сервер проверяет разрешение пользователя перед загрузкой. И если проверка пройдет, отправьте перенаправление (302 временно перемещено) на реальный URL-адрес загрузки https://some.cloud.com/${some_generated_token} , в противном случае ответьте ошибкой.

Может быть, мне следует поместить etag заголовок в ответ, скопированный из реального. Я не уверен, что это сработает. Возможно ли сделать файлы кэша браузера загруженными с перенаправленных URL-адресов?

Подход 2

Вручную внедрите систему кэширования для клиентской части, которая при необходимости загружает реальный файл под капотом. Таким образом, файл фактически загружается из кэша, а не из облака. Файлы идентифицируются чем-то вроде ${some_id}_${checksum} .

Недостатком может быть то, что мне приходится управлять хранилищем вручную. (Так что либо я должен беспокоить пользователя другим параметром, чтобы определить емкость, либо браузер решает это, и у меня нет возможности договориться. Я не уверен в этом.)


Итак, каков наилучший / возможный способ сделать это? И как это реализовать?

Комментарии:

1. В подходе 2, как клиент разрешит идентификатор из токена?

2. @Brenden Клиент не разрешает идентификатор из токена. Сервер генерирует токен на основе идентификатора и некоторой дополнительной информации.

3. есть ли шанс, что вы можете просто прочитать заголовки как частичный запрос (HEAD) и увидеть, что в заголовках есть какая-либо информация, такая как последнее изменение и т. Д., Тогда вы могли бы отправить полный запрос?

4. могу я просто спросить, какой облачный сервис вы используете?

5. @SomeoneSpecial В настоящее время Google cloud, но может измениться в будущем.

Ответ №1:

Я рекомендую подход 2, кэширование на стороне клиента, если идентификатор ресурса может быть каким-то образом разрешен / сообщен на стороне клиента.

API Service Worker может быть полезен для вашего варианта использования. И конкретный раздел, цитируемый из MDN:

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

Пример кода работника службы:

 function deriveStableUrl(request) {
  // somehow decide a stable URL for the varying token URL for the same resource
  // note that, this URL is not for network fetching, but merely a key to index the underlying resource in the cache. 
  return stableUrl;
}

addEventListener('fetch', event => {
  event.respondWith(async function() {
    // Open 'default' cache object, or you can decide the name of your choice. 
    const cache = await caches.open('default');
    // Try to get the response from a cache.
    const url = deriveStableUrl(event.request);
    const cachedResponse = await cache.match(url);
    // Return it if we found one.
    if (cachedResponse) return cachedResponse;
    // If we didn't find a match in the cache, use the network.
    return fetch(event.request).then(resp => {
      // Cache it with the stable URL as key. 
      cache.put(url, resp);
      return resp;
    })
  }());
});
  

Ответ №2:

Подход 3 (интеллектуальное проксирование): предоставьте стабильный URL-адрес на своем собственном хосте (откуда обслуживается интерфейс), передавая токен в заголовке, и пусть эта конечная точка извлекает файл из облачной системы (используя токен) и пересылает его интерфейсу. Это имело бы смысл только в том случае, если А) размер файла не настолько велик, что это приводит к значительным затратам на объем передачи ваших собственных систем и Б) у вас действительно есть серверная часть, с которой это можно сделать.

Комментарии:

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

Ответ №3:

Если вам нужна безопасность, то либо облачный сервис «умный» (проверка на стороне сервера), либо ваш интерфейс «умный» (собственное кэширование собственных проверок по строкам запроса).

Не существует простого способа получить безопасный и в то же время дешевый «простой» сервис.

Одним из решений является использование выборки (url, { header: {Authorization: token}}), а затем использование сервиса, такого как cloudfront.

ваш URL-адрес остается неизменным, поэтому, скорее всего, он будет кэшироваться. Заголовок авторизации изменяется, однако, если вы используете токен jwt, срок действия токена очень длинный, поэтому, скорее всего, он не изменится, если вы не выйдете из системы / не войдете в систему.

Например, сервисы, подобные Cloudfront

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

Запрос пользователя -> Cloudfront -> Перенаправить заголовок авторизации в источник -> исходный файл проверки и возврата.

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

лямбда -> извлечение из s3 -> возврат в cloudfront.

Кэширование содержимого на основе заголовков запросов

Однако обратите внимание, что это не на 100% безопасно.

Отказ от ответственности: Если вы размещаете файлы в облаке без одноразовой подписи, что бы вы ни делали, это небезопасно.