Хм, похоже, на этой неделе я увлёкся охотой за ошибками.
У нас есть форум с включённой функцией secure_uploads; все загрузки хранятся на (официальном) AWS S3.
Проблема: ссылки с короткими URL работают некорректно — в адресе отсутствует часть uploads/{database_id}.
Похоже, проблема в коде внутри UploadsController::show_short:
if upload = Upload.find_by(sha1: sha1)
return handle_secure_upload_request(upload, Discourse.store.get_path_for_upload(upload))
if upload.secure? && SiteSetting.secure_media?
if Discourse.store.internal?
send_file_local_upload(upload)
else
redirect_to Discourse.store.url_for(upload, force_download: params[:dl] == "1")
end
else
render_404
end
Таким образом, если условие upload.secure? && SiteSetting.secure_media? истинно, запрос обрабатывается методом
handle_secure_upload_request(upload, Discourse.store.get_path_for_upload(upload)).
При этом Discourse.store.get_path_for_upload(upload) возвращает URL без части uploads/{database_id}:
original/3X/f/d/fd0b5775899541b9d42e67f8e0dd6bf587a179d3.png
Следовательно, handle_secure_upload_request возвращает подписанный URL, но в нём отсутствует часть пути, поскольку он начинается с /original:
https://redacted.s3.us-east-2.amazonaws.com/original/3X/f/d/fd0b5775899541b9d42e67f8e0dd6bf587a179d3.png?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKI....
Если бы условие upload.secure? && SiteSetting.secure_media? было ложным (а оно не ложное), запрос обрабатывался бы методом Discourse.store.url_for(upload, force_download: params[:dl] == "1").
А этот метод как раз возвращает корректный URL:
https://redacted.s3.us-east-2.amazonaws.com/uploads/db3999/original/3X/f/d/fd0b5775899541b9d42e67f8e0dd6bf587a179d3.png?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKI...
Получается, что существуют методы url_for и get_path_for_upload, которые работают по-разному, и, похоже, используется неправильный?