Не удалось загрузить вложение js

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

Окружение:
Discourse в Docker, работающий за Nginx (Nginx использует SSL).

Логи контейнера Discourse:

    Started GET "p5ePkm5OoKveknnMjyArlS4PPwS.js" for 192.168.32.1 at 2021-02-22 05:48:52 +0000
    Processing by UploadsController#show_short as JS
      Parameters: {"base62"=>"p5ePkm5OoKveknnMjyArlS4PPwS", "extension"=>"js"}
    Sent file afcdf626f9db8d54a1fb5e8ebcab0ea214d9226a.js (2.2ms)
    Security warning: an embedded <script> tag on another site requested protected JavaScript. If you know what you're doing, go ahead and disable forgery protection on this action to permit cross-origin JavaScript embedding.
    Completed 422 Unprocessable Entity in 59ms (ActiveRecord: 0.0ms | Allocations: 17414)
    ActionController::InvalidCrossOriginRequest (Security warning: an embedded <script> tag on another site requested protected JavaScript. If you know what you're doing, go ahead and disable forgery protection on this action to permit cross-origin JavaScript embedding.)
    /opt/bitnami/discourse/vendor/bundle/ruby/2.6.0/gems/actionpack-6.0.3.1/lib/action_controller/metal/request_forgery_protection.rb:266:in `verify_same_origin_request'

Логи Nginx:

    10.164.0.103 - - [22/Feb/2021:05:51:11 +0000] "GET /uploads/short-url/p5ePkm5OoKveknnMjyArlS4PPwS.js HTTP/2.0" 422 781 "getting-started-with-sftp-module/292" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.150 Safari/537.36"

Любая помощь или подсказки будут очень кстати!

2 лайка

Разрешаете ли вы прикреплять файлы *.js к сообщениям пользователей? Есть ли у вас законная необходимость в прикреплении JavaScript-файлов пользователями? Хотим окончательно убедиться в этом, прежде чем двигаться дальше.

1 лайк

Спасибо за быстрый ответ!
Да, это обсуждение вопросов и ответов по программированию, поэтому прикрепление файлов кода с расширением *.js — это законный случай использования.

2 лайка

Всем привет! У меня та же проблема. Мы разрешили загрузку файлов с расширением .js, но никто не может их скачать. Пока не нашли ни одной настройки для исправления этого. Кто-нибудь может помочь?

1 лайк

Можете описать случай использования? Почему это необходимо?

Привет, Джефф

Хотя сейчас мы копируем и вставляем код в текстовую часть поста.
Пример использования: у нас есть файл .js с кодом для Kickstarter или решением повторяющейся проблемы, и мы хотим поделиться им как вложением, чтобы пользователи могли скачать его и сразу использовать в своих проектах.

Однако, если мы изменим расширение файла с .js на .txt, снова появляется сообщение «Запрашиваемое изменение было отклонено». (Это может быть связано с какой-то оптимизацией хранения на стороне сервера: если содержимое файла совпадает с ранее загруженным файлом, то новое вложение ссылается на уже загруженный файл.)
Поэтому я немного изменил содержимое файла с расширением .txt (который на самом деле был .js) и загрузил его снова — теперь я смог скачать файл как вложение.

@codinghorror Существует ли риск безопасности при разрешении загрузки файлов .js?

1 лайк

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

1 лайк

У нас есть форум для разработчиков на fluiggers.com.br, загляните… и мы часто делимся файлами .js.

1 лайк

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

Заголовок Content-Disposition предотвратит выполнение загруженных JS-файлов, и мы устанавливаем его корректно:

attachment; filename="test.js"; filename*=UTF-8''test.js

Это работает для загрузок на S3 и должно работать также для локальных загрузок, но, похоже, в Rails появилось новое (или относительно новое) средство безопасности:

ActionController::InvalidCrossOriginRequest (Предупреждение о безопасности: встроенный тег на другом сайте запросил защищенный JavaScript. Если вы знаете, что делаете, отключите защиту от подделки запросов для этого действия, чтобы разрешить встраивание JavaScript из других источников.)

Должно быть исправимо…

3 лайка

Я столкнулся с той же проблемой: у нас есть форум вопросов и ответов по программированию, и нам нужно иметь возможность предоставлять большие JS-файлы для скачивания.

У меня в сообществе возникла та же проблема. Пользователи хотят делиться JS-файлами, но при попытке их скачать появляется эта ошибка:

Выдержка из лога production-окружения Rails:

Started GET "/uploads/short-url/qDlrltMxEIJ2aYYdt8lZ200E3wA.js" for 94.31.111.247 at 2025-07-09 05:53:30 +0000
Processing by UploadsController#show_short as JS
  Parameters: {"base62"=>"qDlrltMxEIJ2aYYdt8lZ200E3wA", "extension"=>"js"}
Sent file /var/www/discourse/public/uploads/default/original/1X/baab1fc131be960b601467333f5a690b257daeb0.js (0.3ms)
Security warning: an embedded <script> tag on another site requested protected JavaScript. If you know what you're doing, go ahead and disable forgery protection on this action to permit cross-origin JavaScript embedding.
Completed 422 Unprocessable Entity in 17ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)

JS-файлы входят в список разрешённых расширений для загрузки:

Та же проблема у нас. У нас есть JS-файлы, которые работают в нашем собственном программном обеспечении, и ничего, что могло бы когда-либо выполняться в браузере.

Нам удалось исправить проблему с загрузкой в Discourse, перенеся все загрузки в бакет S3 и установив параметр s3_use_cdn_url_for_all_uploads в значение true. Это фактически обходит контроллер коротких ссылок, который, похоже, является главным препятствием для JS-файлов.

Подробности (от моего ИИ, который провёл меня через этот процесс):

  1. Настройка совместимого с S3 хранилища (например, Cloudflare R2)

Discourse не может безопасно отдавать файлы .js с локального диска. Переместите их в бакет.

  • Бакет: Создайте приватный бакет (например, my-discourse-bucket).

  • Ключи API: Сгенерируйте ключ доступа и секретный ключ.

2. Настройка пользовательского домена CDN

В Cloudflare (или у вашего провайдера) подключите пользовательский домен к вашему бакету (например, cdn.example.com). Это гарантирует, что файлы будут отдаваться как статические ресурсы по прямым ссылкам, обходя «страж безопасности» Discourse.

3. Обновление настроек Discourse

В Администрирование → Настройки настройте детали вашего S3. Крайне важно включить следующие параметры, чтобы Discourse не пытался «подписывать» URL временными заголовками, которые могут нарушить работу:

  • s3_use_cdn_url_for_all_uploads: Отметьте этот флажок (это самый важный шаг).

  • s3_cdn_url: Установите значение https://cdn.example.com.

  • s3_region: Используйте us-east-1 (для совместимости с R2).

4. Миграция существующих загрузок (опционально)

Примечание: Это НЕ сработало у нас по неизвестным причинам.

Чтобы исправить старые ссылки в существующих сообщениях, войдите в контейнер и выполните:

Bash

# Внутри /var/discourse
./launcher enter app
rake uploads:migrate_to_s3
rake posts:rebake

Надеюсь, это кому-то поможет.