This project is archived and is in readonly mode.

#5278 ✓resolved
Erik Hetzner

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

    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

    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

    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

    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

    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.

  • Erik Hetzner

    Erik Hetzner October 9th, 2010 @ 01:21 AM

    Hi Rohit,

    Here you go; hope I did things right.

  • Rohit Arondekar

    Rohit Arondekar October 9th, 2010 @ 01:32 AM

    • State changed from “new” to “open”
    • Assigned user set to “Santiago Pastorino”
  • 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

    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

    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

    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

    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

    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

    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>

Pages