Wednesday, May 20th, 2009...2:01 pm
Setting Static Asset Expires Headers with nginx and Passenger
On a recent project I launched, I’m using the combination nginx+passenger for my front end my my Ruby on Rails application.
While trying to boost my YSlow score, I was having a bit of difficulty trying to figure out how to set HTTP expires headers on all the static assets served by my app.
Rails will set an internal time stamp on static assets (images, css files, javascript files, etc…) by appending a integer value onto the end of the asset filename
http://mydomain.com/images/asset.png?12345678
My original attempt at getting nginx to set an expires header for these assets had me adding the following location block to my nginx config file:
location ~* \.(ico|css|js|gif|jpe?g|png)\?[0-9]+$ {
expires max;
break;
}
The regexp I was using was incorrect however as it didn’t take into account that the ?timestamp might not exist in the URI.
Hongli Lai kindly pointed me in the right direction and showed me the proper regexp that he is using.
location ~* \.(ico|css|js|gif|jpe?g|png)(\?[0-9]+)?$ {
expires max;
break;
}

9 Comments
May 21st, 2009 at 3:01 pm
Thanks for this! After hours of trying to figure this out this finally helped me!
May 21st, 2009 at 3:06 pm
awesome. glad to help
June 14th, 2009 at 1:29 am
Another big thank you!! This just helped me finally get expire headers working right on UniversityTutor.com
It’s loading way faster now. Thanks a ton!
June 25th, 2009 at 10:39 am
Your first regular expression doesn’t match anything, as nginx doesn’t include query string (part after the question mark) when matching location.
I prefer to set Expires *only* for assets with timestamp included, otherwise your users will have problems when you change the contents of a file without changing the name.
The following directive will cover this case:
location ~* \.(ico|css|js|gif|jp?g|png) {
if ($args ~* [0-9]+$) {
expires max;
break;
}
}
June 25th, 2009 at 10:41 am
Adam, my second regexp (the one I am actually using) does the same thing as your example.
November 5th, 2009 at 4:15 pm
Hey craig, I think that your regexp doesn’t match “jpeg” file extensions, but (wrongly) “jg”.
November 5th, 2009 at 4:19 pm
@eno,
You are correct. Good eye.
I’ve gone ahead and updated the regexp in my example.
November 12th, 2009 at 7:11 pm
Hey craig, me again
Hongli Lai’s example does not work (as Adam already pointed out, because the location test does not include the URL arguments in the test against the regex. Adam’s solution seems ok to me. My own setup is a bit different; if interested check it out here http://radiospiel.org/0×29-my-nginx-config.
November 12th, 2009 at 7:33 pm
@eno,
Interesting. I’m wondering if this isn’t an nginx version issue, because the regexp I use in the example works fine for me on my website.
But both you and Adam are saying the check against $location doesn’t work, I’m wondering if its because the $location variable changed in nginx.
what version are you running? I’m running version 0.6.36 on the server in question.
Leave a Reply