Page Caching by Subdomain in Rails and Nginx
Posted By Ryan Stout on July 30, 2010
I'm internationalizing an app, and am splitting the locales by subdomain (es.bustaname.com, fr.bustaname.com, etc...) While other people have solved the page_caching issue with subdomains before, I couldn't find a clear explanation. All of the examples were missing one piece of information.
Controller
Add the following into your controller.
class ApplicationController < ActionController::Base # Cache pages with the subdomain def cache_page(content = nil, options = nil) path = "/#{request.host}/" path << case options when Hash url_for(options.merge(:only_path => true, :skip_relative_url_root => true, :format => params[:format])) when String options else if request.path.empty? || request.path == '/' '/index' else request.path end end super(content, path) end end
This will cache each subdomain in its own directory.
To keep things clean I also move my cache directory into public/cache Just add the following to your environment.rb inside of the run block.
Rails::Initializer.run do |config| config.action_controller.page_cache_directory = RAILS_ROOT + '/public/cache/' end
Then the part everyone else seemed to miss is that this will make something like caches_page :index (note the pluralization) work, even though we defined a cache_page method. ActionController::Base has both a class and an instance version of cache_page and a class method called cache_pages. You want to use the class method cache_pages.
Nginx
Next place the following in your nginx.conf file:
# If the file exists in the public folder, send it if (-f $request_filename) { break; } # Check / files with index.html if (-f $document_root/cache/$host/$uri/index.html) { rewrite (.*) /cache/$host/$1/index.html break; } # Check the path + .html if (-f $document_root/cache/$host/$uri.html) { rewrite (.*) /cache/$host/$1.html break; } # Check directly if (-f $document_root/cache/$host/$uri) { rewrite (.*) /cache/$host/$1 break; }
This will look up cached files in /cache/$host/ and should send the files correctly. Be sure to add the nginx config before you send it to mongrel/thin/etc..
Tags: rails, caching, subdomain, cache_page, nginx
Showing 4 comments
Jason Posted 5 months ago
Great post! Any thoughts on how this might work on heroku? http://stackoverflow.com/questions/8304166Darek Posted 6 months ago
Thanks for the post - great and condensed work!Richard Posted about 1 year ago
Hi Ryan, I'm on my latest project to build at about 10 of subdomain for any topic's. Each of them need cache directory's. I created a custom rss for each of them too. My question is, "How to make them all only using 1 cache directory? Is that possibly? How to make it possibly with PHP?" Could you please advice me to my email. I really appreciated for that. I'm looking forward to hearing from you. regards, Richard Daris http://www.uni.street.co.idSaravana Posted over 1 year ago
Thanks for the post Ryan. I had disabled sub-domain support in my website (www.kettik.com) till i had figured out how to handle page caching for the subdomains. Your post has given me a good starting point. Btw, 1 question... how do you handle the case when 'www' is given in the hostname.