hugs 2.0.0 → 2.1.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/Gemfile +1 -0
- data/Gemfile.lock +2 -0
- data/README.md +4 -0
- data/VERSION +1 -1
- data/hugs.gemspec +5 -2
- data/lib/hugs.rb +35 -18
- data/test/test_hugs.rb +91 -35
- metadata +26 -11
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -9,6 +9,7 @@ GEM
|
|
9
9
|
git (>= 1.2.5)
|
10
10
|
rake
|
11
11
|
minitest (2.0.0)
|
12
|
+
multipart-post (1.0.1)
|
12
13
|
net-http-persistent (1.4.1)
|
13
14
|
nokogiri (1.4.4)
|
14
15
|
rake (0.8.7)
|
@@ -23,6 +24,7 @@ PLATFORMS
|
|
23
24
|
DEPENDENCIES
|
24
25
|
jeweler (~> 1.5.1)
|
25
26
|
minitest (~> 2.0.0)
|
27
|
+
multipart-post (~> 1.0.1)
|
26
28
|
net-http-persistent (~> 1.4.1)
|
27
29
|
nokogiri (~> 1.4.4)
|
28
30
|
rake
|
data/README.md
CHANGED
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
2.
|
1
|
+
2.1.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.1.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{2010-12-
|
12
|
+
s.date = %q{2010-12-23}
|
13
13
|
s.email = %q{john@dewey.ws}
|
14
14
|
s.extra_rdoc_files = [
|
15
15
|
"LICENSE",
|
@@ -45,6 +45,7 @@ Gem::Specification.new do |s|
|
|
45
45
|
s.add_runtime_dependency(%q<yajl-ruby>, ["~> 0.7.8"])
|
46
46
|
s.add_runtime_dependency(%q<nokogiri>, ["~> 1.4.4"])
|
47
47
|
s.add_runtime_dependency(%q<net-http-persistent>, ["~> 1.4.1"])
|
48
|
+
s.add_runtime_dependency(%q<multipart-post>, ["~> 1.0.1"])
|
48
49
|
s.add_development_dependency(%q<rake>, [">= 0"])
|
49
50
|
s.add_development_dependency(%q<jeweler>, ["~> 1.5.1"])
|
50
51
|
s.add_development_dependency(%q<minitest>, ["~> 2.0.0"])
|
@@ -53,6 +54,7 @@ Gem::Specification.new do |s|
|
|
53
54
|
s.add_dependency(%q<yajl-ruby>, ["~> 0.7.8"])
|
54
55
|
s.add_dependency(%q<nokogiri>, ["~> 1.4.4"])
|
55
56
|
s.add_dependency(%q<net-http-persistent>, ["~> 1.4.1"])
|
57
|
+
s.add_dependency(%q<multipart-post>, ["~> 1.0.1"])
|
56
58
|
s.add_dependency(%q<rake>, [">= 0"])
|
57
59
|
s.add_dependency(%q<jeweler>, ["~> 1.5.1"])
|
58
60
|
s.add_dependency(%q<minitest>, ["~> 2.0.0"])
|
@@ -62,6 +64,7 @@ Gem::Specification.new do |s|
|
|
62
64
|
s.add_dependency(%q<yajl-ruby>, ["~> 0.7.8"])
|
63
65
|
s.add_dependency(%q<nokogiri>, ["~> 1.4.4"])
|
64
66
|
s.add_dependency(%q<net-http-persistent>, ["~> 1.4.1"])
|
67
|
+
s.add_dependency(%q<multipart-post>, ["~> 1.0.1"])
|
65
68
|
s.add_dependency(%q<rake>, [">= 0"])
|
66
69
|
s.add_dependency(%q<jeweler>, ["~> 1.5.1"])
|
67
70
|
s.add_dependency(%q<minitest>, ["~> 2.0.0"])
|
data/lib/hugs.rb
CHANGED
@@ -1,6 +1,4 @@
|
|
1
|
-
|
2
|
-
require "yajl"
|
3
|
-
require "nokogiri"
|
1
|
+
%w(net/http/persistent net/http/post/multipart yajl nokogiri).each { |r| require r }
|
4
2
|
|
5
3
|
class Hugs
|
6
4
|
Headers = {
|
@@ -8,7 +6,12 @@ class Hugs
|
|
8
6
|
:xml => "application/xml",
|
9
7
|
}.freeze
|
10
8
|
|
11
|
-
|
9
|
+
Classes = [
|
10
|
+
Net::HTTP::Get,
|
11
|
+
Net::HTTP::Delete,
|
12
|
+
Net::HTTP::Post,
|
13
|
+
Net::HTTP::Put,
|
14
|
+
].freeze
|
12
15
|
|
13
16
|
##
|
14
17
|
# Required options:
|
@@ -36,11 +39,12 @@ class Hugs
|
|
36
39
|
# - +:body+: A sub Hash to be JSON encoded, and posted in
|
37
40
|
# the message body.
|
38
41
|
|
39
|
-
|
42
|
+
Classes.each do |clazz|
|
43
|
+
verb = clazz.to_s.split("::")[-1].tr 'A-Z', 'a-z'
|
44
|
+
|
40
45
|
define_method verb do |*args|
|
41
46
|
path = args[0]
|
42
47
|
params = args[1] || {}
|
43
|
-
clazz = eval "Net::HTTP::#{verb.capitalize}"
|
44
48
|
|
45
49
|
response = response_for(clazz, path, params)
|
46
50
|
response.body = parse response.body
|
@@ -66,27 +70,40 @@ private
|
|
66
70
|
# Method arguments have been documented in the callers.
|
67
71
|
|
68
72
|
def response_for request, path, params
|
69
|
-
query
|
70
|
-
body
|
73
|
+
query = params[:query] && params.delete(:query)
|
74
|
+
body = params[:body] && params.delete(:body)
|
75
|
+
upload = params[:upload] && params.delete(:upload)
|
71
76
|
|
72
77
|
@http ||= Net::HTTP::Persistent.new
|
73
78
|
@url ||= URI.parse "#{@scheme}://#{@host}:#{@port}"
|
74
79
|
|
75
|
-
|
76
|
-
|
77
|
-
|
80
|
+
if upload && request.class === Net::HTTP::Post
|
81
|
+
parts = upload[:parts] || {}
|
82
|
+
parts[:file] = UploadIO.new(parts[:file], upload[:content_type]) if parts[:file]
|
83
|
+
|
84
|
+
request = Net::HTTP::Post::Multipart.new path_with_query(path, query), parts
|
85
|
+
else
|
86
|
+
request = request.new path_with_query path, query
|
87
|
+
request.body = encode(body) if body
|
88
|
+
|
89
|
+
common_headers request
|
90
|
+
end
|
78
91
|
|
92
|
+
request.basic_auth(@user, @password) if requires_authentication?
|
79
93
|
@http.request(@url, request)
|
80
94
|
end
|
81
95
|
|
96
|
+
def path_with_query path, query
|
97
|
+
[path, query].compact.join "?"
|
98
|
+
end
|
99
|
+
|
82
100
|
def common_headers request
|
83
|
-
request
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
request.add_field "
|
89
|
-
request.add_field "content-type", Headers[@type]
|
101
|
+
case request
|
102
|
+
when Net::HTTP::Get, Net::HTTP::Delete
|
103
|
+
request.add_field "Accept", Headers[@type]
|
104
|
+
when Net::HTTP::Post, Net::HTTP::Put
|
105
|
+
request.add_field "Accept", Headers[@type]
|
106
|
+
request.add_field "Content-Type", Headers[@type]
|
90
107
|
end
|
91
108
|
end
|
92
109
|
|
data/test/test_hugs.rb
CHANGED
@@ -2,10 +2,14 @@
|
|
2
2
|
|
3
3
|
describe Hugs do
|
4
4
|
before do
|
5
|
+
@scheme = "https"
|
6
|
+
@host = "example.com"
|
7
|
+
@port = 80
|
8
|
+
@base = "#{@host}:#{@port}"
|
5
9
|
@valid_options = {
|
6
|
-
:host =>
|
7
|
-
:port =>
|
8
|
-
:scheme =>
|
10
|
+
:host => @host,
|
11
|
+
:port => @port,
|
12
|
+
:scheme => @scheme,
|
9
13
|
}
|
10
14
|
|
11
15
|
WebMock.reset!
|
@@ -17,39 +21,91 @@ describe Hugs do
|
|
17
21
|
@request = Net::HTTP::Get
|
18
22
|
end
|
19
23
|
|
20
|
-
|
21
|
-
|
24
|
+
describe "path" do
|
25
|
+
it "is valid" do
|
26
|
+
stub_request :get, "#{@scheme}://#{@base}/"
|
22
27
|
|
23
|
-
|
28
|
+
@instance.send :response_for, @request, "/", {}
|
24
29
|
|
25
|
-
|
26
|
-
|
30
|
+
assert_requested :get, "#{@scheme}://#{@base}/"
|
31
|
+
end
|
32
|
+
|
33
|
+
it "is valid when an invalid :query is supplied" do
|
34
|
+
stub_request :get, "#{@scheme}://#{@base}/"
|
35
|
+
|
36
|
+
@instance.send :response_for, @request, "/", :query => nil
|
37
|
+
|
38
|
+
assert_requested :get, "#{@scheme}://#{@base}/"
|
39
|
+
end
|
27
40
|
|
28
|
-
|
29
|
-
|
41
|
+
it "also has a query string" do
|
42
|
+
stub_request(:get, "#{@scheme}://#{@base}/").with:query => {"foo" => "bar"}
|
30
43
|
|
31
|
-
|
44
|
+
@instance.send :response_for, @request, "/", :query => "foo=bar"
|
32
45
|
|
33
|
-
|
46
|
+
assert_requested :get, "#{@scheme}://#{@base}/", :query => {"foo" => "bar"}
|
47
|
+
end
|
34
48
|
end
|
35
49
|
|
36
|
-
|
37
|
-
|
50
|
+
describe "multi-part" do
|
51
|
+
Content_Type_Matcher = %r{multipart/form-data}
|
52
|
+
|
53
|
+
before do
|
54
|
+
@request = Net::HTTP::Post
|
55
|
+
end
|
56
|
+
|
57
|
+
it "uploads a file" do
|
58
|
+
stub_request :post, "#{@scheme}://#{@base}/"
|
38
59
|
|
39
|
-
|
60
|
+
upload = {
|
61
|
+
:upload => {
|
62
|
+
:parts => { :file => "/dev/null" },
|
63
|
+
:content_type => "type/subtype"
|
64
|
+
}
|
65
|
+
}
|
40
66
|
|
41
|
-
|
67
|
+
@instance.send :response_for, @request, "/", upload
|
68
|
+
|
69
|
+
assert_requested :post, "#{@scheme}://#{@base}/", :body => %r{Content-Type: type/subtype}, :headers => {
|
70
|
+
"Content-Type" => Content_Type_Matcher
|
71
|
+
}
|
72
|
+
end
|
73
|
+
|
74
|
+
it "has parts" do
|
75
|
+
stub_request :post, "#{@scheme}://#{@base}/"
|
76
|
+
|
77
|
+
upload = {
|
78
|
+
:upload => {
|
79
|
+
:parts => { :foo => :bar, :baz => :xyzzy },
|
80
|
+
:content_type => "foo/bar"
|
81
|
+
}
|
82
|
+
}
|
83
|
+
|
84
|
+
@instance.send :response_for, @request, "/", upload
|
85
|
+
|
86
|
+
### wtf can't use mx together.
|
87
|
+
content_disposition_matcher = %r{^Content-Disposition: form-data; name="foo".*^bar.*^Content-Disposition: form-data; name="baz".*^xyzzy.*}m
|
88
|
+
assert_requested :post, "#{@scheme}://#{@base}/", :body => content_disposition_matcher, :headers => {
|
89
|
+
"Content-Type" => Content_Type_Matcher
|
90
|
+
}
|
91
|
+
end
|
42
92
|
end
|
43
93
|
|
44
94
|
describe "body" do
|
45
95
|
before do
|
46
|
-
stub_request :get, "
|
96
|
+
stub_request :get, "#{@scheme}://#{@base}/"
|
47
97
|
end
|
48
98
|
|
49
|
-
it "
|
99
|
+
it "is not set when :body invalid" do
|
50
100
|
@instance.send :response_for, @request, "/", :body => nil
|
51
101
|
|
52
|
-
assert_requested :get, "
|
102
|
+
assert_requested :get, "#{@scheme}://#{@base}/", :body => nil
|
103
|
+
end
|
104
|
+
|
105
|
+
it "is not set when :body is missing" do
|
106
|
+
@instance.send :response_for, @request, "/", {}
|
107
|
+
|
108
|
+
assert_requested :get, "#{@scheme}://#{@base}/", {}
|
53
109
|
end
|
54
110
|
|
55
111
|
describe "json" do
|
@@ -57,10 +113,10 @@ describe Hugs do
|
|
57
113
|
@instance = Hugs.new @valid_options.merge(:type => :json)
|
58
114
|
end
|
59
115
|
|
60
|
-
it "
|
116
|
+
it "is valid" do
|
61
117
|
@instance.send :response_for, @request, "/", :body => {:foo => :bar}
|
62
118
|
|
63
|
-
assert_requested :get, "
|
119
|
+
assert_requested :get, "#{@scheme}://#{@base}/", :body => '{"foo":"bar"}'
|
64
120
|
end
|
65
121
|
end
|
66
122
|
|
@@ -69,35 +125,35 @@ describe Hugs do
|
|
69
125
|
@instance = Hugs.new @valid_options.merge(:type => :xml)
|
70
126
|
end
|
71
127
|
|
72
|
-
it "
|
128
|
+
it "is valid" do
|
73
129
|
@instance.send :response_for, @request, "/", :body => "foo bar"
|
74
130
|
|
75
|
-
assert_requested :get, "
|
131
|
+
assert_requested :get, "#{@scheme}://#{@base}/", :body => "foo bar"
|
76
132
|
end
|
77
133
|
end
|
78
134
|
end
|
79
135
|
|
80
136
|
describe "headers" do
|
81
137
|
it "authenticates" do
|
82
|
-
stub_request :get, "
|
138
|
+
stub_request :get, "#{@scheme}://user:credentials@#{@base}/"
|
83
139
|
|
84
140
|
@instance = Hugs.new @valid_options.merge(:user => "user", :password => "credentials")
|
85
141
|
|
86
142
|
@instance.send :response_for, @request, "/", {}
|
87
143
|
|
88
|
-
assert_requested :get, "
|
144
|
+
assert_requested :get, "#{@scheme}://user:credentials@#{@base}/"
|
89
145
|
end
|
90
146
|
|
91
147
|
[:user, :password].each do |option|
|
92
148
|
it "doesn't authenticate when '#{option}' missing" do
|
93
|
-
stub_request :get, "
|
149
|
+
stub_request :get, "#{@scheme}://#{@base}/"
|
94
150
|
|
95
151
|
invalid_options = @valid_options.reject { |k,v| k == option }
|
96
152
|
@instance = Hugs.new invalid_options
|
97
153
|
|
98
154
|
@instance.send :response_for, @request, "/", {}
|
99
155
|
|
100
|
-
assert_requested :get, "
|
156
|
+
assert_requested :get, "#{@scheme}://#{@base}/"
|
101
157
|
end
|
102
158
|
end
|
103
159
|
|
@@ -110,13 +166,13 @@ describe Hugs do
|
|
110
166
|
clazz = eval "Net::HTTP::#{verb.capitalize}"
|
111
167
|
|
112
168
|
it "has '#{subtype}' Content-Type and Accept for '#{clazz}'" do
|
113
|
-
stub_request verb, "
|
169
|
+
stub_request verb, "#{@scheme}://#{@base}/"
|
114
170
|
|
115
171
|
@instance = Hugs.new @valid_options.merge(:type => type)
|
116
172
|
|
117
173
|
@instance.send :response_for, clazz, "/", {}
|
118
174
|
|
119
|
-
assert_requested verb, "
|
175
|
+
assert_requested verb, "#{@scheme}://#{@base}/", :headers => {
|
120
176
|
"Accept" => ["*/*", subtype], "Content-Type" => subtype }
|
121
177
|
end
|
122
178
|
end
|
@@ -125,13 +181,13 @@ describe Hugs do
|
|
125
181
|
clazz = eval "Net::HTTP::#{verb.capitalize}"
|
126
182
|
|
127
183
|
it "has '#{subtype}' Accept for '#{clazz}'" do
|
128
|
-
stub_request verb, "
|
184
|
+
stub_request verb, "#{@scheme}://#{@base}/"
|
129
185
|
|
130
186
|
@instance = Hugs.new @valid_options.merge(:type => type)
|
131
187
|
|
132
188
|
@instance.send :response_for, clazz, "/", {}
|
133
189
|
|
134
|
-
assert_requested verb, "
|
190
|
+
assert_requested verb, "#{@scheme}://#{@base}/", :headers => {
|
135
191
|
"Accept" => ["*/*", subtype] }
|
136
192
|
end
|
137
193
|
end
|
@@ -146,8 +202,8 @@ describe Hugs do
|
|
146
202
|
@instance = Hugs.new @valid_options.merge(:type => :json)
|
147
203
|
end
|
148
204
|
|
149
|
-
it "objectifies
|
150
|
-
stub_request(:get, "
|
205
|
+
it "objectifies and returns a hash" do
|
206
|
+
stub_request(:get, "#{@scheme}://#{@base}/").to_return :body => '{"foo":"bar"}'
|
151
207
|
|
152
208
|
response = @instance.get "/", :body => { :foo => :bar }
|
153
209
|
|
@@ -160,8 +216,8 @@ describe Hugs do
|
|
160
216
|
@instance = Hugs.new @valid_options.merge(:type => :xml)
|
161
217
|
end
|
162
218
|
|
163
|
-
it "parses
|
164
|
-
stub_request(:get, "
|
219
|
+
it "parses and returns a Nokogiri object" do
|
220
|
+
stub_request(:get, "#{@scheme}://#{@base}/").to_return :body => "<STORAGE></STORAGE>"
|
165
221
|
|
166
222
|
response = @instance.get "/", :body => { :foo => :bar }
|
167
223
|
|
metadata
CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
|
|
4
4
|
prerelease: false
|
5
5
|
segments:
|
6
6
|
- 2
|
7
|
+
- 1
|
7
8
|
- 0
|
8
|
-
|
9
|
-
version: 2.0.0
|
9
|
+
version: 2.1.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: 2010-12-
|
17
|
+
date: 2010-12-23 00:00:00 -08:00
|
18
18
|
default_executable:
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
@@ -63,8 +63,23 @@ dependencies:
|
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: *id003
|
65
65
|
- !ruby/object:Gem::Dependency
|
66
|
-
name:
|
66
|
+
name: multipart-post
|
67
67
|
requirement: &id004 !ruby/object:Gem::Requirement
|
68
|
+
none: false
|
69
|
+
requirements:
|
70
|
+
- - ~>
|
71
|
+
- !ruby/object:Gem::Version
|
72
|
+
segments:
|
73
|
+
- 1
|
74
|
+
- 0
|
75
|
+
- 1
|
76
|
+
version: 1.0.1
|
77
|
+
type: :runtime
|
78
|
+
prerelease: false
|
79
|
+
version_requirements: *id004
|
80
|
+
- !ruby/object:Gem::Dependency
|
81
|
+
name: rake
|
82
|
+
requirement: &id005 !ruby/object:Gem::Requirement
|
68
83
|
none: false
|
69
84
|
requirements:
|
70
85
|
- - ">="
|
@@ -74,10 +89,10 @@ dependencies:
|
|
74
89
|
version: "0"
|
75
90
|
type: :development
|
76
91
|
prerelease: false
|
77
|
-
version_requirements: *
|
92
|
+
version_requirements: *id005
|
78
93
|
- !ruby/object:Gem::Dependency
|
79
94
|
name: jeweler
|
80
|
-
requirement: &
|
95
|
+
requirement: &id006 !ruby/object:Gem::Requirement
|
81
96
|
none: false
|
82
97
|
requirements:
|
83
98
|
- - ~>
|
@@ -89,10 +104,10 @@ dependencies:
|
|
89
104
|
version: 1.5.1
|
90
105
|
type: :development
|
91
106
|
prerelease: false
|
92
|
-
version_requirements: *
|
107
|
+
version_requirements: *id006
|
93
108
|
- !ruby/object:Gem::Dependency
|
94
109
|
name: minitest
|
95
|
-
requirement: &
|
110
|
+
requirement: &id007 !ruby/object:Gem::Requirement
|
96
111
|
none: false
|
97
112
|
requirements:
|
98
113
|
- - ~>
|
@@ -104,10 +119,10 @@ dependencies:
|
|
104
119
|
version: 2.0.0
|
105
120
|
type: :development
|
106
121
|
prerelease: false
|
107
|
-
version_requirements: *
|
122
|
+
version_requirements: *id007
|
108
123
|
- !ruby/object:Gem::Dependency
|
109
124
|
name: webmock
|
110
|
-
requirement: &
|
125
|
+
requirement: &id008 !ruby/object:Gem::Requirement
|
111
126
|
none: false
|
112
127
|
requirements:
|
113
128
|
- - "="
|
@@ -119,7 +134,7 @@ dependencies:
|
|
119
134
|
version: 1.6.1
|
120
135
|
type: :development
|
121
136
|
prerelease: false
|
122
|
-
version_requirements: *
|
137
|
+
version_requirements: *id008
|
123
138
|
description:
|
124
139
|
email: john@dewey.ws
|
125
140
|
executables: []
|