class HTTP::Headers

HTTP Headers container.

Constants

ACCEPT

Content-Types that are acceptable for the response.

ACCEPT_ENCODING

Content-codings that are acceptable in the response.

AGE

The age the object has been in a proxy cache in seconds.

AUTHORIZATION

Authentication credentials for HTTP authentication.

CACHE_CONTROL

Used to specify directives that must be obeyed by all caching mechanisms along the request-response chain.

CANONICAL_NAME_RE

Matches HTTP header names when in “Canonical-Http-Format”

COMPLIANT_NAME_RE

Matches valid header field name according to RFC. @see tools.ietf.org/html/rfc7230#section-3.2

CONNECTION

Control options for the current connection and list of hop-by-hop request fields.

CONTENT_ENCODING

Indicates what additional content codings have been applied to the entity-body.

CONTENT_LENGTH

The length of the request body in octets (8-bit bytes).

CONTENT_TYPE

The MIME type of the body of the request (used with POST and PUT requests).

An HTTP cookie previously sent by the server with Set-Cookie.

DATE

The date and time that the message was sent (in “HTTP-date” format as defined by RFC 7231 Date/Time Formats).

ETAG

An identifier for a specific version of a resource, often a message digest.

EXPIRES

Gives the date/time after which the response is considered stale (in “HTTP-date” format as defined by RFC 7231).

HOST

The domain name of the server (for virtual hosting), and the TCP port number on which the server is listening. The port number may be omitted if the port is the standard port for the service requested.

IF_MODIFIED_SINCE

Allows a 304 Not Modified to be returned if content is unchanged.

IF_NONE_MATCH

Allows a 304 Not Modified to be returned if content is unchanged.

LAST_MODIFIED

The last modified date for the requested object (in “HTTP-date” format as defined by RFC 7231).

LOCATION

Used in redirection, or when a new resource has been created.

PROXY_AUTHORIZATION

Authorization credentials for connecting to a proxy.

An HTTP cookie.

TRANSFER_ENCODING

The form of encoding used to safely transfer the entity to the user. Currently defined methods are: chunked, compress, deflate, gzip, identity.

USER_AGENT

The user agent string of the user agent.

VARY

Tells downstream proxies how to match future request headers to decide whether the cached response can be used rather than requesting a fresh one from the origin server.

Public Class Methods

[](object)
Alias for: coerce
coerce(object) click to toggle source

Coerces given `object` into Headers.

@raise [Error] if object can't be coerced @param [#to_hash, to_h, to_a] object @return [Headers]

# File lib/http/headers.rb, line 203
def coerce(object)
  unless object.is_a? self
    object = case
             when object.respond_to?(:to_hash) then object.to_hash
             when object.respond_to?(:to_h)    then object.to_h
             when object.respond_to?(:to_a)    then object.to_a
             else raise Error, "Can't coerce #{object.inspect} to Headers"
             end
  end

  headers = new
  object.each { |k, v| headers.add k, v }
  headers
end
Also aliased as: []
new() click to toggle source

Class constructor.

# File lib/http/headers.rb, line 23
def initialize
  # The @pile stores each header value using a three element array:
  #  0 - the normalized header key, used for lookup
  #  1 - the header key as it will be sent with a request
  #  2 - the value
  @pile = []
end

Public Instance Methods

==(other) click to toggle source

Compares headers to another Headers or Array of key/value pairs

@return [Boolean]

# File lib/http/headers.rb, line 142
def ==(other)
  return false unless other.respond_to? :to_a

  to_a == other.to_a
end
[](name) click to toggle source

Smart version of {#get}.

@return [nil] if header was not set @return [String] if header has exactly one value @return [Array<String>] if header has more than one value

# File lib/http/headers.rb, line 92
def [](name)
  values = get(name)

  case values.count
  when 0 then nil
  when 1 then values.first
  else        values
  end
end
[]=(name, value)
Alias for: set
add(name, value) click to toggle source

Appends header.

@param [String, Symbol] name header name. When specified as a string, the

name is sent as-is. When specified as a symbol, the name is converted
to a string of capitalized words separated by a dash. Word boundaries
are determined by an underscore (`_`) or a dash (`-`).
Ex: `:content_type` is sent as `"Content-Type"`, and `"auth_key"` (string)
is sent as `"auth_key"`.

@param [Array<#to_s>, to_s] value header value(s) to be appended @return [void]

# File lib/http/headers.rb, line 60
def add(name, value)
  lookup_name = normalize_header(name.to_s)
  wire_name = case name
              when String
                name
              when Symbol
                lookup_name
              else
                raise HTTP::HeaderError, "HTTP header must be a String or Symbol: #{name.inspect}"
              end
  Array(value).each do |v|
    @pile << [
      lookup_name,
      wire_name,
      validate_value(v)
    ]
  end
end
delete(name) click to toggle source

Removes header.

@param [#to_s] name header name @return [void]

# File lib/http/headers.rb, line 45
def delete(name)
  name = normalize_header name.to_s
  @pile.delete_if { |k, _| k == name }
end
each() { |item| ... } click to toggle source

Calls the given block once for each key/value pair in headers container.

@return [Enumerator] if no block given @return [Headers] self-reference

# File lib/http/headers.rb, line 152
def each
  return to_enum(__method__) unless block_given?

  @pile.each { |item| yield(item[1..2]) }
  self
end
get(name) click to toggle source

Returns list of header values if any.

@return [Array<String>]

# File lib/http/headers.rb, line 82
def get(name)
  name = normalize_header name.to_s
  @pile.select { |k, _| k == name }.map { |_, _, v| v }
end
include?(name) click to toggle source

Tells whenever header with given `name` is set or not.

@return [Boolean]

# File lib/http/headers.rb, line 105
def include?(name)
  name = normalize_header name.to_s
  @pile.any? { |k, _| k == name }
end
initialize_copy(orig) click to toggle source

Properly clones internal key/value storage.

@api private

Calls superclass method
# File lib/http/headers.rb, line 176
def initialize_copy(orig)
  super
  @pile = @pile.map(&:dup)
end
inspect() click to toggle source

Returns human-readable representation of `self` instance.

@return [String]

# File lib/http/headers.rb, line 128
def inspect
  "#<#{self.class} #{to_h.inspect}>"
end
keys() click to toggle source

Returns list of header names.

@return [Array<String>]

# File lib/http/headers.rb, line 135
def keys
  @pile.map { |_, k, _| k }.uniq
end
merge(other) click to toggle source

Returns new instance with `other` headers merged in.

@see merge! @return [Headers]

# File lib/http/headers.rb, line 193
def merge(other)
  dup.tap { |dupped| dupped.merge! other }
end
merge!(other) click to toggle source

Merges `other` headers into `self`.

@see merge @return [void]

# File lib/http/headers.rb, line 185
def merge!(other)
  self.class.coerce(other).to_h.each { |name, values| set name, values }
end
set(name, value) click to toggle source

Sets header.

@param (see add) @return [void]

# File lib/http/headers.rb, line 35
def set(name, value)
  delete(name)
  add(name, value)
end
Also aliased as: []=
to_a() click to toggle source

Returns headers key/value pairs.

@return [Array<[String, String]>]

# File lib/http/headers.rb, line 121
def to_a
  @pile.map { |item| item[1..2] }
end
to_h() click to toggle source

Returns Rack-compatible headers Hash

@return [Hash]

# File lib/http/headers.rb, line 113
def to_h
  keys.to_h { |k| [k, self[k]] }
end
Also aliased as: to_hash
to_hash()
Alias for: to_h

Private Instance Methods

normalize_header(name) click to toggle source

Transforms `name` to canonical HTTP header capitalization

@param [String] name @raise [HeaderError] if normalized name does not

match {HEADER_NAME_RE}

@return [String] canonical HTTP header name

# File lib/http/headers.rb, line 228
def normalize_header(name)
  return name if name =~ CANONICAL_NAME_RE

  normalized = name.split(/[\-_]/).each(&:capitalize!).join("-")

  return normalized if normalized =~ COMPLIANT_NAME_RE

  raise HeaderError, "Invalid HTTP header field name: #{name.inspect}"
end
validate_value(value) click to toggle source

Ensures there is no new line character in the header value

@param [String] value @raise [HeaderError] if value includes new line character @return [String] stringified header value

# File lib/http/headers.rb, line 243
def validate_value(value)
  v = value.to_s
  return v unless v.include?("\n")

  raise HeaderError, "Invalid HTTP header field value: #{v.inspect}"
end