Rails + Caching + XML = Bad Mime Types

So I’ve started working on a replacement RSS feed for the blog. It’s not really a drastic change, just a few little add-ons and a move internally from ERb templates to Builder templates. I’m also working very hard to have it so the feed is cached on the file system, and thus enabling Apache to give a 304 (nothing has changed) message. (Currently it give a 200 OK message and every byte, for every request.)

My problem is this: When I tell the BlogController to caches_page :fastrss it ends up using a .html file extension on the file it creates, then Apache servers it with a text/html mime type, then the feed validator rightfully complains. What I need to do is figure out how to tell the cache system to use a .xml for just that method on the blog controller, and then figure out how to edit the Apache .htaccess file to look for the .xml file before handing over the request to the dispatcher.

To be honest I was hoping the cache system would have noticed I was using Builder and used the .xml extension automatically. It just seems like something Rails would have done. Maybe I expect to much. Anyways, I’ve done a fair amount of Googling but have yet to find a solution that felt right. I have to imaging others out there have solved this. If you can help please let me know.

PS: The /blog/fastrss/ feed is only temporary. Once I work out these issues it will disappear and replace the the current RSS implementation.

Posted on: February 17, 2006 – 10:59 PM

6 Comments

  1. Well, looking at the current Rails caching system it appears it only supports a single prefix, however it allows you to set the extension using a class attribute ActionController::Caching::Pages.page_cache_extension = '.xml'

    You might consider this hack to work this out in your case. You can simply use the Apache directive ForceType to set your content type by adding the following to your Apache VirtualHost:

    <Location /blog/fastrss.html>
    ForceType text/xml
    </Location> 
    

    If you don’t want to do that you could crack open ActionController::Caching::Pages and try to scratch your itch that way, but it looks like the code was pretty much only designed to cache one type of file. Changing it to allow for multiple file types (which you could pass as a argument for example) would not be a huge undertaking. It is also worth noting the if you want caching to work for multiple file extensions you end up adding overhead to every request because it will require one RewriteRule per file extension in your .htaccess file (which will be processed, and check the disk on each request)

  2. Oops s|text/xml|application/xml|

  3. I believe I just had this working, but through a roundabout fashion. In routes.rb, I had

    map.connect '/album/:id/images.xml', :controller => 'album', :action => 'images'
    

    And when I used caches_page :images in my album controller, it created public/album/#/images.xml. I don’t know if the same will work for you, but perhaps this will get you started down that road?

  4. Adam, I think I like the ForceType solution the best since not all actions in the controller should get the xml file extensions. I tried it however and ran into a problem. When I added the ForceType to my .htaccess file I got an error: Location not allowed here. Looking at my VirtualHost I am applying All to AllowOverride so it should work, but it’s not. Any ideas?

    <VirtualHost *> 
    ServerName http://www.clickablebliss.com
    ServerAlias clickablebliss.com
    ServerAdmin mike@clickablebliss.com
    DocumentRoot /webserver/cbwebsite/current/public/
    ErrorLog /webserver/cbwebsite/logs/error_log
    CustomLog /webserver/cbwebsite/logs/access_log combined
    <Directory /webserver/cbwebsite/current/public/> 
        Options ExecCGI FollowSymLinks 
        AllowOverride All 
        Allow from all 
        Order allow,deny 
    </Directory> 
    </VirtualHost>
    
  5. Tom wrote:

    I also ran into the “Location not allowed here” problem. I think this is due to certain limitation of the Apache setup of your host. For some reason, FilesMatch does work:

    <FilesMatch "\.xml$">
        ForceType application/xml
    </FilesMatch>
    

    It allows me to cache files with .xml extension…

    Tom

  6. I don’t even know,fellow!) continued to write in the same vein, it is interesting people!

Post a Comment | Comment RSS feed

(used for gravatar), address not displayed on site)