Restrict Download by MIME Type in Nginx

linuxnginxunix

I have the following stanza in my nginx virtual host config. The goal is to only allow direct (deep link) downloads of only video content types, and return a 404 or some other error for anything else:

location ~* ^/webdata/.+(\.mp4|\.m4v|\.mpg|\.mpeg|\.mpg|\.mts|\.avi)$ {
root /srv/data;
}

As you can see the above achieves this rather crudely by matching the end of the requested URL. If it doesn't end in .mp4, .m4v, .mpg, etc. the stanza isn't triggered and the client doesn't get the file.

Ideally I'd like to be able to be able to do something like this (this obviously doesn't work, since $content_type refers to the content-type HTTP reqest header from the client, and not the content-type of the requested resource, if I am not mistaken):

location /webdata {
if ($content_type =~ 'video/.*')
{
root /srv/data/;
}
}

Is there a way to do this?

Comment: Based on question 577471, it seems like nginx relies purely on filenames/URI, rather than using something like MIME magic to figure out the content type based on actual file content headers, like most modern Linux desktop environments do. If this is true, then this may not be possible.

Best Answer

In standard nginx installations, there is a file called mime.types, which maps file extensions to MIME types.

So, for requests to static files, nginx checks the extension of the file to be sent to the client and then looks up from mime.types what Content-Type header to send to the client.

So, there cannot be any MIME magic in location blocks.

If you meant that nginx would pick up the MIME type based on the file content, that would be very inefficient.

Currently, when nginx is serving the request, it will look up the MIME type from the table and add the MIME type header. Then it will open the file and basically it simply copies it to the client socket.

However, if one wants nginx to select the MIME type based on the file content, in the worst case it has to read and interpret through the whole file in order to find out the correct file type. This would require much more CPU, and would make the performance much worse. That is the reason there is no such feature in nginx.

The best approach is to have proper extensions for the files you are sending to the clients.

If that is not possible, then you have to implement this file content inspection yourself in your preferred language.

Related Topic