content negotiation and media types order in the accept header

Hello,

I am having trouble with content negotiation due to some Accept headers not clearly specifying an order amongst all desired media types. For example, Safari provides:

application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5

Right now, if a Rails resource can be represented both in html and application/xml, rails will return an application/xml representation.

Asking about it in the rest-discuss mailing list, the http specs do not provide any guide on which media-type to pick if multiple ones have the same q value. In Safari's example, there are three possible media types that can be picked.

Other language and frameworks have decided to use a first-q value, second-alphabetical sorting of the list and find the first one that it is capable of providing. This solves the problem for typical representations because json and xml comes after html.

I am attaching my original question on the rest-discuss list and mike's answer which mentions the first framework (his link shows other - python and erlang - frameworks that chose the same path).

The rails code that affects it is within the mime_responds.rb:

        if ActionController::Base.use_accept_header           @mime_type_priority = Array(Mime::Type.lookup_by_extension (@request.parameters[:format]) || @request.accepts)         else           @mime_type_priority = [@request.format]         end

The issue with Rails by default is that the first priority for Safari in the list is priority = 'application/xml' and @responses do not include it (Rails registered xml only, not application/xml):             if @responses[priority]               @responses[priority].call               return # mime type match found, be happy and return             end

If we register a application/xml, then Safari starts getting a xml representation, where most would give back a html representation back.

Any suggestions?

note: the sorting is according to the name after the /

Regards

Guilherme Silveira Caelum | Ensino e Inovação http://www.caelum.com.br/

Right now, if a Rails resource can be represented both in html and application/xml, rails will return an application/xml representation.

If there are multiple representations with the same q level we take the priority in the order you specify them. e.g. if you have

respond_to do |format|   format.xml   format.html end

You get xml, flip the block order around and you get HTML instead. This allows both the client and the server to express their preference where an alpha sorting wouldn't. I'm guessing that you have your xml declarations first.

I personally think this is a much better solution than what you're describing here as you get proper content-negotiation rather than just a fancy parser which somehow decides which of the equivalent entries it should consider 'best'.

Having said all of that, in my personal opinion the accept header is a horrific idea in practise as there are simply dozens of corner cases where browsers send idiotic values. I've seen IE saying it doesn't support HTML or XML (new tab ie7) various plugins sending completely malformed headers etc. I'm a firm believer that you should pretty much always disable use_accept_header if you'll ever have browsers connecting. But rails supports both paths.

Hello Michael,

I'm guessing that you have your xml declarations first.

Its actually a generic format.xxx registration procedure so the framework can handle content-negotiation by default instead of the client having to describe it every time (I believe rails3 handle it with their responders from what Ive seen).

But knowing that solves the problem... thanks...

I personally think this is a much better solution than what you're describing here as you get proper content-negotiation rather than just a fancy parser which somehow decides which of the equivalent entries it should consider 'best'.

Yes

I've seen IE saying it doesn't support HTML or XML (new tab ie7) various plugins sending completely malformed headers etc.

The famous IE 'accept' problems... ie8 still has issues from what I have read.

Thanks again, it solved the problem.

Cheers

guilherme