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?
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:
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.
@martin regarding Attachment links, I cannot see how they can be set to always “force download”. Right now when uploading a non-image file, the resulting rendered url is a short-url without the ?dl=1 param which is resolved to the value of the url attribute of the corresponding upload (which is not a presigned_url and also fails in our case as the url is not the s3 cdn_url but a constructed one that might only work for certain s3 providers).
Is there a way to always force download attachments, or is the current behavior actually a bug?
With an endpoint url of https://s3.de.ovh.cloud.net and a configured s3 cdn_url to https://storage.de.ovh.cloud.net/v1/<some-unique-user-id>/<the-bucket-name>
When short urls are resolved, discourse uses the endpoint url to construct the resulting url (which fails since it does not include the correct ovh user-id - the part in the s3 cdn_url).
Forcing short urls to have dl=1 would however construct a working presigned_url which would be fine for me.
I set these (s3 specific) environment variables within the container yaml:
Maybe this would be out-of-scope for this topic, but if the current behavior is intended, how or where would one override short-url-rendering in frontend? I am thinking of simply hooking into the cooking-process of posts and then appending the query param to attachment short-urls. I am aware of how to write js-plugins for discourse, but most of the time I am just having a hard time finding the right Widget to “reopen” or function to override.
Ok so I found the place where Markdown for attachments is generated and as far as I understand the plugin API one cannot (easily) override it (I even think one should not do it).
So my initial thought of adding a ?dl=1 param to those urls seems like the wrong way to do it.
serve files from S3 via a CDN (unfeasible for attachments as @martin pointed, as we may not be able to correctly set the filename for download in this case)
create a presigned url for the S3 object
But the current behavior does neither and expects the S3 bucket to have a public ACL. This also seems to be the case for supported S3 providers (including amazon), so I’d ask why not make the force_download option in Discourse.store.url_for default to true when resolving short-urls for S3 stores?
We are facing the same issue with Cloudflare R2, as it doesn’t seem to allow using the direct S3 url without a presigned URL.
And R2 doesn’t support ACL for buckets.