|Subject:||HTTP::Negotiate checks prefixes the wrong way round|
Ticket(and its patch) is the reverse of what the HTTP specification states. Firstly, a quick script to show the issue (in the same style as ticket 13275): #!/usr/bin/perl use strict; use warnings FATAL => 'all'; use HTTP::Negotiate qw(choose); use HTTP::Headers; use Data::Dumper; my @variants = ( [ 'English', undef, undef, undef, undef, 'en-gb', undef ], [ 'Norwegian', undef, undef, undef, undef, 'nb', undef ], ); local $HTTP::Negotiate::DEBUG = 1; my @preferences = choose(\@variants, HTTP::Headers->new('Accept-Language' => 'en,nb;q=0.1')); print Dumper @preferences; This should return the English variant first, but returns the Norwegian variant. The HTTP specification states: "A language-range [in an Accept-Language request header] matches a language-tag [in a variant] if it exactly equals the tag, or if it exactly equals a prefix of the tag such that the first tag character following the prefix is "-"." - ie. the request can be a prefix of the document language, not the other way round which the index() line of Negotiate.pm is currently doing. This is confirmed by the Apache documentation at which says: "For example, if a client requests documents with the language en-GB for British English, the server is not normally allowed by the HTTP/1.1 standard to match that against a document that is marked as simply en. (Note that it is almost surely a configuration error to include en-GB and not en in the Accept-Language header, since it is very unlikely that a reader understands British English, but doesn't understand English in general. Unfortunately, many current clients have default configurations that resemble this.)" This is precisely the situation in ticket 13275, where actually HTTP::Negotiate was doing the correct thing in returning the Non-Specific option. The fix for this issue is simply to reverse the patch supplied for ticket 13275. I realise (if you read on in the Apache documentation) that Apache has made the decision to implicitly add parent languages with low quality levels, but I do not think a low-level module such as HTTP::Negotiate should do this, it should be up to the caller.