class Faraday::Utils::Headers

A case-insensitive Hash that preserves the original case of a header when set.

Adapted from Rack::Utils::HeaderHash

Constants

KeyMap

symbol -> string mapper + cache

Public Class Methods

Calls superclass method
# File lib/faraday/utils/headers.rb, line 14
def self.allocate
  new_self = super
  new_self.initialize_names
  new_self
end
# File lib/faraday/utils/headers.rb, line 10
def self.from(value)
  new(value)
end
Calls superclass method
# File lib/faraday/utils/headers.rb, line 20
def initialize(hash = nil)
  super()
  @names = {}
  update(hash || {})
end

Public Instance Methods

Calls superclass method
# File lib/faraday/utils/headers.rb, line 50
def [](key)
  key = KeyMap[key]
  super || super(@names[key.downcase])
end
Calls superclass method
# File lib/faraday/utils/headers.rb, line 55
def []=(key, val)
  key = KeyMap[key]
  key = (@names[key.downcase] ||= key)
  # join multiple values with a comma
  val = val.to_ary.join(', ') if val.respond_to?(:to_ary)
  super
end
Also aliased as: store

Join multiple values with a comma.

# File lib/faraday/utils/headers.rb, line 174
def add_parsed(key, value)
  if key?(key)
    self[key] = self[key].to_s
    self[key] << ', ' << value
  else
    self[key] = value
  end
end
Calls superclass method
# File lib/faraday/utils/headers.rb, line 80
def clear
  @names.clear
  super
end
# File lib/faraday/utils/headers.rb, line 86
def compact! = rebuilding_names { super }
def rehash = rebuilding_names { super }

# Without a block these return an enumerator that calls back into the
# method once iterated, so the index only needs rebuilding in that call.
def delete_if = block_given? ? rebuilding_names { super } : super
def keep_if = block_given? ? rebuilding_names { super } : super
def reject! = block_given? ? rebuilding_names { super } : super
def select! = block_given? ? rebuilding_names { super } : super
alias filter! select!

# A mapping hash is a valid alternative to a block.
def transform_keys!(*args, &block)
  args.empty? && !block ? super : rebuilding_names { super }
end

def dig(key, *rest)
  key = KeyMap[key]
  key = @names.fetch(key.downcase, key)
  super
end

def include?(key)
  @names.include? key.downcase
end

alias has_key? include?
alias member? include?
alias key? include?

def merge!(other)
  other.each { |k, v| self[k] = v }
  self
end

alias update merge!

def merge(other)
  hash = dup
  hash.merge! other
end

def replace(other)
  clear
  @names.clear
  update other
  self
end

def to_hash
  {}.update(self)
end

def parse(header_string)
  return unless header_string && !header_string.empty?

  headers = header_string.split("\r\n")

  # Find the last set of response headers.
  start_index = headers.rindex { |x| x.start_with?('HTTP/') } || 0
  last_response = headers.slice(start_index, headers.size)

  last_response
    .tap { |a| a.shift if a.first.start_with?('HTTP/') }
    .map { |h| h.split(/:\s*/, 2) } # split key and value
    .reject { |p| p[0].nil? } # ignore blank lines
    .each { |key, value| add_parsed(key, value) }
end

protected

attr_reader :names

private

# Runs the block, then rebuilds the name index even if the block raised
# or exited early, as the underlying Hash may already be partially mutated.
def rebuilding_names
  yield
ensure
  rebuild_names
end

def rebuild_names
  @names = each_key.to_h { |key| [KeyMap[key].downcase, key] }
end

# Join multiple values with a comma.
def add_parsed(key, value)
  if key?(key)
    self[key] = self[key].to_s
    self[key] << ', ' << value
  else
    self[key] = value
  end
end
    
Calls superclass method
# File lib/faraday/utils/headers.rb, line 71
def delete(key)
  key = KeyMap[key]
  key = @names[key.downcase]
  return unless key

  @names.delete key.downcase
  super
end

Without a block these return an enumerator that calls back into the method once iterated, so the index only needs rebuilding in that call.

Calls superclass method
# File lib/faraday/utils/headers.rb, line 91
    def delete_if = block_given? ? rebuilding_names { super } : super
    def keep_if = block_given? ? rebuilding_names { super } : super
    def reject! = block_given? ? rebuilding_names { super } : super
    def select! = block_given? ? rebuilding_names { super } : super
    alias filter! select!

    # A mapping hash is a valid alternative to a block.
    def transform_keys!(*args, &block)
      args.empty? && !block ? super : rebuilding_names { super }
    end

    def dig(key, *rest)
      key = KeyMap[key]
      key = @names.fetch(key.downcase, key)
      super
    end

    def include?(key)
      @names.include? key.downcase
    end

    alias has_key? include?
    alias member? include?
    alias key? include?

    def merge!(other)
      other.each { |k, v| self[k] = v }
      self
    end

    alias update merge!

    def merge(other)
      hash = dup
      hash.merge! other
    end

    def replace(other)
      clear
      @names.clear
      update other
      self
    end

    def to_hash
      {}.update(self)
    end

    def parse(header_string)
      return unless header_string && !header_string.empty?

      headers = header_string.split("\r\n")

      # Find the last set of response headers.
      start_index = headers.rindex { |x| x.start_with?('HTTP/') } || 0
      last_response = headers.slice(start_index, headers.size)

      last_response
        .tap { |a| a.shift if a.first.start_with?('HTTP/') }
        .map { |h| h.split(/:\s*/, 2) } # split key and value
        .reject { |p| p[0].nil? } # ignore blank lines
        .each { |key, value| add_parsed(key, value) }
    end

    protected

    attr_reader :names

    private

    # Runs the block, then rebuilds the name index even if the block raised
    # or exited early, as the underlying Hash may already be partially mutated.
    def rebuilding_names
      yield
    ensure
      rebuild_names
    end

    def rebuild_names
      @names = each_key.to_h { |key| [KeyMap[key].downcase, key] }
    end

    # Join multiple values with a comma.
    def add_parsed(key, value)
      if key?(key)
        self[key] = self[key].to_s
        self[key] << ', ' << value
      else
        self[key] = value
      end
    end
  end
end
Calls superclass method
# File lib/faraday/utils/headers.rb, line 102
def dig(key, *rest)
  key = KeyMap[key]
  key = @names.fetch(key.downcase, key)
  super
end
Calls superclass method
# File lib/faraday/utils/headers.rb, line 65
def fetch(key, ...)
  key = KeyMap[key]
  key = @names.fetch(key.downcase, key)
  super
end
# File lib/faraday/utils/headers.rb, line 108
def include?(key)
  @names.include? key.downcase
end

on dup/clone, we need to duplicate @names hash

Calls superclass method
# File lib/faraday/utils/headers.rb, line 31
def initialize_copy(other)
  super
  @names = other.names.dup
end
# File lib/faraday/utils/headers.rb, line 26
def initialize_names
  @names = {}
end
Calls superclass method
# File lib/faraday/utils/headers.rb, line 92
      def keep_if = block_given? ? rebuilding_names { super } : super
      def reject! = block_given? ? rebuilding_names { super } : super
      def select! = block_given? ? rebuilding_names { super } : super
      alias filter! select!

      # A mapping hash is a valid alternative to a block.
      def transform_keys!(*args, &block)
        args.empty? && !block ? super : rebuilding_names { super }
      end

      def dig(key, *rest)
        key = KeyMap[key]
        key = @names.fetch(key.downcase, key)
        super
      end

      def include?(key)
        @names.include? key.downcase
      end

      alias has_key? include?
      alias member? include?
      alias key? include?

      def merge!(other)
        other.each { |k, v| self[k] = v }
        self
      end

      alias update merge!

      def merge(other)
        hash = dup
        hash.merge! other
      end

      def replace(other)
        clear
        @names.clear
        update other
        self
      end

      def to_hash
        {}.update(self)
      end

      def parse(header_string)
        return unless header_string && !header_string.empty?

        headers = header_string.split("\r\n")

        # Find the last set of response headers.
        start_index = headers.rindex { |x| x.start_with?('HTTP/') } || 0
        last_response = headers.slice(start_index, headers.size)

        last_response
          .tap { |a| a.shift if a.first.start_with?('HTTP/') }
          .map { |h| h.split(/:\s*/, 2) } # split key and value
          .reject { |p| p[0].nil? } # ignore blank lines
          .each { |key, value| add_parsed(key, value) }
      end

      protected

      attr_reader :names

      private

      # Runs the block, then rebuilds the name index even if the block raised
      # or exited early, as the underlying Hash may already be partially mutated.
      def rebuilding_names
        yield
      ensure
        rebuild_names
      end

      def rebuild_names
        @names = each_key.to_h { |key| [KeyMap[key].downcase, key] }
      end

      # Join multiple values with a comma.
      def add_parsed(key, value)
        if key?(key)
          self[key] = self[key].to_s
          self[key] << ', ' << value
        else
          self[key] = value
        end
      end
    end
  end
end
# File lib/faraday/utils/headers.rb, line 123
def merge(other)
  hash = dup
  hash.merge! other
end
# File lib/faraday/utils/headers.rb, line 116
def merge!(other)
  other.each { |k, v| self[k] = v }
  self
end
# File lib/faraday/utils/headers.rb, line 139
def parse(header_string)
  return unless header_string && !header_string.empty?

  headers = header_string.split("\r\n")

  # Find the last set of response headers.
  start_index = headers.rindex { |x| x.start_with?('HTTP/') } || 0
  last_response = headers.slice(start_index, headers.size)

  last_response
    .tap { |a| a.shift if a.first.start_with?('HTTP/') }
    .map { |h| h.split(/:\s*/, 2) } # split key and value
    .reject { |p| p[0].nil? } # ignore blank lines
    .each { |key, value| add_parsed(key, value) }
end
# File lib/faraday/utils/headers.rb, line 169
def rebuild_names
  @names = each_key.to_h { |key| [KeyMap[key].downcase, key] }
end

Runs the block, then rebuilds the name index even if the block raised or exited early, as the underlying Hash may already be partially mutated.

# File lib/faraday/utils/headers.rb, line 163
def rebuilding_names
  yield
ensure
  rebuild_names
end
# File lib/faraday/utils/headers.rb, line 87
  def rehash = rebuilding_names { super }

  # Without a block these return an enumerator that calls back into the
  # method once iterated, so the index only needs rebuilding in that call.
  def delete_if = block_given? ? rebuilding_names { super } : super
  def keep_if = block_given? ? rebuilding_names { super } : super
  def reject! = block_given? ? rebuilding_names { super } : super
  def select! = block_given? ? rebuilding_names { super } : super
  alias filter! select!

  # A mapping hash is a valid alternative to a block.
  def transform_keys!(*args, &block)
    args.empty? && !block ? super : rebuilding_names { super }
  end

  def dig(key, *rest)
    key = KeyMap[key]
    key = @names.fetch(key.downcase, key)
    super
  end

  def include?(key)
    @names.include? key.downcase
  end

  alias has_key? include?
  alias member? include?
  alias key? include?

  def merge!(other)
    other.each { |k, v| self[k] = v }
    self
  end

  alias update merge!

  def merge(other)
    hash = dup
    hash.merge! other
  end

  def replace(other)
    clear
    @names.clear
    update other
    self
  end

  def to_hash
    {}.update(self)
  end

  def parse(header_string)
    return unless header_string && !header_string.empty?

    headers = header_string.split("\r\n")

    # Find the last set of response headers.
    start_index = headers.rindex { |x| x.start_with?('HTTP/') } || 0
    last_response = headers.slice(start_index, headers.size)

    last_response
      .tap { |a| a.shift if a.first.start_with?('HTTP/') }
      .map { |h| h.split(/:\s*/, 2) } # split key and value
      .reject { |p| p[0].nil? } # ignore blank lines
      .each { |key, value| add_parsed(key, value) }
  end

  protected

  attr_reader :names

  private

  # Runs the block, then rebuilds the name index even if the block raised
  # or exited early, as the underlying Hash may already be partially mutated.
  def rebuilding_names
    yield
  ensure
    rebuild_names
  end

  def rebuild_names
    @names = each_key.to_h { |key| [KeyMap[key].downcase, key] }
  end

  # Join multiple values with a comma.
  def add_parsed(key, value)
    if key?(key)
      self[key] = self[key].to_s
      self[key] << ', ' << value
    else
      self[key] = value
    end
  end
end
Calls superclass method
# File lib/faraday/utils/headers.rb, line 93
    def reject! = block_given? ? rebuilding_names { super } : super
    def select! = block_given? ? rebuilding_names { super } : super
    alias filter! select!

    # A mapping hash is a valid alternative to a block.
    def transform_keys!(*args, &block)
      args.empty? && !block ? super : rebuilding_names { super }
    end

    def dig(key, *rest)
      key = KeyMap[key]
      key = @names.fetch(key.downcase, key)
      super
    end

    def include?(key)
      @names.include? key.downcase
    end

    alias has_key? include?
    alias member? include?
    alias key? include?

    def merge!(other)
      other.each { |k, v| self[k] = v }
      self
    end

    alias update merge!

    def merge(other)
      hash = dup
      hash.merge! other
    end

    def replace(other)
      clear
      @names.clear
      update other
      self
    end

    def to_hash
      {}.update(self)
    end

    def parse(header_string)
      return unless header_string && !header_string.empty?

      headers = header_string.split("\r\n")

      # Find the last set of response headers.
      start_index = headers.rindex { |x| x.start_with?('HTTP/') } || 0
      last_response = headers.slice(start_index, headers.size)

      last_response
        .tap { |a| a.shift if a.first.start_with?('HTTP/') }
        .map { |h| h.split(/:\s*/, 2) } # split key and value
        .reject { |p| p[0].nil? } # ignore blank lines
        .each { |key, value| add_parsed(key, value) }
    end

    protected

    attr_reader :names

    private

    # Runs the block, then rebuilds the name index even if the block raised
    # or exited early, as the underlying Hash may already be partially mutated.
    def rebuilding_names
      yield
    ensure
      rebuild_names
    end

    def rebuild_names
      @names = each_key.to_h { |key| [KeyMap[key].downcase, key] }
    end

    # Join multiple values with a comma.
    def add_parsed(key, value)
      if key?(key)
        self[key] = self[key].to_s
        self[key] << ', ' << value
      else
        self[key] = value
      end
    end
  end
end
# File lib/faraday/utils/headers.rb, line 128
def replace(other)
  clear
  @names.clear
  update other
  self
end
Calls superclass method
# File lib/faraday/utils/headers.rb, line 94
  def select! = block_given? ? rebuilding_names { super } : super
  alias filter! select!

  # A mapping hash is a valid alternative to a block.
  def transform_keys!(*args, &block)
    args.empty? && !block ? super : rebuilding_names { super }
  end

  def dig(key, *rest)
    key = KeyMap[key]
    key = @names.fetch(key.downcase, key)
    super
  end

  def include?(key)
    @names.include? key.downcase
  end

  alias has_key? include?
  alias member? include?
  alias key? include?

  def merge!(other)
    other.each { |k, v| self[k] = v }
    self
  end

  alias update merge!

  def merge(other)
    hash = dup
    hash.merge! other
  end

  def replace(other)
    clear
    @names.clear
    update other
    self
  end

  def to_hash
    {}.update(self)
  end

  def parse(header_string)
    return unless header_string && !header_string.empty?

    headers = header_string.split("\r\n")

    # Find the last set of response headers.
    start_index = headers.rindex { |x| x.start_with?('HTTP/') } || 0
    last_response = headers.slice(start_index, headers.size)

    last_response
      .tap { |a| a.shift if a.first.start_with?('HTTP/') }
      .map { |h| h.split(/:\s*/, 2) } # split key and value
      .reject { |p| p[0].nil? } # ignore blank lines
      .each { |key, value| add_parsed(key, value) }
  end

  protected

  attr_reader :names

  private

  # Runs the block, then rebuilds the name index even if the block raised
  # or exited early, as the underlying Hash may already be partially mutated.
  def rebuilding_names
    yield
  ensure
    rebuild_names
  end

  def rebuild_names
    @names = each_key.to_h { |key| [KeyMap[key].downcase, key] }
  end

  # Join multiple values with a comma.
  def add_parsed(key, value)
    if key?(key)
      self[key] = self[key].to_s
      self[key] << ', ' << value
    else
      self[key] = value
    end
  end
end
# File lib/faraday/utils/headers.rb, line 85
def shift = rebuilding_names { super }
def compact! = rebuilding_names { super }
def rehash = rebuilding_names { super }

# Without a block these return an enumerator that calls back into the
# method once iterated, so the index only needs rebuilding in that call.
def delete_if = block_given? ? rebuilding_names { super } : super
def keep_if = block_given? ? rebuilding_names { super } : super
def reject! = block_given? ? rebuilding_names { super } : super
def select! = block_given? ? rebuilding_names { super } : super
alias filter! select!

# A mapping hash is a valid alternative to a block.
def transform_keys!(*args, &block)
  args.empty? && !block ? super : rebuilding_names { super }
end

def dig(key, *rest)
  key = KeyMap[key]
  key = @names.fetch(key.downcase, key)
  super
end

def include?(key)
  @names.include? key.downcase
end

alias has_key? include?
alias member? include?
alias key? include?

def merge!(other)
  other.each { |k, v| self[k] = v }
  self
end

alias update merge!

def merge(other)
  hash = dup
  hash.merge! other
end

def replace(other)
  clear
  @names.clear
  update other
  self
end

def to_hash
  {}.update(self)
end

def parse(header_string)
  return unless header_string && !header_string.empty?

  headers = header_string.split("\r\n")

  # Find the last set of response headers.
  start_index = headers.rindex { |x| x.start_with?('HTTP/') } || 0
  last_response = headers.slice(start_index, headers.size)

  last_response
    .tap { |a| a.shift if a.first.start_with?('HTTP/') }
    .map { |h| h.split(/:\s*/, 2) } # split key and value
    .reject { |p| p[0].nil? } # ignore blank lines
    .each { |key, value| add_parsed(key, value) }
end

protected

attr_reader :names

private

# Runs the block, then rebuilds the name index even if the block raised
# or exited early, as the underlying Hash may already be partially mutated.
def rebuilding_names
  yield
ensure
  rebuild_names
end

def rebuild_names
  @names = each_key.to_h { |key| [KeyMap[key].downcase, key] }
end

# Join multiple values with a comma.
def add_parsed(key, value)
  if key?(key)
    self[key] = self[key].to_s
    self[key] << ', ' << value
  else
    self[key] = value
  end
end
# File lib/faraday/utils/headers.rb, line 135
def to_hash
  {}.update(self)
end

A mapping hash is a valid alternative to a block.

Calls superclass method
# File lib/faraday/utils/headers.rb, line 98
def transform_keys!(*args, &block)
  args.empty? && !block ? super : rebuilding_names { super }
end