URL CDN S3 non utilisée sur les téléchargements non image

Maybe related to S3 CDN URL ignored when uploading into posts.

At first I thought I had missed some configuration, but it’s reproducible here on meta:
https://meta.discourse.org/uploads/short-url/dw1U4hctATusBlHsUmWQXeme66j.csv (uploaded here) is a 302 redirect to
//assets-meta-cdck-prod-meta.s3.dualstack.us-west-1.amazonaws.com/original/3X/5/e/5ebb2cfb8cc907e8e8f7c6559a72d2f4a8ba2f8f.csv

Shouldn’t it redirect to https://d11a6trkgmumsb.cloudfront.net/original/3X/5/e/5ebb2cfb8cc907e8e8f7c6559a72d2f4a8ba2f8f.csv instead?

5 « J'aime »

Hmmm there may possibly be an issue here @martin can you investigate? We should probably redirect to the CDN if possible.

5 « J'aime »

This is a little bit tricky, I had a look at this just now. Basically we are always downloading from S3 with a presigned URL if we are doing a “force download”, which is what happens when we are clicking on the attachment link or clicking on the Download button on an image. This is so the appropriate content-disposition headers can be added:

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

I do not think it is possible to make the CDN URL behave in this way? The CDN URL for images is only used when displaying them inline, not when downloading them. Also in the case of secure images and attachments which have a private ACL the presigned URL must always be used.

2 « J'aime »

@martin concernant les liens de pièces jointes, je ne vois pas comment ils peuvent être configurés pour toujours « forcer le téléchargement ». Actuellement, lors du téléchargement d’un fichier non image, l’URL rendue résultante est une URL courte sans le paramètre ?dl=1 qui est résolu à la valeur de l’attribut url de l’upload correspondant (qui n’est pas une URL pré-signée et échoue également dans notre cas car l’URL n’est pas la cdn_url s3 mais une URL construite qui pourrait ne fonctionner que pour certains fournisseurs s3).

Existe-t-il un moyen de forcer systématiquement le téléchargement des pièces jointes, ou le comportement actuel est-il en fait un bug ?

1 « J'aime »

Pouvez-vous développer ici, utilisez-vous Amazon S3 ou un autre fournisseur ? Si oui, lequel ?

1 « J'aime »

Oui, il semble que j’utilise un fournisseur S3 non pris en charge (OVH Object Storage)

Avec une URL de point de terminaison de https://s3.de.ovh.cloud.net et une s3 cdn_url configurée sur https://storage.de.ovh.cloud.net/v1/<some-unique-user-id>/<the-bucket-name>

Lorsque les URL courtes sont résolues, Discourse utilise l’URL du point de terminaison pour construire l’URL résultante (ce qui échoue car elle n’inclut pas le bon ID utilisateur OVH - la partie de la s3 cdn_url).

Forcer les URL courtes à avoir dl=1 construirait cependant une presigned_url fonctionnelle, ce qui me conviendrait.

J’ai défini ces variables d’environnement (spécifiques à S3) dans le YAML du conteneur :

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/<some-unique-user-id>/<the-bucket-name>
DISCOURSE_S3_UPLOAD_BUCKET: <the-bucket-name>
DISCOURSE_S3_INSTALL_CORS_RULE: false
1 « J'aime »

Peut-être que cela sort du cadre de ce sujet, mais si le comportement actuel est intentionnel, comment ou où pourrait-on remplacer le rendu des URL courtes dans le frontend ? Je pense simplement à intercepter le processus de cuisson des articles, puis à ajouter le paramètre de requête aux URL courtes des pièces jointes. Je sais comment écrire des plugins JS pour Discourse, mais la plupart du temps, j’ai du mal à trouver le bon Widget pour « rouvrir » ou la fonction à remplacer.

Ok, j’ai trouvé l’endroit où la génération des pièces jointes Markdown est générée et, d’après ce que je comprends de l’API des plugins, on ne peut pas (facilement) la remplacer (je pense même qu’on ne devrait pas le faire).

Donc, mon idée initiale d’ajouter un paramètre ?dl=1 à ces URL semble être la mauvaise approche.

Concernant le fait de ne pas forcer le téléchargement pour les URL courtes résolues : si je comprends bien l’argument contre les ACL publiques sur les buckets S3, il faudrait soit :

  1. servir les fichiers de S3 via un CDN (irréalisable pour les pièces jointes, comme l’a souligné @martin, car nous pourrions ne pas être en mesure de définir correctement le nom de fichier pour le téléchargement dans ce cas)
  2. créer une URL pré-signée pour l’objet S3

Mais le comportement actuel ne fait ni l’un ni l’autre et s’attend à ce que le bucket S3 ait une ACL publique. C’est également le cas pour les fournisseurs S3 pris en charge (y compris Amazon), alors je me demandais pourquoi ne pas faire en sorte que l’option force_download dans Discourse.store.url_for soit définie par défaut sur true (https://github.com/discourse/discourse/blob/v2.8.0.beta11/app/controllers/uploads_controller.rb#L121) lors de la résolution des URL courtes pour les stockages S3 ?

1 « J'aime »

J’ai le même problème ici, ce que j’attends, c’est que le fichier derrière uploads/short-url soit téléchargé ou redirigé vers l’URL du CDN S3.

2 « J'aime »

Nous rencontrons le même problème avec Cloudflare R2, car il ne semble pas autoriser l’utilisation de l’URL S3 directe sans une URL pré-signée.
Et R2 ne prend pas en charge les ACL pour les buckets.

Il semble que Discourse ait récemment ajouté une option « Utiliser l’URL CDN pour tous les téléchargements » qui résout ce problème.