]> git.donarmstrong.com Git - dsa-puppet.git/blob - 3rdparty/modules/aviator/feature/faraday/utils.rb
try again, with puppetforge modules, correctly included now
[dsa-puppet.git] / 3rdparty / modules / aviator / feature / faraday / utils.rb
1 require 'thread'
2 Faraday.require_libs 'parameters'
3
4 module Faraday
5   module Utils
6     extend self
7
8     # Adapted from Rack::Utils::HeaderHash
9     class Headers < ::Hash
10       def self.from(value)
11         new(value)
12       end
13
14       def initialize(hash = nil)
15         super()
16         @names = {}
17         self.update(hash || {})
18       end
19
20       # need to synchronize concurrent writes to the shared KeyMap
21       keymap_mutex = Mutex.new
22
23       # symbol -> string mapper + cache
24       KeyMap = Hash.new do |map, key|
25         value = if key.respond_to?(:to_str)
26           key
27         else
28           key.to_s.split('_').            # :user_agent => %w(user agent)
29             each { |w| w.capitalize! }.   # => %w(User Agent)
30             join('-')                     # => "User-Agent"
31         end
32         keymap_mutex.synchronize { map[key] = value }
33       end
34       KeyMap[:etag] = "ETag"
35
36       def [](k)
37         k = KeyMap[k]
38         super(k) || super(@names[k.downcase])
39       end
40
41       def []=(k, v)
42         k = KeyMap[k]
43         k = (@names[k.downcase] ||= k)
44         # join multiple values with a comma
45         v = v.to_ary.join(', ') if v.respond_to? :to_ary
46         super(k, v)
47       end
48
49       def fetch(k, *args, &block)
50         k = KeyMap[k]
51         key = @names.fetch(k.downcase, k)
52         super(key, *args, &block)
53       end
54
55       def delete(k)
56         k = KeyMap[k]
57         if k = @names[k.downcase]
58           @names.delete k.downcase
59           super(k)
60         end
61       end
62
63       def include?(k)
64         @names.include? k.downcase
65       end
66
67       alias_method :has_key?, :include?
68       alias_method :member?, :include?
69       alias_method :key?, :include?
70
71       def merge!(other)
72         other.each { |k, v| self[k] = v }
73         self
74       end
75       alias_method :update, :merge!
76
77       def merge(other)
78         hash = dup
79         hash.merge! other
80       end
81
82       def replace(other)
83         clear
84         self.update other
85         self
86       end
87
88       def to_hash() ::Hash.new.update(self) end
89
90       def parse(header_string)
91         return unless header_string && !header_string.empty?
92         header_string.split(/\r\n/).
93           tap  { |a| a.shift if a.first.index('HTTP/') == 0 }. # drop the HTTP status line
94           map  { |h| h.split(/:\s+/, 2) }.reject { |p| p[0].nil? }. # split key and value, ignore blank lines
95           each { |key, value|
96             # join multiple values with a comma
97             if self[key]
98               self[key] << ', ' << value
99             else
100               self[key] = value
101             end
102           }
103       end
104     end
105
106     # hash with stringified keys
107     class ParamsHash < Hash
108       def [](key)
109         super(convert_key(key))
110       end
111
112       def []=(key, value)
113         super(convert_key(key), value)
114       end
115
116       def delete(key)
117         super(convert_key(key))
118       end
119
120       def include?(key)
121         super(convert_key(key))
122       end
123
124       alias_method :has_key?, :include?
125       alias_method :member?, :include?
126       alias_method :key?, :include?
127
128       def update(params)
129         params.each do |key, value|
130           self[key] = value
131         end
132         self
133       end
134       alias_method :merge!, :update
135
136       def merge(params)
137         dup.update(params)
138       end
139
140       def replace(other)
141         clear
142         update(other)
143       end
144
145       def merge_query(query, encoder = nil)
146         if query && !query.empty?
147           update((encoder || Utils.default_params_encoder).decode(query))
148         end
149         self
150       end
151
152       def to_query(encoder = nil)
153         (encoder || Utils.default_params_encoder).encode(self)
154       end
155
156       private
157
158       def convert_key(key)
159         key.to_s
160       end
161     end
162
163     def build_query(params)
164       FlatParamsEncoder.encode(params)
165     end
166
167     def build_nested_query(params)
168       NestedParamsEncoder.encode(params)
169     end
170
171     ESCAPE_RE = /[^a-zA-Z0-9 .~_-]/
172
173     def escape(s)
174       s.to_s.gsub(ESCAPE_RE) {|match|
175         '%' + match.unpack('H2' * match.bytesize).join('%').upcase
176       }.tr(' ', '+')
177     end
178
179     def unescape(s) CGI.unescape s.to_s end
180
181     DEFAULT_SEP = /[&;] */n
182
183     # Adapted from Rack
184     def parse_query(query)
185       FlatParamsEncoder.decode(query)
186     end
187
188     def parse_nested_query(query)
189       NestedParamsEncoder.decode(query)
190     end
191
192     def default_params_encoder
193       @default_params_encoder ||= NestedParamsEncoder
194     end
195
196     class << self
197       attr_writer :default_params_encoder
198     end
199
200     # Stolen from Rack
201     def normalize_params(params, name, v = nil)
202       name =~ %r(\A[\[\]]*([^\[\]]+)\]*)
203       k = $1 || ''
204       after = $' || ''
205
206       return if k.empty?
207
208       if after == ""
209         if params[k]
210           params[k] = Array[params[k]] unless params[k].kind_of?(Array)
211           params[k] << v
212         else
213           params[k] = v
214         end
215       elsif after == "[]"
216         params[k] ||= []
217         raise TypeError, "expected Array (got #{params[k].class.name}) for param `#{k}'" unless params[k].is_a?(Array)
218         params[k] << v
219       elsif after =~ %r(^\[\]\[([^\[\]]+)\]$) || after =~ %r(^\[\](.+)$)
220         child_key = $1
221         params[k] ||= []
222         raise TypeError, "expected Array (got #{params[k].class.name}) for param `#{k}'" unless params[k].is_a?(Array)
223         if params[k].last.is_a?(Hash) && !params[k].last.key?(child_key)
224           normalize_params(params[k].last, child_key, v)
225         else
226           params[k] << normalize_params({}, child_key, v)
227         end
228       else
229         params[k] ||= {}
230         raise TypeError, "expected Hash (got #{params[k].class.name}) for param `#{k}'" unless params[k].is_a?(Hash)
231         params[k] = normalize_params(params[k], after, v)
232       end
233
234       return params
235     end
236
237     # Normalize URI() behavior across Ruby versions
238     #
239     # url - A String or URI.
240     #
241     # Returns a parsed URI.
242     def URI(url)
243       if url.respond_to?(:host)
244         url
245       elsif url.respond_to?(:to_str)
246         default_uri_parser.call(url)
247       else
248         raise ArgumentError, "bad argument (expected URI object or URI string)"
249       end
250     end
251
252     def default_uri_parser
253       @default_uri_parser ||= begin
254         require 'uri'
255         Kernel.method(:URI)
256       end
257     end
258
259     def default_uri_parser=(parser)
260       @default_uri_parser = if parser.respond_to?(:call) || parser.nil?
261         parser
262       else
263         parser.method(:parse)
264       end
265     end
266
267     # Receives a String or URI and returns just the path with the query string sorted.
268     def normalize_path(url)
269       url = URI(url)
270       (url.path.start_with?('/') ? url.path : '/' + url.path) +
271       (url.query ? "?#{sort_query_params(url.query)}" : "")
272     end
273
274     # Recursive hash update
275     def deep_merge!(target, hash)
276       hash.each do |key, value|
277         if Hash === value and Hash === target[key]
278           target[key] = deep_merge(target[key], value)
279         else
280           target[key] = value
281         end
282       end
283       target
284     end
285
286     # Recursive hash merge
287     def deep_merge(source, hash)
288       deep_merge!(source.dup, hash)
289     end
290
291     protected
292
293     def sort_query_params(query)
294       query.split('&').sort.join('&')
295     end
296   end
297 end