Lighthouse has a new layout. Prefer the old one? Return to the old layout, and switch back any time from the link at the top of each page.

This project is archived and is in readonly mode.

Rails respond_to processes XML but caches HTML

#6110

The 'root' page of my site is rendered by the posts#index action. To support rss and html, I have a respond_to block that looks like:

 respond_to do |wants|
  wants.html 
  wants.xml {
    render :layout => false;
    response.headers["Content-Type"] = "application/xml; charset=utf-8"
  }
end

I also have a 'caches_page' set on the index page.

If someone comes to the site in a browser and just requests "/", then they get served the html version of the page, and Rails also writes a cached page for index.html

There isn't really any way to request "/" with a format of XML, but if I hit "/posts.xml" it renders XML and caches posts.xml (similarly if I hit "/posts" or "/posts.html" it will cache posts.html). That all works just fine.

Now for the tricky bit. If something requests "/" but has an accept header like:

Accept: text/xml

Then Rails will process it as XML (probably correct), but CACHES it as html, destroying my cache. The next visitor to the site will be forever server an html file that actually contains XML. Here is the Rails log message proving this is happening:

Started GET "/" for 127.0.0.1 at 2010-11-30 20:47:27 +0000
  Processing by PostsController#index as XML
  Post Load (1.4ms)  SELECT "posts".* FROM "posts" WHERE ...
Rendered posts/index.xml.rxml (243.8ms)
Write page /..../index.html (0.6ms)
Completed 200 OK in 423ms (Views: 244.8ms | ActiveRecord: 1.4ms)

Is this a bug? I browsed some of the code, and the 'page caching' code doesn't consider the processing format of the request - it just parses the URL to see if there is a :format extension. If no extension is found, it use the defaul (html). This problem occured on my live site - I suspect it was a robot that came in with the text/xml header, but anything that does this can break a sites cache pretty easily.

Reported by Stephen · December 3rd, 2010 @ 12:51 PM

State: resolved
Milestone: none
Assigned to: José Valim José Valim
Importance: Low

Activity

  1. Neeraj Singh
    Neeraj Singh
    • State changed from new to open
    • Assigned user set to Neeraj Singh
    • Importance changed from to Low

    December 4th, 2010 @ 03:04 AM

  2. Neeraj Singh
    Neeraj Singh

    If the request has an extension like .xml, .js or .html then the cached page will have the extension that was supplied from the request.

    If the request does not have extension then a default .html extension is used as per https://github.com/rails/rails/blob/master/actionpack/lib/action_co...

    The HTTP_ACCEPT header value is totally being ignored.

    I will try to find more information about the above mentioned code from rails core team.

    December 4th, 2010 @ 03:45 AM

  3. Stephen
    Stephen

    Yea I had a browse of that code in pages.rb.

    It's almost as if the pages.rb code needs to know the value in the respond_to method to correctly work out the extension it should use.

    I don't know enough about the internals to know if it the relevant objects are accessible inside pages.rb I'm afraid.

    December 5th, 2010 @ 09:55 PM

  4. Neeraj Singh
    Neeraj Singh

    I have a fix that is working. Trying to write a test. Will update when fix is ready.

    December 5th, 2010 @ 10:07 PM

  5. Neeraj Singh
    Neeraj Singh
    • Assigned user changed from Neeraj Singh to José Valim

    December 6th, 2010 @ 10:56 AM

  6. Neeraj Singh
    Neeraj Singh

    For reference adding that ticket #1244 caches_page does not respect Accept header is about the same issue.

    December 6th, 2010 @ 09:34 PM

  7. Repository
    Repository
    • State changed from open to resolved

    (from [0027b654215cd6310d0d17daeaafec8ebbfb38d4]) Ensure that while caching a page rails takes into account the resolved mime type for the request

    [#6110 Rails respond_to processes XML but caches HTML state:resolved]

    Signed-off-by: José Valim jose.valim@gmail.com
    https://github.com/rails/rails/commit/0027b654215cd6310d0d17daeaafe...

    December 9th, 2010 @ 03:18 PM