Class: Arrow::AcceptParam

Inherits:
Object
  • Object
show all
Includes:
Loggable, Comparable
Defined in:
lib/arrow/acceptparam.rb

Overview

Arrow::AcceptParam – a parser for Accept headers, allowing for weighted and wildcard comparisions.

Synopsis

require 'arrow/acceptparam'

ap = Arrow::AcceptParam.parse( “text/html;q=0.9;level=2” )

ap.type #=> ‘text’ ap.subtype #=> ‘html’ ap.qvalue #=> 0.9 ap =~ ‘text/*’ #=> true

Authors

This class was originally written as part of the ThingFish project.

Please see the file LICENSE in the top-level directory for licensing details.

Constant Summary collapse

Q_DEFAULT =

The default quality value (weight) if none is specified

1.0
Q_MAX =

The maximum quality value

Q_DEFAULT

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(type, subtype, qval = Q_DEFAULT, *extensions) ⇒ AcceptParam

Create a new Arrow::AcceptParam with the given media range, quality value (qval), and extensions



55
56
57
58
59
60
61
62
63
# File 'lib/arrow/acceptparam.rb', line 55

def initialize( type, subtype, qval=Q_DEFAULT, *extensions )
	type    = nil if type == '*'
	subtype = nil if subtype == '*'

	@type       = type
	@subtype    = subtype
	@qvalue     = normalize_qvalue( qval )
	@extensions = extensions.flatten
end

Instance Attribute Details

#extensionsObject (readonly)

An array of any accept-extensions specified with the parameter



80
81
82
# File 'lib/arrow/acceptparam.rb', line 80

def extensions
  @extensions
end

#qvalueObject (readonly)

The weight of the param



77
78
79
# File 'lib/arrow/acceptparam.rb', line 77

def qvalue
  @qvalue
end

#subtypeObject (readonly)

The ‘subtype’ part of the media range



74
75
76
# File 'lib/arrow/acceptparam.rb', line 74

def subtype
  @subtype
end

#typeObject (readonly)

The ‘type’ part of the media range



71
72
73
# File 'lib/arrow/acceptparam.rb', line 71

def type
  @type
end

Class Method Details

.parse(accept_param) ⇒ Object

Parse the given accept_param and return an AcceptParam object.

Raises:

  • (Arrow::RequestError)


42
43
44
45
46
47
48
49
50
# File 'lib/arrow/acceptparam.rb', line 42

def self::parse( accept_param )
	raise Arrow::RequestError, "Bad Accept param: no media-range" unless
		accept_param =~ %r{/}
	media_range, *stuff = accept_param.split( /\s*;\s*/ )
	type, subtype = media_range.downcase.split( '/', 2 )
	qval, opts = stuff.partition {|par| par =~ /^q\s*=/ }

	return new( type, subtype, qval.first, *opts )
end

Instance Method Details

#<=>(other) ⇒ Object

Comparable interface. Sort parameters by weight: Returns -1 if other is less specific than the receiver, 0 if other is as specific as the receiver, and +1 if other is more specific than the receiver.



161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
# File 'lib/arrow/acceptparam.rb', line 161

def <=>( other )

	if rval = (other.qvalue <=> @qvalue).nonzero?
		return rval
	end

	if @type.nil?
		return 1 if ! other.type.nil?
	elsif other.type.nil?
		return -1
	end

	if @subtype.nil?
		return 1 if ! other.subtype.nil?
	elsif other.subtype.nil?
		return -1
	end

	if rval = (other.extensions.length <=> @extensions.length).nonzero?
		return rval
	end

	return self.mediatype <=> other.mediatype
end

#=~(other) ⇒ Object

Match operator – returns true if other (an AcceptParan or something that can to_s to a mime type) is a mime type which matches the receiving AcceptParam.



86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
# File 'lib/arrow/acceptparam.rb', line 86

def =~( other )
	unless other.is_a?( Arrow::AcceptParam )
		other = self.class.parse( other.to_s ) rescue nil
		return false unless other
	end

	# */* returns true in either side of the comparison.
	# ASSUMPTION: There will never be a case when a type is wildcarded
	#             and the subtype is specific. (e.g., */xml)
	#             We gave up trying to read RFC 2045.
	return true if other.type.nil? || self.type.nil?

	# text/html =~ text/html
	# text/* =~ text/html
	# text/html =~ text/*
	if other.type == self.type
		return true if other.subtype.nil? || self.subtype.nil?
		return true if other.subtype == self.subtype
	end

	return false
end

#extension_stringsObject

Return a String containing any extensions for this parameter, joined with ‘;’



152
153
154
155
# File 'lib/arrow/acceptparam.rb', line 152

def extension_strings
	return nil if @extensions.empty?
	return @extensions.compact.join('; ')
end

#inspectObject

Return a human-readable version of the object



111
112
113
114
115
116
117
118
119
120
# File 'lib/arrow/acceptparam.rb', line 111

def inspect
	return "#<%s:0x%07x '%s/%s' q=%0.3f %p>" % [
		self.class.name,
		self.object_id * 2,
		self.type || '*',
		self.subtype || '*',
		self.qvalue,
		self.extensions,
	]
end

#mediatypeObject Also known as: mimetype, content_type

The mediatype of the parameter, consisting of the type and subtype separated by ‘/’.



136
137
138
# File 'lib/arrow/acceptparam.rb', line 136

def mediatype
	return "%s/%s" % [ self.type || '*', self.subtype || '*' ]
end

#qvaluestringObject

The weighting or “qvalue” of the parameter in the form “q=<value>”



144
145
146
147
# File 'lib/arrow/acceptparam.rb', line 144

def qvaluestring
	# 3 digit precision, trim excess zeros
	return sprintf( "q=%0.3f", self.qvalue ).gsub(/0{1,2}$/, '')
end

#to_sObject

Return the parameter as a String suitable for inclusion in an Accept HTTP header



125
126
127
128
129
130
131
# File 'lib/arrow/acceptparam.rb', line 125

def to_s
	return [
		self.mediatype,
		self.qvaluestring,
		self.extension_strings
	].compact.join(';')
end