Add expires header conditionally based on mime type in nginx
Solution 1:
As of nginx 1.7.9:
map $sent_http_content_type $expires {
default off;
application/pdf 42d;
~image/ max;
}
expires $expires;
NOTE: $sent_http_content_type is valid, but it cannot be accessed until the server has processed the request...
The answer is pointed at the map entry for application/pdf
which allows a date value, or could even be application/pdf modified +42d
for example
Solution 2:
The if
directive in Nginx is processed early on at the rewrite stage, and hence the $sent_http_content_type
variable has not yet been initialised - see this nginx bug report for details.
EDIT: Comparing usernames, that bug report might well be you, actually! (^_^)
Similarly, the expires
directive doesn't seem to support variables in the same way that, for example, add_header
does. So, since you're not in a position to statically specify the location based on file extensions, I can only think of two basic approaches.
One would be to use the map
and add_header
approach suggested by Vadim above to manually set HTTP headers instead of allowing the expires
directive to do it. This is rather less flexible as it won't set the Expires
header, but I'd hope that any browser these days would do the right thing with just Cache-Control
being set. Here's an example that I've briefly tested:
map $sent_http_content_type $cacheable_types {
"text/css" "max-age=864000";
"image/jpeg" "max-age=864000";
default "";
}
# ...
server {
# ...
location / {
# ...
add_header "Cache-Control" $cacheable_types;
}
}
The value 864000 is 10 days in seconds - you'll have to change this to whatever you wish. The advantage of this approach is that you can specify different times for each file type, and even override other aspects of the Cache-Control
header - you discussion of this header here, and the official part from the HTTP RFC here if you prefer something more formal.
The second approach would be to just arrange that requests that will result in cacheable content all come under a specific path that you can use in a location
directive like this:
location / {
# ...
location /static {
expires 10d;
}
}
This makes the nginx configuration easier because you can use its builtin expires
directive, but whether it's an option very much depends whether you can enforce that pattern of URLs on your code.