This project is archived and is in readonly mode.
Order of an accept header should not matter to respond_to (Rails 3.0.0.rc)
Reported by Erik Hetzner | August 2nd, 2010 @ 11:19 PM | in 3.x
If a client supplies an "Accept: text/html,*/*
"
header, this should be equivalent to "Accept:
*/*,text/html
". In the patch to add a (failing) test
attached, this is not the case.
Example:
class AdvancedController < ActionController::Base
def xml_only
respond_to do |format|
format.xml do
render :content_type => 'application/xml',
:text => "invalid xml" and return
end
end
end
end
If a client requests this with "Accept: */*,
text/html
", the format.xml block is used, but if the client
requests "Accept: text/html,*/*
", it is not.
My apologies that I cannot currently supply a fix. Thank you!
Comments and changes to this ticket
-
trevmex August 3rd, 2010 @ 12:26 AM
- Tag set to http accepts mime action_dispatch
It seems that this is as planned. See the post at http://geminstallthat.wordpress.com/2008/05/14/ie6-accept-header-is...
There is a regex in actionpack/lib/action_dispatch/http/mime_negotiation.rb that checks for this (line 51):xhr? || (accept && accept !~ /,\s**\/*/)
Although the HTTP 1.1 spec (http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html) says it is allowed, the patch is in place for IE6. Thoughts?
-
Erik Hetzner August 3rd, 2010 @ 01:15 AM
Thanks for adding the appropriate tags; I wasn't sure which to add.
I don't have a lot of experience with the latest Rails, so take what I have to say with a grain of salt.
While IE's Accept header is a little strange, it is basically equivalent to "/", which is not a ridiculous header to send if your client really can accept most formats.
In this case it is the server's responsibility to choose the preferred format to return to the client. Since format.html is the first in the respond_to block, shouldn't it have higher priority than a format.any catch-all response?
Thanks.
-
Erik Hetzner August 4th, 2010 @ 12:31 AM
Above, third paragraph should be:
While IE's Accept header is a little strange, it is basically equivalent to "
*/*
", which is not a ridiculous header to send if your client really can accept most formats.Markdown stole my
*
s. -
Erik Hetzner August 4th, 2010 @ 12:43 AM
As background, I encountered this bug when attempting to create & view a resource that only had an Atom representation:
def recent respond_to do |format| format.atom do render :content_type => 'application/atom+xml', :text => "invalid atom" and return end end end
Which does not work as expected (by displaying an atom feed) with a Firefox Accept header:
text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
, but instead returns a 406 Not Acceptable. So this bug has potential real world impact. -
Rohit Arondekar October 7th, 2010 @ 06:15 AM
- Importance changed from to Low
Any updates here?
Also Erik can you make that failing test patch according to http://rails.lighthouseapp.com/projects/8994/sending-patches so that you get credit for commit.
-
Rohit Arondekar October 9th, 2010 @ 01:32 AM
- State changed from new to open
- Assigned user set to Santiago Pastorino
-
Santiago Pastorino November 7th, 2010 @ 12:31 PM
- Milestone set to 3.x
- Assigned user changed from Santiago Pastorino to José Valim
-
José Valim December 4th, 2010 @ 05:48 PM
- State changed from open to resolved
We have changed this behavior on master. Please read: http://www.neeraj.name/2010/11/23/mime-type-resolution-in-rails.html for more information.
-
Erik Hetzner December 4th, 2010 @ 06:10 PM
Thanks!
A quick read of that blog post reveals:
I am going to assume that in this case HTTP_ACCEPT sent by browser looks really simple like this text/javascript, text/html, text/plain
[...]
So browser is saying that I prefer documents in following order js html plain
This is not correct, as this bug report states. Order does not matter in an accept header, only q values matter in deciding which the client prefers. I don't know if the implementation is effected, but the blog post should probably be corrected.
-
Neeraj Singh December 4th, 2010 @ 06:22 PM
rails currently does take q value into account.
However if there is no q value specified then what. In that case rails gives preference to the ones specified earlier in the HTTP_ACCEPT value.
Hope that clears your question.
-
Erik Hetzner December 4th, 2010 @ 09:26 PM
Hi Neeraj,
Of course rails is free to return whatever it wants from the set of possible values supplied by the accept header, if they have equal q values.
But the client has not preferred, in the above example, javascript over html. If rails returns javascript, it is because rails prefers it, not the client.
As an application author I would like to be able to specify in some way that I would rather return HTML than, say, javascript, or the other way round, if the client has not specified a preference. And the order of the accept header does not specify a preference.
In any case, thank you for working on this!
-
José Valim December 4th, 2010 @ 09:32 PM
Exactly Erik, I believe this scenario is fixed in Rails master. The blog post explains why and how it is fixed.
-
Erik Hetzner December 5th, 2010 @ 06:39 PM
Maybe we can start over. I posted a comment on the blog post. Quotations are from the blog post.
For all documents that have same q value give high priority to the one that came first in the list.
An HTTP client does not mean to prioritize mime types by their ordering in the accept header; nothing in the spec says that order matters.
So browser is saying that I prefer documents in following order
js html plain
Again, the client is not saying that it prefers documents in any order; js, html & plain have the same q value; order does not matter.
Now, rails can do whatever it wants with these headers, as long as it honors q values. But order of accept headers is basically random,
and using it to make decisions will, in my opinion, lead to strange errors.Here is a real world problem with this.
"Accept: /" is treated differently from "Accept: text/xml, text/html" in terms of which respond_to block is used. In other words, if the respond_to block contains:
format.xml { ... } format.html { ... }
If the client uses "Accept: /", the html block will be used. If the client uses
"Accept: text/xml, text/html", the xml block will be used. This would be suprising to the application author, as well as the client.I know that there are real world problems with bad accept headers being sent by the client, but I don't see how this solution solves those problems.
Create your profile
Help contribute to this project by taking a few moments to create your personal profile. Create your profile »
<h2 style="font-size: 14px">Tickets have moved to Github</h2>
The new ticket tracker is available at <a href="https://github.com/rails/rails/issues">https://github.com/rails/rails/issues</a>