How to set expiration headers for a Rails app?

Hi,

Currently I’m putting final touches on my latest Rails app:

http://188.226.157.101/

When I run a page loading test with Firefox’ YSlow, I get an F-rating for adding expiration headers:

For instance expiration headers for my webfonts referenced from Google Webfonts CDN and images stored on Amazon S3 and resources coming from my /assets folder

Is there a way to add expiration headers to assets coming from Google Web Fonts and Amazon S3 ?

thanks for your advice,

Anthony

It looks like the only assets it has an issue with are the ones coming from your asset pipeline. You can set those header in apache of nginx like so.

# The Expires* directives requires the Apache module
# `mod_expires` to be enabled.

    <Location /assets/>
      # Use of ETag is discouraged when Last-Modified is present
      Header unset ETag
      FileETag None
      # RFC says only cache for 1 year
      ExpiresActive On
      ExpiresDefault "access plus 1 year"
    </Location>

For nginx:

location ~ ^/assets/ {
  expires 1y;
  add_header Cache-Control public;
 
  add_header ETag "";
  break;
}

That info came directly from the rails docs.

1 Like

Thanks a lot Jared,

Where do I put those settings for Nginx?

I tried to add these to the /etc/nginx/nginx.conf file, but then the Nginx webserver fails to restart.

greetings,

Anthony

the location needs to do inside the server block

    server {
            listen   80;
            root /home/rails/public;
            server_name _;
            index index.htm index.html;
    
            location / {
                    try_files $uri/index.html $uri.html $uri @app;
            }
    
    	location ~* ^.+\.(jpg|jpeg|gif|png|ico|zip|tgz|gz|rar|bz2|doc|xls|exe|pdf|ppt|txt|tar|mid|midi|wav|bmp|rtf|mp3|flv|mpeg|avi)$ {
                            try_files $uri @app;
             }

            location ~ ^/assets/ {
               expires 1y;
               add_header Cache-Control public;

               add_header ETag "";
               break;
              }
    
             location @app {
                    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                    proxy_set_header Host $http_host;
                    proxy_redirect off;
                    proxy_pass http://app_server;
        }
    
    }

If you are running ubuntu this would be in the sites enabled directory. It may be different depending on your OS.

Oh I see, it’s working now : )

Thanks a lot!!

greetings,

Anthony

No problem. Glad it solved your issue. :smile:

Hi Jared,

Is there also a way to set expiration headers for assets coming from Amazon S3 ?

I still getting complaints by Firefox YSlow for assets coming from Amazon S3:

greetings,

Anthony

You’ll need to do it on upload.

http://www.bucketexplorer.com/documentation/amazon-s3--how-to-set-cache-control-header-for-s3-object.html

Here is a stack-overflow with the information you’re wanting.

thanks Jared!

I added this line to my carrierwave.rb initializer:

config.fog_attributes = {'Cache-Control'=>"max-age=#{365.day.to_i}"}

Then I deleted some images and uploaded them again. But this doesn’t seem to have any effect. Firefox Yslow is still complaining about the expiration headers for my assets coming from Amazon S3

greetings,

Anthony

That looks correct. I’m not sure why it’s not adding the headers. Have you tried checking to see if the cache headers do get set on the new images? Also it looks like its complaining about the Expires header. Which is an old header type that used to signify the caching age. Some older browsers and older bots still use this. You can read more about it here. You should be setting both on the images, for backward compatibility.

You can see it above in the nginx config. Also the Etag should be set too.

           expires 1y;
           add_header Cache-Control public;
           add_header ETag "";

my nginx settings look like this:

location ~ ^/assets/ {
gzip_static on;
expires 1y;
add_header Cache-Control public;

add_header ETag "";
break;
}

I also changed the carrierwave.rb initalizer file and added this setting:

config.aws_attributes = { :cache_control => 'max-age=315576000', :expires => 1.year.from_now.httpdate }

then I deleted a couple of images and uploaded new ones on the homepage: ‘environ-peeling-kuur.jpg’ and ‘gelaatsverzorging.jpg’

But it doesn’t seem to have any effect, Firefox YSlow keeps telling me that the experiation headers for 8 amazon aws assets are not set (while I expect that would have decreased by 2).