Skip to content

Instantly share code, notes, and snippets.

@bct
Created January 26, 2009 02:19
Show Gist options
  • Save bct/52666 to your computer and use it in GitHub Desktop.
Save bct/52666 to your computer and use it in GitHub Desktop.
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