Caching, Resources and Fast-CGI in Ruby on Rails
by Jarrett Colby
Broken Resources with Caching
map.resources connects multiple actions to the same URL; the only differentation is the HTTP method. For example, consider the following requests:
GET employees/5 PUT employees/5
In theory, the first should invoke EmployeesController#show, and the second should invoke EmployeesController#update.
But, if you turn on page caching under Fast-CGI, Apache might just bypass your routes altogether. Look at this line in the standard Rails .htaccess file:
RewriteRule ^([^.]+)$ cache/$1.html [QSA]
Uh-oh. Apache will read this, and for any request to employees/5, it will serve up the file cache/employees/5.html. The request will never be handed off to Rails. This includes POST, PUT, and DELETE requests. Thus, POST requests will send you to the index, while PUT and DELETE requests will send you to the show page for the record.
The Solution
My solution—which may not be the only or best one—is to edit .htaccess so that it's sensitive to request methods. Here's my modified caching code:
RewriteCond %{REQUEST_METHOD} GET
RewriteRule ^$ cache/index.html [QSA]
RewriteCond %{REQUEST_METHOD} GET
RewriteRule ^([^.]+)$ cache/$1.html [QSA]
This tell Apache that it should only look in the cache for GET requests. Obviously, this won't work if you want to use page caching for other request methods—but how often do you need to do that?