Module: Wants::MIMEParse
- Included in:
- TestMimeParsing
- Defined in:
- lib/wants/mimeparse.rb
Overview
From code.google.com/p/mimeparse
This module provides basic functions for handling mime-types. It can handle matching mime-types against a list of media-ranges. See section 14.1 of the HTTP specification [RFC 2616] for a complete explanation.
http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.1
This is a port of Joe Gregario’s mimeparse.py, which can be found at
<http://code.google.com/p/mimeparse/>.
ported from version 0.1.2
Comments are mostly excerpted from the original.
Class Method Summary collapse
-
.best_match(supported, header) ⇒ Object
Takes a list of supported mime-types and finds the best match for all the media-ranges listed in header.
-
.fitness_and_quality_parsed(mime_type, parsed_ranges) ⇒ Object
Find the best match for a given mime-type against a list of media_ranges that have already been parsed by #parse_media_range.
-
.parse_media_range(range) ⇒ Object
Carves up a media range and returns an Array of the [type, subtype, params] where “params” is a Hash of all the parameters for the media range.
-
.parse_mime_type(mime_type) ⇒ Object
Carves up a mime-type and returns an Array of the [type, subtype, params] where “params” is a Hash of all the parameters for the media range.
-
.quality(mime_type, ranges) ⇒ Object
Returns the quality “q” of a mime_type when compared against the media-ranges in ranges.
-
.quality_parsed(mime_type, parsed_ranges) ⇒ Object
Find the best match for a given mime-type against a list of media_ranges that have already been parsed by #parse_media_range.
Class Method Details
.best_match(supported, header) ⇒ Object
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:
header. The value of supported is an Enumerable of mime-types
irb> best_match(["application/xbel+xml", "text/xml"], "text/*;q=0.5,*/*; q=0.1")
=> "text/xml"
127 128 129 130 131 132 133 134 135 136 137 |
# File 'lib/wants/mimeparse.rb', line 127 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] end weighted_matches.sort! weighted_matches.last[0][1].zero? ? nil : weighted_matches.last[1] end |
.fitness_and_quality_parsed(mime_type, parsed_ranges) ⇒ Object
Find the best match for a given mime-type against a list of
media_ranges that have already been parsed by #parse_media_range
Returns the fitness and the “q” quality parameter of the best match,
or [-1, 0] if no match was found. Just as for #quality_parsed,
"parsed_ranges" must be an Enumerable of parsed media ranges.
76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 |
# File 'lib/wants/mimeparse.rb', line 76 def fitness_and_quality_parsed(mime_type, parsed_ranges) best_fitness = -1 best_fit_q = 0 target_type, target_subtype, target_params = parse_media_range(mime_type) parsed_ranges.each do |type,subtype,params| if (type == target_type or type == "*" or target_type == "*") and (subtype == target_subtype or subtype == "*" or target_subtype == "*") param_matches = target_params.find_all { |k,v| k != "q" and params.has_key?(k) and v == params[k] }.length fitness = (type == target_type) ? 100 : 0 fitness += (subtype == target_subtype) ? 10 : 0 fitness += param_matches if fitness > best_fitness best_fitness = fitness best_fit_q = params["q"] end end end [best_fitness, best_fit_q.to_f] end |
.parse_media_range(range) ⇒ Object
Carves up a media range and returns an Array of the
[type, subtype, params] where "params" is a Hash of all
the parameters for the media range.
For example, the media range “application/*;q=0.5” would
get parsed into:
- “application”, “*”, { “q”, “0.5” }
-
In addition this function also guarantees that there
is a value for "q" in the params dictionary, filling it in with a proper default if necessary.
61 62 63 64 65 66 67 68 |
# File 'lib/wants/mimeparse.rb', line 61 def parse_media_range(range) type, subtype, params = parse_mime_type(range) unless params.has_key?("q") and params["q"] and params["q"].to_f and params["q"].to_f <= 1 and params["q"].to_f >= 0 params["q"] = "1" end [type, subtype, params] end |
.parse_mime_type(mime_type) ⇒ Object
Carves up a mime-type and returns an Array of the
[type, subtype, params] where "params" is a Hash of all
the parameters for the media range.
For example, the media range “application/xhtml;q=0.5” would
get parsed into:
- “application”, “xhtml”, { “q” => “0.5” }
29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
# File 'lib/wants/mimeparse.rb', line 29 def parse_mime_type(mime_type) parts = mime_type.split(";") params = {} parts[1..-1].map do |param| k,v = param.split("=").map { |s| s.strip } params[k] = v end full_type = parts[0].strip # Java URLConnection class sends an Accept header that includes a single "*" # Turn it into a legal wildcard. full_type = "*/*" if full_type == "*" type, subtype = full_type.split("/") raise "malformed mime type" unless subtype [type.strip, subtype.strip, params] end |
.quality(mime_type, ranges) ⇒ Object
Returns the quality “q” of a mime_type when compared against
the media-ranges in ranges. For example:
irb> quality("text/html", "text/*;q=0.3, text/html;q=0.7, text/html;level=1, text/html;level=2;q=0.4, */*;q=0.5")
=> 0.7
115 116 117 118 |
# File 'lib/wants/mimeparse.rb', line 115 def quality(mime_type, ranges) parsed_ranges = ranges.split(",").map { |r| parse_media_range(r) } quality_parsed(mime_type, parsed_ranges) end |
.quality_parsed(mime_type, parsed_ranges) ⇒ Object
Find the best match for a given mime-type against a list of
media_ranges that have already been parsed by #parse_media_range
Returns the “q” quality parameter of the best match, 0 if no match
was found. This function behaves the same as #quality except that
"parsed_ranges" must be an Enumerable of parsed media ranges.
106 107 108 |
# File 'lib/wants/mimeparse.rb', line 106 def quality_parsed(mime_type, parsed_ranges) fitness_and_quality_parsed(mime_type, parsed_ranges)[1] end |