Problem with Rails Page Caching and Auto Extensions

I have a JSON and XML based API that needs to be cached on a page. I set my routes on the api to include the format as part of the url, so a url like this one works:

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

The problem that I see is that in the public folder of the server the files are saved as xml.xml and json.json , and this leads to a cache miss the next time the URL is accessed.

Is there any way:

  • Disable automatic expansion so that they are saved without expansion at all? (EX: RAILS_ROOT/public/foo/1/bar/2/json )
  • Force all extensions to be .html for each call. (EX: RAILS_ROOT/public/foo/1/bar/2/json.html )

Any of them forces my server to return a cached file instead of a miss. How can i do this?

EDIT:
Someone asked about the appropriate 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 :
Although I was looking for an official way to do this using the built-in support for page caching, I ended up using the 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 ] 
+6
source share
2 answers

You can do it 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 available, it will write the page to the cache (RAILS_ROOT / public / foo / 1 / bar / 2 / json. HTML)

And if you get http://example.com/foo/1/bar/2/json again, you will get RAILS_ROOT / public / foo / 1 / bar / 2 / json.html, but your http server (Apache?) Should Be aware of the content type of these files.

Otherwise, the content type will be 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> 
+3
source

In your application.rb configuration block, try adding:

 config.action_controller.page_cache_extension = '.html' 

It should ignore the expansion calculated on demand, and always use it. You can also try using this with an empty string.

EDIT: this will not actually work, because it only sets the default value. If the request has an extension (in your case, concluded from: format), it will be used.

I suggest changing: the format in your routes to something else that the rails will not attach much importance to, for example: fmt. Then the rails should not add an extension, but the default is ".html".

EDIT2: If you need to use: format, you can defuse Rails:

 ActionController::Caching::Pages::ClassMethods private def page_cache_file(path) name = (path.empty? || path == "/") ? "/index" : URI.unescape(path.chomp('/')) name << page_cache_extension #unless (name.split('/').last || name).include? '.' return name end end 

Notice the comment mark I added before the if. This is the part that overrides the default value from my first answer.

0
source

Source: https://habr.com/ru/post/888080/


All Articles