hugs 2.2.0 → 2.3.0
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/README.md +0 -4
- data/VERSION +1 -1
- data/hugs.gemspec +2 -2
- data/lib/hugs/errors.rb +10 -6
- data/test/lib/hugs/client_test.rb +32 -41
- data/test/lib/hugs/errors_test.rb +26 -54
- data/test/test_helper.rb +18 -1
- metadata +3 -3
data/README.md
CHANGED
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
2.
|
1
|
+
2.3.0
|
data/hugs.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{hugs}
|
8
|
-
s.version = "2.
|
8
|
+
s.version = "2.3.0"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["retr0h"]
|
12
|
-
s.date = %q{2011-01-
|
12
|
+
s.date = %q{2011-01-13}
|
13
13
|
s.email = %q{john@dewey.ws}
|
14
14
|
s.extra_rdoc_files = [
|
15
15
|
"LICENSE",
|
data/lib/hugs/errors.rb
CHANGED
@@ -3,7 +3,10 @@ module Hugs
|
|
3
3
|
class Error < StandardError; end
|
4
4
|
|
5
5
|
class HTTPStatusError < Error
|
6
|
-
|
6
|
+
attr_accessor :response
|
7
|
+
|
8
|
+
def initialize msg, response
|
9
|
+
@response = response
|
7
10
|
super msg
|
8
11
|
end
|
9
12
|
end
|
@@ -66,15 +69,16 @@ module Hugs
|
|
66
69
|
}
|
67
70
|
|
68
71
|
case response.code
|
69
|
-
when raise_4xx && %r{^4[0-9]{2}$} ; raise_for(response
|
70
|
-
when raise_5xx && %r{^5[0-9]{2}$} ; raise_for(response
|
72
|
+
when raise_4xx && %r{^4[0-9]{2}$} ; raise_for(response)
|
73
|
+
when raise_5xx && %r{^5[0-9]{2}$} ; raise_for(response)
|
71
74
|
end
|
72
75
|
end
|
73
76
|
|
74
77
|
private
|
75
|
-
def self.raise_for
|
76
|
-
error, message = @errors[code.to_i]
|
77
|
-
|
78
|
+
def self.raise_for response
|
79
|
+
error, message = @errors[response.code.to_i]
|
80
|
+
|
81
|
+
raise error.new message, response
|
78
82
|
end
|
79
83
|
end
|
80
84
|
end
|
@@ -2,18 +2,9 @@
|
|
2
2
|
|
3
3
|
describe Hugs::Client do
|
4
4
|
before do
|
5
|
-
@
|
6
|
-
@host = "example.com"
|
7
|
-
@port = 80
|
8
|
-
@base = "#{@host}:#{@port}"
|
9
|
-
@valid_options = {
|
10
|
-
:host => @host,
|
11
|
-
:port => @port,
|
12
|
-
:scheme => @scheme,
|
13
|
-
}
|
5
|
+
@instance = Hugs::Client.new valid_options
|
14
6
|
|
15
7
|
WebMock.reset!
|
16
|
-
@instance = Hugs::Client.new @valid_options
|
17
8
|
end
|
18
9
|
|
19
10
|
describe "#response_for" do
|
@@ -23,27 +14,27 @@ describe Hugs::Client do
|
|
23
14
|
|
24
15
|
describe "path" do
|
25
16
|
it "is valid" do
|
26
|
-
stub_request :get,
|
17
|
+
stub_request :get, url
|
27
18
|
|
28
19
|
@instance.send :response_for, @request, "/", {}
|
29
20
|
|
30
|
-
assert_requested :get,
|
21
|
+
assert_requested :get, url
|
31
22
|
end
|
32
23
|
|
33
24
|
it "is valid when an invalid :query is supplied" do
|
34
|
-
stub_request :get,
|
25
|
+
stub_request :get, url
|
35
26
|
|
36
27
|
@instance.send :response_for, @request, "/", :query => nil
|
37
28
|
|
38
|
-
assert_requested :get,
|
29
|
+
assert_requested :get, url
|
39
30
|
end
|
40
31
|
|
41
32
|
it "also has a query string" do
|
42
|
-
stub_request(:get,
|
33
|
+
stub_request(:get, url).with:query => {"foo" => "bar"}
|
43
34
|
|
44
35
|
@instance.send :response_for, @request, "/", :query => "foo=bar"
|
45
36
|
|
46
|
-
assert_requested :get,
|
37
|
+
assert_requested :get, url, :query => {"foo" => "bar"}
|
47
38
|
end
|
48
39
|
end
|
49
40
|
|
@@ -55,7 +46,7 @@ describe Hugs::Client do
|
|
55
46
|
end
|
56
47
|
|
57
48
|
it "uploads a file" do
|
58
|
-
stub_request :post,
|
49
|
+
stub_request :post, url
|
59
50
|
upload = {
|
60
51
|
:upload => {
|
61
52
|
:parts => { :file => "/dev/null" },
|
@@ -65,13 +56,13 @@ describe Hugs::Client do
|
|
65
56
|
|
66
57
|
@instance.send :response_for, @request, "/", upload
|
67
58
|
|
68
|
-
assert_requested :post,
|
59
|
+
assert_requested :post, url, :body => %r{Content-Type: type/subtype}, :headers => {
|
69
60
|
"Content-Type" => Content_Type_Matcher
|
70
61
|
}
|
71
62
|
end
|
72
63
|
|
73
64
|
it "has parts" do
|
74
|
-
stub_request :post,
|
65
|
+
stub_request :post, url
|
75
66
|
upload = {
|
76
67
|
:upload => {
|
77
68
|
:parts => { :foo => :bar, :baz => :xyzzy },
|
@@ -83,7 +74,7 @@ describe Hugs::Client do
|
|
83
74
|
|
84
75
|
### wtf can't use mx together.
|
85
76
|
content_disposition_matcher = %r{^Content-Disposition: form-data; name="foo".*^bar.*^Content-Disposition: form-data; name="baz".*^xyzzy.*}m
|
86
|
-
assert_requested :post,
|
77
|
+
assert_requested :post, url, :body => content_disposition_matcher, :headers => {
|
87
78
|
"Content-Type" => Content_Type_Matcher
|
88
79
|
}
|
89
80
|
end
|
@@ -93,8 +84,8 @@ describe Hugs::Client do
|
|
93
84
|
describe "parses response" do
|
94
85
|
describe "json" do
|
95
86
|
it "objectifies and returns a hash" do
|
96
|
-
stub_request(:get,
|
97
|
-
instance = Hugs::Client.new
|
87
|
+
stub_request(:get, url).to_return :body => '{"foo":"bar"}'
|
88
|
+
instance = Hugs::Client.new valid_options(:type => :json)
|
98
89
|
|
99
90
|
response = instance.get "/"
|
100
91
|
|
@@ -104,8 +95,8 @@ describe Hugs::Client do
|
|
104
95
|
|
105
96
|
describe "xml" do
|
106
97
|
it "parses and returns a Nokogiri object" do
|
107
|
-
stub_request(:get,
|
108
|
-
instance = Hugs::Client.new
|
98
|
+
stub_request(:get, url).to_return :body => "<STORAGE></STORAGE>"
|
99
|
+
instance = Hugs::Client.new valid_options(:type => :xml)
|
109
100
|
|
110
101
|
response = instance.get "/"
|
111
102
|
|
@@ -116,38 +107,38 @@ describe Hugs::Client do
|
|
116
107
|
|
117
108
|
describe "encodes request" do
|
118
109
|
before do
|
119
|
-
stub_request :get,
|
110
|
+
stub_request :get, url
|
120
111
|
end
|
121
112
|
|
122
113
|
it "is not set when :body invalid" do
|
123
114
|
@instance.send :response_for, @request, "/", :body => nil
|
124
115
|
|
125
|
-
assert_requested :get,
|
116
|
+
assert_requested :get, url, :body => nil
|
126
117
|
end
|
127
118
|
|
128
119
|
it "is not set when :body is missing" do
|
129
120
|
@instance.send :response_for, @request, "/", {}
|
130
121
|
|
131
|
-
assert_requested :get,
|
122
|
+
assert_requested :get, url, {}
|
132
123
|
end
|
133
124
|
|
134
125
|
describe "json" do
|
135
126
|
it "is valid" do
|
136
|
-
instance = Hugs::Client.new
|
127
|
+
instance = Hugs::Client.new valid_options(:type => :json)
|
137
128
|
|
138
129
|
instance.send :response_for, @request, "/", :body => {:foo => :bar}
|
139
130
|
|
140
|
-
assert_requested :get,
|
131
|
+
assert_requested :get, url, :body => '{"foo":"bar"}'
|
141
132
|
end
|
142
133
|
end
|
143
134
|
|
144
135
|
describe "xml" do
|
145
136
|
it "is valid" do
|
146
|
-
instance = Hugs::Client.new
|
137
|
+
instance = Hugs::Client.new valid_options(:type => :xml)
|
147
138
|
|
148
139
|
instance.send :response_for, @request, "/", :body => "foo bar"
|
149
140
|
|
150
|
-
assert_requested :get,
|
141
|
+
assert_requested :get, url, :body => "foo bar"
|
151
142
|
end
|
152
143
|
end
|
153
144
|
end
|
@@ -157,11 +148,11 @@ describe Hugs::Client do
|
|
157
148
|
describe "headers" do
|
158
149
|
describe "authentication" do
|
159
150
|
it "uses basic auth when providing user and password" do
|
160
|
-
stub_request :get, "
|
161
|
-
instance = Hugs::Client.new
|
151
|
+
stub_request :get, url("/", "user:credentials")
|
152
|
+
instance = Hugs::Client.new valid_options(:user => "user", :password => "credentials")
|
162
153
|
|
163
154
|
instance.send :response_for, @request, "/", {}
|
164
|
-
assert_requested :get, "
|
155
|
+
assert_requested :get, url("/", "user:credentials")
|
165
156
|
end
|
166
157
|
|
167
158
|
it "doesn't use basic auth without a user" do
|
@@ -216,26 +207,26 @@ describe Hugs::Client do
|
|
216
207
|
|
217
208
|
assert mimetype, "Unsupported Mimetype '#{type}'"
|
218
209
|
|
219
|
-
clazz =
|
210
|
+
clazz = Net::HTTP.const_get verb.capitalize
|
220
211
|
|
221
|
-
stub_request verb,
|
222
|
-
instance = Hugs::Client.new
|
212
|
+
stub_request verb, url
|
213
|
+
instance = Hugs::Client.new valid_options(:type => type)
|
223
214
|
|
224
215
|
instance.send :response_for, clazz, "/", {}
|
225
216
|
|
226
217
|
headers = { "Accept" => ["*/*", mimetype] }
|
227
218
|
headers["Content-Type"] = mimetype if [:put, :put].include? type
|
228
219
|
|
229
|
-
assert_requested verb,
|
220
|
+
assert_requested verb, url, :headers => headers
|
230
221
|
end
|
231
222
|
|
232
223
|
def assert_doesnt_use_basic_auth_without option
|
233
|
-
stub_request :get,
|
234
|
-
instance = Hugs::Client.new
|
224
|
+
stub_request :get, url
|
225
|
+
instance = Hugs::Client.new valid_options(option => "value")
|
235
226
|
|
236
227
|
instance.send :response_for, @request, "/", {}
|
237
228
|
|
238
|
-
assert_requested :get,
|
229
|
+
assert_requested :get, url
|
239
230
|
end
|
240
231
|
end
|
241
232
|
end
|
@@ -2,73 +2,45 @@ require "test_helper"
|
|
2
2
|
|
3
3
|
describe Hugs::Errors do
|
4
4
|
before do
|
5
|
-
@
|
6
|
-
@host = "example.com"
|
7
|
-
@port = 80
|
8
|
-
@base = "#{@host}:#{@port}"
|
9
|
-
@valid_options = {
|
10
|
-
:host => @host,
|
11
|
-
:port => @port,
|
12
|
-
:scheme => @scheme,
|
13
|
-
}
|
5
|
+
@instance = Hugs::Client.new valid_options
|
14
6
|
|
15
|
-
@instance = Hugs::Client.new @valid_options
|
16
7
|
WebMock.reset!
|
17
8
|
end
|
18
9
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
402 => [Hugs::Errors::PaymentRequired, 'Payment Required'],
|
23
|
-
403 => [Hugs::Errors::Forbidden, 'Forbidden'],
|
24
|
-
404 => [Hugs::Errors::NotFound, 'Not Found'],
|
25
|
-
405 => [Hugs::Errors::MethodNotAllowed, 'Method Not Allowed'],
|
26
|
-
406 => [Hugs::Errors::NotAcceptable, 'Not Acceptable'],
|
27
|
-
407 => [Hugs::Errors::ProxyAuthenticationRequired, 'Proxy Authentication Required'],
|
28
|
-
408 => [Hugs::Errors::RequestTimeout, 'Request Timeout'],
|
29
|
-
409 => [Hugs::Errors::Conflict, 'Conflict'],
|
30
|
-
410 => [Hugs::Errors::Gone, 'Gone'],
|
31
|
-
411 => [Hugs::Errors::LengthRequired, 'Length Required'],
|
32
|
-
412 => [Hugs::Errors::PreconditionFailed, 'Precondition Failed'],
|
33
|
-
413 => [Hugs::Errors::RequestEntityTooLarge, 'Request Entity Too Large'],
|
34
|
-
414 => [Hugs::Errors::RequestURITooLong, 'Request-URI Too Long'],
|
35
|
-
415 => [Hugs::Errors::UnsupportedMediaType, 'Unsupported Media Type'],
|
36
|
-
416 => [Hugs::Errors::RequestedRangeNotSatisfiable, 'Request Range Not Satisfiable'],
|
37
|
-
417 => [Hugs::Errors::ExpectationFailed, 'Expectation Failed'],
|
38
|
-
422 => [Hugs::Errors::UnprocessableEntity, 'Unprocessable Entity'],
|
39
|
-
}
|
10
|
+
describe "response codes" do
|
11
|
+
Errors_4xx = (400..417).to_a << 422
|
12
|
+
Errors_5xx = (500..504).to_a
|
40
13
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
503 => [Hugs::Errors::ServiceUnavailable, 'Service Unavailable'],
|
46
|
-
504 => [Hugs::Errors::GatewayTimeout, 'Gateway Timeout']
|
47
|
-
}
|
14
|
+
(Errors_4xx + Errors_5xx).each do |code|
|
15
|
+
it "raises on #{code}" do
|
16
|
+
assert_raises_on code
|
17
|
+
end
|
48
18
|
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
@instance.raise_5xx = false
|
19
|
+
it "does not raise on #{code}" do
|
20
|
+
assert_does_not_raise_on code
|
21
|
+
end
|
53
22
|
end
|
54
23
|
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
it "raises" do
|
59
|
-
(code.to_s =~ %r{^4[0-9]{2}$}) ? (@instance.raise_4xx = true) : (@instance.raise_5xx = true)
|
60
|
-
stub_request(:get, "#{@scheme}://#{@base}/").to_return :status => [code, message]
|
24
|
+
def assert_raises_on code
|
25
|
+
(code.to_s =~ %r{^4[0-9]{2}$}) ? (@instance.raise_4xx = true) : (@instance.raise_5xx = true)
|
26
|
+
stub_request(:get, url).to_return :status => [code, "error #{code}"]
|
61
27
|
|
62
|
-
|
28
|
+
begin
|
29
|
+
@instance.send :response_for, Net::HTTP::Get, "/", {}
|
30
|
+
rescue => e
|
31
|
+
e.class.superclass.must_be_same_as Hugs::Errors::HTTPStatusError
|
32
|
+
e.must_respond_to :response
|
33
|
+
return
|
63
34
|
end
|
35
|
+
raise StandardError.new "did not raise expected exception"
|
36
|
+
end
|
64
37
|
|
65
|
-
|
66
|
-
|
38
|
+
def assert_does_not_raise_on code
|
39
|
+
stub_request(:get, url).to_return :status => [code, "error #{code}"]
|
67
40
|
|
68
|
-
|
41
|
+
response = @instance.send :response_for, Net::HTTP::Get, "/", {}
|
69
42
|
|
70
|
-
|
71
|
-
end
|
43
|
+
response.code.must_equal code.to_s
|
72
44
|
end
|
73
45
|
end
|
74
46
|
end
|
data/test/test_helper.rb
CHANGED
@@ -1,10 +1,27 @@
|
|
1
1
|
require "bundler"
|
2
2
|
Bundler.setup :default, :test
|
3
3
|
|
4
|
-
%w(minitest/spec webmock ./lib/hugs).each { |r| require r }
|
4
|
+
%w(minitest/spec webmock ./lib/hugs uri).each { |r| require r }
|
5
5
|
|
6
6
|
class MiniTest::Unit::TestCase
|
7
7
|
include WebMock::API
|
8
|
+
|
9
|
+
def valid_options opts = {}
|
10
|
+
{
|
11
|
+
:host => "example.com",
|
12
|
+
:port => 80,
|
13
|
+
:scheme => "https"
|
14
|
+
}.merge opts
|
15
|
+
end
|
16
|
+
|
17
|
+
def url path = "/", credentials = nil
|
18
|
+
URI::HTTPS.build(
|
19
|
+
valid_options(
|
20
|
+
:path => path,
|
21
|
+
:userinfo => credentials
|
22
|
+
)
|
23
|
+
).to_s
|
24
|
+
end
|
8
25
|
end
|
9
26
|
|
10
27
|
MiniTest::Unit.autorun
|
metadata
CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
|
|
4
4
|
prerelease: false
|
5
5
|
segments:
|
6
6
|
- 2
|
7
|
-
-
|
7
|
+
- 3
|
8
8
|
- 0
|
9
|
-
version: 2.
|
9
|
+
version: 2.3.0
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- retr0h
|
@@ -14,7 +14,7 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2011-01-
|
17
|
+
date: 2011-01-13 00:00:00 -08:00
|
18
18
|
default_executable:
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|