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