Created
January 26, 2009 02:19
-
-
Save bct/52666 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Index: mimeparse.rb | |
=================================================================== | |
--- mimeparse.rb (revision 10) | |
+++ mimeparse.rb (working copy) | |
@@ -117,6 +117,16 @@ | |
quality_parsed(mime_type, parsed_ranges) | |
end | |
+def _best_match(supported, parsed_header, &comparator) | |
+ weighted_matches = supported.map do |mime_type| | |
+ [comparator.call(mime_type, parsed_header), -supported.index(mime_type), mime_type] | |
+ end | |
+ | |
+ weighted_matches.sort! | |
+ | |
+ weighted_matches.last[0][1].zero? ? nil : weighted_matches.last[2] | |
+end | |
+ | |
# Takes a list of supported mime-types and finds the best match | |
# for all the media-ranges listed in header. The value of header | |
# must be a string that conforms to the format of the HTTP Accept: | |
@@ -127,15 +137,44 @@ | |
def best_match(supported, header) | |
parsed_header = header.split(",").map { |r| parse_media_range(r) } | |
- weighted_matches = supported.map do |mime_type| | |
- [fitness_and_quality_parsed(mime_type, parsed_header), mime_type] | |
+ _best_match(supported, parsed_header) do |thing, parsed_header| | |
+ fitness_and_quality_parsed(thing, parsed_header) | |
end | |
+end | |
- weighted_matches.sort! | |
+def encoding_quality(encoding, parsed_header) | |
+ best_q = 0 | |
+ fitness = -1 | |
- weighted_matches.last[0][1].zero? ? nil : weighted_matches.last[1] | |
+ parsed_header.each do |e,q| | |
+ if e == '*' and fitness < 0 | |
+ best_q = q | |
+ fitness = 1 | |
+ elsif e == encoding | |
+ best_q = q | |
+ fitness = 1 | |
+ end | |
+ end | |
+ | |
+ [fitness, best_q] | |
end | |
+ | |
+def select_best_encoding(supported, parsed_header) | |
+ return nil if supported.empty? | |
+ | |
+ match = _best_match(supported, parsed_header) do |thing, parsed_header| | |
+ encoding_quality(thing, parsed_header) | |
+ end | |
+ | |
+ if match.nil? | |
+ value = encoding_quality('identity', parsed_header) | |
+ no_identity = (value[0] != -1) and value[1].zero? | |
+ f = 'identity' unless no_identity | |
+ else | |
+ match | |
+ end | |
end | |
+end | |
if __FILE__ == $0 | |
require "test/unit" | |
@@ -185,9 +224,9 @@ | |
# direct match of our second choice with a q parameter | |
assert_best_match "application/xml", "application/xml; q=1" | |
# match using a subtype wildcard | |
- assert_best_match "application/xml", "application/*; q=1" | |
+ assert_best_match "application/xbel+xml", "application/*; q=1" | |
# match using a type wildcard | |
- assert_best_match "application/xml", "*/*" | |
+ assert_best_match "application/xbel+xml", "*/*" | |
@supported_mime_types = [ "application/xbel+xml", "text/xml" ] | |
# match using a type versus a lower weighted subtype | |
@@ -209,8 +248,40 @@ | |
assert_best_match 'image/*', 'image/*' | |
end | |
+ def test_best_encoding_match | |
+ @supported_encodings = %w() | |
+ | |
+ assert_best_encoding nil, [["x", 1]] | |
+ | |
+ @supported_encodings = %w(identity) | |
+ | |
+ assert_best_encoding nil, [["identity", 0.0]] | |
+ assert_best_encoding nil, [["*", 0.0]] | |
+ assert_best_encoding 'identity', [["compress", 1.0], ["gzip", 1.0]] | |
+ | |
+ @supported_encodings = %w(compress gzip identity) | |
+ | |
+ assert_best_encoding 'compress', [['compress', 1.0], ['gzip', 1.0]] | |
+ assert_best_encoding 'gzip', [['compress', 0.5], ['gzip', 1.0]] | |
+ | |
+ @supported_encodings = %w(foo bar identity) | |
+ | |
+ assert_best_encoding 'identity', [] | |
+ assert_best_encoding 'foo', [['*', 1.0]] | |
+ assert_best_encoding 'bar', [['*', 1.0], ['foo', 0.9]] | |
+ assert_best_encoding 'identity', [['foo', 0], ['bar', 0]] | |
+ | |
+ @supported_encodings = %w(foo bar baz identity) | |
+ | |
+ assert_best_encoding 'identity', [['*', 0], ['identity', 0.1]] | |
+ end | |
+ | |
def assert_best_match(expected, header) | |
assert_equal(expected, best_match(@supported_mime_types, header)) | |
end | |
+ | |
+ def assert_best_encoding(expected, header) | |
+ assert_equal(expected, select_best_encoding(@supported_encodings, header)) | |
+ end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment