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' => Split,
  
  # 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.



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

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.



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

def fields
  @fields
end

Class Method Details

.[](hash) ⇒ Object



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

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

Instance Method Details

#==(other) ⇒ Object



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

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

#[](key) ⇒ Object



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

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.



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

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

#add(key, value) ⇒ Object



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

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

#clearObject



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

def clear
  @fields.clear
  @indexed = nil
end

#delete(key) ⇒ Object

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



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

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



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

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

#each(&block) ⇒ Object



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

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

#empty?Boolean

Returns:

  • (Boolean)


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

def empty?
  @fields.empty?
end

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



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

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



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

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

#include?(key) ⇒ Boolean

Returns:

  • (Boolean)


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

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

#inspectObject



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

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

#merge(headers) ⇒ Object



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

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

#merge!(headers) ⇒ Object



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

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

#to_hObject

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



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

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