httparty 0.13.1 → 0.13.2

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of httparty might be problematic. Click here for more details.

Files changed (43) hide show
  1. checksums.yaml +4 -4
  2. data/Guardfile +3 -3
  3. data/History +74 -11
  4. data/README.md +4 -1
  5. data/Rakefile +1 -2
  6. data/bin/httparty +4 -4
  7. data/examples/README.md +64 -0
  8. data/examples/aaws.rb +3 -3
  9. data/examples/basic.rb +5 -5
  10. data/examples/crack.rb +1 -1
  11. data/examples/delicious.rb +5 -5
  12. data/examples/headers_and_user_agents.rb +1 -1
  13. data/examples/logging.rb +38 -0
  14. data/examples/rubyurl.rb +1 -1
  15. data/examples/stackexchange.rb +1 -1
  16. data/examples/tripit_sign_in.rb +5 -5
  17. data/examples/twitter.rb +5 -5
  18. data/examples/whoismyrep.rb +1 -1
  19. data/features/steps/httparty_steps.rb +2 -2
  20. data/httparty.gemspec +2 -0
  21. data/lib/httparty.rb +35 -17
  22. data/lib/httparty/connection_adapter.rb +4 -2
  23. data/lib/httparty/cookie_hash.rb +1 -1
  24. data/lib/httparty/hash_conversions.rb +12 -12
  25. data/lib/httparty/logger/apache_logger.rb +1 -1
  26. data/lib/httparty/logger/logger.rb +1 -1
  27. data/lib/httparty/net_digest_auth.rb +4 -1
  28. data/lib/httparty/request.rb +41 -21
  29. data/lib/httparty/version.rb +1 -1
  30. data/spec/httparty/connection_adapter_spec.rb +52 -36
  31. data/spec/httparty/cookie_hash_spec.rb +8 -8
  32. data/spec/httparty/logger/apache_logger_spec.rb +29 -14
  33. data/spec/httparty/net_digest_auth_spec.rb +11 -0
  34. data/spec/httparty/parser_spec.rb +10 -10
  35. data/spec/httparty/request_spec.rb +209 -30
  36. data/spec/httparty/response_spec.rb +41 -41
  37. data/spec/httparty/ssl_spec.rb +4 -4
  38. data/spec/httparty_spec.rb +78 -59
  39. data/spec/support/ssl_test_helper.rb +6 -6
  40. data/spec/support/stub_response.rb +2 -2
  41. data/website/index.html +3 -3
  42. metadata +15 -14
  43. data/spec/spec.opts +0 -2
@@ -7,4 +7,4 @@ class Rep
7
7
  end
8
8
 
9
9
  pp Rep.get('http://whoismyrepresentative.com/getall_mems.php?zip=46544')
10
- pp Rep.get('http://whoismyrepresentative.com/getall_mems.php', :query => {:zip => 46544})
10
+ pp Rep.get('http://whoismyrepresentative.com/getall_mems.php', query: {zip: 46544})
@@ -30,7 +30,7 @@ When /I call HTTParty#get with '(.*)' and a basic_auth hash:/ do |url, auth_tabl
30
30
  h = auth_table.hashes.first
31
31
  @response_from_httparty = HTTParty.get(
32
32
  "http://#{@host_and_port}#{url}",
33
- :basic_auth => { :username => h["username"], :password => h["password"] }
33
+ basic_auth: { username: h["username"], password: h["password"] }
34
34
  )
35
35
  end
36
36
 
@@ -38,6 +38,6 @@ When /I call HTTParty#get with '(.*)' and a digest_auth hash:/ do |url, auth_tab
38
38
  h = auth_table.hashes.first
39
39
  @response_from_httparty = HTTParty.get(
40
40
  "http://#{@host_and_port}#{url}",
41
- :digest_auth => { :username => h["username"], :password => h["password"] }
41
+ digest_auth: { username: h["username"], password: h["password"] }
42
42
  )
43
43
  end
@@ -6,6 +6,7 @@ Gem::Specification.new do |s|
6
6
  s.name = "httparty"
7
7
  s.version = HTTParty::VERSION
8
8
  s.platform = Gem::Platform::RUBY
9
+ s.licenses = ['MIT']
9
10
  s.authors = ["John Nunemaker", "Sandro Turriate"]
10
11
  s.email = ["nunemaker@gmail.com"]
11
12
  s.homepage = "http://jnunemaker.github.com/httparty"
@@ -17,6 +18,7 @@ Gem::Specification.new do |s|
17
18
  s.add_dependency 'json', "~> 1.8"
18
19
  s.add_dependency 'multi_xml', ">= 0.5.2"
19
20
 
21
+ # If this line is removed, all hard partying will cease.
20
22
  s.post_install_message = "When you HTTParty, you must party hard!"
21
23
 
22
24
  s.files = `git ls-files`.split("\n")
@@ -41,13 +41,13 @@ module HTTParty
41
41
  # == Common Request Options
42
42
  # Request methods (get, post, patch, put, delete, head, options) all take a common set of options. These are:
43
43
  #
44
- # [:+body+:] Body of the request. If passed a Hash, will try to normalize it first, by default passing it to ActiveSupport::to_params. Any other kind of object will get used as-is.
44
+ # [:+body+:] Body of the request. If passed an object that responds to #to_hash, will try to normalize it first, by default passing it to ActiveSupport::to_params. Any other kind of object will get used as-is.
45
45
  # [:+http_proxyaddr+:] Address of proxy server to use.
46
46
  # [:+http_proxyport+:] Port of proxy server to use.
47
47
  # [:+http_proxyuser+:] User for proxy server authentication.
48
48
  # [:+http_proxypass+:] Password for proxy server authentication.
49
49
  # [:+limit+:] Maximum number of redirects to follow. Takes precedences over :+no_follow+.
50
- # [:+query+:] Query string, or a Hash representing it. Normalized according to the same rules as :+body+. If you specify this on a POST, you must use a Hash. See also HTTParty::ClassMethods.default_params.
50
+ # [:+query+:] Query string, or an object that responds to #to_hash representing it. Normalized according to the same rules as :+body+. If you specify this on a POST, you must use an object which responds to #to_hash. See also HTTParty::ClassMethods.default_params.
51
51
  # [:+timeout+:] Timeout for opening connection and reading data.
52
52
  # [:+local_host:] Local address to bind to before connecting.
53
53
  # [:+local_port:] Local port to bind to before connecting.
@@ -58,7 +58,7 @@ module HTTParty
58
58
  # * :+debug_output+: see HTTParty::ClassMethods.debug_output.
59
59
  # * :+digest_auth+: see HTTParty::ClassMethods.digest_auth. Only one of :+basic_auth+ and :+digest_auth+ can be used at a time; if you try using both, you'll get an ArgumentError.
60
60
  # * :+format+: see HTTParty::ClassMethods.format.
61
- # * :+headers+: see HTTParty::ClassMethods.headers. Must be a Hash.
61
+ # * :+headers+: see HTTParty::ClassMethods.headers. Must be a an object which responds to #to_hash.
62
62
  # * :+maintain_method_across_redirects+: see HTTParty::ClassMethods.maintain_method_across_redirects.
63
63
  # * :+no_follow+: see HTTParty::ClassMethods.no_follow.
64
64
  # * :+parser+: see HTTParty::ClassMethods.parser.
@@ -116,7 +116,7 @@ module HTTParty
116
116
  # basic_auth 'username', 'password'
117
117
  # end
118
118
  def basic_auth(u, p)
119
- default_options[:basic_auth] = {:username => u, :password => p}
119
+ default_options[:basic_auth] = {username: u, password: p}
120
120
  end
121
121
 
122
122
  # Allows setting digest authentication username and password.
@@ -126,14 +126,14 @@ module HTTParty
126
126
  # digest_auth 'username', 'password'
127
127
  # end
128
128
  def digest_auth(u, p)
129
- default_options[:digest_auth] = {:username => u, :password => p}
129
+ default_options[:digest_auth] = {username: u, password: p}
130
130
  end
131
131
 
132
132
  # Do not send rails style query strings.
133
133
  # Specically, don't use bracket notation when sending an array
134
134
  #
135
135
  # For a query:
136
- # get '/', :query => {:selected_ids => [1,2,3]}
136
+ # get '/', query: {selected_ids: [1,2,3]}
137
137
  #
138
138
  # The default query string looks like this:
139
139
  # /?selected_ids[]=1&selected_ids[]=2&selected_ids[]=3
@@ -156,10 +156,10 @@ module HTTParty
156
156
  #
157
157
  # class Foo
158
158
  # include HTTParty
159
- # default_params :api_key => 'secret', :another => 'foo'
159
+ # default_params api_key: 'secret', another: 'foo'
160
160
  # end
161
161
  def default_params(h={})
162
- raise ArgumentError, 'Default params must be a hash' unless h.is_a?(Hash)
162
+ raise ArgumentError, 'Default params must an object which respond to #to_hash' unless h.respond_to?(:to_hash)
163
163
  default_options[:default_params] ||= {}
164
164
  default_options[:default_params].merge!(h)
165
165
  end
@@ -216,13 +216,13 @@ module HTTParty
216
216
  # headers 'Accept' => 'text/html'
217
217
  # end
218
218
  def headers(h={})
219
- raise ArgumentError, 'Headers must be a hash' unless h.is_a?(Hash)
219
+ raise ArgumentError, 'Headers must an object which responds to #to_hash' unless h.respond_to?(:to_hash)
220
220
  default_options[:headers] ||= {}
221
- default_options[:headers].merge!(h)
221
+ default_options[:headers].merge!(h.to_hash)
222
222
  end
223
223
 
224
224
  def cookies(h={})
225
- raise ArgumentError, 'Cookies must be a hash' unless h.is_a?(Hash)
225
+ raise ArgumentError, 'Cookies must an object which respond to #to_hash' unless h.respond_to?(:to_hash)
226
226
  default_cookies.add_cookies(h)
227
227
  end
228
228
 
@@ -294,6 +294,24 @@ module HTTParty
294
294
  default_options[:maintain_method_across_redirects] = value
295
295
  end
296
296
 
297
+ # Declare that you wish to resend the full HTTP request across redirects,
298
+ # even on redirects that should logically become GET requests.
299
+ # A 303 redirect in HTTP signifies that the redirected url should normally
300
+ # retrieved using a GET request, for instance, it is the output of a previous
301
+ # POST. maintain_method_across_redirects respects this behavior, but you
302
+ # can force HTTParty to resend_on_redirect even on 303 responses.
303
+ #
304
+ # @example
305
+ # class Foo
306
+ # include HTTParty
307
+ # base_uri 'http://google.com'
308
+ # resend_on_redirect
309
+ # end
310
+
311
+ def resend_on_redirect(value = true)
312
+ default_options[:resend_on_redirect] = value
313
+ end
314
+
297
315
  # Allows setting a PEM file to be used
298
316
  #
299
317
  # class Foo
@@ -320,7 +338,7 @@ module HTTParty
320
338
  # Helpful for overriding the default rails normalization of Array queries.
321
339
  #
322
340
  # For a query:
323
- # get '/', :query => {:selected_ids => [1,2,3]}
341
+ # get '/', query: {selected_ids: [1,2,3]}
324
342
  #
325
343
  # The default query string normalizer returns:
326
344
  # /?selected_ids[]=1&selected_ids[]=2&selected_ids[]=3
@@ -428,7 +446,7 @@ module HTTParty
428
446
  # @example provide optional configuration for your connection_adapter
429
447
  # class Foo
430
448
  # include HTTParty
431
- # connection_adapter Proc.new {|uri, options| ... }, {:foo => :bar}
449
+ # connection_adapter Proc.new {|uri, options| ... }, {foo: :bar}
432
450
  # end
433
451
  #
434
452
  # @see HTTParty::ConnectionAdapter
@@ -452,7 +470,7 @@ module HTTParty
452
470
  #
453
471
  # # Simple get with full url and query parameters
454
472
  # # ie: http://foo.com/resource.json?limit=10
455
- # Foo.get('http://foo.com/resource.json', :query => {:limit => 10})
473
+ # Foo.get('http://foo.com/resource.json', query: {limit: 10})
456
474
  def get(path, options={}, &block)
457
475
  perform_request Net::HTTP::Get, path, options, &block
458
476
  end
@@ -464,11 +482,11 @@ module HTTParty
464
482
  # end
465
483
  #
466
484
  # # Simple post with full url and setting the body
467
- # Foo.post('http://foo.com/resources', :body => {:bar => 'baz'})
485
+ # Foo.post('http://foo.com/resources', body: {bar: 'baz'})
468
486
  #
469
487
  # # Simple post with full url using :query option,
470
488
  # # which gets set as form data on the request.
471
- # Foo.post('http://foo.com/resources', :query => {:bar => 'baz'})
489
+ # Foo.post('http://foo.com/resources', query: {bar: 'baz'})
472
490
  def post(path, options={}, &block)
473
491
  perform_request Net::HTTP::Post, path, options, &block
474
492
  end
@@ -515,7 +533,7 @@ module HTTParty
515
533
  private
516
534
 
517
535
  def perform_request(http_method, path, options, &block) #:nodoc:
518
- options = default_options.merge(options)
536
+ options = ModuleInheritableAttributes.hash_deep_dup(default_options).merge(options)
519
537
  process_headers(options)
520
538
  process_cookies(options)
521
539
  Request.new(http_method, path, options).perform(&block)
@@ -45,6 +45,7 @@ module HTTParty
45
45
  # * :+debug_output+: see HTTParty::ClassMethods.debug_output.
46
46
  # * :+pem+: contains pem data. see HTTParty::ClassMethods.pem.
47
47
  # * :+verify+: verify the server’s certificate against the ca certificate.
48
+ # * :+verify_peer+: set to false to turn off server verification but still send client certificate
48
49
  # * :+ssl_ca_file+: see HTTParty::ClassMethods.ssl_ca_file.
49
50
  # * :+ssl_ca_path+: see HTTParty::ClassMethods.ssl_ca_path.
50
51
  # * :+connection_adapter_options+: contains the hash you passed to HTTParty.connection_adapter when you configured your connection adapter
@@ -152,10 +153,11 @@ module HTTParty
152
153
  end
153
154
 
154
155
  # Client certificate authentication
156
+ # Note: options[:pem] must contain the content of a PEM file having the private key appended
155
157
  if options[:pem]
156
158
  http.cert = OpenSSL::X509::Certificate.new(options[:pem])
157
159
  http.key = OpenSSL::PKey::RSA.new(options[:pem], options[:pem_password])
158
- http.verify_mode = OpenSSL::SSL::VERIFY_PEER
160
+ http.verify_mode = options[:verify_peer] == false ? OpenSSL::SSL::VERIFY_NONE : OpenSSL::SSL::VERIFY_PEER
159
161
  end
160
162
 
161
163
  # PKCS12 client certificate authentication
@@ -163,7 +165,7 @@ module HTTParty
163
165
  p12 = OpenSSL::PKCS12.new(options[:p12], options[:p12_password])
164
166
  http.cert = p12.certificate
165
167
  http.key = p12.key
166
- http.verify_mode = OpenSSL::SSL::VERIFY_PEER
168
+ http.verify_mode = options[:verify_peer] == false ? OpenSSL::SSL::VERIFY_NONE : OpenSSL::SSL::VERIFY_PEER
167
169
  end
168
170
 
169
171
  # SSL certificate authority file and/or directory
@@ -1,6 +1,6 @@
1
1
  class HTTParty::CookieHash < Hash #:nodoc:
2
2
 
3
- CLIENT_COOKIES = %w{path expires domain path secure HTTPOnly}
3
+ CLIENT_COOKIES = %w{path expires domain path secure httponly}
4
4
 
5
5
  def add_cookies(value)
6
6
  case value
@@ -3,16 +3,16 @@ module HTTParty
3
3
  # @return <String> This hash as a query string
4
4
  #
5
5
  # @example
6
- # { :name => "Bob",
7
- # :address => {
8
- # :street => '111 Ruby Ave.',
9
- # :city => 'Ruby Central',
10
- # :phones => ['111-111-1111', '222-222-2222']
6
+ # { name: "Bob",
7
+ # address: {
8
+ # street: '111 Ruby Ave.',
9
+ # city: 'Ruby Central',
10
+ # phones: ['111-111-1111', '222-222-2222']
11
11
  # }
12
12
  # }.to_params
13
13
  # #=> "name=Bob&address[city]=Ruby Central&address[phones][]=111-111-1111&address[phones][]=222-222-2222&address[street]=111 Ruby Ave."
14
14
  def self.to_params(hash)
15
- params = hash.map { |k,v| normalize_param(k,v) }.join
15
+ params = hash.to_hash.map { |k,v| normalize_param(k,v) }.join
16
16
  params.chop! # trailing &
17
17
  params
18
18
  end
@@ -27,18 +27,18 @@ module HTTParty
27
27
  param = ''
28
28
  stack = []
29
29
 
30
- if value.is_a?(Array)
31
- param << value.map { |element| normalize_param("#{key}[]", element) }.join
32
- elsif value.is_a?(Hash)
33
- stack << [key,value]
30
+ if value.respond_to?(:to_ary)
31
+ param << value.to_ary.map { |element| normalize_param("#{key}[]", element) }.join
32
+ elsif value.respond_to?(:to_hash)
33
+ stack << [key,value.to_hash]
34
34
  else
35
35
  param << "#{key}=#{URI.encode(value.to_s, Regexp.new("[^#{URI::PATTERN::UNRESERVED}]"))}&"
36
36
  end
37
37
 
38
38
  stack.each do |parent, hash|
39
39
  hash.each do |k, v|
40
- if v.is_a?(Hash)
41
- stack << ["#{parent}[#{k}]", v]
40
+ if v.respond_to?(:to_hash)
41
+ stack << ["#{parent}[#{k}]", v.to_hash]
42
42
  else
43
43
  param << normalize_param("#{parent}[#{k}]", v)
44
44
  end
@@ -14,7 +14,7 @@ module HTTParty
14
14
  current_time = Time.now.strftime("%Y-%m-%d %H:%M:%S %z")
15
15
  http_method = request.http_method.name.split("::").last.upcase
16
16
  path = request.path.to_s
17
- content_length = response['Content-Length']
17
+ content_length = response.respond_to?(:headers) ? response.headers['Content-Length'] : response['Content-Length']
18
18
  @logger.send @level, "[#{TAG_NAME}] [#{current_time}] #{response.code} \"#{http_method} #{path}\" #{content_length || "-"} "
19
19
  end
20
20
  end
@@ -5,7 +5,7 @@ module HTTParty
5
5
  module Logger
6
6
  def self.build(logger, level, formatter)
7
7
  level ||= :info
8
- format ||= :apache
8
+ formatter ||= :apache
9
9
 
10
10
  case formatter
11
11
  when :curl
@@ -44,7 +44,10 @@ module Net
44
44
  private
45
45
 
46
46
  def parse(response_header)
47
- response_header['www-authenticate'] =~ /Digest (.*)/
47
+ header = response_header['www-authenticate']
48
+ .gsub(/qop=(auth(?:-int)?)/, %Q(qop="\\1"))
49
+
50
+ header =~ /Digest (.*)/
48
51
  params = {}
49
52
  $1.gsub(/(\w+)="(.*?)"/) { params[$1] = $2 }
50
53
  params
@@ -18,8 +18,8 @@ module HTTParty
18
18
  Array(query).sort_by { |a| a[0].to_s }.map do |key, value|
19
19
  if value.nil?
20
20
  key.to_s
21
- elsif value.is_a?(Array)
22
- value.map {|v| "#{key}=#{URI.encode(v.to_s, Regexp.new("[^#{URI::PATTERN::UNRESERVED}]"))}"}
21
+ elsif value.respond_to?(:to_ary)
22
+ value.to_ary.map {|v| "#{key}=#{URI.encode(v.to_s, Regexp.new("[^#{URI::PATTERN::UNRESERVED}]"))}"}
23
23
  else
24
24
  HashConversions.to_params(key => value)
25
25
  end
@@ -33,13 +33,14 @@ module HTTParty
33
33
  self.http_method = http_method
34
34
  self.path = path
35
35
  self.options = {
36
- :limit => o.delete(:no_follow) ? 1 : 5,
37
- :assume_utf16_is_big_endian => true,
38
- :default_params => {},
39
- :follow_redirects => true,
40
- :parser => Parser,
41
- :connection_adapter => ConnectionAdapter
36
+ limit: o.delete(:no_follow) ? 1 : 5,
37
+ assume_utf16_is_big_endian: true,
38
+ default_params: {},
39
+ follow_redirects: true,
40
+ parser: Parser,
41
+ connection_adapter: ConnectionAdapter
42
42
  }.merge(o)
43
+ set_basic_auth_from_uri
43
44
  end
44
45
 
45
46
  def path=(uri)
@@ -55,6 +56,10 @@ module HTTParty
55
56
  end
56
57
 
57
58
  def uri
59
+ if redirect && path.relative? && path.path[0] != "/"
60
+ path.path = @last_uri.path.gsub(/[^\/]+$/, "") + path.path
61
+ end
62
+
58
63
  new_uri = path.relative? ? URI.parse("#{base_uri}#{path}") : path.clone
59
64
 
60
65
  # avoid double query string on redirects [#12]
@@ -118,11 +123,11 @@ module HTTParty
118
123
  end
119
124
 
120
125
  def body
121
- options[:body].is_a?(Hash) ? normalize_query(options[:body]) : options[:body]
126
+ options[:body].respond_to?(:to_hash) ? normalize_query(options[:body]) : options[:body]
122
127
  end
123
128
 
124
129
  def credentials
125
- options[:basic_auth] || options[:digest_auth]
130
+ (options[:basic_auth] || options[:digest_auth]).to_hash
126
131
  end
127
132
 
128
133
  def username
@@ -149,14 +154,14 @@ module HTTParty
149
154
  @raw_request = http_method.new(request_uri(uri))
150
155
  @raw_request.body = body if body
151
156
  @raw_request.body_stream = options[:body_stream] if options[:body_stream]
152
- @raw_request.initialize_http_header(options[:headers])
157
+ @raw_request.initialize_http_header(options[:headers].to_hash) if options[:headers].respond_to?(:to_hash)
153
158
  @raw_request.basic_auth(username, password) if options[:basic_auth]
154
159
  setup_digest_auth if options[:digest_auth]
155
160
  end
156
161
 
157
162
  def setup_digest_auth
158
163
  auth_request = http_method.new(uri.request_uri)
159
- auth_request.initialize_http_header(options[:headers])
164
+ auth_request.initialize_http_header(options[:headers].to_hash) if options[:headers].respond_to?(:to_hash)
160
165
  res = http.request(auth_request)
161
166
 
162
167
  if res['www-authenticate'] != nil && res['www-authenticate'].length > 0
@@ -168,8 +173,8 @@ module HTTParty
168
173
  query_string_parts = []
169
174
  query_string_parts << uri.query unless uri.query.nil?
170
175
 
171
- if options[:query].is_a?(Hash)
172
- query_string_parts << normalize_query(options[:default_params].merge(options[:query]))
176
+ if options[:query].respond_to?(:to_hash)
177
+ query_string_parts << normalize_query(options[:default_params].merge(options[:query].to_hash))
173
178
  else
174
179
  query_string_parts << normalize_query(options[:default_params]) unless options[:default_params].empty?
175
180
  query_string_parts << options[:query] unless options[:query].nil?
@@ -257,13 +262,21 @@ module HTTParty
257
262
  end
258
263
  self.path = last_response['location']
259
264
  self.redirect = true
260
- self.http_method = Net::HTTP::Get unless options[:maintain_method_across_redirects]
265
+ if last_response.class == Net::HTTPSeeOther
266
+ unless options[:maintain_method_across_redirects] and options[:resend_on_redirect]
267
+ self.http_method = Net::HTTP::Get
268
+ end
269
+ else
270
+ unless options[:maintain_method_across_redirects]
271
+ self.http_method = Net::HTTP::Get
272
+ end
273
+ end
261
274
  capture_cookies(last_response)
262
275
  perform(&block)
263
276
  else
264
277
  body = body || last_response.body
265
278
  body = encode_body(body)
266
- Response.new(self, last_response, lambda { parse_response(body) }, :body => body)
279
+ Response.new(self, last_response, lambda { parse_response(body) }, body: body)
267
280
  end
268
281
  end
269
282
 
@@ -299,7 +312,7 @@ module HTTParty
299
312
  def capture_cookies(response)
300
313
  return unless response['Set-Cookie']
301
314
  cookies_hash = HTTParty::CookieHash.new()
302
- cookies_hash.add_cookies(options[:headers]['Cookie']) if options[:headers] && options[:headers]['Cookie']
315
+ cookies_hash.add_cookies(options[:headers].to_hash['Cookie']) if options[:headers] && options[:headers].to_hash['Cookie']
303
316
  response.get_fields('Set-Cookie').each { |cookie| cookies_hash.add_cookies(cookie) }
304
317
  options[:headers] ||= {}
305
318
  options[:headers]['Cookie'] = cookies_hash.to_cookie_string
@@ -317,15 +330,22 @@ module HTTParty
317
330
  def validate
318
331
  raise HTTParty::RedirectionTooDeep.new(last_response), 'HTTP redirects too deep' if options[:limit].to_i <= 0
319
332
  raise ArgumentError, 'only get, post, patch, put, delete, head, and options methods are supported' unless SupportedHTTPMethods.include?(http_method)
320
- raise ArgumentError, ':headers must be a hash' if options[:headers] && !options[:headers].is_a?(Hash)
333
+ raise ArgumentError, ':headers must be a hash' if options[:headers] && !options[:headers].respond_to?(:to_hash)
321
334
  raise ArgumentError, 'only one authentication method, :basic_auth or :digest_auth may be used at a time' if options[:basic_auth] && options[:digest_auth]
322
- raise ArgumentError, ':basic_auth must be a hash' if options[:basic_auth] && !options[:basic_auth].is_a?(Hash)
323
- raise ArgumentError, ':digest_auth must be a hash' if options[:digest_auth] && !options[:digest_auth].is_a?(Hash)
324
- raise ArgumentError, ':query must be hash if using HTTP Post' if post? && !options[:query].nil? && !options[:query].is_a?(Hash)
335
+ raise ArgumentError, ':basic_auth must be a hash' if options[:basic_auth] && !options[:basic_auth].respond_to?(:to_hash)
336
+ raise ArgumentError, ':digest_auth must be a hash' if options[:digest_auth] && !options[:digest_auth].respond_to?(:to_hash)
337
+ raise ArgumentError, ':query must be hash if using HTTP Post' if post? && !options[:query].nil? && !options[:query].respond_to?(:to_hash)
325
338
  end
326
339
 
327
340
  def post?
328
341
  Net::HTTP::Post == http_method
329
342
  end
343
+
344
+ def set_basic_auth_from_uri
345
+ if path.userinfo
346
+ username, password = path.userinfo.split(':')
347
+ options[:basic_auth] = {:username => username, :password => password}
348
+ end
349
+ end
330
350
  end
331
351
  end