Bon, il semble que je sois en plein dans une chasse aux bugs cette semaine.
Nous avons un forum avec l’option secure_uploads activée ; tous les fichiers sont hébergés sur AWS S3 (officiel).
Problème : les liens courts ne semblent pas fonctionner correctement ; la partie uploads/{database_id} manque dans l’URL.
Il semble que le code fautif se trouve dans 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
Ainsi, si upload.secure? && SiteSetting.secure_media? est vrai, la requête est traitée par
handle_secure_upload_request(upload, Discourse.store.get_path_for_upload(upload)).
Or, Discourse.store.get_path_for_upload(upload) renvoie une URL sans la partie uploads/{database_id} :
original/3X/f/d/fd0b5775899541b9d42e67f8e0dd6bf587a179d3.png
Par conséquent, handle_secure_upload_request renvoie une URL signée, mais avec une partie manquante dans l’URL puisqu’elle commence par /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....
Si upload.secure? && SiteSetting.secure_media? était faux (ce qui n’est pas le cas), la requête serait traitée par Discourse.store.url_for(upload, force_download: params[:dl] == "1").
Et cela renvoie effectivement une URL correcte :
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...
Il semble donc qu’il existe une méthode url_for et une méthode get_path_for_upload qui se comportent différemment, et celle qui est utilisée semble être la mauvaise ?