jugend-httparty 0.5.2.3 → 0.5.3.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/History +25 -7
- data/Rakefile +4 -4
- data/VERSION +1 -1
- data/features/digest_authentication.feature +20 -0
- data/features/steps/env.rb +8 -1
- data/features/steps/httparty_steps.rb +8 -0
- data/features/steps/mongrel_helper.rb +22 -0
- data/features/steps/remote_service_steps.rb +11 -2
- data/features/supports_timeout_option.feature +1 -0
- data/jugend-httparty.gemspec +14 -12
- data/lib/httparty.rb +45 -6
- data/lib/httparty/net_digest_auth.rb +35 -0
- data/lib/httparty/request.rb +103 -91
- data/lib/httparty/response.rb +54 -10
- data/spec/httparty/request_spec.rb +38 -0
- data/spec/httparty/response_spec.rb +53 -32
- data/spec/httparty_spec.rb +31 -1
- data/spec/spec_helper.rb +6 -2
- data/spec/support/stub_response.rb +1 -1
- metadata +13 -12
data/History
CHANGED
@@ -1,12 +1,30 @@
|
|
1
|
-
== 0.5.
|
2
|
-
*
|
1
|
+
== 0.5.3.4
|
2
|
+
* Update gem name to jugend-httparty
|
3
|
+
|
4
|
+
== 0.5.3.3
|
5
|
+
* Remove RubyforgeTasks
|
6
|
+
|
7
|
+
== 0.5.3.2
|
8
|
+
* Remove deprecated rubyforge gem push
|
9
|
+
|
10
|
+
== 0.5.3.1
|
11
|
+
* Update Pathname initialization to support earlier version of ruby (<=1.8.4)
|
3
12
|
|
4
|
-
== 0.5.
|
5
|
-
|
13
|
+
== 0.5.3 (master)
|
14
|
+
* major enhancements
|
15
|
+
* Digest Auth (bartiaco, sbecker, gilles, and aaronrussell)
|
16
|
+
* Maintain HTTP method across redirects (bartiaco and sbecker)
|
17
|
+
* HTTParty::Response#response returns the Net::HTTPResponse object
|
18
|
+
* HTTParty::Response#headers returns a HTTParty::Response::Headers object
|
19
|
+
which quacks like a Hash + Net::HTTPHeader. The #headers method continues
|
20
|
+
to be backwards-compatible with the old Hash return value but may become
|
21
|
+
deprecated in the future.
|
6
22
|
|
7
|
-
|
8
|
-
* Update
|
9
|
-
|
23
|
+
* minor enhancements
|
24
|
+
* Update crack requirement to version 0.1.7
|
25
|
+
You may still get a warning because Crack's version constant is out of date
|
26
|
+
* Timeout option can be set for all requests using HTTParty.default_timeout (taazza)
|
27
|
+
* Closed #38 "headers hash should downcase keys so canonical header name can be used"
|
10
28
|
|
11
29
|
== 0.5.2 2010-01-31
|
12
30
|
* minor enhancements
|
data/Rakefile
CHANGED
@@ -7,14 +7,14 @@ begin
|
|
7
7
|
gem.summary = %Q{Makes http fun! Also, makes consuming restful web services dead easy.}
|
8
8
|
gem.description = %Q{Makes http fun! Also, makes consuming restful web services dead easy.}
|
9
9
|
gem.email = "nunemaker@gmail.com"
|
10
|
-
gem.homepage = "http://httparty
|
10
|
+
gem.homepage = "http://github.com/jugend/httparty"
|
11
11
|
gem.authors = ["John Nunemaker", "Sandro Turriate"]
|
12
|
-
gem.add_dependency 'crack', '0.1.
|
12
|
+
gem.add_dependency 'crack', '0.1.7'
|
13
13
|
gem.add_development_dependency "activesupport", "~>2.3"
|
14
|
-
gem.add_development_dependency "cucumber", "~>0.
|
14
|
+
gem.add_development_dependency "cucumber", "~>0.7"
|
15
15
|
gem.add_development_dependency "fakeweb", "~>1.2"
|
16
16
|
gem.add_development_dependency "mongrel", "~>1.1"
|
17
|
-
gem.add_development_dependency "rspec", "1.
|
17
|
+
gem.add_development_dependency "rspec", "~>1.3"
|
18
18
|
gem.post_install_message = "When you HTTParty, you must party hard!"
|
19
19
|
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
20
20
|
end
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.5.
|
1
|
+
0.5.3.4
|
@@ -0,0 +1,20 @@
|
|
1
|
+
Feature: Digest Authentication
|
2
|
+
|
3
|
+
As a developer
|
4
|
+
I want to be able to use a service that requires Digest Authentication
|
5
|
+
Because that is not an uncommon requirement
|
6
|
+
|
7
|
+
Scenario: Passing no credentials to a page requiring Digest Authentication
|
8
|
+
Given a restricted page at '/protected.html'
|
9
|
+
When I call HTTParty#get with '/protected.html'
|
10
|
+
Then it should return a response with a 401 response code
|
11
|
+
|
12
|
+
Scenario: Passing proper credentials to a page requiring Digest Authentication
|
13
|
+
Given a remote service that returns 'Digest Authenticated Page'
|
14
|
+
And that service is accessed at the path '/protected.html'
|
15
|
+
And that service is protected by Digest Authentication
|
16
|
+
And that service requires the username 'jcash' with the password 'maninblack'
|
17
|
+
When I call HTTParty#get with '/protected.html' and a digest_auth hash:
|
18
|
+
| username | password |
|
19
|
+
| jcash | maninblack |
|
20
|
+
Then the return value should match 'Digest Authenticated Page'
|
data/features/steps/env.rb
CHANGED
@@ -4,7 +4,14 @@ require 'lib/httparty'
|
|
4
4
|
require 'spec/expectations'
|
5
5
|
|
6
6
|
Before do
|
7
|
-
|
7
|
+
def new_port
|
8
|
+
server = TCPServer.new('0.0.0.0', nil)
|
9
|
+
port = server.addr[1]
|
10
|
+
ensure
|
11
|
+
server.close
|
12
|
+
end
|
13
|
+
|
14
|
+
port = ENV["HTTPARTY_PORT"] || new_port
|
8
15
|
@host_and_port = "0.0.0.0:#{port}"
|
9
16
|
@server = Mongrel::HttpServer.new("0.0.0.0", port)
|
10
17
|
@server.run
|
@@ -17,3 +17,11 @@ When /I call HTTParty#get with '(.*)' and a basic_auth hash:/ do |url, auth_tabl
|
|
17
17
|
:basic_auth => { :username => h["username"], :password => h["password"] }
|
18
18
|
)
|
19
19
|
end
|
20
|
+
|
21
|
+
When /I call HTTParty#get with '(.*)' and a digest_auth hash:/ do |url, auth_table|
|
22
|
+
h = auth_table.hashes.first
|
23
|
+
@response_from_httparty = HTTParty.get(
|
24
|
+
"http://#{@host_and_port}#{url}",
|
25
|
+
:digest_auth => { :username => h["username"], :password => h["password"] }
|
26
|
+
)
|
27
|
+
end
|
@@ -50,6 +50,28 @@ def add_basic_authentication_to(handler)
|
|
50
50
|
handler.extend(m)
|
51
51
|
end
|
52
52
|
|
53
|
+
def add_digest_authentication_to(handler)
|
54
|
+
m = Module.new do
|
55
|
+
attr_writer :username, :password
|
56
|
+
|
57
|
+
def self.extended(base)
|
58
|
+
base.instance_eval { @custom_headers["WWW-Authenticate"] = 'Digest realm="testrealm@host.com",qop="auth,auth-int",nonce="nonce",opaque="opaque"' }
|
59
|
+
base.class_eval { alias_method_chain :process, :digest_authentication }
|
60
|
+
end
|
61
|
+
|
62
|
+
def process_with_digest_authentication(request, response)
|
63
|
+
if authorized?(request) then process_without_digest_authentication(request, response)
|
64
|
+
else reply_with(response, 401, "Incorrect. You have 20 seconds to comply.")
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def authorized?(request)
|
69
|
+
request.params["HTTP_AUTHORIZATION"] =~ /Digest.*uri=/
|
70
|
+
end
|
71
|
+
end
|
72
|
+
handler.extend(m)
|
73
|
+
end
|
74
|
+
|
53
75
|
def new_mongrel_redirector(target_url, relative_path = false)
|
54
76
|
target_url = "http://#{@host_and_port}#{target_url}" unless relative_path
|
55
77
|
Mongrel::RedirectHandler.new(target_url)
|
@@ -13,8 +13,8 @@ Given /that service is accessed at the path '(.*)'/ do |path|
|
|
13
13
|
end
|
14
14
|
|
15
15
|
Given /^that service takes (\d+) seconds to generate a response$/ do |time|
|
16
|
-
|
17
|
-
@handler.preprocessor =
|
16
|
+
@server_response_time = time.to_i
|
17
|
+
@handler.preprocessor = lambda { sleep time.to_i }
|
18
18
|
end
|
19
19
|
|
20
20
|
Given /the response from the service has a Content-Type of '(.*)'/ do |content_type|
|
@@ -33,6 +33,10 @@ Given /that service is protected by Basic Authentication/ do
|
|
33
33
|
add_basic_authentication_to @handler
|
34
34
|
end
|
35
35
|
|
36
|
+
Given /that service is protected by Digest Authentication/ do
|
37
|
+
add_digest_authentication_to @handler
|
38
|
+
end
|
39
|
+
|
36
40
|
Given /that service requires the username '(.*)' with the password '(.*)'/ do |username, password|
|
37
41
|
@handler.username = username
|
38
42
|
@handler.password = password
|
@@ -50,3 +54,8 @@ end
|
|
50
54
|
Given /I want to hit this in a browser/ do
|
51
55
|
@server.acceptor.join
|
52
56
|
end
|
57
|
+
|
58
|
+
Then /I wait for the server to recover/ do
|
59
|
+
timeout = @request_options[:timeout] || 0
|
60
|
+
sleep @server_response_time - timeout
|
61
|
+
end
|
data/jugend-httparty.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{jugend-httparty}
|
8
|
-
s.version = "0.5.
|
8
|
+
s.version = "0.5.3.4"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["John Nunemaker", "Sandro Turriate"]
|
12
|
-
s.date = %q{2010-
|
12
|
+
s.date = %q{2010-05-26}
|
13
13
|
s.default_executable = %q{httparty}
|
14
14
|
s.description = %q{Makes http fun! Also, makes consuming restful web services dead easy.}
|
15
15
|
s.email = %q{nunemaker@gmail.com}
|
@@ -38,6 +38,7 @@ Gem::Specification.new do |s|
|
|
38
38
|
"features/basic_authentication.feature",
|
39
39
|
"features/command_line.feature",
|
40
40
|
"features/deals_with_http_error_codes.feature",
|
41
|
+
"features/digest_authentication.feature",
|
41
42
|
"features/handles_multiple_formats.feature",
|
42
43
|
"features/steps/env.rb",
|
43
44
|
"features/steps/httparty_response_steps.rb",
|
@@ -52,6 +53,7 @@ Gem::Specification.new do |s|
|
|
52
53
|
"lib/httparty/core_extensions.rb",
|
53
54
|
"lib/httparty/exceptions.rb",
|
54
55
|
"lib/httparty/module_inheritable_attributes.rb",
|
56
|
+
"lib/httparty/net_digest_auth.rb",
|
55
57
|
"lib/httparty/parser.rb",
|
56
58
|
"lib/httparty/request.rb",
|
57
59
|
"lib/httparty/response.rb",
|
@@ -72,7 +74,7 @@ Gem::Specification.new do |s|
|
|
72
74
|
"website/css/common.css",
|
73
75
|
"website/index.html"
|
74
76
|
]
|
75
|
-
s.homepage = %q{http://httparty
|
77
|
+
s.homepage = %q{http://github.com/jugend/httparty}
|
76
78
|
s.post_install_message = %q{When you HTTParty, you must party hard!}
|
77
79
|
s.rdoc_options = ["--charset=UTF-8"]
|
78
80
|
s.require_paths = ["lib"]
|
@@ -101,27 +103,27 @@ Gem::Specification.new do |s|
|
|
101
103
|
s.specification_version = 3
|
102
104
|
|
103
105
|
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
104
|
-
s.add_runtime_dependency(%q<crack>, ["= 0.1.
|
106
|
+
s.add_runtime_dependency(%q<crack>, ["= 0.1.7"])
|
105
107
|
s.add_development_dependency(%q<activesupport>, ["~> 2.3"])
|
106
|
-
s.add_development_dependency(%q<cucumber>, ["~> 0.
|
108
|
+
s.add_development_dependency(%q<cucumber>, ["~> 0.7"])
|
107
109
|
s.add_development_dependency(%q<fakeweb>, ["~> 1.2"])
|
108
110
|
s.add_development_dependency(%q<mongrel>, ["~> 1.1"])
|
109
|
-
s.add_development_dependency(%q<rspec>, ["
|
111
|
+
s.add_development_dependency(%q<rspec>, ["~> 1.3"])
|
110
112
|
else
|
111
|
-
s.add_dependency(%q<crack>, ["= 0.1.
|
113
|
+
s.add_dependency(%q<crack>, ["= 0.1.7"])
|
112
114
|
s.add_dependency(%q<activesupport>, ["~> 2.3"])
|
113
|
-
s.add_dependency(%q<cucumber>, ["~> 0.
|
115
|
+
s.add_dependency(%q<cucumber>, ["~> 0.7"])
|
114
116
|
s.add_dependency(%q<fakeweb>, ["~> 1.2"])
|
115
117
|
s.add_dependency(%q<mongrel>, ["~> 1.1"])
|
116
|
-
s.add_dependency(%q<rspec>, ["
|
118
|
+
s.add_dependency(%q<rspec>, ["~> 1.3"])
|
117
119
|
end
|
118
120
|
else
|
119
|
-
s.add_dependency(%q<crack>, ["= 0.1.
|
121
|
+
s.add_dependency(%q<crack>, ["= 0.1.7"])
|
120
122
|
s.add_dependency(%q<activesupport>, ["~> 2.3"])
|
121
|
-
s.add_dependency(%q<cucumber>, ["~> 0.
|
123
|
+
s.add_dependency(%q<cucumber>, ["~> 0.7"])
|
122
124
|
s.add_dependency(%q<fakeweb>, ["~> 1.2"])
|
123
125
|
s.add_dependency(%q<mongrel>, ["~> 1.1"])
|
124
|
-
s.add_dependency(%q<rspec>, ["
|
126
|
+
s.add_dependency(%q<rspec>, ["~> 1.3"])
|
125
127
|
end
|
126
128
|
end
|
127
129
|
|
data/lib/httparty.rb
CHANGED
@@ -3,17 +3,15 @@ require 'net/http'
|
|
3
3
|
require 'net/https'
|
4
4
|
require 'crack'
|
5
5
|
|
6
|
-
|
7
|
-
warn "warning: HTTParty depends on version 0.1.6 of crack, not #{Crack::VERSION}."
|
8
|
-
end
|
9
|
-
|
10
|
-
dir = Pathname(__FILE__).dirname.expand_path
|
6
|
+
dir = Pathname.new(__FILE__).dirname.expand_path
|
11
7
|
|
12
8
|
require dir + 'httparty/module_inheritable_attributes'
|
13
9
|
require dir + 'httparty/cookie_hash'
|
10
|
+
require dir + 'httparty/net_digest_auth'
|
14
11
|
|
15
12
|
module HTTParty
|
16
13
|
VERSION = "0.5.2".freeze
|
14
|
+
CRACK_DEPENDENCY = "0.1.7".freeze
|
17
15
|
|
18
16
|
module AllowedFormatsDeprecation
|
19
17
|
def const_missing(const)
|
@@ -73,6 +71,16 @@ module HTTParty
|
|
73
71
|
default_options[:basic_auth] = {:username => u, :password => p}
|
74
72
|
end
|
75
73
|
|
74
|
+
# Allows setting digest authentication username and password.
|
75
|
+
#
|
76
|
+
# class Foo
|
77
|
+
# include HTTParty
|
78
|
+
# digest_auth 'username', 'password'
|
79
|
+
# end
|
80
|
+
def digest_auth(u, p)
|
81
|
+
default_options[:digest_auth] = {:username => u, :password => p}
|
82
|
+
end
|
83
|
+
|
76
84
|
# Allows setting default parameters to be appended to each request.
|
77
85
|
# Great for api keys and such.
|
78
86
|
#
|
@@ -86,6 +94,18 @@ module HTTParty
|
|
86
94
|
default_options[:default_params].merge!(h)
|
87
95
|
end
|
88
96
|
|
97
|
+
# Allows setting a default timeout for all HTTP calls
|
98
|
+
# Timeout is specified in seconds.
|
99
|
+
#
|
100
|
+
# class Foo
|
101
|
+
# include HTTParty
|
102
|
+
# default_timeout 10
|
103
|
+
# end
|
104
|
+
def default_timeout(t)
|
105
|
+
raise ArgumentError, 'Timeout must be an integer' unless t && t.is_a?(Integer)
|
106
|
+
default_options[:timeout] = t
|
107
|
+
end
|
108
|
+
|
89
109
|
# Set an output stream for debugging, defaults to $stderr.
|
90
110
|
# The output stream is passed on to Net::HTTP#set_debug_output.
|
91
111
|
#
|
@@ -97,7 +117,7 @@ module HTTParty
|
|
97
117
|
default_options[:debug_output] = stream
|
98
118
|
end
|
99
119
|
|
100
|
-
# Allows setting
|
120
|
+
# Allows setting HTTP headers to be used for each request.
|
101
121
|
#
|
102
122
|
# class Foo
|
103
123
|
# include HTTParty
|
@@ -154,6 +174,21 @@ module HTTParty
|
|
154
174
|
default_options[:no_follow] = value
|
155
175
|
end
|
156
176
|
|
177
|
+
# Declare that you wish to maintain the chosen HTTP method across redirects.
|
178
|
+
# The default behavior is to follow redirects via the GET method.
|
179
|
+
# If you wish to maintain the original method, you can set this option to true.
|
180
|
+
#
|
181
|
+
# @example
|
182
|
+
# class Foo
|
183
|
+
# include HTTParty
|
184
|
+
# base_uri 'http://google.com'
|
185
|
+
# maintain_method_across_redirects true
|
186
|
+
# end
|
187
|
+
|
188
|
+
def maintain_method_across_redirects(value = true)
|
189
|
+
default_options[:maintain_method_across_redirects] = value
|
190
|
+
end
|
191
|
+
|
157
192
|
# Allows setting a PEM file to be used
|
158
193
|
#
|
159
194
|
# class Foo
|
@@ -302,3 +337,7 @@ require dir + 'httparty/exceptions'
|
|
302
337
|
require dir + 'httparty/parser'
|
303
338
|
require dir + 'httparty/request'
|
304
339
|
require dir + 'httparty/response'
|
340
|
+
|
341
|
+
if Crack::VERSION != HTTParty::CRACK_DEPENDENCY
|
342
|
+
warn "warning: HTTParty depends on version #{HTTParty::CRACK_DEPENDENCY} of crack, not #{Crack::VERSION}."
|
343
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'digest/md5'
|
2
|
+
require 'net/http'
|
3
|
+
|
4
|
+
module Net
|
5
|
+
module HTTPHeader
|
6
|
+
def digest_auth(user, password, response)
|
7
|
+
response['www-authenticate'] =~ /^(\w+) (.*)/
|
8
|
+
|
9
|
+
params = {}
|
10
|
+
$2.gsub(/(\w+)="(.*?)"/) { params[$1] = $2 }
|
11
|
+
params.merge!("cnonce" => Digest::MD5.hexdigest("%x" % (Time.now.to_i + rand(65535))))
|
12
|
+
|
13
|
+
a_1 = Digest::MD5.hexdigest("#{user}:#{params['realm']}:#{password}")
|
14
|
+
a_2 = Digest::MD5.hexdigest("#{@method}:#{@path}")
|
15
|
+
|
16
|
+
request_digest = Digest::MD5.hexdigest(
|
17
|
+
[a_1, params['nonce'], "0", params['cnonce'], params['qop'], a_2].join(":")
|
18
|
+
)
|
19
|
+
|
20
|
+
header = [
|
21
|
+
%Q(Digest username="#{user}"),
|
22
|
+
%Q(realm="#{params['realm']}"),
|
23
|
+
%Q(qop="#{params['qop']}"),
|
24
|
+
%Q(uri="#{@path}"),
|
25
|
+
%Q(nonce="#{params['nonce']}"),
|
26
|
+
%Q(nc="0"),
|
27
|
+
%Q(cnonce="#{params['cnonce']}"),
|
28
|
+
%Q(opaque="#{params['opaque']}"),
|
29
|
+
%Q(response="#{request_digest}")
|
30
|
+
]
|
31
|
+
|
32
|
+
@header['Authorization'] = header
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
data/lib/httparty/request.rb
CHANGED
@@ -13,7 +13,7 @@ module HTTParty
|
|
13
13
|
|
14
14
|
SupportedURISchemes = [URI::HTTP, URI::HTTPS]
|
15
15
|
|
16
|
-
attr_accessor :http_method, :path, :options, :last_response
|
16
|
+
attr_accessor :http_method, :path, :options, :last_response, :redirect
|
17
17
|
|
18
18
|
def initialize(http_method, path, o={})
|
19
19
|
self.http_method = http_method
|
@@ -33,7 +33,7 @@ module HTTParty
|
|
33
33
|
new_uri = path.relative? ? URI.parse("#{options[:base_uri]}#{path}") : path
|
34
34
|
|
35
35
|
# avoid double query string on redirects [#12]
|
36
|
-
unless
|
36
|
+
unless redirect
|
37
37
|
new_uri.query = query_string(new_uri)
|
38
38
|
end
|
39
39
|
|
@@ -52,7 +52,6 @@ module HTTParty
|
|
52
52
|
options[:parser]
|
53
53
|
end
|
54
54
|
|
55
|
-
|
56
55
|
def perform
|
57
56
|
validate
|
58
57
|
setup_raw_request
|
@@ -62,133 +61,146 @@ module HTTParty
|
|
62
61
|
|
63
62
|
private
|
64
63
|
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
if options[:timeout] && options[:timeout].is_a?(Integer)
|
70
|
-
http.open_timeout = options[:timeout]
|
71
|
-
http.read_timeout = options[:timeout]
|
72
|
-
end
|
73
|
-
|
74
|
-
if options[:pem] && http.use_ssl?
|
75
|
-
http.cert = OpenSSL::X509::Certificate.new(options[:pem])
|
76
|
-
http.key = OpenSSL::PKey::RSA.new(options[:pem])
|
77
|
-
http.verify_mode = OpenSSL::SSL::VERIFY_PEER
|
78
|
-
else
|
79
|
-
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
80
|
-
end
|
81
|
-
|
82
|
-
if options[:debug_output]
|
83
|
-
http.set_debug_output(options[:debug_output])
|
84
|
-
end
|
64
|
+
def http
|
65
|
+
http = Net::HTTP.new(uri.host, uri.port, options[:http_proxyaddr], options[:http_proxyport])
|
66
|
+
http.use_ssl = ssl_implied?
|
85
67
|
|
86
|
-
|
68
|
+
if options[:timeout] && options[:timeout].is_a?(Integer)
|
69
|
+
http.open_timeout = options[:timeout]
|
70
|
+
http.read_timeout = options[:timeout]
|
87
71
|
end
|
88
72
|
|
89
|
-
|
90
|
-
|
73
|
+
if options[:pem] && http.use_ssl?
|
74
|
+
http.cert = OpenSSL::X509::Certificate.new(options[:pem])
|
75
|
+
http.key = OpenSSL::PKey::RSA.new(options[:pem])
|
76
|
+
http.verify_mode = OpenSSL::SSL::VERIFY_PEER
|
77
|
+
else
|
78
|
+
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
91
79
|
end
|
92
80
|
|
93
|
-
|
94
|
-
|
81
|
+
if options[:debug_output]
|
82
|
+
http.set_debug_output(options[:debug_output])
|
95
83
|
end
|
96
84
|
|
97
|
-
|
98
|
-
|
99
|
-
end
|
85
|
+
http
|
86
|
+
end
|
100
87
|
|
101
|
-
|
102
|
-
|
103
|
-
|
88
|
+
def ssl_implied?
|
89
|
+
uri.port == 443 || uri.instance_of?(URI::HTTPS)
|
90
|
+
end
|
104
91
|
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
@raw_request.initialize_http_header(options[:headers])
|
109
|
-
@raw_request.basic_auth(username, password) if options[:basic_auth]
|
110
|
-
end
|
92
|
+
def body
|
93
|
+
options[:body].is_a?(Hash) ? options[:body].to_params : options[:body]
|
94
|
+
end
|
111
95
|
|
112
|
-
|
113
|
-
|
114
|
-
|
96
|
+
def credentials
|
97
|
+
options[:basic_auth] || options[:digest_auth]
|
98
|
+
end
|
115
99
|
|
116
|
-
|
117
|
-
|
118
|
-
|
100
|
+
def username
|
101
|
+
credentials[:username]
|
102
|
+
end
|
103
|
+
|
104
|
+
def password
|
105
|
+
credentials[:password]
|
106
|
+
end
|
107
|
+
|
108
|
+
def setup_raw_request
|
109
|
+
@raw_request = http_method.new(uri.request_uri)
|
110
|
+
@raw_request.body = body if body
|
111
|
+
@raw_request.initialize_http_header(options[:headers])
|
112
|
+
@raw_request.basic_auth(username, password) if options[:basic_auth]
|
113
|
+
setup_digest_auth if options[:digest_auth]
|
114
|
+
end
|
115
|
+
|
116
|
+
def setup_digest_auth
|
117
|
+
res = http.head(uri.request_uri, options[:headers])
|
118
|
+
if res['www-authenticate'] != nil && res['www-authenticate'].length > 0
|
119
|
+
@raw_request.digest_auth(username, password, res)
|
119
120
|
end
|
121
|
+
end
|
120
122
|
|
121
|
-
|
122
|
-
|
123
|
-
|
123
|
+
def perform_actual_request
|
124
|
+
http.request(@raw_request)
|
125
|
+
end
|
124
126
|
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
query_string_parts << options[:query] unless options[:query].nil?
|
130
|
-
end
|
127
|
+
def get_response
|
128
|
+
self.last_response = perform_actual_request
|
129
|
+
options[:format] ||= format_from_mimetype(last_response['content-type'])
|
130
|
+
end
|
131
131
|
|
132
|
-
|
132
|
+
def query_string(uri)
|
133
|
+
query_string_parts = []
|
134
|
+
query_string_parts << uri.query unless uri.query.nil?
|
135
|
+
|
136
|
+
if options[:query].is_a?(Hash)
|
137
|
+
query_string_parts << options[:default_params].merge(options[:query]).to_params
|
138
|
+
else
|
139
|
+
query_string_parts << options[:default_params].to_params unless options[:default_params].empty?
|
140
|
+
query_string_parts << options[:query] unless options[:query].nil?
|
133
141
|
end
|
134
142
|
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
143
|
+
query_string_parts.size > 0 ? query_string_parts.join('&') : nil
|
144
|
+
end
|
145
|
+
|
146
|
+
# Raises exception Net::XXX (http error code) if an http error occured
|
147
|
+
def handle_response
|
148
|
+
case last_response
|
149
|
+
when Net::HTTPMultipleChoice, # 300
|
150
|
+
Net::HTTPMovedPermanently, # 301
|
151
|
+
Net::HTTPFound, # 302
|
152
|
+
Net::HTTPSeeOther, # 303
|
153
|
+
Net::HTTPUseProxy, # 305
|
154
|
+
Net::HTTPTemporaryRedirect
|
144
155
|
if last_response.key?('location')
|
145
156
|
options[:limit] -= 1
|
146
157
|
self.path = last_response['location']
|
147
|
-
|
148
|
-
self.http_method = Net::HTTP::Get
|
158
|
+
self.redirect = true
|
159
|
+
self.http_method = Net::HTTP::Get unless options[:maintain_method_across_redirects]
|
149
160
|
capture_cookies(last_response)
|
150
161
|
perform
|
151
162
|
else
|
152
163
|
last_response
|
153
164
|
end
|
154
165
|
else
|
155
|
-
Response.new(
|
156
|
-
end
|
166
|
+
Response.new(last_response, parse_response(last_response.body))
|
157
167
|
end
|
168
|
+
end
|
158
169
|
|
159
|
-
|
160
|
-
|
161
|
-
|
170
|
+
def parse_response(body)
|
171
|
+
parser.call(body, format)
|
172
|
+
end
|
162
173
|
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
174
|
+
def capture_cookies(response)
|
175
|
+
return unless response['Set-Cookie']
|
176
|
+
cookies_hash = HTTParty::CookieHash.new()
|
177
|
+
cookies_hash.add_cookies(options[:headers]['Cookie']) if options[:headers] && options[:headers]['Cookie']
|
178
|
+
cookies_hash.add_cookies(response['Set-Cookie'])
|
179
|
+
options[:headers] ||= {}
|
180
|
+
options[:headers]['Cookie'] = cookies_hash.to_cookie_string
|
181
|
+
end
|
171
182
|
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
end
|
183
|
+
# Uses the HTTP Content-Type header to determine the format of the
|
184
|
+
# response It compares the MIME type returned to the types stored in the
|
185
|
+
# SupportedFormats hash
|
186
|
+
def format_from_mimetype(mimetype)
|
187
|
+
if mimetype && parser.respond_to?(:format_from_mimetype)
|
188
|
+
parser.format_from_mimetype(mimetype)
|
179
189
|
end
|
190
|
+
end
|
180
191
|
|
181
192
|
def validate
|
182
193
|
raise HTTParty::RedirectionTooDeep.new(last_response), 'HTTP redirects too deep' if options[:limit].to_i <= 0
|
183
194
|
raise ArgumentError, 'only get, post, put, delete, head, and options methods are supported' unless SupportedHTTPMethods.include?(http_method)
|
184
195
|
raise ArgumentError, ':headers must be a hash' if options[:headers] && !options[:headers].is_a?(Hash)
|
196
|
+
raise ArgumentError, 'only one authentication method, :basic_auth or :digest_auth may be used at a time' if options[:basic_auth] && options[:digest_auth]
|
185
197
|
raise ArgumentError, ':basic_auth must be a hash' if options[:basic_auth] && !options[:basic_auth].is_a?(Hash)
|
198
|
+
raise ArgumentError, ':digest_auth must be a hash' if options[:digest_auth] && !options[:digest_auth].is_a?(Hash)
|
186
199
|
raise ArgumentError, ':query must be hash if using HTTP Post' if post? && !options[:query].nil? && !options[:query].is_a?(Hash)
|
187
200
|
end
|
188
201
|
|
189
|
-
|
190
|
-
|
191
|
-
|
202
|
+
def post?
|
203
|
+
Net::HTTP::Post == http_method
|
204
|
+
end
|
192
205
|
end
|
193
206
|
end
|
194
|
-
|
data/lib/httparty/response.rb
CHANGED
@@ -1,18 +1,62 @@
|
|
1
1
|
module HTTParty
|
2
2
|
class Response < HTTParty::BasicObject #:nodoc:
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
3
|
+
class Headers
|
4
|
+
include Net::HTTPHeader
|
5
|
+
|
6
|
+
def initialize(header)
|
7
|
+
@header = header
|
8
|
+
end
|
9
|
+
|
10
|
+
def ==(other)
|
11
|
+
@header == other
|
12
|
+
end
|
13
|
+
|
14
|
+
def inspect
|
15
|
+
@header.inspect
|
16
|
+
end
|
17
|
+
|
18
|
+
def method_missing(name, *args, &block)
|
19
|
+
if @header.respond_to?(name)
|
20
|
+
@header.send(name, *args, &block)
|
21
|
+
else
|
22
|
+
super
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def respond_to?(method)
|
27
|
+
super || @header.respond_to?(method)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
attr_reader :response, :parsed_response, :body, :headers
|
32
|
+
|
33
|
+
def initialize(response, parsed_response)
|
34
|
+
@response = response
|
35
|
+
@body = response.body
|
36
|
+
@parsed_response = parsed_response
|
37
|
+
@headers = Headers.new(response.to_hash)
|
38
|
+
end
|
39
|
+
|
40
|
+
def class
|
41
|
+
Object.instance_method(:class).bind(self).call
|
42
|
+
end
|
43
|
+
|
44
|
+
def code
|
45
|
+
response.code.to_i
|
46
|
+
end
|
47
|
+
|
48
|
+
def inspect
|
49
|
+
%(<#{self.class} @response=#{response.inspect}>)
|
12
50
|
end
|
13
51
|
|
14
52
|
def method_missing(name, *args, &block)
|
15
|
-
|
53
|
+
if parsed_response.respond_to?(name)
|
54
|
+
parsed_response.send(name, *args, &block)
|
55
|
+
elsif response.respond_to?(name)
|
56
|
+
response.send(name, *args, &block)
|
57
|
+
else
|
58
|
+
super
|
59
|
+
end
|
16
60
|
end
|
17
61
|
end
|
18
62
|
end
|
@@ -30,6 +30,17 @@ describe HTTParty::Request do
|
|
30
30
|
@request.send(:setup_raw_request)
|
31
31
|
@request.instance_variable_get(:@raw_request)['authorization'].should_not be_nil
|
32
32
|
end
|
33
|
+
|
34
|
+
it "should use digest auth when configured" do
|
35
|
+
FakeWeb.register_uri(:head, "http://api.foo.com/v1",
|
36
|
+
:www_authenticate => 'Digest realm="Log Viewer", qop="auth", nonce="2CA0EC6B0E126C4800E56BA0C0003D3C", opaque="5ccc069c403ebaf9f0171e9517f40e41", stale=false')
|
37
|
+
|
38
|
+
@request.options[:digest_auth] = {:username => 'foobar', :password => 'secret'}
|
39
|
+
@request.send(:setup_raw_request)
|
40
|
+
|
41
|
+
raw_request = @request.instance_variable_get(:@raw_request)
|
42
|
+
raw_request.instance_variable_get(:@header)['Authorization'].should_not be_nil
|
43
|
+
end
|
33
44
|
end
|
34
45
|
|
35
46
|
describe "#uri" do
|
@@ -353,6 +364,13 @@ describe HTTParty::Request do
|
|
353
364
|
@request.perform.should == {"hash" => {"foo" => "bar"}}
|
354
365
|
@request.http_method.should == Net::HTTP::Get
|
355
366
|
end
|
367
|
+
|
368
|
+
it 'should not make resulting request a get request if options[:maintain_method_across_redirects] is true' do
|
369
|
+
@request.options[:maintain_method_across_redirects] = true
|
370
|
+
@request.http_method = Net::HTTP::Delete
|
371
|
+
@request.perform.should == {"hash" => {"foo" => "bar"}}
|
372
|
+
@request.http_method.should == Net::HTTP::Delete
|
373
|
+
end
|
356
374
|
end
|
357
375
|
|
358
376
|
describe "infinitely" do
|
@@ -373,5 +391,25 @@ describe HTTParty::Request do
|
|
373
391
|
}.should raise_error(ArgumentError)
|
374
392
|
end
|
375
393
|
end
|
394
|
+
|
395
|
+
describe "argument validation" do
|
396
|
+
it "should raise argument error if basic_auth and digest_auth are both present" do
|
397
|
+
lambda {
|
398
|
+
HTTParty::Request.new(Net::HTTP::Post, 'http://api.foo.com/v1', :basic_auth => {}, :digest_auth => {}).perform
|
399
|
+
}.should raise_error(ArgumentError, "only one authentication method, :basic_auth or :digest_auth may be used at a time")
|
400
|
+
end
|
401
|
+
|
402
|
+
it "should raise argument error if basic_auth is not a hash" do
|
403
|
+
lambda {
|
404
|
+
HTTParty::Request.new(Net::HTTP::Post, 'http://api.foo.com/v1', :basic_auth => ["foo", "bar"]).perform
|
405
|
+
}.should raise_error(ArgumentError, ":basic_auth must be a hash")
|
406
|
+
end
|
407
|
+
|
408
|
+
it "should raise argument error if digest_auth is not a hash" do
|
409
|
+
lambda {
|
410
|
+
HTTParty::Request.new(Net::HTTP::Post, 'http://api.foo.com/v1', :digest_auth => ["foo", "bar"]).perform
|
411
|
+
}.should raise_error(ArgumentError, ":digest_auth must be a hash")
|
412
|
+
end
|
413
|
+
end
|
376
414
|
end
|
377
415
|
|
@@ -1,62 +1,83 @@
|
|
1
1
|
require File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helper'))
|
2
2
|
|
3
3
|
describe HTTParty::Response do
|
4
|
+
before do
|
5
|
+
@last_modified = Date.new(2010, 1, 15).to_s
|
6
|
+
@content_length = '1024'
|
7
|
+
@response_object = {'foo' => 'bar'}
|
8
|
+
@response_object = Net::HTTPOK.new('1.1', 200, 'OK')
|
9
|
+
@response_object.stub(:body => "{foo:'bar'}")
|
10
|
+
@response_object['last-modified'] = @last_modified
|
11
|
+
@response_object['content-length'] = @content_length
|
12
|
+
@parsed_response = {"foo" => "bar"}
|
13
|
+
@response = HTTParty::Response.new(@response_object, @parsed_response)
|
14
|
+
end
|
15
|
+
|
4
16
|
describe "initialization" do
|
5
|
-
|
6
|
-
@
|
7
|
-
@body = "{foo:'bar'}"
|
8
|
-
@code = '200'
|
9
|
-
@message = 'OK'
|
10
|
-
@response = HTTParty::Response.new(@response_object, @body, @code, @message)
|
11
|
-
end
|
12
|
-
|
13
|
-
it "should set delegate" do
|
14
|
-
@response.delegate.should == @response_object
|
17
|
+
it "should set the Net::HTTP Response" do
|
18
|
+
@response.response.should == @response_object
|
15
19
|
end
|
16
|
-
|
20
|
+
|
17
21
|
it "should set body" do
|
18
|
-
@response.body.should == @body
|
22
|
+
@response.body.should == @response_object.body
|
19
23
|
end
|
20
|
-
|
24
|
+
|
21
25
|
it "should set code" do
|
22
|
-
@response.code.should.to_s == @code
|
26
|
+
@response.code.should.to_s == @response_object.code
|
23
27
|
end
|
24
28
|
|
25
29
|
it "should set code as a Fixnum" do
|
26
30
|
@response.code.should be_an_instance_of(Fixnum)
|
27
31
|
end
|
28
|
-
|
29
|
-
it "should set body" do
|
30
|
-
@response.body.should == @body
|
31
|
-
end
|
32
32
|
end
|
33
|
-
|
34
|
-
it "
|
35
|
-
response = HTTParty::Response.new(
|
36
|
-
response.headers.should == {'
|
33
|
+
|
34
|
+
it "returns response headers" do
|
35
|
+
response = HTTParty::Response.new(@response_object, @parsed_response)
|
36
|
+
response.headers.should == {'last-modified' => [@last_modified], 'content-length' => [@content_length]}
|
37
37
|
end
|
38
|
-
|
38
|
+
|
39
39
|
it "should send missing methods to delegate" do
|
40
|
-
response = HTTParty::Response.new({'foo' => 'bar'}
|
40
|
+
response = HTTParty::Response.new(@response_object, {'foo' => 'bar'})
|
41
41
|
response['foo'].should == 'bar'
|
42
42
|
end
|
43
|
-
|
44
|
-
it "should be able to iterate
|
45
|
-
response = HTTParty::Response.new([{'foo' => 'bar'}, {'foo' => 'baz'}]
|
43
|
+
|
44
|
+
it "should be able to iterate if it is array" do
|
45
|
+
response = HTTParty::Response.new(@response_object, [{'foo' => 'bar'}, {'foo' => 'baz'}])
|
46
46
|
response.size.should == 2
|
47
|
-
|
47
|
+
expect {
|
48
48
|
response.each { |item| }
|
49
|
-
}.
|
49
|
+
}.to_not raise_error
|
50
|
+
end
|
51
|
+
|
52
|
+
it "allows headers to be accessed by mixed-case names in hash notation" do
|
53
|
+
response = HTTParty::Response.new(@response_object, @parsed_response)
|
54
|
+
response.headers['Content-LENGTH'].should == @content_length
|
55
|
+
end
|
56
|
+
|
57
|
+
it "returns a comma-delimited value when multiple values exist" do
|
58
|
+
@response_object.add_field 'set-cookie', 'csrf_id=12345; path=/'
|
59
|
+
@response_object.add_field 'set-cookie', '_github_ses=A123CdE; path=/'
|
60
|
+
response = HTTParty::Response.new(@response_object, @parsed_response)
|
61
|
+
response.headers['set-cookie'].should == "csrf_id=12345; path=/, _github_ses=A123CdE; path=/"
|
50
62
|
end
|
51
|
-
|
63
|
+
|
64
|
+
# Backwards-compatibility - previously, #headers returned a Hash
|
65
|
+
it "responds to hash methods" do
|
66
|
+
response = HTTParty::Response.new(@response_object, @parsed_response)
|
67
|
+
hash_methods = {}.methods - response.headers.methods
|
68
|
+
hash_methods.each do |method_name|
|
69
|
+
response.headers.respond_to?(method_name).should be_true
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
52
73
|
xit "should allow hashes to be accessed with dot notation" do
|
53
74
|
response = HTTParty::Response.new({'foo' => 'bar'}, "{foo:'bar'}", 200, 'OK')
|
54
75
|
response.foo.should == 'bar'
|
55
76
|
end
|
56
|
-
|
77
|
+
|
57
78
|
xit "should allow nested hashes to be accessed with dot notation" do
|
58
79
|
response = HTTParty::Response.new({'foo' => {'bar' => 'baz'}}, "{foo: {bar:'baz'}}", 200, 'OK')
|
59
80
|
response.foo.should == {'bar' => 'baz'}
|
60
81
|
response.foo.bar.should == 'baz'
|
61
82
|
end
|
62
|
-
end
|
83
|
+
end
|
data/spec/httparty_spec.rb
CHANGED
@@ -203,6 +203,17 @@ describe HTTParty do
|
|
203
203
|
end
|
204
204
|
end
|
205
205
|
|
206
|
+
describe "default timeout" do
|
207
|
+
it "should default to nil" do
|
208
|
+
@klass.default_options[:timeout].should == nil
|
209
|
+
end
|
210
|
+
|
211
|
+
it "should support updating" do
|
212
|
+
@klass.default_timeout 10
|
213
|
+
@klass.default_options[:timeout].should == 10
|
214
|
+
end
|
215
|
+
end
|
216
|
+
|
206
217
|
describe "debug_output" do
|
207
218
|
it "stores the given stream as a default_option" do
|
208
219
|
@klass.debug_output $stdout
|
@@ -222,6 +233,13 @@ describe HTTParty do
|
|
222
233
|
end
|
223
234
|
end
|
224
235
|
|
236
|
+
describe "digest http authentication" do
|
237
|
+
it "should work" do
|
238
|
+
@klass.digest_auth 'foobar', 'secret'
|
239
|
+
@klass.default_options[:digest_auth].should == {:username => 'foobar', :password => 'secret'}
|
240
|
+
end
|
241
|
+
end
|
242
|
+
|
225
243
|
describe "parser" do
|
226
244
|
let(:parser) do
|
227
245
|
Proc.new{ |data, format| CustomParser.parse(data) }
|
@@ -243,7 +261,7 @@ describe HTTParty do
|
|
243
261
|
@klass.format :json
|
244
262
|
class MyParser < HTTParty::Parser
|
245
263
|
SupportedFormats = {}
|
246
|
-
end
|
264
|
+
end unless defined?(MyParser)
|
247
265
|
expect do
|
248
266
|
@klass.parser MyParser
|
249
267
|
end.to raise_error(HTTParty::UnsupportedFormat)
|
@@ -316,6 +334,18 @@ describe HTTParty do
|
|
316
334
|
end
|
317
335
|
end
|
318
336
|
|
337
|
+
describe "#maintain_method_across_redirects" do
|
338
|
+
it "sets maintain_method_across_redirects to true by default" do
|
339
|
+
@klass.maintain_method_across_redirects
|
340
|
+
@klass.default_options[:maintain_method_across_redirects].should be_true
|
341
|
+
end
|
342
|
+
|
343
|
+
it "sets the maintain_method_across_redirects option to false" do
|
344
|
+
@klass.maintain_method_across_redirects false
|
345
|
+
@klass.default_options[:maintain_method_across_redirects].should be_false
|
346
|
+
end
|
347
|
+
end
|
348
|
+
|
319
349
|
describe "with explicit override of automatic redirect handling" do
|
320
350
|
before do
|
321
351
|
@request = HTTParty::Request.new(Net::HTTP::Get, 'http://api.foo.com/v1', :format => :xml, :no_follow => true)
|
data/spec/spec_helper.rb
CHANGED
@@ -2,8 +2,6 @@ require File.join(File.dirname(__FILE__), '..', 'lib', 'httparty')
|
|
2
2
|
require 'spec/autorun'
|
3
3
|
require 'fakeweb'
|
4
4
|
|
5
|
-
FakeWeb.allow_net_connect = false
|
6
|
-
|
7
5
|
def file_fixture(filename)
|
8
6
|
open(File.join(File.dirname(__FILE__), 'fixtures', "#{filename.to_s}")).read
|
9
7
|
end
|
@@ -12,4 +10,10 @@ Dir[File.expand_path(File.join(File.dirname(__FILE__),'support','**','*.rb'))].e
|
|
12
10
|
|
13
11
|
Spec::Runner.configure do |config|
|
14
12
|
config.include HTTParty::StubResponse
|
13
|
+
config.before(:suite) do
|
14
|
+
FakeWeb.allow_net_connect = false
|
15
|
+
end
|
16
|
+
config.after(:suite) do
|
17
|
+
FakeWeb.allow_net_connect = true
|
18
|
+
end
|
15
19
|
end
|
@@ -14,7 +14,7 @@ module HTTParty
|
|
14
14
|
end
|
15
15
|
|
16
16
|
def stub_response(body, code = 200)
|
17
|
-
unless @http
|
17
|
+
unless defined?(@http) && @http
|
18
18
|
@http = Net::HTTP.new('localhost', 80)
|
19
19
|
@request.stub!(:http).and_return(@http)
|
20
20
|
@request.stub!(:uri).and_return(URI.parse("http://foo.com/foobar"))
|
metadata
CHANGED
@@ -5,9 +5,9 @@ version: !ruby/object:Gem::Version
|
|
5
5
|
segments:
|
6
6
|
- 0
|
7
7
|
- 5
|
8
|
-
- 2
|
9
8
|
- 3
|
10
|
-
|
9
|
+
- 4
|
10
|
+
version: 0.5.3.4
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- John Nunemaker
|
@@ -16,7 +16,7 @@ autorequire:
|
|
16
16
|
bindir: bin
|
17
17
|
cert_chain: []
|
18
18
|
|
19
|
-
date: 2010-
|
19
|
+
date: 2010-05-26 00:00:00 +08:00
|
20
20
|
default_executable: httparty
|
21
21
|
dependencies:
|
22
22
|
- !ruby/object:Gem::Dependency
|
@@ -29,8 +29,8 @@ dependencies:
|
|
29
29
|
segments:
|
30
30
|
- 0
|
31
31
|
- 1
|
32
|
-
-
|
33
|
-
version: 0.1.
|
32
|
+
- 7
|
33
|
+
version: 0.1.7
|
34
34
|
type: :runtime
|
35
35
|
version_requirements: *id001
|
36
36
|
- !ruby/object:Gem::Dependency
|
@@ -55,8 +55,8 @@ dependencies:
|
|
55
55
|
- !ruby/object:Gem::Version
|
56
56
|
segments:
|
57
57
|
- 0
|
58
|
-
-
|
59
|
-
version: "0.
|
58
|
+
- 7
|
59
|
+
version: "0.7"
|
60
60
|
type: :development
|
61
61
|
version_requirements: *id003
|
62
62
|
- !ruby/object:Gem::Dependency
|
@@ -90,13 +90,12 @@ dependencies:
|
|
90
90
|
prerelease: false
|
91
91
|
requirement: &id006 !ruby/object:Gem::Requirement
|
92
92
|
requirements:
|
93
|
-
- -
|
93
|
+
- - ~>
|
94
94
|
- !ruby/object:Gem::Version
|
95
95
|
segments:
|
96
96
|
- 1
|
97
|
-
-
|
98
|
-
|
99
|
-
version: 1.2.9
|
97
|
+
- 3
|
98
|
+
version: "1.3"
|
100
99
|
type: :development
|
101
100
|
version_requirements: *id006
|
102
101
|
description: Makes http fun! Also, makes consuming restful web services dead easy.
|
@@ -128,6 +127,7 @@ files:
|
|
128
127
|
- features/basic_authentication.feature
|
129
128
|
- features/command_line.feature
|
130
129
|
- features/deals_with_http_error_codes.feature
|
130
|
+
- features/digest_authentication.feature
|
131
131
|
- features/handles_multiple_formats.feature
|
132
132
|
- features/steps/env.rb
|
133
133
|
- features/steps/httparty_response_steps.rb
|
@@ -142,6 +142,7 @@ files:
|
|
142
142
|
- lib/httparty/core_extensions.rb
|
143
143
|
- lib/httparty/exceptions.rb
|
144
144
|
- lib/httparty/module_inheritable_attributes.rb
|
145
|
+
- lib/httparty/net_digest_auth.rb
|
145
146
|
- lib/httparty/parser.rb
|
146
147
|
- lib/httparty/request.rb
|
147
148
|
- lib/httparty/response.rb
|
@@ -162,7 +163,7 @@ files:
|
|
162
163
|
- website/css/common.css
|
163
164
|
- website/index.html
|
164
165
|
has_rdoc: true
|
165
|
-
homepage: http://httparty
|
166
|
+
homepage: http://github.com/jugend/httparty
|
166
167
|
licenses: []
|
167
168
|
|
168
169
|
post_install_message: When you HTTParty, you must party hard!
|