Tuesday, August 16, 2011

Rails incorrectly parses HTTP Accept header for single media with range

Try hitting your Rails app with an HTTP header like this:

Accept: text/html;q=0.7

You will most likely get an exception that looks something like this:

Missing template home/index with {:locale=>[:en, :en],  :formats=>["text/html;q=0.7"], :handlers=>[:rhtml, :erb, :haml,  :rxml, :builder, :rjs]} in view paths  "/path/to/my_app/app/views"

This is because the ActionPack Mime::Type class is buggy in the way it parses this header when there is only one media type specified, and that media type has a range specified (the ";q=0.7"). This is perfectly valid HTML, and ActionPack actually handles the ranges correctly when there are more than one type specified.

An issue has been open for a while on this: https://github.com/rails/rails/issues/736 -- working patches have been proposed but not applied, yet the issue got closed for some reason.

I prefer not to patch my own version of Rails, so instead I am using a small monkey patch that works around this problem. I've created a file named config/initializers/rails_issue_736.rb that fixes the Mime::Type.lookup method to only use the part that comes before the semi-colon:


Huggie said...

Thanks for sharing this! Just saw a Hoptoad with this exact error, and you were the first search result for such an Accept header. I'll have to monkeypatch like you for now, but hopefully we can get a fix in ActionPack itself.

scottwb said...

Hoptoad is exactly how I found this too. Some domain tool crawler hits my site with that header. Glad this was helpful.