S3 CDN URL не используется при загрузке файлов, отличных от изображений

Возможно, это связано с игнорированием S3 CDN URL при загрузке в посты.

Сначала я подумал, что упустил какую-то настройку, но это воспроизводится здесь, на meta:
https://meta.discourse.org/uploads/short-url/dw1U4hctATusBlHsUmWQXeme66j.csv (загружено здесь) — это перенаправление 302 на
//assets-meta-cdck-prod-meta.s3.dualstack.us-west-1.amazonaws.com/original/3X/5/e/5ebb2cfb8cc907e8e8f7c6559a72d2f4a8ba2f8f.csv

Разве оно не должно перенаправлять на https://d11a6trkgmumsb.cloudfront.net/original/3X/5/e/5ebb2cfb8cc907e8e8f7c6559a72d2f4a8ba2f8f.csv?

5 лайков

Хм, возможно, здесь есть проблема. @martin, сможешь разобраться? Если возможно, нам стоит перенаправлять на CDN.

5 лайков

Это немного непросто, я только что посмотрел на это. По сути, при «принудительной загрузке» мы всегда скачиваем файлы из S3 по подписанному URL-адресу. Именно так происходит при нажатии на ссылку вложения или на кнопку «Скачать» на изображении. Это необходимо для добавления соответствующих заголовков content-disposition:

attachment; filename="#{upload.original_filename}"; filename*=UTF-8''#{upload.original_filename}

Не думаю, что можно заставить CDN-URL вести себя подобным образом? CDN-URL для изображений используется только при их отображении внутри страницы, а не при загрузке. Кроме того, в случае защищённых изображений и вложений с приватным ACL всегда должен использоваться подписанный URL-адрес.

2 лайка

@martin, насчёт ссылок на вложения: я не вижу, как их можно настроить на принудительную загрузку («force download»). В данный момент при загрузке файла, отличного от изображения, сгенерированный URL является короткой ссылкой без параметра ?dl=1. Эта ссылка разрешается в значение атрибута url соответствующего вложения (которое не является подписанным URL). В нашем случае это приводит к ошибке, так как указанный URL — не ссылка на CDN S3, а сконструированный адрес, который может работать только с определёнными провайдерами S3.

Существует ли способ всегда принудительно загружать вложения, или текущее поведение на самом деле является ошибкой?

1 лайк

Можете уточнить? Вы используете Amazon S3 или другого провайдера? Если да, то какого именно?

1 лайк

Да, похоже, я использую неподдерживаемого провайдера S3 (OVH Object Storage)

С конечной точкой https://s3.de.ovh.cloud.net и настроенным s3 cdn_url как https://storage.de.ovh.cloud.net/v1/<уникальный-идентификатор-пользователя>/<имя-бакета>

При разрешении коротких ссылок Discourse использует конечную точку для построения результирующего URL (что не работает, так как он не включает правильный идентификатор пользователя OVH — часть, указанную в s3 cdn_url).

Однако принудительное добавление dl=1 к коротким ссылкам позволило бы сформировать работающую предподписанную ссылку, что меня устроило бы.

Я установил следующие (специфичные для S3) переменные окружения в файле конфигурации контейнера:

DISCOURSE_USE_S3: true
DISCOURSE_S3_REGION: DE
DISCOURSE_S3_ENDPOINT: https://s3.de.cloud.ovh.net
DISCOURSE_S3_ACCESS_KEY_ID: ...
DISCOURSE_S3_SECRET_ACCESS_KEY: ...
DISCOURSE_S3_CDN_URL: https://storage.de.ovh.cloud.net/v1/<уникальный-идентификатор-пользователя>/<имя-бакета>
DISCOURSE_S3_UPLOAD_BUCKET: <имя-бакета>
DISCOURSE_S3_INSTALL_CORS_RULE: false
1 лайк

Возможно, это выходит за рамки данной темы, но если текущее поведение намеренное, то как или где можно переопределить рендеринг коротких ссылок во фронтенде? Я думаю о том, чтобы просто подключиться к процессу обработки постов и затем добавлять параметр запроса к коротким ссылкам вложений. Я знаю, как писать JS-плагины для Discourse, но чаще всего мне трудно найти нужный виджет для «переоткрытия» или функцию для переопределения.

Хорошо, я нашел место, где генерируется Markdown для вложений, и насколько я понимаю API плагинов, его нельзя (легко) переопределить (я даже думаю, что так делать не стоит).

Поэтому моя первоначальная идея добавить параметр ?dl=1 к этим URL-адресам кажется неверным подходом.

Что касается отсутствия принудительной загрузки для разрешенных коротких URL-адресов: если я правильно понимаю аргумент против публичных ACL для ведер S3, то следует либо:

  1. предоставлять файлы из S3 через CDN (что невозможно для вложений, как указал @martin, поскольку в этом случае мы можем не иметь возможности корректно установить имя файла для загрузки)
  2. создавать подписанный URL для объекта S3

Но текущее поведение не делает ни того, ни другого и предполагает, что ведро S3 имеет публичный ACL. Это также, похоже, относится к поддерживаемым провайдерам S3 (включая Amazon), поэтому я бы спросил, почему бы не сделать опцию force_download в Discourse.store.url_for по умолчанию равной true при разрешении коротких URL-адресов для хранилищ S3?

1 лайк

У меня та же проблема. Я ожидаю, что файл, находящийся по адресу uploads/short-url, будет загружен или перенаправлен на URL S3 CDN.

2 лайка

Мы сталкиваемся с той же проблемой с Cloudflare R2, так как, похоже, он не позволяет использовать прямую S3-ссылку без подписанного URL. Кроме того, R2 не поддерживает ACL для бакетов.

Похоже, что недавно в Discourse добавили опцию «Использовать CDN-URL S3 для всех загрузок», которая решает эту проблему.