Incorrect mime-types (content-type header) for mp4 and js

Hello!

I’ve just noticed that discourse is putting incorrect Content-type) headers to several file types:
mp4 files from /uploads/ goes with content-type: application/mp4 instead of video/mp4
my uploads went from S3 so it is up to the S3 hosting provider.

Some javascript (.js) e.g. from /brotli_asset/ goes with application/javascript instead of text/javascript .

I use discourse_docker without any modifications, I’ve checked included nginx, it contains correct mime-types configuration file. Seems that it’s discourse backend guilty of sending this incorrect mime-types.

Hello! As far as I have got the problem with uploads was on my side and caused by S3-provider (I have successfully resolved it by overriding the setting in my nginx). And the problem with JS from /brotli_asset/ is somewhere in “internal” nginx of the discourse, so seems to be bug in discourse_docker.
Shame on me, but I failed to find any place to report bug better than this part of the forum. Can you point me please?

This is the correct place, you found it alright.

Can you explain why is this a problem that we should care about? Does it breaks anything?

In short words discourse sends javascript from different location with different mime-types. E.g. /theme-javascripts/ff3c633d0d4192c83a194066eaa9d823b5c2d8f6.js goes with text/javascript (correct) and previously mentioned /brotli_asset/… with application/javascript. It can confuse proxy servers between discourse and client so as analytic systems, where I have noticed the issue.

Seems you just need to correctly setup internal nginx in discourse docker image for brotli assets.

Can you name the proxy / analytic system that broken because of this? Share an example of the issue happening in the wild?

In my goaccess reports mime-types dashboard of discourse is splitted values for js: one for text/javascript and another for application/javascript.

The second one: both gzip_types and brotli_types directives in nginx are operated by mime-types. So for discourse people have to setup both correct text/javascript and incorrect application/javascript.
The same for any proxy recompressing content that bases on mime-type.

Bumping this topic because I believe it creates a small issue, or at least an unwanted behavior.

Opening a video file hosted on Discourse forces the download of the video instead of playing it in the browser.

Right-click, copy video address, paste the link in the browser’s address bar.

Weird thing is that on a local dev installation, it properly plays the video in the browser:

When loading the video URL, headers are different between a regular install and a dev install.

On the regular production install, the video content type is set to application/mp4, whereas it’s set to video/mp4 on a dev install.

Crossposting Discourse send PDF inline because the author fixed a similar unwanted behavior with PDFs.

I’m all ears if someone has a solution to prevent mp4s from being forcibly downloaded.

4 Likes

Oh good find - this is weird.

It looks like MiniMime (a library we use and own) might be returning these values

pry(main)> MiniMime.lookup_by_filename("a.mp4").content_type
=> "application/mp4"

I’ll create a PR and we’ll discuss if it’s an issue changing these.

4 Likes

Just a quick update -

The ext_mime_db above that we use follows IANA Media Types defined here - https://www.iana.org/assignments/media-types/media-types.xhtml. Unfortunately, this means that mp4 is correctly application/mp4 :sweat_smile:


Though, looking into our S3 uploader implementation further, I do see that we are adding Content-Disposition header "attachment" for pretty much every upload that is not an image, but it feels like it was only intended to be added for svgs. Using "attachment" would result in the content to get downloaded rather than open in a new tab. For videos, it is a mixture of application/video and attachment that is causing this.

We can at least remove this header, I think.

2 Likes

Not sure I fully understand, so quick question about this PR :person_raising_hand:

Why do the modifications specifically target s3-related files, when the forced download occurs even when not using s3? :thinking:

Will it fix the issue in general anyway?
Will it also fix forced download for other files that could be opened in the browser such as PDFs?

When uploading to S3, we have to specify headers like the Content-Disposition and Content-Type of the file. These are the values that will be returned when loading the file - PutObject - Amazon Simple Storage Service

Can you explain when this is happening?

The PR will remove the Content-Disposition: attachment header which forces the download regardless of any browser you use.

Once you’ve upgraded your site, the Content-Type is used instead, and the browser will decide what to do with it. One thing to note, there is no problem with Content-Type: application/mp4 on Safari and Firefox, but on Chrome, it still forces a download (probably due to some bad history Chrome has with the mp4 file type).

2 Likes