Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
MediaType refactoring step 1, extract from Conneg module. See #1.
- Loading branch information
1 parent
618ebe7
commit 53264b8
Showing
3 changed files
with
84 additions
and
70 deletions.
There are no files selected for viewing
This file contains 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
This file contains 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
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
module Webmachine | ||
# Encapsulates a MIME media type, with logic for matching types. | ||
class MediaType | ||
# Matches valid media types | ||
MEDIA_TYPE_REGEX = /^\s*([^;\s]+)\s*((?:;\S+\s*)*)\s*$/ | ||
|
||
# Matches sub-type parameters | ||
PARAMS_REGEX = /;([^=]+)=([^;=\s]+)/ | ||
|
||
# Creates a new MediaType by parsing its string representation. | ||
def self.parse(obj) | ||
case obj | ||
when MediaType | ||
obj | ||
when Array | ||
unless String == obj[0] && Hash === obj[1] | ||
raise ArgumentError, t('invalid_media_type', :type => obj.inspect) | ||
end | ||
type = parse(obj) | ||
type.params.merge! obj[1] | ||
type | ||
when MEDIA_TYPE_REGEX | ||
type, raw_params = $1, $2 | ||
params = Hash[raw_params.scan(PARAMS_REGEX)] | ||
new(type, params) | ||
end | ||
end | ||
|
||
# @return [String] the MIME media type | ||
attr_accessor :type | ||
|
||
# @return [Hash] any type parameters, e.g. charset | ||
attr_accessor :params | ||
|
||
def initialize(type, params={}) | ||
@type, @params = type, params | ||
end | ||
|
||
# Detects whether the {MediaType} represents an open wildcard | ||
# type, that is, "*/*" without any {#params}. | ||
def matches_all? | ||
@type == "*/*" && @params.empty? | ||
end | ||
|
||
def ==(other) | ||
other = self.class.parse(other) if String === other | ||
other.type == type && other.params == params | ||
end | ||
|
||
# Detects whether this {MediaType} matches the other {MediaType}, | ||
# taking into account wildcards. | ||
def match?(other) | ||
type_matches?(other) && other.params == params | ||
end | ||
|
||
# Reconstitutes the type into a String | ||
def to_s | ||
[type, *params.map {|k,v| "#{k}=#{v}" }].join(";") | ||
end | ||
|
||
# @return [String] The major type, e.g. "application", "text", "image" | ||
def major | ||
type.split("/").first | ||
end | ||
|
||
# @return [String] the minor or sub-type, e.g. "json", "html", "jpeg" | ||
def minor | ||
type.split("/").last | ||
end | ||
|
||
def type_matches?(other) | ||
if ["*", "*/*", type].include?(other.type) | ||
true | ||
else | ||
other.major == major && other.minor == "*" | ||
end | ||
end | ||
end | ||
end |