Полный URL в файле ассетов erb —> проблемы с мультисайтом

Новая реализация service worker в workbox использует UrlHelper.absolute. Поскольку это скомпилированный ресурс, он хранит полный URL, включая полное имя хоста основного сервера в мультисайтовой среде.

https://github.com/discourse/discourse/blob/master/app/assets/javascripts/service-worker.js.erb#L3-L6

Думаю, следует использовать UrlHelper.local_cdn_url вместо этого. Это также устраняет необходимость перекомпиляции ресурсов после изменения имени хоста.

1 лайк

Общее мнение таково, что Service Workers никогда не должны обслуживаться через CDN:

То есть вы имеете в виду файлы importScripts? У вас есть кластер с несколькими сайтами, где у каждого сайта свой URL CDN?

1 лайк

Да, importScripts и modulePathPrefix находятся на строках 3 и 6 этого файла ERB.

Однако вы меня не до конца поняли. Проблемы возникают в тех случаях, когда в кластере мультисайтов нет CDN.

Обе функции UrlHelper.absolute и UrlHelper.local_cdn_url могут обрабатывать ситуации как с CDN, так и без него.

absolute:

без CDN: https://primarysite.ofmultisitecluster.com/javascripts/workbox/workbox-sw.js плохо — удалённый источник для всех сайтов, кроме основного, что раскрывает имя хоста основного кластера
с CDN: //cdnurl/javascripts/workbox/workbox-sw.js

local_cdn_url:

без CDN: /javascripts/workbox/workbox-sw.js хорошо — относительный URL
с CDN: //cdnurl/javascripts/workbox/workbox-sw.js

Таким образом, нам нужен именно второй вариант.

Проблема в том, что эти строки (3 и 6) не относятся к файлу сервис-воркера.

Сервис-воркер загружается с базового домена (поскольку его нельзя обслуживать через CDN), но этот сервис-воркер лениво импортирует скрипты во время выполнения (в данном случае файлы библиотеки Workbox), и их можно обслуживать через CDN.

Таким образом, проблема заключается в том, что ваш кластер мультисайтов не настроен с использованием CDN, что и выявляет эту ошибку. Эта ошибка маскируется, когда установлено значение DISCOURSE_CDN. Я просто хотел узнать, почему это не влияет на нас.

1 лайк

Вы правы, я отредактировал свой второй пост, чтобы исправить свои ошибки.
Дело не в файле сервисного работника, оно находится внутри файла сервисного работника.

Да, именно в этом случае ошибка проявляется.

3 лайка

Просто уточняю: мой диагноз верен, и это баг, который будет исправлен? Нужно ли от нас что-то для помощи?

3 лайка

Да, похоже на ошибку, которую нужно исправить. Я займусь этим на этой неделе!

3 лайка

Хм, я только что попробовал это в консоли Meta:

## Текущее состояние
[1] pry(main)> UrlHelper.absolute("/javascripts/workbox/workbox-sw.js")
=> "https://d3bpeqsaub0i6y.cloudfront.net/javascripts/workbox/workbox-sw.js"

### Предлагаемое изменение
[2] pry(main)> UrlHelper.local_cdn_url("/javascripts/workbox/workbox-sw.js")
=> "/javascripts/workbox/workbox-sw.js"

Мне кажется, эти функции не являются взаимозаменяемыми.

3 лайка

Вы правы, local_cdn_url заменяет локальный URL на CDN-URL. И это даже не локальный URL, а относительный.

Так что, думаю, этих вариантов будет достаточно вместо вызовов UrlHelper?

importScripts("<%= (Discourse.asset_host || '') + "/javascripts/workbox/workbox-sw.js" %>");

и

modulePathPrefix: (Discourse.asset_host || '') + "/javascripts/workbox",

1 лайк

При чтении текущей реализации UrlHelper.absolute:

Кажется, что URL формируется путём конкатенации Discourse.base_url_no_prefix и параметра, когда CDN равен nil, что соответствует вашему случаю.

Таким образом, проблема в том, что Discourse.base_url_no_prefix всегда возвращает первый хост в мульти-сайтовой среде?

Изучаю код :eyes:

Имя переменной здесь current_hostname на строке 288 сильно намекает на поддержку мульти-сайтовости :thinking:

А согласно

похоже, что это так. Пока что тупик…

Ищу дальше: этот маршрут получил специальную обработку, потому что браузеры активно его запрашивают, и мы не можем переложить эту проблему на CDN. При этом у нас была ошибка, связанная с утечкой в мульти-сайтовой среде, которую исправил @sam год назад:

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

2 лайка

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

1 лайк

@falco, ты видел моё предложенное решение двумя постами выше этого?

Да, но в моих тестах это не покрывает подпапки без CDN :sob:

Думаю, нам нужно будет использовать:

"#{Discourse.asset_host}#{Discourse.base_prefix}/javascripts/workworkbox"
1 лайк

Хм, хороший момент насчёт подпапки.

Но… Discourse.asset_host может быть nil, и я никогда не слышал о Discourse.base_prefix?

Как насчёт этого:

importScripts("<%= (Discourse.asset_host || GlobalSetting.relative_url_root) + "/javascripts/workbox/workbox-sw.js" %>");

modulePathPrefix: "<%= (Discourse.asset_host || GlobalSetting.relative_url_root) + "/javascripts/workbox" %>",

В данном случае это именно то, что нам нужно:

irb(main):001:0> puts "a#{nil}bc"
abc

О, я имел в виду Discourse.base_path.

Только что закоммитил исправление, пожалуйста, проверьте его.

3 лайка

Выглядит хорошо для нашего случая.. спасибо!

Но… просто чтобы убедиться.. я не уверен, как вы обрабатываете ресурсы на CDN в сочетании с подпапкой, но если вы используете Discourse.asset_host, префиксуете ли вы все пути на хосте ресурсов также с путем подпапки? Потому что именно это делает код сейчас.
Если вы действительно делаете это, то можете полностью игнорировать этот абзац :slight_smile:

3 лайка

Вся эта история с подпапками и CDN действительно вызвала у нас множество проблем. @featheredtoast провёл работу по оптимизации этого процесса, и мы потратили много времени на то, чтобы убедиться, что наш код обслуживания ресурсов корректно работает со всеми этими странными комбинациями бакетов, подпапок и т. д.

Я думаю, мы в безопасности :smile:, но при необходимости мы можем снова открыть эту тему.

Спасибо за сообщение об ошибке!

8 лайков

Эта тема была автоматически закрыта через 7 дней. Новые ответы больше не принимаются.