Class: Protocol::HTTP::Headers

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

Overview

Headers are an array of key-value pairs. Some header keys represent multiple values.

Defined Under Namespace

Classes: Merged

Constant Summary collapse

Split =
Header::Split
Multiple =
Header::Multiple
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' => Header::Connection,
	
	# Headers specifically for proxies:
	'via' => Split,
	'x-forwarded-for' => Split,
	
	# Headers which may be specified multiple times, but which can't be concatenated:
	'www-authenticate' => Multiple,
	'proxy-authenticate' => Multiple,
	
	# Custom headers:
	'set-cookie' => Header::SetCookie,
	'cookie' => Header::Cookie,
}.tap{|hash| hash.default = Split}

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(fields = nil, indexed = nil) ⇒ Headers

Returns a new instance of Headers.



39
40
41
42
43
44
45
46
47
48
49
50
51
# File 'lib/protocol/http/headers.rb', line 39

def initialize(fields = nil, indexed = nil)
	if fields
		@fields = fields.dup
	else
		@fields = []
	end
	
	if indexed
		@indexed = indexed.dup
	else
		@indexed = nil
	end
end

Instance Attribute Details

#fieldsObject (readonly)

An array of ‘[key, value]` pairs.



63
64
65
# File 'lib/protocol/http/headers.rb', line 63

def fields
  @fields
end

Class Method Details

.[](hash) ⇒ Object



35
36
37
# File 'lib/protocol/http/headers.rb', line 35

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

Instance Method Details

#==(other) ⇒ Object



219
220
221
222
223
224
225
226
227
228
# File 'lib/protocol/http/headers.rb', line 219

def == other
	case other
	when Hash
		to_h == other
	when Headers
		@fields == other.fields
	else
		@fields == other
	end
end

#[](key) ⇒ Object



202
203
204
# File 'lib/protocol/http/headers.rb', line 202

def [] key
	to_h[key]
end

#[]=(key, value) ⇒ Object

Append the value to the given key. Some values can be appended multiple times, others can only be set once.

Parameters:

  • key (String)

    The header key.

  • value

    The header value.



125
126
127
128
129
130
131
# File 'lib/protocol/http/headers.rb', line 125

def []= key, value
	if @indexed
		merge_into(@indexed, key.downcase, value)
	end
	
	@fields << [key, value]
end

#add(key, value) ⇒ Object



106
107
108
# File 'lib/protocol/http/headers.rb', line 106

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

#clearObject



57
58
59
60
# File 'lib/protocol/http/headers.rb', line 57

def clear
	@fields.clear
	@indexed = nil
end

#delete(key) ⇒ Object

Delete all headers with the given key, and return the merged value.



165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
# File 'lib/protocol/http/headers.rb', line 165

def delete(key)
	deleted, @fields = @fields.partition do |field|
		field.first.downcase == key
	end
	
	if deleted.empty?
		return nil
	end
	
	if @indexed
		return @indexed.delete(key)
	elsif policy = MERGE_POLICY[key]
		(key, value), *tail = deleted
		merged = policy.new(value)
		
		tail.each{|k,v| merged << v}
		
		return merged
	else
		key, value = deleted.last
		return value
	end
end

#dupObject



53
54
55
# File 'lib/protocol/http/headers.rb', line 53

def dup
	self.class.new(@fields, @indexed)
end

#each(&block) ⇒ Object



81
82
83
# File 'lib/protocol/http/headers.rb', line 81

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

#empty?Boolean

Returns:

  • (Boolean)


77
78
79
# File 'lib/protocol/http/headers.rb', line 77

def empty?
	@fields.empty?
end

#extract(keys) ⇒ Object Also known as: slice!



89
90
91
92
93
94
95
96
97
98
99
100
101
# File 'lib/protocol/http/headers.rb', line 89

def extract(keys)
	deleted, @fields = @fields.partition do |field|
		keys.include?(field.first.downcase)
	end
	
	if @indexed
		keys.each do |key|
			@indexed.delete(key)
		end
	end
	
	return deleted
end

#freezeObject



65
66
67
68
69
70
71
72
73
74
75
# File 'lib/protocol/http/headers.rb', line 65

def freeze
	return if frozen?
	
	# Ensure @indexed is generated:
	self.to_h
	
	@fields.freeze
	@indexed.freeze
	
	super
end

#include?(key) ⇒ Boolean

Returns:

  • (Boolean)


85
86
87
# File 'lib/protocol/http/headers.rb', line 85

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

#inspectObject



215
216
217
# File 'lib/protocol/http/headers.rb', line 215

def inspect
	"#<#{self.class} #{@fields.inspect}>"
end

#merge(headers) ⇒ Object



118
119
120
# File 'lib/protocol/http/headers.rb', line 118

def merge(headers)
	self.dup.merge!(headers)
end

#merge!(headers) ⇒ Object



110
111
112
113
114
115
116
# File 'lib/protocol/http/headers.rb', line 110

def merge!(headers)
	headers.each do |key, value|
		self[key] = value
	end
	
	return self
end

#to_hObject

A hash table of ‘policy.map(values)`



207
208
209
210
211
212
213
# File 'lib/protocol/http/headers.rb', line 207

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