Class: HTTP::Protocol::Headers

Inherits:
Object
  • Object
show all
Defined in:
lib/http/protocol/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.



67
68
69
70
# File 'lib/http/protocol/headers.rb', line 67

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

Instance Attribute Details

#fieldsObject (readonly)

Returns the value of attribute fields.



72
73
74
# File 'lib/http/protocol/headers.rb', line 72

def fields
  @fields
end

Class Method Details

.[](hash) ⇒ Object



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

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

Instance Method Details

#==(other) ⇒ Object



191
192
193
194
195
196
197
# File 'lib/http/protocol/headers.rb', line 191

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

#[](key) ⇒ Object



177
178
179
180
181
# File 'lib/http/protocol/headers.rb', line 177

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

#[]=(key, value) ⇒ Object



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

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



121
122
123
# File 'lib/http/protocol/headers.rb', line 121

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.



95
96
97
98
99
100
101
102
103
104
105
106
107
# File 'lib/http/protocol/headers.rb', line 95

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



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

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

#empty?Boolean

Returns:

  • (Boolean)


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

def empty?
  @fields.empty?
end

#freezeObject



74
75
76
77
78
79
80
# File 'lib/http/protocol/headers.rb', line 74

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

#include?(key) ⇒ Boolean

Returns:

  • (Boolean)


90
91
92
# File 'lib/http/protocol/headers.rb', line 90

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

#merge(hash, key, value) ⇒ Object



162
163
164
165
166
167
168
169
170
171
172
173
174
175
# File 'lib/http/protocol/headers.rb', line 162

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



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

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



183
184
185
186
187
188
189
# File 'lib/http/protocol/headers.rb', line 183

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