this adds a new accept type
This new class handles various accept strings and makes them available throught the same API. This way, language and media type feels the same.
This commit is contained in:
parent
a7d3106df2
commit
be5cd61bb9
|
@ -55,7 +55,7 @@ module Zero
|
|||
# get the media types
|
||||
# @return [Accept] on Accept object managing all types and their order
|
||||
def media_types
|
||||
@accept ||= Request::Accept.new(@env[CONST_HTTP_ACCEPT])
|
||||
@accept ||= Request::Accept.new(@env)
|
||||
end
|
||||
|
||||
# get the method of the request
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
require_relative 'accept_type'
|
||||
|
||||
module Zero
|
||||
class Request
|
||||
# encapsulates the accept header to easier work with
|
||||
|
@ -7,6 +9,10 @@ module Zero
|
|||
MEDIA_PARAM_SEPERATOR = ';'
|
||||
MEDIA_QUALITY_REGEX = /q=[01]\./
|
||||
|
||||
KEY_HTTP_ACCEPT = 'HTTP_ACCEPT'
|
||||
KEY_HTTP_ACCEPT_LANGUAGE = 'HTTP_ACCEPT_LANGUAGE'
|
||||
KEY_HTTP_ACCEPT_ENCODING = 'HTTP_ACCEPT_ENCODING'
|
||||
|
||||
def self.map=(map)
|
||||
@@map = map
|
||||
end
|
||||
|
@ -16,65 +22,15 @@ module Zero
|
|||
end
|
||||
|
||||
# create a new accept object
|
||||
def initialize(accept_string)
|
||||
if accept_string.nil?
|
||||
@types = []
|
||||
else
|
||||
@types = parse_media_types(accept_string)
|
||||
end
|
||||
def initialize(environment)
|
||||
@accept_types = AcceptType.new(environment[KEY_HTTP_ACCEPT])
|
||||
@accept_language = AcceptType.new(environment[KEY_HTTP_ACCEPT_LANGUAGE])
|
||||
@accept_encoding = AcceptType.new(environment[KEY_HTTP_ACCEPT_ENCODING])
|
||||
end
|
||||
|
||||
# return the preferred type
|
||||
# @return String the preferred media type
|
||||
def preferred
|
||||
@types.first
|
||||
end
|
||||
|
||||
# iterate over all media types
|
||||
def each
|
||||
@types.each {|type| yield type}
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# converts the accept string to a useable array
|
||||
# @param accept_string the string containing media ranges and options
|
||||
def parse_media_types(accept_string = '*/*')
|
||||
accept_string.
|
||||
gsub(/\s/, '').
|
||||
split(MEDIA_TYPE_SEPERATOR).
|
||||
map do |accept_range|
|
||||
extract_order(*accept_range.split(MEDIA_PARAM_SEPERATOR))
|
||||
end.
|
||||
sort_by(&:last).
|
||||
map(&:first)
|
||||
end
|
||||
|
||||
# extract the order of the type
|
||||
# @param media_type the type itself
|
||||
# @param params further options to the type
|
||||
# @return Array the media type and quality in that order
|
||||
def extract_order(media_type, *params)
|
||||
params.each do |param|
|
||||
if param.match(MEDIA_QUALITY_REGEX)
|
||||
return [map_type(media_type), 10 - param[4..-1].to_i]
|
||||
end
|
||||
end
|
||||
[map_type(media_type), 0]
|
||||
end
|
||||
|
||||
# map media types to the type given in the map
|
||||
# @param type [String] the media type
|
||||
# @return the media type of the mapping or the original
|
||||
def map_type(type)
|
||||
return map[type] if map.has_key?(type)
|
||||
type
|
||||
end
|
||||
|
||||
# a small wrapper to the class method
|
||||
def map
|
||||
self.class.map
|
||||
end
|
||||
attr_reader :accept_types
|
||||
attr_reader :accept_language
|
||||
attr_reader :accept_encoding
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -0,0 +1,66 @@
|
|||
module Zero
|
||||
class Request
|
||||
# This class provides an interface to access information of accept schemas.
|
||||
class AcceptType
|
||||
MEDIA_TYPE_SEPERATOR = ','
|
||||
MEDIA_PARAM_SEPERATOR = ';'
|
||||
MEDIA_QUALITY_REGEX = /q=[01]\./
|
||||
|
||||
# create a new instance of AcceptType
|
||||
def initialize(string)
|
||||
if string.nil?
|
||||
@elements = []
|
||||
else
|
||||
@elements = parse_elements(string)
|
||||
end
|
||||
end
|
||||
|
||||
# return the preferred type
|
||||
# @return String the preferred media type
|
||||
def preferred
|
||||
@elements.first
|
||||
end
|
||||
|
||||
# iterate over all media types
|
||||
def each
|
||||
@elements.each {|element| yield element}
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# converts the accept string to a useable array
|
||||
# @param string the string containing media ranges and options
|
||||
def parse_elements(string = '*/*')
|
||||
string.
|
||||
gsub(/\s/, '').
|
||||
split(MEDIA_TYPE_SEPERATOR).
|
||||
map do |accept_range|
|
||||
extract_order(*accept_range.split(MEDIA_PARAM_SEPERATOR))
|
||||
end.
|
||||
sort_by(&:last).
|
||||
map(&:first)
|
||||
end
|
||||
|
||||
# extract the order of the type
|
||||
# @param media_type the type itself
|
||||
# @param params further options to the type
|
||||
# @return Array the media type and quality in that order
|
||||
def extract_order(media_type, *params)
|
||||
params.each do |param|
|
||||
if param.match(MEDIA_QUALITY_REGEX)
|
||||
return [media_type, 10 - param[4..-1].to_i]
|
||||
end
|
||||
end
|
||||
[media_type, 0]
|
||||
end
|
||||
|
||||
# map media types to the type given in the map
|
||||
# @param type [String] the media type
|
||||
# @return the media type of the mapping or the original
|
||||
def map_type(type)
|
||||
return map[type] if map.has_key?(type)
|
||||
type
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
Loading…
Reference in New Issue