A client is experiencing issues with secure media uploads on a Docker-based Discourse with AWS S3. The problem occurs when sound files (mp3 and m4a) are embedded in a post, and the download is postponed until the play button is pressed. After a minute or so, the sound file may not play, resulting in an AWS 403 Expired error. This issue seems to be related to the delay between page load and file request.
Falco suggests that the problem might be due to how browsers work with audio and video tags and the default value of preload. Falco recommends adding a preload=auto attribute to the <audio> tag to hint the browser to download the file on page load.
However, RGJ points out that there is no explicit <audio> tag, as it is generated automatically by Discourse. Falco suggests that it makes sense to add the preload attribute when the secure media setting is enabled.
Martin explains that the problem was caused by browsers sending an initial request to audio and video files to get metadata, which started the 15-second expiry countdown. To fix this, preloading on video and audio has been disabled when secure media is enabled. Existing posts with audio and video will need to have their HTML rebuilt to see the change.
We have a client having issues with secure media uploads.
This client is running a docker based Discourse (official install) with AWS S3 and secure media enabled.
The forum has a number of mp3 and m4a sound files.
Discourse automatically embeds a nice player like this:
Problem: the sound files do not work reliably. Sometimes they do not play.
I cannot reproduce this 100% reliable, I think because of caching, but it seems that the download is postponed until the play button is pressed. That sounds logical and good.
But it doesn’t play nice with secure media uploads - if you leave a page open for a while and press the play button after a minute or so, the sound file does not (always) play. At that point, AWS returns a 403 Expired error. It looks like the request is not signed at the moment the file is requested, but earlier. The error message clearly states that the request expired in the past.
I suspect this has to do with the delay, but I am not 100% sure. Fact is that this is happening to sound files only (i.e. not to embedded images which are always downloaded immediately).
Yes, server time is correct.
I can repro on a fresh install running latest beta. Just put two sound files in a topic and mess around a bit.
That may be because of how browsers work with audio and video tags and the default value of preload. Are the files specially long? AFAIK browsers will download using byte ranges on demand.
If you have a <audio> or <video> tag, setting an attribute of preload=auto on it will hint the browser to download it all on page load, so you wouldn’t have this problem with the signed s3 url expiring.
As with those things always go, sites started to abuse this attribute and it isn’t always blindly followed anymore, but is a hint the browser will consider.
There is no explicit <audio> tag, it is generated automatically by Discourse when the audio file is being inserted. Without a preload attribute.
The part I don’t get: if the /secure-media-uploads route is generating the signed URL, why does it matter how much time there is between the page load and the route getting hit? After all, it is generating the signed route and then immediately redirecting to that. But somehow, it does seem to matter. It seems like something is being cached or something?
There is in the generated HTML from the post markdown, and that is what I’m talking about. I’d say it makes sense to add that attribute when the setting is enabled.
I believe the whole of point of the feature is exactly that. Have URLs that can’t be shared elsewhere for the uploads, and the only way to have that is using URLs that expire.
Yes, I understand that. And the expire timer starts counting at the moment the /secure-media-uploads route is called, and not when the page is being loaded.
Still, it seems to matter if the page was loaded long before the route is hit. And then it breaks, somehow. I just don’t get why this is happening.
This has now been fixed here FIX: Disable preloading audio + video when secure media enabled (#8922) · discourse/discourse@7ff58f1 · GitHub@RGJ. The problem was happening because browsers send an initial request to audio + video files to get metadata for the file e.g. duration. However because of the secure presigned URL, this initial request started the 15 second expiry countdown, so when users went to play audio + video after that time period we got the 403 error from AWS.
We now disable preloading on video + audio when secure media is enabled. Existing posts with audio + video will need to have their HTML rebuilt to see the change.