class Protocol::HTTP::Headers

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

Constants

Multiple
POLICY
Split
TRAILER

Attributes

fields[R]

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

Public Class Methods

[](headers) click to toggle source

Construct an instance from a headers Array or Hash. No-op if already an instance of `Headers`. If the underlying array is frozen, it will be duped. @return [Headers] an instance of headers.

# File lib/protocol/http/headers.rb, line 44
def self.[] headers
        if headers.nil?
                return self.new
        end
        
        if headers.is_a?(self)
                if headers.frozen?
                        return headers.dup
                else
                        return headers
                end
        end
        
        fields = headers.to_a
        
        if fields.frozen?
                fields = fields.dup
        end
        
        return self.new(fields)
end
new(fields = [], indexed = nil) click to toggle source
# File lib/protocol/http/headers.rb, line 66
def initialize(fields = [], indexed = nil)
        @fields = fields
        @indexed = indexed
        
        # Marks where trailer start in the @fields array.
        @tail = nil
end

Public Instance Methods

==(other) click to toggle source
# File lib/protocol/http/headers.rb, line 309
def == other
        case other
        when Hash
                to_h == other
        when Headers
                @fields == other.fields
        else
                @fields == other
        end
end
[](key) click to toggle source
# File lib/protocol/http/headers.rb, line 292
def [] key
        to_h[key]
end
[]=(key, value) click to toggle source

Append the value to the given key. Some values can be appended multiple times, others can only be set once. @param key [String] The header key. @param value The header value.

# File lib/protocol/http/headers.rb, line 205
def []= key, value
        if @indexed
                merge_into(@indexed, key.downcase, value)
        end
        
        @fields << [key, value]
end
add(key, value) click to toggle source

Add the specified header key value pair.

@param key [String] the header key. @param value [String] the header value to assign.

# File lib/protocol/http/headers.rb, line 177
def add(key, value)
        self[key] = value
end
clear() click to toggle source
# File lib/protocol/http/headers.rb, line 81
def clear
        @fields.clear
        @indexed = nil
        @tail = nil
end
delete(key) click to toggle source

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

# File lib/protocol/http/headers.rb, line 255
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 = 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
each(&block) click to toggle source
# File lib/protocol/http/headers.rb, line 147
def each(&block)
        @fields.each(&block)
end
empty?() click to toggle source
# File lib/protocol/http/headers.rb, line 143
def empty?
        @fields.empty?
end
extract(keys) click to toggle source
# File lib/protocol/http/headers.rb, line 159
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
flatten() click to toggle source
# File lib/protocol/http/headers.rb, line 97
def flatten
        self.dup.flatten!
end
flatten!() click to toggle source

Flatten trailer into the headers.

# File lib/protocol/http/headers.rb, line 88
def flatten!
        if @tail
                self.delete(TRAILER)
                @tail = nil
        end
        
        return self
end
freeze() click to toggle source
Calls superclass method
# File lib/protocol/http/headers.rb, line 131
def freeze
        return if frozen?
        
        # Ensure @indexed is generated:
        self.to_h
        
        @fields.freeze
        @indexed.freeze
        
        super
end
include?(key) click to toggle source
# File lib/protocol/http/headers.rb, line 151
def include? key
        self[key] != nil
end
initialize_dup(other) click to toggle source
Calls superclass method
# File lib/protocol/http/headers.rb, line 74
def initialize_dup(other)
        super
        
        @fields = @fields.dup
        @indexed = @indexed.dup
end
inspect() click to toggle source
# File lib/protocol/http/headers.rb, line 305
def inspect
        "#<#{self.class} #{@fields.inspect}>"
end
keys() click to toggle source
# File lib/protocol/http/headers.rb, line 155
def keys
        self.to_h.keys
end
merge(headers) click to toggle source
# File lib/protocol/http/headers.rb, line 198
def merge(headers)
        self.dup.merge!(headers)
end
merge!(headers) click to toggle source
# File lib/protocol/http/headers.rb, line 190
def merge!(headers)
        headers.each do |key, value|
                self[key] = value
        end
        
        return self
end
set(key, value) click to toggle source

Set the specified header key to the specified value, replacing any existing header keys with the same name. @param key [String] the header key to replace. @param value [String] the header value to assign.

# File lib/protocol/http/headers.rb, line 184
def set(key, value)
        # TODO This could be a bit more efficient:
        self.delete(key)
        self.add(key, value)
end
to_h() click to toggle source

A hash table of `{key, policy.map(values)}`

# File lib/protocol/http/headers.rb, line 297
def to_h
        @indexed ||= @fields.inject({}) do |hash, (key, value)|
                merge_into(hash, key.downcase, value)
                
                hash
        end
end
trailer(&block) click to toggle source

Enumerate all headers in the trailer, if there are any.

# File lib/protocol/http/headers.rb, line 123
def trailer(&block)
        return to_enum(:trailer) unless block_given?
        
        if @tail
                @fields.drop(@tail).each(&block)
        end
end
trailer!(&block) click to toggle source

Record the current headers, and prepare to receive trailer.

# File lib/protocol/http/headers.rb, line 110
def trailer!(&block)
        return nil unless self.include?(TRAILER)
        
        @tail ||= @fields.size
        
        return to_enum(:trailer!) unless block_given?
        
        if @tail
                @fields.drop(@tail).each(&block)
        end
end
trailer?() click to toggle source

@return the trailer if there are any.

# File lib/protocol/http/headers.rb, line 105
def trailer?
        @tail != nil
end

Protected Instance Methods

merge_into(hash, key, value) click to toggle source
# File lib/protocol/http/headers.rb, line 279
          def merge_into(hash, key, value)
        if policy = POLICY[key]
                if current_value = hash[key]
                        current_value << value
                else
                        hash[key] = policy.new(value)
                end
        else
                # We can't merge these, we only expose the last one set.
                hash[key] = value
        end
end