+++ /dev/null
-require 'thread'
-Faraday.require_libs 'parameters'
-
-module Faraday
- module Utils
- extend self
-
- # Adapted from Rack::Utils::HeaderHash
- class Headers < ::Hash
- def self.from(value)
- new(value)
- end
-
- def initialize(hash = nil)
- super()
- @names = {}
- self.update(hash || {})
- end
-
- # need to synchronize concurrent writes to the shared KeyMap
- keymap_mutex = Mutex.new
-
- # symbol -> string mapper + cache
- KeyMap = Hash.new do |map, key|
- value = if key.respond_to?(:to_str)
- key
- else
- key.to_s.split('_'). # :user_agent => %w(user agent)
- each { |w| w.capitalize! }. # => %w(User Agent)
- join('-') # => "User-Agent"
- end
- keymap_mutex.synchronize { map[key] = value }
- end
- KeyMap[:etag] = "ETag"
-
- def [](k)
- k = KeyMap[k]
- super(k) || super(@names[k.downcase])
- end
-
- def []=(k, v)
- k = KeyMap[k]
- k = (@names[k.downcase] ||= k)
- # join multiple values with a comma
- v = v.to_ary.join(', ') if v.respond_to? :to_ary
- super(k, v)
- end
-
- def fetch(k, *args, &block)
- k = KeyMap[k]
- key = @names.fetch(k.downcase, k)
- super(key, *args, &block)
- end
-
- def delete(k)
- k = KeyMap[k]
- if k = @names[k.downcase]
- @names.delete k.downcase
- super(k)
- end
- end
-
- def include?(k)
- @names.include? k.downcase
- end
-
- alias_method :has_key?, :include?
- alias_method :member?, :include?
- alias_method :key?, :include?
-
- def merge!(other)
- other.each { |k, v| self[k] = v }
- self
- end
- alias_method :update, :merge!
-
- def merge(other)
- hash = dup
- hash.merge! other
- end
-
- def replace(other)
- clear
- self.update other
- self
- end
-
- def to_hash() ::Hash.new.update(self) end
-
- def parse(header_string)
- return unless header_string && !header_string.empty?
- header_string.split(/\r\n/).
- tap { |a| a.shift if a.first.index('HTTP/') == 0 }. # drop the HTTP status line
- map { |h| h.split(/:\s+/, 2) }.reject { |p| p[0].nil? }. # split key and value, ignore blank lines
- each { |key, value|
- # join multiple values with a comma
- if self[key]
- self[key] << ', ' << value
- else
- self[key] = value
- end
- }
- end
- end
-
- # hash with stringified keys
- class ParamsHash < Hash
- def [](key)
- super(convert_key(key))
- end
-
- def []=(key, value)
- super(convert_key(key), value)
- end
-
- def delete(key)
- super(convert_key(key))
- end
-
- def include?(key)
- super(convert_key(key))
- end
-
- alias_method :has_key?, :include?
- alias_method :member?, :include?
- alias_method :key?, :include?
-
- def update(params)
- params.each do |key, value|
- self[key] = value
- end
- self
- end
- alias_method :merge!, :update
-
- def merge(params)
- dup.update(params)
- end
-
- def replace(other)
- clear
- update(other)
- end
-
- def merge_query(query, encoder = nil)
- if query && !query.empty?
- update((encoder || Utils.default_params_encoder).decode(query))
- end
- self
- end
-
- def to_query(encoder = nil)
- (encoder || Utils.default_params_encoder).encode(self)
- end
-
- private
-
- def convert_key(key)
- key.to_s
- end
- end
-
- def build_query(params)
- FlatParamsEncoder.encode(params)
- end
-
- def build_nested_query(params)
- NestedParamsEncoder.encode(params)
- end
-
- ESCAPE_RE = /[^a-zA-Z0-9 .~_-]/
-
- def escape(s)
- s.to_s.gsub(ESCAPE_RE) {|match|
- '%' + match.unpack('H2' * match.bytesize).join('%').upcase
- }.tr(' ', '+')
- end
-
- def unescape(s) CGI.unescape s.to_s end
-
- DEFAULT_SEP = /[&;] */n
-
- # Adapted from Rack
- def parse_query(query)
- FlatParamsEncoder.decode(query)
- end
-
- def parse_nested_query(query)
- NestedParamsEncoder.decode(query)
- end
-
- def default_params_encoder
- @default_params_encoder ||= NestedParamsEncoder
- end
-
- class << self
- attr_writer :default_params_encoder
- end
-
- # Stolen from Rack
- def normalize_params(params, name, v = nil)
- name =~ %r(\A[\[\]]*([^\[\]]+)\]*)
- k = $1 || ''
- after = $' || ''
-
- return if k.empty?
-
- if after == ""
- if params[k]
- params[k] = Array[params[k]] unless params[k].kind_of?(Array)
- params[k] << v
- else
- params[k] = v
- end
- elsif after == "[]"
- params[k] ||= []
- raise TypeError, "expected Array (got #{params[k].class.name}) for param `#{k}'" unless params[k].is_a?(Array)
- params[k] << v
- elsif after =~ %r(^\[\]\[([^\[\]]+)\]$) || after =~ %r(^\[\](.+)$)
- child_key = $1
- params[k] ||= []
- raise TypeError, "expected Array (got #{params[k].class.name}) for param `#{k}'" unless params[k].is_a?(Array)
- if params[k].last.is_a?(Hash) && !params[k].last.key?(child_key)
- normalize_params(params[k].last, child_key, v)
- else
- params[k] << normalize_params({}, child_key, v)
- end
- else
- params[k] ||= {}
- raise TypeError, "expected Hash (got #{params[k].class.name}) for param `#{k}'" unless params[k].is_a?(Hash)
- params[k] = normalize_params(params[k], after, v)
- end
-
- return params
- end
-
- # Normalize URI() behavior across Ruby versions
- #
- # url - A String or URI.
- #
- # Returns a parsed URI.
- def URI(url)
- if url.respond_to?(:host)
- url
- elsif url.respond_to?(:to_str)
- default_uri_parser.call(url)
- else
- raise ArgumentError, "bad argument (expected URI object or URI string)"
- end
- end
-
- def default_uri_parser
- @default_uri_parser ||= begin
- require 'uri'
- Kernel.method(:URI)
- end
- end
-
- def default_uri_parser=(parser)
- @default_uri_parser = if parser.respond_to?(:call) || parser.nil?
- parser
- else
- parser.method(:parse)
- end
- end
-
- # Receives a String or URI and returns just the path with the query string sorted.
- def normalize_path(url)
- url = URI(url)
- (url.path.start_with?('/') ? url.path : '/' + url.path) +
- (url.query ? "?#{sort_query_params(url.query)}" : "")
- end
-
- # Recursive hash update
- def deep_merge!(target, hash)
- hash.each do |key, value|
- if Hash === value and Hash === target[key]
- target[key] = deep_merge(target[key], value)
- else
- target[key] = value
- end
- end
- target
- end
-
- # Recursive hash merge
- def deep_merge(source, hash)
- deep_merge!(source.dup, hash)
- end
-
- protected
-
- def sort_query_params(query)
- query.split('&').sort.join('&')
- end
- end
-end