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.
- checksums.yaml +7 -0
- data/Gemfile +0 -1
- data/README.md +2 -1
- data/Rakefile +1 -4
- data/examples/aaws.rb +4 -4
- data/examples/crack.rb +2 -2
- data/examples/delicious.rb +4 -4
- data/examples/headers_and_user_agents.rb +1 -1
- data/examples/twitter.rb +4 -4
- data/examples/whoismyrep.rb +2 -2
- data/features/handles_compressed_responses.feature +8 -0
- data/features/handles_multiple_formats.feature +8 -0
- data/features/steps/httparty_response_steps.rb +8 -1
- data/features/steps/httparty_steps.rb +9 -1
- data/httparty.gemspec +3 -1
- data/lib/httparty.rb +30 -5
- data/lib/httparty/connection_adapter.rb +36 -2
- data/lib/httparty/cookie_hash.rb +1 -1
- data/lib/httparty/logger/apache_logger.rb +22 -0
- data/lib/httparty/logger/curl_logger.rb +48 -0
- data/lib/httparty/logger/logger.rb +18 -0
- data/lib/httparty/parser.rb +3 -8
- data/lib/httparty/request.rb +81 -2
- data/lib/httparty/response.rb +6 -1
- data/lib/httparty/version.rb +1 -1
- data/script/release +42 -0
- data/spec/httparty/connection_adapter_spec.rb +33 -0
- data/spec/httparty/cookie_hash_spec.rb +7 -0
- data/spec/httparty/logger/apache_logger_spec.rb +26 -0
- data/spec/httparty/logger/curl_logger_spec.rb +18 -0
- data/spec/httparty/logger/logger_spec.rb +22 -0
- data/spec/httparty/net_digest_auth_spec.rb +2 -2
- data/spec/httparty/parser_spec.rb +2 -8
- data/spec/httparty/request_spec.rb +90 -3
- data/spec/httparty/response_spec.rb +1 -1
- data/spec/httparty/ssl_spec.rb +18 -6
- data/spec/spec_helper.rb +6 -0
- data/spec/support/ssl_test_helper.rb +4 -4
- metadata +23 -25
checksums.yaml
ADDED
@@ -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
data/README.md
CHANGED
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]
|
data/examples/aaws.rb
CHANGED
@@ -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
|
data/examples/crack.rb
CHANGED
@@ -15,5 +15,5 @@ class Rep
|
|
15
15
|
)
|
16
16
|
end
|
17
17
|
|
18
|
-
pp Rep.get('http://whoismyrepresentative.com/
|
19
|
-
pp Rep.get('http://whoismyrepresentative.com/
|
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})
|
data/examples/delicious.rb
CHANGED
@@ -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'] }
|
data/examples/twitter.rb
CHANGED
@@ -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')
|
data/examples/whoismyrep.rb
CHANGED
@@ -6,5 +6,5 @@ class Rep
|
|
6
6
|
include HTTParty
|
7
7
|
end
|
8
8
|
|
9
|
-
pp Rep.get('http://whoismyrepresentative.com/
|
10
|
-
pp Rep.get('http://whoismyrepresentative.com/
|
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
|
data/httparty.gemspec
CHANGED
@@ -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.
|
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!"
|
data/lib/httparty.rb
CHANGED
@@ -4,13 +4,14 @@ require 'net/https'
|
|
4
4
|
require 'uri'
|
5
5
|
require 'zlib'
|
6
6
|
require 'multi_xml'
|
7
|
-
require '
|
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
|
-
|
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
|
-
|
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]
|
data/lib/httparty/cookie_hash.rb
CHANGED
@@ -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
|
data/lib/httparty/parser.rb
CHANGED
@@ -42,8 +42,8 @@ module HTTParty
|
|
42
42
|
'application/xml' => :xml,
|
43
43
|
'application/json' => :json,
|
44
44
|
'text/json' => :json,
|
45
|
-
'application/javascript' => :
|
46
|
-
'text/javascript' => :
|
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
|
-
|
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
|
data/lib/httparty/request.rb
CHANGED
@@ -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
|
-
|
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
|
data/lib/httparty/response.rb
CHANGED
@@ -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
|
|
data/lib/httparty/version.rb
CHANGED
data/script/release
ADDED
@@ -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
|
148
|
-
|
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 == :
|
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 == :
|
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
|
|
data/spec/httparty/ssl_spec.rb
CHANGED
@@ -10,12 +10,24 @@ describe HTTParty::Request do
|
|
10
10
|
FakeWeb.allow_net_connect = false
|
11
11
|
end
|
12
12
|
|
13
|
-
it "should
|
14
|
-
|
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
|
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
|
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
|
data/spec/spec_helper.rb
CHANGED
@@ -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}/",
|
27
|
+
return HTTParty.get("https://localhost:#{test_server.port}/", options)
|
28
28
|
else
|
29
|
-
return HTTParty.get("https://localhost:#{test_server.port}/",
|
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.
|
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-
|
12
|
+
date: 2013-10-10 00:00:00.000000000 Z
|
14
13
|
dependencies:
|
15
14
|
- !ruby/object:Gem::Dependency
|
16
|
-
name:
|
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.
|
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.
|
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:
|
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:
|
155
|
+
rubygems_version: 2.0.3
|
161
156
|
signing_key:
|
162
|
-
specification_version:
|
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
|