Class: Async::HTTP::Headers

Inherits:
Object
  • Object
show all
Defined in:
lib/async/http/headers.rb

Defined Under Namespace

Classes: Merged, Multiple, Split

Constant Summary collapse

MERGE_POLICY =
{
	# Headers which may only be specified once.
	'content-type' => false,
	'content-disposition' => false,
	'content-length' => false,
	'user-agent' => false,
	'referer' => false,
	'host' => false,
	'authorization' => false,
	'proxy-authorization' => false,
	'if-modified-since' => false,
	'if-unmodified-since' => false,
	'from' => false,
	'location' => false,
	'max-forwards' => false,
	
	'connection' => Split,
	
	# Headers specifically for proxies:
	'via' => Split,
	'x-forwarded-for' => Split,
	
	# Headers which may be specified multiple times, but which can't be concatenated.
	'set-cookie' => Multiple,
	'www-authenticate' => Multiple,
	'proxy-authenticate' => Multiple
}.tap{|hash| hash.default = Split}

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(fields = []) ⇒ Headers

Returns a new instance of Headers.



56
57
58
59
# File 'lib/async/http/headers.rb', line 56

def initialize(fields = [])
	@fields = fields
	@indexed = to_h
end

Instance Attribute Details

#fieldsObject (readonly)

Returns the value of attribute fields.



61
62
63
# File 'lib/async/http/headers.rb', line 61

def fields
  @fields
end

Class Method Details

.[](hash) ⇒ Object



52
53
54
# File 'lib/async/http/headers.rb', line 52

def self.[] hash
	self.new(hash.to_a)
end

Instance Method Details

#==(other) ⇒ Object



180
181
182
183
184
185
186
# File 'lib/async/http/headers.rb', line 180

def == other
	if other.is_a? Hash
		to_h == other
	else
		@fields == other.fields
	end
end

#[](key) ⇒ Object



166
167
168
169
170
# File 'lib/async/http/headers.rb', line 166

def [] key
	@indexed ||= to_h
	
	@indexed[key]
end

#[]=(key, value) ⇒ Object



114
115
116
117
118
119
120
121
# File 'lib/async/http/headers.rb', line 114

def []= key, value
	@fields << [key, value]
	
	if @indexed
		# It would be good to do some kind of validation here.
		merge(@indexed, key.downcase, value)
	end
end

#add(key, value) ⇒ Object



110
111
112
# File 'lib/async/http/headers.rb', line 110

def add(key, value)
	self[key] = value
end

#delete(key) ⇒ Object

Delete all headers with the given key, and return the value of the last one, if any.



84
85
86
87
88
89
90
91
92
93
94
95
96
# File 'lib/async/http/headers.rb', line 84

def delete(key)
	values, @fields = @fields.partition do |field|
		field.first.downcase == key
	end
	
	if @indexed
		@indexed.delete(key)
	end
	
	if field = values.last
		return field.last
	end
end

#each(&block) ⇒ Object



75
76
77
# File 'lib/async/http/headers.rb', line 75

def each(&block)
	@fields.each(&block)
end

#empty?Boolean

Returns:

  • (Boolean)


71
72
73
# File 'lib/async/http/headers.rb', line 71

def empty?
	@fields.empty?
end

#freezeObject



63
64
65
66
67
68
69
# File 'lib/async/http/headers.rb', line 63

def freeze
	return if frozen?
	
	@indexed = to_h
	
	super
end

#include?(key) ⇒ Boolean

Returns:

  • (Boolean)


79
80
81
# File 'lib/async/http/headers.rb', line 79

def include? key
	self[key] != nil
end

#merge(hash, key, value) ⇒ Object



151
152
153
154
155
156
157
158
159
160
161
162
163
164
# File 'lib/async/http/headers.rb', line 151

def merge(hash, key, value)
	if policy = MERGE_POLICY[key]
		if current_value = hash[key]
			current_value << value
		else
			hash[key] = policy.new(value)
		end
	else
		raise ArgumentError, "Header #{key} can only be set once!" if hash.include?(key)
		
		# We can't merge these, we only expose the last one set.
		hash[key] = value
	end
end

#slice!(keys) ⇒ Object



98
99
100
101
102
103
104
105
106
107
108
# File 'lib/async/http/headers.rb', line 98

def slice!(keys)
	values, @fields = @fields.partition do |field|
		keys.include?(field.first.downcase)
	end
	
	if @indexed
		keys.each do |key|
			@indexed.delete(key)
		end
	end
end

#to_hObject



172
173
174
175
176
177
178
# File 'lib/async/http/headers.rb', line 172

def to_h
	@fields.inject({}) do |hash, (key, value)|
		merge(hash, key.downcase, value)
		
		hash
	end
end