Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Problem with Rails page caching and automatic extensions

I have a JSON and XML based API that needs to be page cached. I have setup my routes on the api to include the format as part of the URL, such that URL's like this work:

http://example.com/foo/1/bar/2/xml
http://example.com/foo/1/bar/2/json

The problem I am seeing is that in the server's public folder, the files are being saved as xml.xml and json.json, and this causes cache misses the next time the URL is accessed.

Is there a way to either:

  1. Turn off the auto extension generation so that they are saved without an extension at all? (EX: RAILS_ROOT/public/foo/1/bar/2/json)
  2. Force all the extensions to be .html for every call. (EX: RAILS_ROOT/public/foo/1/bar/2/json.html)

Either of these would cause my server to return the cached file instead of a miss. How can I do this?

EDIT:
Somebody asked for the relevant route:

scope '(foo/:foo_id)', :foo_id => /\d+/ do
  get '/bar/:bar_id/:format' => 'bars#show', :bar_id => /\d+/, :format => /json|xml|html/
end



SOLUTION:
While I was looking for an official way to make this happen using the built in page caching support, I ended up just using an after filter and my own page cache method, as suggested by Anton

# application_controller.rb
def cache_api_page
  if REDACTEDServer::Application.config.action_controller.perform_caching
    self.class.cache_page(response.body, request.path, '')
    puts "CACHED PATH: #{request.path}"
  end
end

# bar_controller.rb
 after_filter :cache_api_page, :only => [ :show, :index ]
like image 630
coneybeare Avatar asked May 13 '11 22:05

coneybeare


1 Answers

You can do that like this:

class FooController < ApplicationController

  after_filter(:only => :show, :if => Proc.new { |c| c.request.format.json? }) do |controller|
    controller.class.cache_page(controller.response.body, controller.request.path, '.html')
  end

end

When http://example.com/foo/1/bar/2/json is accessed, it will write page to cache (RAILS_ROOT/public/foo/1/bar/2/json.html)

And if you get http://example.com/foo/1/bar/2/json again, you receive RAILS_ROOT/public/foo/1/bar/2/json.html, but your http server(Apache?) should know about content type of this files.

Otherwise content type will set to 'text/html'

UPDATE

To you .htaccess

<FilesMatch "\/json$">
<IfModule mod_headers.c>
  Header set Content-Type "text/json"
</IfModule>
</FilesMatch>


<FilesMatch "\/xml$">
<IfModule mod_headers.c>
  Header set Content-Type "text/xml"
</IfModule>
</FilesMatch>
like image 145
Anton Avatar answered Oct 02 '22 08:10

Anton