mjackson / rack-accept

HTTP Accept* for Ruby/Rack
http://mjackson.github.com/rack-accept
47 stars 16 forks source link

RFC-compliance #1

Closed SSDany closed 14 years ago

SSDany commented 14 years ago
m = Rack::Accept::MediaType.new('text/*, text/html, text/html;level=1, */*')

m.matches('text/html;level=1') #=> ["text/html;level=1", "text/html", "text/*", "*/*"]
#OK

m.matches('text/html;level=1;answer=42') #=> ["*/*"]
#oops

m.best_of(['text/html','text/xml']) #=> "text/xml"
#oops, more specific ("text/html") should win;
take a look at RFC2616, section 14, "text/*, text/html, text/html;level=1, */*" example.

RFC-compliant implementations of this algorythm: http://code.google.com/p/mimeparse/ (but there are some issues in parsing and weighing of media types) http://github.com/SSDany/rack-acceptable

mjackson commented 14 years ago

I've addressed both of these issues in the 0.4 release. The fixes are in 403aeff0a606aabeba5b0dafed17ce0853243592 and 309f7f93cb29288bc0b25762916fd6f11bf1b995.

The best_of method should indeed return "text/html" in your test case, but not for the reason you mentioned. When RFC 2616 talks about matching and precedence, it is referring to the precedence that one value may take over another because it is more specific. The matches method of each header class takes care of figuring out this order. However, best_of compares values based solely on quality factor. In your example "text/html" and "text/xml" both have a quality factor of 1 which means that they will sort evenly. The result should be whichever one came first in the array you pass in.

Thanks for bringing this issue to my attention.