httparty 0.11.0 → 0.12.0

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 (39) hide show
  1. checksums.yaml +7 -0
  2. data/Gemfile +0 -1
  3. data/README.md +2 -1
  4. data/Rakefile +1 -4
  5. data/examples/aaws.rb +4 -4
  6. data/examples/crack.rb +2 -2
  7. data/examples/delicious.rb +4 -4
  8. data/examples/headers_and_user_agents.rb +1 -1
  9. data/examples/twitter.rb +4 -4
  10. data/examples/whoismyrep.rb +2 -2
  11. data/features/handles_compressed_responses.feature +8 -0
  12. data/features/handles_multiple_formats.feature +8 -0
  13. data/features/steps/httparty_response_steps.rb +8 -1
  14. data/features/steps/httparty_steps.rb +9 -1
  15. data/httparty.gemspec +3 -1
  16. data/lib/httparty.rb +30 -5
  17. data/lib/httparty/connection_adapter.rb +36 -2
  18. data/lib/httparty/cookie_hash.rb +1 -1
  19. data/lib/httparty/logger/apache_logger.rb +22 -0
  20. data/lib/httparty/logger/curl_logger.rb +48 -0
  21. data/lib/httparty/logger/logger.rb +18 -0
  22. data/lib/httparty/parser.rb +3 -8
  23. data/lib/httparty/request.rb +81 -2
  24. data/lib/httparty/response.rb +6 -1
  25. data/lib/httparty/version.rb +1 -1
  26. data/script/release +42 -0
  27. data/spec/httparty/connection_adapter_spec.rb +33 -0
  28. data/spec/httparty/cookie_hash_spec.rb +7 -0
  29. data/spec/httparty/logger/apache_logger_spec.rb +26 -0
  30. data/spec/httparty/logger/curl_logger_spec.rb +18 -0
  31. data/spec/httparty/logger/logger_spec.rb +22 -0
  32. data/spec/httparty/net_digest_auth_spec.rb +2 -2
  33. data/spec/httparty/parser_spec.rb +2 -8
  34. data/spec/httparty/request_spec.rb +90 -3
  35. data/spec/httparty/response_spec.rb +1 -1
  36. data/spec/httparty/ssl_spec.rb +18 -6
  37. data/spec/spec_helper.rb +6 -0
  38. data/spec/support/ssl_test_helper.rb +4 -4
  39. metadata +23 -25
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 88f8c122e637f99fecd417041020833f2ba2a775
4
+ data.tar.gz: 308db16b7ab96c4beb228bf72eaf85626c40298b
5
+ SHA512:
6
+ metadata.gz: ba5e4e41966cb967db3dae1988eb551721cf134f55d008e376353b482538cacda2a35294d7f52a43ddb81a137783e64ef8723962e8b5259617c2d21bc9a07f07
7
+ data.tar.gz: 7388e5ec85b6a1c5fb862c1ea11e92c1c501da28bce3a4f2af93ec0b4b535fa059a091632e5710c51c5cf3ce520e8c7f3120f95dd797cedbb84c45490fd23871
data/Gemfile CHANGED
@@ -6,7 +6,6 @@ gem 'cucumber', '~> 0.7'
6
6
  gem 'fakeweb', '~> 1.2'
7
7
  gem 'rspec', '~> 1.3'
8
8
  gem 'mongrel', '1.2.0.pre2'
9
- gem 'multi_json', '~> 1.3'
10
9
 
11
10
  group :development do
12
11
  gem 'guard'
data/README.md CHANGED
@@ -10,7 +10,8 @@ gem install httparty
10
10
 
11
11
  ## Requirements
12
12
 
13
- * multi_json and multi_xml
13
+ * Ruby 1.9.3 or higher
14
+ * multi_xml
14
15
  * You like to party!
15
16
 
16
17
  ## Examples
data/Rakefile CHANGED
@@ -1,6 +1,3 @@
1
- require 'bundler'
2
- Bundler::GemHelper.install_tasks
3
-
4
1
  require 'spec/rake/spectask'
5
2
  Spec::Rake::SpecTask.new(:spec) do |spec|
6
3
  spec.ruby_opts << '-rubygems'
@@ -12,4 +9,4 @@ end
12
9
  require 'cucumber/rake/task'
13
10
  Cucumber::Rake::Task.new(:features)
14
11
 
15
- task :default => [:spec, :features]
12
+ task :default => [:spec, :features]
@@ -11,17 +11,17 @@ module AAWS
11
11
  include HTTParty
12
12
  base_uri 'http://ecs.amazonaws.com'
13
13
  default_params :Service => 'AWSECommerceService', :Operation => 'ItemSearch', :SearchIndex => 'Books'
14
-
14
+
15
15
  def initialize(key)
16
16
  self.class.default_params :AWSAccessKeyId => key
17
17
  end
18
-
18
+
19
19
  def search(options={})
20
20
  raise ArgumentError, 'You must search for something' if options[:query].blank?
21
-
21
+
22
22
  # amazon uses nasty camelized query params
23
23
  options[:query] = options[:query].inject({}) { |h, q| h[q[0].to_s.camelize] = q[1]; h }
24
-
24
+
25
25
  # make a request and return the items (NOTE: this doesn't handle errors at this point)
26
26
  self.class.get('/onca/xml', options)['ItemSearchResponse']['Items']
27
27
  end
@@ -15,5 +15,5 @@ class Rep
15
15
  )
16
16
  end
17
17
 
18
- pp Rep.get('http://whoismyrepresentative.com/whoismyrep.php?zip=46544')
19
- pp Rep.get('http://whoismyrepresentative.com/whoismyrep.php', :query => {:zip => 46544})
18
+ pp Rep.get('http://whoismyrepresentative.com/getall_mems.php?zip=46544')
19
+ pp Rep.get('http://whoismyrepresentative.com/getall_mems.php', :query => {:zip => 46544})
@@ -6,11 +6,11 @@ config = YAML::load(File.read(File.join(ENV['HOME'], '.delicious')))
6
6
  class Delicious
7
7
  include HTTParty
8
8
  base_uri 'https://api.del.icio.us/v1'
9
-
9
+
10
10
  def initialize(u, p)
11
11
  @auth = {:username => u, :password => p}
12
12
  end
13
-
13
+
14
14
  # query params that filter the posts are:
15
15
  # tag (optional). Filter by this tag.
16
16
  # dt (optional). Filter by this date (CCYY-MM-DDThh:mm:ssZ).
@@ -20,7 +20,7 @@ class Delicious
20
20
  options.merge!({:basic_auth => @auth})
21
21
  self.class.get('/posts/get', options)
22
22
  end
23
-
23
+
24
24
  # query params that filter the posts are:
25
25
  # tag (optional). Filter by this tag.
26
26
  # count (optional). Number of items to retrieve (Default:15, Maximum:100).
@@ -34,4 +34,4 @@ delicious = Delicious.new(config['username'], config['password'])
34
34
  pp delicious.posts(:query => {:tag => 'ruby'})
35
35
  pp delicious.recent
36
36
 
37
- delicious.recent['posts']['post'].each { |post| puts post['href'] }
37
+ delicious.recent['posts']['post'].each { |post| puts post['href'] }
@@ -2,5 +2,5 @@
2
2
 
3
3
  require 'httparty'
4
4
 
5
- APPLICATION_NAME = "Httparty"
5
+ APPLICATION_NAME = "Httparty"
6
6
  response = HTTParty.get('http://example.com', :headers => {"User-Agent" => APPLICATION_NAME})
@@ -6,18 +6,18 @@ config = YAML::load(File.read(File.join(ENV['HOME'], '.twitter')))
6
6
  class Twitter
7
7
  include HTTParty
8
8
  base_uri 'twitter.com'
9
-
9
+
10
10
  def initialize(u, p)
11
11
  @auth = {:username => u, :password => p}
12
12
  end
13
-
13
+
14
14
  # which can be :friends, :user or :public
15
15
  # options[:query] can be things like since, since_id, count, etc.
16
16
  def timeline(which=:friends, options={})
17
17
  options.merge!({:basic_auth => @auth})
18
18
  self.class.get("/statuses/#{which}_timeline.json", options)
19
19
  end
20
-
20
+
21
21
  def post(text)
22
22
  options = { :query => {:status => text}, :basic_auth => @auth }
23
23
  self.class.post('/statuses/update.json', options)
@@ -28,4 +28,4 @@ twitter = Twitter.new(config['email'], config['password'])
28
28
  pp twitter.timeline
29
29
  # pp twitter.timeline(:friends, :query => {:since_id => 868482746})
30
30
  # pp twitter.timeline(:friends, :query => 'since_id=868482746')
31
- # pp twitter.post('this is a test of 0.2.0')
31
+ # pp twitter.post('this is a test of 0.2.0')
@@ -6,5 +6,5 @@ class Rep
6
6
  include HTTParty
7
7
  end
8
8
 
9
- pp Rep.get('http://whoismyrepresentative.com/whoismyrep.php?zip=46544')
10
- pp Rep.get('http://whoismyrepresentative.com/whoismyrep.php', :query => {:zip => 46544})
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})
@@ -17,3 +17,11 @@ Feature: Handles Compressed Responses
17
17
  And that service is accessed at the path '/gzip_service.html'
18
18
  When I call HTTParty#get with '/gzip_service.html'
19
19
  Then the return value should match '<h1>Some HTML</h1>'
20
+
21
+ Scenario: Supports HEAD request with gzip encoding
22
+ Given a remote gzip service
23
+ And that service is accessed at the path '/gzip_head.gz.js'
24
+ When I call HTTParty#head with '/gzip_head.gz.js'
25
+ Then it should return a response with a 200 response code
26
+ Then it should return a response with a gzip content-encoding
27
+ Then it should return a response with a blank body
@@ -32,3 +32,11 @@ Feature: Handles Multiple Formats
32
32
  Then it should return a Hash equaling:
33
33
  | key | value |
34
34
  | singer | waylon jennings |
35
+
36
+ Scenario: A Javascript remote file
37
+ Given a remote service that returns '$(function() { alert("hi"); });'
38
+ And that service is accessed at the path '/service.js'
39
+ And the response from the service has a Content-Type of 'application/javascript'
40
+ When I call HTTParty#get with '/service.js'
41
+ Then it should return a String
42
+ And the return value should match '$(function() { alert("hi"); });'
@@ -11,7 +11,6 @@ def constantize(camel_cased_word)
11
11
  constant
12
12
  end
13
13
 
14
-
15
14
  Then /it should return an? (\w+)$/ do |class_string|
16
15
  @response_from_httparty.should be_an_instance_of(class_string.class)
17
16
  end
@@ -34,6 +33,14 @@ Then /it should return a response with a (\d+) response code/ do |code|
34
33
  @response_from_httparty.code.should eql(code.to_i)
35
34
  end
36
35
 
36
+ Then /it should return a response with a (.*) content\-encoding$/ do |content_type|
37
+ @response_from_httparty.headers['content-encoding'].should eql('gzip')
38
+ end
39
+
40
+ Then /it should return a response with a blank body$/ do
41
+ @response_from_httparty.body.should be(nil)
42
+ end
43
+
37
44
  Then /it should raise (?:an|a) ([\w:]+) exception/ do |exception|
38
45
  @exception_from_httparty.should_not be_nil
39
46
  @exception_from_httparty.should be_a constantize(exception)
@@ -10,6 +10,14 @@ When /I call HTTParty#get with '(.*)'$/ do |url|
10
10
  end
11
11
  end
12
12
 
13
+ When /^I call HTTParty#head with '(.*)'$/ do |url|
14
+ begin
15
+ @response_from_httparty = HTTParty.head("http://#{@host_and_port}#{url}", @request_options)
16
+ rescue HTTParty::RedirectionTooDeep, Timeout::Error => e
17
+ @exception_from_httparty = e
18
+ end
19
+ end
20
+
13
21
  When /I call HTTParty#get with '(.*)' and a basic_auth hash:/ do |url, auth_table|
14
22
  h = auth_table.hashes.first
15
23
  @response_from_httparty = HTTParty.get(
@@ -24,4 +32,4 @@ When /I call HTTParty#get with '(.*)' and a digest_auth hash:/ do |url, auth_tab
24
32
  "http://#{@host_and_port}#{url}",
25
33
  :digest_auth => { :username => h["username"], :password => h["password"] }
26
34
  )
27
- end
35
+ end
@@ -12,7 +12,9 @@ Gem::Specification.new do |s|
12
12
  s.summary = %q{Makes http fun! Also, makes consuming restful web services dead easy.}
13
13
  s.description = %q{Makes http fun! Also, makes consuming restful web services dead easy.}
14
14
 
15
- s.add_dependency 'multi_json', "~> 1.0"
15
+ s.required_ruby_version = '>= 1.9.3'
16
+
17
+ s.add_dependency 'json', "~> 1.8"
16
18
  s.add_dependency 'multi_xml', ">= 0.5.2"
17
19
 
18
20
  s.post_install_message = "When you HTTParty, you must party hard!"
@@ -4,13 +4,14 @@ require 'net/https'
4
4
  require 'uri'
5
5
  require 'zlib'
6
6
  require 'multi_xml'
7
- require 'multi_json'
7
+ require 'json'
8
8
 
9
9
  require 'httparty/module_inheritable_attributes'
10
10
  require 'httparty/cookie_hash'
11
11
  require 'httparty/net_digest_auth'
12
12
  require 'httparty/version'
13
13
  require 'httparty/connection_adapter'
14
+ require 'httparty/logger/logger'
14
15
 
15
16
  # @see HTTParty::ClassMethods
16
17
  module HTTParty
@@ -47,6 +48,8 @@ module HTTParty
47
48
  # [:+limit+:] Maximum number of redirects to follow. Takes precedences over :+no_follow+.
48
49
  # [:+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.
49
50
  # [:+timeout+:] Timeout for opening connection and reading data.
51
+ # [:+local_host:] Local address to bind to before connecting.
52
+ # [:+local_port:] Local port to bind to before connecting.
50
53
  #
51
54
  # There are also another set of options with names corresponding to various class methods. The methods in question are those that let you set a class-wide default, and the options override the defaults on a request-by-request basis. Those options are:
52
55
  # * :+base_uri+: see HTTParty::ClassMethods.base_uri.
@@ -68,6 +71,18 @@ module HTTParty
68
71
 
69
72
  extend AllowedFormatsDeprecation
70
73
 
74
+ # Turns on logging
75
+ #
76
+ # class Foo
77
+ # include HTTParty
78
+ # logger Logger.new('http_logger'), :info, :apache
79
+ # end
80
+ def logger(logger, level=:info, format=:apache)
81
+ default_options[:logger] = logger
82
+ default_options[:log_level] = level
83
+ default_options[:log_format] = format
84
+ end
85
+
71
86
  # Allows setting http proxy information to be used
72
87
  #
73
88
  # class Foo
@@ -312,7 +327,7 @@ module HTTParty
312
327
 
313
328
  # Allows setting of SSL ciphers to use. This only works in Ruby 1.9+.
314
329
  # You can get a list of valid specific ciphers from OpenSSL::Cipher.ciphers.
315
- # You also can specify a cipher suite here, listed here at openssl.org:
330
+ # You also can specify a cipher suite here, listed here at openssl.org:
316
331
  # http://www.openssl.org/docs/apps/ciphers.html#CIPHER_SUITE_NAMES
317
332
  #
318
333
  # class Foo
@@ -323,7 +338,13 @@ module HTTParty
323
338
  default_options[:ciphers] = cipher_names
324
339
  end
325
340
 
326
- # Allows setting an OpenSSL certificate authority file
341
+ # Allows setting an OpenSSL certificate authority file. The file
342
+ # should contain one or more certificates in PEM format.
343
+ #
344
+ # Setting this option enables certificate verification. All
345
+ # certificates along a chain must be available in ssl_ca_file or
346
+ # ssl_ca_path for verification to succeed.
347
+ #
327
348
  #
328
349
  # class Foo
329
350
  # include HTTParty
@@ -333,7 +354,11 @@ module HTTParty
333
354
  default_options[:ssl_ca_file] = path
334
355
  end
335
356
 
336
- # Allows setting an OpenSSL certificate authority path (directory)
357
+ # Allows setting an OpenSSL certificate authority path (directory).
358
+ #
359
+ # Setting this option enables certificate verification. All
360
+ # certificates along a chain must be available in ssl_ca_file or
361
+ # ssl_ca_path for verification to succeed.
337
362
  #
338
363
  # class Foo
339
364
  # include HTTParty
@@ -512,7 +537,7 @@ module HTTParty
512
537
  def self.move(*args, &block)
513
538
  Basement.move(*args, &block)
514
539
  end
515
-
540
+
516
541
  def self.copy(*args, &block)
517
542
  Basement.move(*args, &block)
518
543
  end
@@ -66,7 +66,11 @@ module HTTParty
66
66
 
67
67
  def connection
68
68
  host = clean_host(uri.host)
69
- http = Net::HTTP.new(host, uri.port, options[:http_proxyaddr], options[:http_proxyport], options[:http_proxyuser], options[:http_proxypass])
69
+ if options[:http_proxyaddr]
70
+ http = Net::HTTP.new(host, uri.port, options[:http_proxyaddr], options[:http_proxyport], options[:http_proxyuser], options[:http_proxypass])
71
+ else
72
+ http = Net::HTTP.new(host, uri.port)
73
+ end
70
74
 
71
75
  http.use_ssl = ssl_implied?(uri)
72
76
 
@@ -85,6 +89,25 @@ module HTTParty
85
89
  http.ciphers = options[:ciphers]
86
90
  end
87
91
 
92
+ # Bind to a specific local address or port
93
+ #
94
+ # @see https://bugs.ruby-lang.org/issues/6617
95
+ if options[:local_host]
96
+ if RUBY_VERSION >= "2.0.0"
97
+ http.local_host = options[:local_host]
98
+ else
99
+ Kernel.warn("Warning: option :local_host requires Ruby version 2.0 or later")
100
+ end
101
+ end
102
+
103
+ if options[:local_port]
104
+ if RUBY_VERSION >= "2.0.0"
105
+ http.local_port = options[:local_port]
106
+ else
107
+ Kernel.warn("Warning: option :local_port requires Ruby version 2.0 or later")
108
+ end
109
+ end
110
+
88
111
  return http
89
112
  end
90
113
 
@@ -104,7 +127,18 @@ module HTTParty
104
127
 
105
128
  def attach_ssl_certificates(http, options)
106
129
  if http.use_ssl?
107
- http.verify_mode = OpenSSL::SSL::VERIFY_NONE
130
+ if options.fetch(:verify, true)
131
+ http.verify_mode = OpenSSL::SSL::VERIFY_PEER
132
+ if options[:cert_store]
133
+ http.cert_store = options[:cert_store]
134
+ else
135
+ # Use the default cert store by default, i.e. system ca certs
136
+ http.cert_store = OpenSSL::X509::Store.new
137
+ http.cert_store.set_default_paths
138
+ end
139
+ else
140
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE
141
+ end
108
142
 
109
143
  # Client certificate authentication
110
144
  if options[:pem]
@@ -8,7 +8,7 @@ class HTTParty::CookieHash < Hash #:nodoc:
8
8
  merge!(value)
9
9
  when String
10
10
  value.split('; ').each do |cookie|
11
- array = cookie.split('=')
11
+ array = cookie.split('=',2)
12
12
  self[array[0].to_sym] = array[1]
13
13
  end
14
14
  else
@@ -0,0 +1,22 @@
1
+ module HTTParty
2
+ module Logger
3
+ class ApacheLogger #:nodoc:
4
+ TAG_NAME = HTTParty.name
5
+
6
+ attr_accessor :level, :logger, :current_time
7
+
8
+ def initialize(logger, level)
9
+ @logger = logger
10
+ @level = level.to_sym
11
+ end
12
+
13
+ def format(request, response)
14
+ current_time = Time.now.strftime("%Y-%m-%d %H:%M:%S %z")
15
+ http_method = request.http_method.name.split("::").last.upcase
16
+ path = request.path.to_s
17
+ content_length = response['Content-Length']
18
+ @logger.send @level, "[#{TAG_NAME}] [#{current_time}] #{response.code} \"#{http_method} #{path}\" #{content_length || "-"} "
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,48 @@
1
+ module HTTParty
2
+ module Logger
3
+ class CurlLogger #:nodoc:
4
+ TAG_NAME = HTTParty.name
5
+ OUT = ">"
6
+ IN = "<"
7
+
8
+ attr_accessor :level, :logger, :current_time
9
+
10
+ def initialize(logger, level)
11
+ @logger = logger
12
+ @level = level.to_sym
13
+ end
14
+
15
+ def format(request, response)
16
+ messages = []
17
+ time = Time.now.strftime("%Y-%m-%d %H:%M:%S %z")
18
+ http_method = request.http_method.name.split("::").last.upcase
19
+ path = request.path.to_s
20
+
21
+ messages << print(time, OUT, "#{http_method} #{path}")
22
+
23
+ if request.options[:headers] && request.options[:headers].size > 0
24
+ request.options[:headers].each do |k, v|
25
+ messages << print(time, OUT, "#{k}: #{v}")
26
+ end
27
+ end
28
+
29
+ messages << print(time, OUT, request.raw_body)
30
+ messages << print(time, OUT, "")
31
+ messages << print(time, IN, "HTTP/#{response.http_version} #{response.code}")
32
+
33
+ headers = response.respond_to?(:headers) ? response.headers : response
34
+ response.each_header do |response_header|
35
+ messages << print(time, IN, "#{response_header.capitalize}: #{headers[response_header]}")
36
+ end
37
+
38
+ messages << print(time, IN, "\n#{response.body}")
39
+
40
+ @logger.send @level, messages.join("\n")
41
+ end
42
+
43
+ def print(time, direction, line)
44
+ "[#{TAG_NAME}] [#{time}] #{direction} #{line}"
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,18 @@
1
+ require 'httparty/logger/apache_logger'
2
+ require 'httparty/logger/curl_logger'
3
+
4
+ module HTTParty
5
+ module Logger
6
+ def self.build(logger, level, formatter)
7
+ level ||= :info
8
+ format ||= :apache
9
+
10
+ case formatter
11
+ when :curl
12
+ Logger::CurlLogger.new(logger, level)
13
+ else
14
+ Logger::ApacheLogger.new(logger, level)
15
+ end
16
+ end
17
+ end
18
+ end
@@ -42,8 +42,8 @@ module HTTParty
42
42
  'application/xml' => :xml,
43
43
  'application/json' => :json,
44
44
  'text/json' => :json,
45
- 'application/javascript' => :json,
46
- 'text/javascript' => :json,
45
+ 'application/javascript' => :plain,
46
+ 'text/javascript' => :plain,
47
47
  'text/html' => :html,
48
48
  'text/plain' => :plain
49
49
  }
@@ -110,12 +110,7 @@ module HTTParty
110
110
  end
111
111
 
112
112
  def json
113
- # https://github.com/sferik/rails/commit/5e62670131dfa1718eaf21ff8dd3371395a5f1cc
114
- if MultiJson.respond_to?(:adapter)
115
- MultiJson.load(body)
116
- else
117
- MultiJson.decode(body)
118
- end
113
+ JSON.load(body, nil)
119
114
  end
120
115
 
121
116
  def html
@@ -34,6 +34,7 @@ module HTTParty
34
34
  self.path = path
35
35
  self.options = {
36
36
  :limit => o.delete(:no_follow) ? 1 : 5,
37
+ :assume_utf16_is_big_endian => true,
37
38
  :default_params => {},
38
39
  :follow_redirects => true,
39
40
  :parser => Parser,
@@ -102,10 +103,14 @@ module HTTParty
102
103
  end
103
104
  end
104
105
 
105
- handle_deflation
106
+ handle_deflation unless http_method == Net::HTTP::Head
106
107
  handle_response(chunked_body, &block)
107
108
  end
108
109
 
110
+ def raw_body
111
+ @raw_request.body
112
+ end
113
+
109
114
  private
110
115
 
111
116
  def http
@@ -172,9 +177,82 @@ module HTTParty
172
177
  query_string_parts.size > 0 ? query_string_parts.join('&') : nil
173
178
  end
174
179
 
180
+ def get_charset
181
+ content_type = last_response["content-type"]
182
+ if content_type.nil?
183
+ return nil
184
+ end
185
+
186
+ if content_type =~ /;\s*charset\s*=\s*([^=,;"\s]+)/i
187
+ return $1
188
+ end
189
+
190
+ if content_type =~ /;\s*charset\s*=\s*"((\\.|[^\\"])+)"/i
191
+ return $1.gsub(/\\(.)/, '\1')
192
+ end
193
+
194
+ nil
195
+ end
196
+
197
+ def encode_with_ruby_encoding(body, charset)
198
+ begin
199
+ encoding = Encoding.find(charset)
200
+ body.force_encoding(encoding)
201
+ rescue
202
+ body
203
+ end
204
+ end
205
+
206
+ def assume_utf16_is_big_endian
207
+ options[:assume_utf16_is_big_endian]
208
+ end
209
+
210
+ def encode_utf_16(body)
211
+ if body.bytesize >= 2
212
+ if body.getbyte(0) == 0xFF && body.getbyte(1) == 0xFE
213
+ return body.force_encoding("UTF-16LE")
214
+ elsif body.getbyte(0) == 0xFE && body.getbyte(1) == 0xFF
215
+ return body.force_encoding("UTF-16BE")
216
+ end
217
+ end
218
+
219
+ if assume_utf16_is_big_endian
220
+ body.force_encoding("UTF-16BE")
221
+ else
222
+ body.force_encoding("UTF-16LE")
223
+ end
224
+
225
+ end
226
+
227
+ def _encode_body(body)
228
+ charset = get_charset
229
+
230
+ if charset.nil?
231
+ return body
232
+ end
233
+
234
+ if "utf-16".casecmp(charset) == 0
235
+ encode_utf_16(body)
236
+ else
237
+ encode_with_ruby_encoding(body, charset)
238
+ end
239
+ end
240
+
241
+ def encode_body(body)
242
+ if "".respond_to?(:encoding)
243
+ _encode_body(body)
244
+ else
245
+ body
246
+ end
247
+ end
248
+
175
249
  def handle_response(body, &block)
176
250
  if response_redirects?
177
251
  options[:limit] -= 1
252
+ if options[:logger]
253
+ logger = HTTParty::Logger.build(options[:logger], options[:log_level], options[:log_format])
254
+ logger.format(self, last_response)
255
+ end
178
256
  self.path = last_response['location']
179
257
  self.redirect = true
180
258
  self.http_method = Net::HTTP::Get unless options[:maintain_method_across_redirects]
@@ -182,6 +260,7 @@ module HTTParty
182
260
  perform(&block)
183
261
  else
184
262
  body = body || last_response.body
263
+ body = encode_body(body)
185
264
  Response.new(self, last_response, lambda { parse_response(body) }, :body => body)
186
265
  end
187
266
  end
@@ -219,7 +298,7 @@ module HTTParty
219
298
  return unless response['Set-Cookie']
220
299
  cookies_hash = HTTParty::CookieHash.new()
221
300
  cookies_hash.add_cookies(options[:headers]['Cookie']) if options[:headers] && options[:headers]['Cookie']
222
- cookies_hash.add_cookies(response['Set-Cookie'])
301
+ response.get_fields('Set-Cookie').each { |cookie| cookies_hash.add_cookies(cookie) }
223
302
  options[:headers] ||= {}
224
303
  options[:headers]['Cookie'] = cookies_hash.to_cookie_string
225
304
  end
@@ -12,6 +12,11 @@ module HTTParty
12
12
  @body = options[:body] || response.body
13
13
  @parsed_block = parsed_block
14
14
  @headers = Headers.new(response.to_hash)
15
+
16
+ if request.options[:logger]
17
+ logger = ::HTTParty::Logger.build(request.options[:logger], request.options[:log_level], request.options[:log_format])
18
+ logger.format(request, self)
19
+ end
15
20
  end
16
21
 
17
22
  def parsed_response
@@ -41,7 +46,7 @@ module HTTParty
41
46
  end
42
47
 
43
48
  # Support old multiple_choice? method from pre 2.0.0 era.
44
- if ::RUBY_VERSION >= "2.0.0"
49
+ if ::RUBY_VERSION >= "2.0.0" && ::RUBY_PLATFORM != "java"
45
50
  alias_method :multiple_choice?, :multiple_choices?
46
51
  end
47
52
 
@@ -1,3 +1,3 @@
1
1
  module HTTParty
2
- VERSION = "0.11.0"
2
+ VERSION = "0.12.0"
3
3
  end
@@ -0,0 +1,42 @@
1
+ #!/bin/sh
2
+ #/ Usage: release
3
+ #/
4
+ #/ Tag the version in the repo and push the gem.
5
+ #/
6
+
7
+ set -e
8
+ cd $(dirname "$0")/..
9
+
10
+ [ "$1" = "--help" -o "$1" = "-h" -o "$1" = "help" ] && {
11
+ grep '^#/' <"$0"| cut -c4-
12
+ exit 0
13
+ }
14
+
15
+ gem_name=httparty
16
+
17
+ # Build a new gem archive.
18
+ rm -rf $gem_name-*.gem
19
+ gem build -q $gem_name.gemspec
20
+
21
+ # Make sure we're on the master branch.
22
+ (git branch | grep -q '* master') || {
23
+ echo "Only release from the master branch."
24
+ exit 1
25
+ }
26
+
27
+ # Figure out what version we're releasing.
28
+ tag=v`ls $gem_name-*.gem | sed "s/^$gem_name-\(.*\)\.gem$/\1/"`
29
+
30
+ echo "Releasing $tag"
31
+
32
+ # Make sure we haven't released this version before.
33
+ git fetch -t origin
34
+
35
+ (git tag -l | grep -q "$tag") && {
36
+ echo "Whoops, there's already a '${tag}' tag."
37
+ exit 1
38
+ }
39
+
40
+ # Tag it and bag it.
41
+ gem push $gem_name-*.gem && git tag "$tag" &&
42
+ git push origin master && git push origin "$tag"
@@ -64,6 +64,22 @@ describe HTTParty::ConnectionAdapter do
64
64
  context "when dealing with ssl" do
65
65
  let(:uri) { URI 'https://foobar.com' }
66
66
 
67
+ context "uses the system cert_store, by default" do
68
+ let(:system_cert_store) do
69
+ system_cert_store = mock('default_cert_store')
70
+ system_cert_store.should_receive(:set_default_paths)
71
+ OpenSSL::X509::Store.should_receive(:new).and_return(system_cert_store)
72
+ system_cert_store
73
+ end
74
+ it { should use_cert_store(system_cert_store) }
75
+ end
76
+
77
+ context "should use the specified cert store, when one is given" do
78
+ let(:custom_cert_store) { mock('custom_cert_store') }
79
+ let(:options) { {:cert_store => custom_cert_store} }
80
+ it { should use_cert_store(custom_cert_store) }
81
+ end
82
+
67
83
  context "using port 443 for ssl" do
68
84
  let(:uri) { URI 'https://api.foo.com/v1:443' }
69
85
  it { should use_ssl }
@@ -176,6 +192,23 @@ describe HTTParty::ConnectionAdapter do
176
192
  end
177
193
  end
178
194
 
195
+ context 'when not providing a proxy address' do
196
+ let(:uri) { URI 'http://proxytest.com' }
197
+
198
+ it "does not pass any proxy parameters to the connection" do
199
+ http = Net::HTTP.new("proxytest.com")
200
+ Net::HTTP.should_receive(:new).once.with("proxytest.com", 80).and_return(http)
201
+ adapter.connection
202
+ end
203
+ end
204
+
205
+ context 'when providing a local bind address and port' do
206
+ let(:options) { {:local_host => "127.0.0.1", :local_port => 12345 } }
207
+
208
+ its(:local_host) { should == '127.0.0.1' }
209
+ its(:local_port) { should == 12345 }
210
+ end if RUBY_VERSION >= '2.0'
211
+
179
212
  context "when providing PEM certificates" do
180
213
  let(:pem) { :pem_contents }
181
214
  let(:options) { {:pem => pem, :pem_password => "password"} }
@@ -35,6 +35,13 @@ describe HTTParty::CookieHash do
35
35
  @cookie_hash.length.should eql(1)
36
36
  @cookie_hash[:foo].should eql("tar")
37
37
  end
38
+
39
+ it "should handle '=' within cookie value" do
40
+ @cookie_hash.add_cookies("first=one=1; second=two=2==")
41
+ @cookie_hash.keys.should include(:first, :second)
42
+ @cookie_hash[:first].should == 'one=1'
43
+ @cookie_hash[:second].should == 'two=2=='
44
+ end
38
45
  end
39
46
 
40
47
  describe 'with other class' do
@@ -0,0 +1,26 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'spec_helper'))
2
+
3
+ describe HTTParty::Logger::ApacheLogger do
4
+ describe "#format" do
5
+ it "formats a response in a style that resembles apache's access log" do
6
+ request_time = Time.new.strftime("%Y-%m-%d %H:%M:%S %z")
7
+ log_message = "[HTTParty] [#{request_time}] 302 \"GET http://my.domain.com/my_path\" - "
8
+
9
+ request_double = double(
10
+ :http_method => Net::HTTP::Get,
11
+ :path => "http://my.domain.com/my_path"
12
+ )
13
+ response_double = double(
14
+ :code => 302,
15
+ :[] => nil
16
+ )
17
+
18
+ logger_double = double
19
+ logger_double.should_receive(:info).with(log_message)
20
+
21
+ subject = described_class.new(logger_double, :info)
22
+ subject.current_time = request_time
23
+ subject.format(request_double, response_double)
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,18 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'spec_helper'))
2
+
3
+ describe HTTParty::Logger::CurlLogger do
4
+ describe "#format" do
5
+ it "formats a response in a style that resembles a -v curl" do
6
+ logger_double = double
7
+ logger_double.should_receive(:info).with(
8
+ /\[HTTParty\] \[\d{4}-\d\d-\d\d \d\d:\d\d:\d\d\ [+-]\d{4}\] > GET http:\/\/localhost/)
9
+
10
+ subject = described_class.new(logger_double, :info)
11
+
12
+ stub_http_response_with("google.html")
13
+
14
+ response = HTTParty::Request.new.perform
15
+ subject.format(response.request, response)
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,22 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'spec_helper'))
2
+
3
+ describe HTTParty::Logger do
4
+ describe ".build" do
5
+ subject { HTTParty::Logger }
6
+
7
+ it "defaults level to :info" do
8
+ logger_double = double()
9
+ subject.build(logger_double, nil, nil).level.should == :info
10
+ end
11
+
12
+ it "defaults format to :apache" do
13
+ logger_double = double()
14
+ subject.build(logger_double, nil, nil).should be_an_instance_of(HTTParty::Logger::ApacheLogger)
15
+ end
16
+
17
+ it "builds :curl style logger" do
18
+ logger_double = double()
19
+ subject.build(logger_double, nil, :curl).should be_an_instance_of(HTTParty::Logger::CurlLogger)
20
+ end
21
+ end
22
+ end
@@ -30,11 +30,11 @@ describe Net::HTTPHeader::DigestAuthenticator do
30
30
  before do
31
31
  @digest = setup_digest({
32
32
  'www-authenticate' => 'Digest realm="myhost@testrealm.com"'
33
- })
33
+ })
34
34
  end
35
35
 
36
36
  it "should not set opaque" do
37
- authorization_header.should_not include(%Q(opaque=))
37
+ authorization_header.should_not include(%Q(opaque=))
38
38
  end
39
39
  end
40
40
 
@@ -144,14 +144,8 @@ describe HTTParty::Parser do
144
144
  subject.send(:xml)
145
145
  end
146
146
 
147
- it "parses json with MultiJson" do
148
- MultiJson.should_receive(:load).with('body')
149
- subject.send(:json)
150
- end
151
-
152
- it "uses MultiJson.decode if MultiJson does not respond to adapter" do
153
- MultiJson.should_receive(:respond_to?).with(:adapter).and_return(false)
154
- MultiJson.should_receive(:decode).with('body')
147
+ it "parses json with JSON" do
148
+ JSON.should_receive(:load).with('body', nil)
155
149
  subject.send(:json)
156
150
  end
157
151
 
@@ -198,13 +198,13 @@ describe HTTParty::Request do
198
198
 
199
199
  it 'should handle text/javascript' do
200
200
  ["text/javascript", "text/javascript; charset=iso8859-1"].each do |ct|
201
- @request.send(:format_from_mimetype, ct).should == :json
201
+ @request.send(:format_from_mimetype, ct).should == :plain
202
202
  end
203
203
  end
204
204
 
205
205
  it 'should handle application/javascript' do
206
206
  ["application/javascript", "application/javascript; charset=iso8859-1"].each do |ct|
207
- @request.send(:format_from_mimetype, ct).should == :json
207
+ @request.send(:format_from_mimetype, ct).should == :plain
208
208
  end
209
209
  end
210
210
 
@@ -239,6 +239,77 @@ describe HTTParty::Request do
239
239
  @request.perform.headers.should == { "key" => ["value"] }
240
240
  end
241
241
 
242
+ if "".respond_to?(:encoding)
243
+
244
+ it "should process charset in content type properly" do
245
+ response = stub_response "Content"
246
+ response.initialize_http_header("Content-Type" => "text/plain;charset = utf-8")
247
+ resp = @request.perform
248
+ resp.body.encoding.should == Encoding.find("UTF-8")
249
+ end
250
+
251
+ it "should process charset in content type properly if it has a different case" do
252
+ response = stub_response "Content"
253
+ response.initialize_http_header("Content-Type" => "text/plain;CHARSET = utf-8")
254
+ resp = @request.perform
255
+ resp.body.encoding.should == Encoding.find("UTF-8")
256
+ end
257
+
258
+ it "should process quoted charset in content type properly" do
259
+ response = stub_response "Content"
260
+ response.initialize_http_header("Content-Type" => "text/plain;charset = \"utf-8\"")
261
+ resp = @request.perform
262
+ resp.body.encoding.should == Encoding.find("UTF-8")
263
+ end
264
+
265
+ it "should process utf-16 charset with little endian bom correctly" do
266
+ @request.options[:assume_utf16_is_big_endian] = true
267
+
268
+ response = stub_response "\xFF\xFEC\x00o\x00n\x00t\x00e\x00n\x00t\x00"
269
+ response.initialize_http_header("Content-Type" => "text/plain;charset = utf-16")
270
+ resp = @request.perform
271
+ resp.body.encoding.should == Encoding.find("UTF-16LE")
272
+ end
273
+
274
+ it "should process utf-16 charset with big endian bom correctly" do
275
+ @request.options[:assume_utf16_is_big_endian] = false
276
+
277
+ response = stub_response "\xFE\xFF\x00C\x00o\x00n\x00t\x00e\x00n\x00t"
278
+ response.initialize_http_header("Content-Type" => "text/plain;charset = utf-16")
279
+ resp = @request.perform
280
+ resp.body.encoding.should == Encoding.find("UTF-16BE")
281
+ end
282
+
283
+ it "should assume utf-16 little endian if options has been chosen" do
284
+ @request.options[:assume_utf16_is_big_endian] = false
285
+
286
+ response = stub_response "C\x00o\x00n\x00t\x00e\x00n\x00t\x00"
287
+ response.initialize_http_header("Content-Type" => "text/plain;charset = utf-16")
288
+ resp = @request.perform
289
+ resp.body.encoding.should == Encoding.find("UTF-16LE")
290
+ end
291
+
292
+
293
+ it "should perform no encoding if the charset is not available" do
294
+
295
+ response = stub_response "Content"
296
+ response.initialize_http_header("Content-Type" => "text/plain;charset = utf-lols")
297
+ resp = @request.perform
298
+ resp.body.should == "Content"
299
+ resp.body.encoding.should == "Content".encoding
300
+ end
301
+
302
+ it "should perform no encoding if the content type is specified but no charset is specified" do
303
+
304
+ response = stub_response "Content"
305
+ response.initialize_http_header("Content-Type" => "text/plain")
306
+ resp = @request.perform
307
+ resp.body.should == "Content"
308
+ resp.body.encoding.should == "Content".encoding
309
+ end
310
+ end
311
+
312
+
242
313
  describe 'with non-200 responses' do
243
314
  context "3xx responses" do
244
315
  it 'returns a valid object for 304 not modified' do
@@ -424,6 +495,16 @@ describe HTTParty::Request do
424
495
  @request.options[:headers]['Cookie'].should match(/keep=me/)
425
496
  end
426
497
 
498
+ it "should handle multiple Set-Cookie headers between redirects" do
499
+ @redirect.add_field 'set-cookie', 'foo=bar; name=value; HTTPOnly'
500
+ @redirect.add_field 'set-cookie', 'one=1; two=2; HTTPOnly'
501
+ @request.perform
502
+ @request.options[:headers]['Cookie'].should match(/foo=bar/)
503
+ @request.options[:headers]['Cookie'].should match(/name=value/)
504
+ @request.options[:headers]['Cookie'].should match(/one=1/)
505
+ @request.options[:headers]['Cookie'].should match(/two=2/)
506
+ end
507
+
427
508
  it 'should make resulting request a get request if it not already' do
428
509
  @request.http_method = Net::HTTP::Delete
429
510
  @request.perform.should == {"hash" => {"foo" => "bar"}}
@@ -436,6 +517,13 @@ describe HTTParty::Request do
436
517
  @request.perform.should == {"hash" => {"foo" => "bar"}}
437
518
  @request.http_method.should == Net::HTTP::Delete
438
519
  end
520
+
521
+ it 'should log the redirection' do
522
+ logger_double = double
523
+ logger_double.should_receive(:info).twice
524
+ @request.options[:logger] = logger_double
525
+ @request.perform
526
+ end
439
527
  end
440
528
 
441
529
  describe "infinitely" do
@@ -511,4 +599,3 @@ describe HTTParty::Request do
511
599
  end
512
600
  end
513
601
  end
514
-
@@ -198,7 +198,7 @@ describe HTTParty::Response do
198
198
  }
199
199
 
200
200
  # Ruby 2.0, new name for this response.
201
- if RUBY_VERSION >= "2.0.0"
201
+ if RUBY_VERSION >= "2.0.0" && ::RUBY_PLATFORM != "java"
202
202
  SPECIFIC_CODES[:multiple_choices?] = Net::HTTPMultipleChoices
203
203
  end
204
204
 
@@ -10,12 +10,24 @@ describe HTTParty::Request do
10
10
  FakeWeb.allow_net_connect = false
11
11
  end
12
12
 
13
- it "should work when no trusted CA list is specified" do
14
- ssl_verify_test(nil, nil, "selfsigned.crt").should == {'success' => true}
13
+ it "should fail when no trusted CA list is specified, by default" do
14
+ lambda do
15
+ ssl_verify_test(nil, nil, "selfsigned.crt")
16
+ end.should raise_error OpenSSL::SSL::SSLError
17
+ end
18
+
19
+ it "should work when no trusted CA list is specified, when the verify option is set to false" do
20
+ ssl_verify_test(nil, nil, "selfsigned.crt", :verify => false).should == {'success' => true}
21
+ end
22
+
23
+ it "should fail when no trusted CA list is specified, with a bogus hostname, by default" do
24
+ lambda do
25
+ ssl_verify_test(nil, nil, "bogushost.crt")
26
+ end.should raise_error OpenSSL::SSL::SSLError
15
27
  end
16
28
 
17
- it "should work when no trusted CA list is specified, even with a bogus hostname" do
18
- ssl_verify_test(nil, nil, "bogushost.crt").should == {'success' => true}
29
+ it "should work when no trusted CA list is specified, even with a bogus hostname, when the verify option is set to true" do
30
+ ssl_verify_test(nil, nil, "bogushost.crt", :verify => false).should == {'success' => true}
19
31
  end
20
32
 
21
33
  it "should work when using ssl_ca_file with a self-signed CA" do
@@ -27,10 +39,10 @@ describe HTTParty::Request do
27
39
  end
28
40
 
29
41
  it "should work when using ssl_ca_path with a certificate authority" do
30
- http = Net::HTTP.new('www.google.com', 443, nil, nil, nil, nil)
42
+ http = Net::HTTP.new('www.google.com', 443)
31
43
  response = stub(Net::HTTPResponse, :[] => '', :body => '', :to_hash => {})
32
44
  http.stub(:request).and_return(response)
33
- Net::HTTP.should_receive(:new).with('www.google.com', 443, nil, nil, nil, nil).and_return(http)
45
+ Net::HTTP.should_receive(:new).with('www.google.com', 443).and_return(http)
34
46
  http.should_receive(:ca_path=).with('/foo/bar')
35
47
  HTTParty.get('https://www.google.com', :ssl_ca_path => '/foo/bar')
36
48
  end
@@ -28,3 +28,9 @@ Spec::Matchers.define :use_ssl do
28
28
  connection.use_ssl?
29
29
  end
30
30
  end
31
+
32
+ Spec::Matchers.define :use_cert_store do |cert_store|
33
+ match do |connection|
34
+ connection.cert_store == cert_store
35
+ end
36
+ end
@@ -2,11 +2,11 @@ require 'pathname'
2
2
 
3
3
  module HTTParty
4
4
  module SSLTestHelper
5
- def ssl_verify_test(mode, ca_basename, server_cert_filename)
5
+ def ssl_verify_test(mode, ca_basename, server_cert_filename, options = {})
6
6
  options = {
7
7
  :format => :json,
8
8
  :timeout => 30,
9
- }
9
+ }.merge(options)
10
10
 
11
11
  if mode
12
12
  ca_path = File.expand_path("../../fixtures/ssl/generated/#{ca_basename}", __FILE__)
@@ -24,9 +24,9 @@ module HTTParty
24
24
  if mode
25
25
  ca_path = File.expand_path("../../fixtures/ssl/generated/#{ca_basename}", __FILE__)
26
26
  raise ArgumentError.new("#{ca_path} does not exist") unless File.exist?(ca_path)
27
- return HTTParty.get("https://localhost:#{test_server.port}/", :format => :json, :timeout => 30, mode => ca_path)
27
+ return HTTParty.get("https://localhost:#{test_server.port}/", options)
28
28
  else
29
- return HTTParty.get("https://localhost:#{test_server.port}/", :format => :json, :timeout => 30)
29
+ return HTTParty.get("https://localhost:#{test_server.port}/", options)
30
30
  end
31
31
  ensure
32
32
  test_server.stop if test_server
metadata CHANGED
@@ -1,8 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: httparty
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.11.0
5
- prerelease:
4
+ version: 0.12.0
6
5
  platform: ruby
7
6
  authors:
8
7
  - John Nunemaker
@@ -10,38 +9,34 @@ authors:
10
9
  autorequire:
11
10
  bindir: bin
12
11
  cert_chain: []
13
- date: 2013-04-10 00:00:00.000000000 Z
12
+ date: 2013-10-10 00:00:00.000000000 Z
14
13
  dependencies:
15
14
  - !ruby/object:Gem::Dependency
16
- name: multi_json
15
+ name: json
17
16
  requirement: !ruby/object:Gem::Requirement
18
- none: false
19
17
  requirements:
20
18
  - - ~>
21
19
  - !ruby/object:Gem::Version
22
- version: '1.0'
20
+ version: '1.8'
23
21
  type: :runtime
24
22
  prerelease: false
25
23
  version_requirements: !ruby/object:Gem::Requirement
26
- none: false
27
24
  requirements:
28
25
  - - ~>
29
26
  - !ruby/object:Gem::Version
30
- version: '1.0'
27
+ version: '1.8'
31
28
  - !ruby/object:Gem::Dependency
32
29
  name: multi_xml
33
30
  requirement: !ruby/object:Gem::Requirement
34
- none: false
35
31
  requirements:
36
- - - ! '>='
32
+ - - '>='
37
33
  - !ruby/object:Gem::Version
38
34
  version: 0.5.2
39
35
  type: :runtime
40
36
  prerelease: false
41
37
  version_requirements: !ruby/object:Gem::Requirement
42
- none: false
43
38
  requirements:
44
- - - ! '>='
39
+ - - '>='
45
40
  - !ruby/object:Gem::Version
46
41
  version: 0.5.2
47
42
  description: Makes http fun! Also, makes consuming restful web services dead easy.
@@ -94,6 +89,9 @@ files:
94
89
  - lib/httparty/core_extensions.rb
95
90
  - lib/httparty/exceptions.rb
96
91
  - lib/httparty/hash_conversions.rb
92
+ - lib/httparty/logger/apache_logger.rb
93
+ - lib/httparty/logger/curl_logger.rb
94
+ - lib/httparty/logger/logger.rb
97
95
  - lib/httparty/module_inheritable_attributes.rb
98
96
  - lib/httparty/net_digest_auth.rb
99
97
  - lib/httparty/parser.rb
@@ -101,6 +99,7 @@ files:
101
99
  - lib/httparty/response.rb
102
100
  - lib/httparty/response/headers.rb
103
101
  - lib/httparty/version.rb
102
+ - script/release
104
103
  - spec/fixtures/delicious.xml
105
104
  - spec/fixtures/empty.xml
106
105
  - spec/fixtures/google.html
@@ -118,6 +117,9 @@ files:
118
117
  - spec/fixtures/undefined_method_add_node_for_nil.xml
119
118
  - spec/httparty/connection_adapter_spec.rb
120
119
  - spec/httparty/cookie_hash_spec.rb
120
+ - spec/httparty/logger/apache_logger_spec.rb
121
+ - spec/httparty/logger/curl_logger_spec.rb
122
+ - spec/httparty/logger/logger_spec.rb
121
123
  - spec/httparty/net_digest_auth_spec.rb
122
124
  - spec/httparty/parser_spec.rb
123
125
  - spec/httparty/request_spec.rb
@@ -133,33 +135,26 @@ files:
133
135
  - website/index.html
134
136
  homepage: http://jnunemaker.github.com/httparty
135
137
  licenses: []
138
+ metadata: {}
136
139
  post_install_message: When you HTTParty, you must party hard!
137
140
  rdoc_options: []
138
141
  require_paths:
139
142
  - lib
140
143
  required_ruby_version: !ruby/object:Gem::Requirement
141
- none: false
142
144
  requirements:
143
- - - ! '>='
145
+ - - '>='
144
146
  - !ruby/object:Gem::Version
145
- version: '0'
146
- segments:
147
- - 0
148
- hash: -4402844038872120399
147
+ version: 1.9.3
149
148
  required_rubygems_version: !ruby/object:Gem::Requirement
150
- none: false
151
149
  requirements:
152
- - - ! '>='
150
+ - - '>='
153
151
  - !ruby/object:Gem::Version
154
152
  version: '0'
155
- segments:
156
- - 0
157
- hash: -4402844038872120399
158
153
  requirements: []
159
154
  rubyforge_project:
160
- rubygems_version: 1.8.23
155
+ rubygems_version: 2.0.3
161
156
  signing_key:
162
- specification_version: 3
157
+ specification_version: 4
163
158
  summary: Makes http fun! Also, makes consuming restful web services dead easy.
164
159
  test_files:
165
160
  - features/basic_authentication.feature
@@ -192,6 +187,9 @@ test_files:
192
187
  - spec/fixtures/undefined_method_add_node_for_nil.xml
193
188
  - spec/httparty/connection_adapter_spec.rb
194
189
  - spec/httparty/cookie_hash_spec.rb
190
+ - spec/httparty/logger/apache_logger_spec.rb
191
+ - spec/httparty/logger/curl_logger_spec.rb
192
+ - spec/httparty/logger/logger_spec.rb
195
193
  - spec/httparty/net_digest_auth_spec.rb
196
194
  - spec/httparty/parser_spec.rb
197
195
  - spec/httparty/request_spec.rb