pillow 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE +20 -0
- data/README.md +15 -0
- data/Rakefile +18 -0
- data/VERSION +1 -0
- data/lib/pillow.rb +9 -0
- data/lib/pillow/method.rb +41 -0
- data/lib/pillow/request.rb +67 -0
- data/lib/pillow/resource.rb +100 -0
- data/lib/pillow/response.rb +18 -0
- data/spec/pillow/method_spec.rb +228 -0
- data/spec/pillow/request_spec.rb +230 -0
- data/spec/pillow/resource_spec.rb +156 -0
- data/spec/pillow/response_spec.rb +42 -0
- data/spec/spec.opts +1 -0
- data/spec/spec_helper.rb +17 -0
- metadata +141 -0
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2010 Alexander Kern and Artcentric Networks LLC
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
# Pillow
|
2
|
+
|
3
|
+
Take a nap, Pillow lets you REST.
|
4
|
+
|
5
|
+
## Description
|
6
|
+
|
7
|
+
Pillow lets you use HTTP to its absolute fullest extent. Rather than expose an API to cover up the details of the protocol, it uses the protocol to structure the client itself. URL's are not defined in the resources, forcing the use of links and URL templates to navigate throughout the web service. Think of it like an automated web browser.
|
8
|
+
|
9
|
+
## Examples
|
10
|
+
|
11
|
+
_Coming soon_
|
12
|
+
|
13
|
+
## License
|
14
|
+
|
15
|
+
Pillow is licensed under the MIT License.
|
data/Rakefile
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
begin
|
2
|
+
require 'jeweler'
|
3
|
+
Jeweler::Tasks.new do |gemspec|
|
4
|
+
gemspec.name = 'pillow'
|
5
|
+
gemspec.summary = 'Take a nap, Pillow lets you REST.'
|
6
|
+
gemspec.description = 'Ruby HTTP client that takes full advantage of HTTP.'
|
7
|
+
gemspec.email = 'alex@kernul.com'
|
8
|
+
gemspec.authors = ['Alexander Kern']
|
9
|
+
|
10
|
+
gemspec.add_dependency('patron')
|
11
|
+
gemspec.add_dependency('json')
|
12
|
+
gemspec.add_dependency('addressable')
|
13
|
+
|
14
|
+
gemspec.add_development_dependency('rspec')
|
15
|
+
end
|
16
|
+
rescue LoadError
|
17
|
+
puts 'Jeweler not available. Install it with: gem install jeweler'
|
18
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.5.0
|
data/lib/pillow.rb
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
class Pillow::Method
|
2
|
+
|
3
|
+
attr_reader :method, :resource
|
4
|
+
|
5
|
+
def initialize(method, resource)
|
6
|
+
@method = method
|
7
|
+
@resource = resource
|
8
|
+
end
|
9
|
+
|
10
|
+
def before(&before)
|
11
|
+
@before = before if before
|
12
|
+
@before
|
13
|
+
end
|
14
|
+
|
15
|
+
def after(&after)
|
16
|
+
@after = after if after
|
17
|
+
@after
|
18
|
+
end
|
19
|
+
|
20
|
+
def process(*args)
|
21
|
+
request = Pillow::Request.new(method, resource.url)
|
22
|
+
request.query_values.replace(resource.query_values)
|
23
|
+
request.headers.replace(resource.headers)
|
24
|
+
|
25
|
+
before.call(request, *args) if before
|
26
|
+
|
27
|
+
options = {}
|
28
|
+
options[:data] = request.raw_body if request.raw_body
|
29
|
+
|
30
|
+
raw_response = resource.session.request(request.method, request.full_url,
|
31
|
+
request.headers, options)
|
32
|
+
|
33
|
+
response = Pillow::Response.new
|
34
|
+
response.status = raw_response.status
|
35
|
+
response.headers = raw_response.headers
|
36
|
+
response.raw_body = raw_response.body
|
37
|
+
|
38
|
+
return after.call(response, *args) if after
|
39
|
+
response
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'addressable/uri'
|
3
|
+
require 'json'
|
4
|
+
|
5
|
+
class Pillow::Request
|
6
|
+
|
7
|
+
HTTP_METHODS = [:options, :get, :head, :post, :put, :delete, :trace, :patch]
|
8
|
+
HTTP_METHODS_WITH_BODY = [:post, :put, :patch]
|
9
|
+
|
10
|
+
attr_reader :method, :url, :query_values, :headers
|
11
|
+
|
12
|
+
def initialize(method, url)
|
13
|
+
self.method = method
|
14
|
+
@url = url
|
15
|
+
@query_values = {}
|
16
|
+
@headers = {}
|
17
|
+
end
|
18
|
+
|
19
|
+
def method=(method)
|
20
|
+
if HTTP_METHODS.include?(method)
|
21
|
+
@method = method
|
22
|
+
end
|
23
|
+
|
24
|
+
@method ||= :get
|
25
|
+
end
|
26
|
+
|
27
|
+
def body
|
28
|
+
if HTTP_METHODS_WITH_BODY.include?(method)
|
29
|
+
@body || ''
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def body=(body)
|
34
|
+
if HTTP_METHODS_WITH_BODY.include?(method)
|
35
|
+
@body = body
|
36
|
+
|
37
|
+
if headers['Content-Type'] == 'application/json'
|
38
|
+
@raw_body = body.to_json
|
39
|
+
else
|
40
|
+
@raw_body = body
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def raw_body
|
46
|
+
if HTTP_METHODS_WITH_BODY.include?(method)
|
47
|
+
@raw_body || ''
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def raw_body=(raw_body)
|
52
|
+
if HTTP_METHODS_WITH_BODY.include?(method)
|
53
|
+
@raw_body = raw_body
|
54
|
+
@body = raw_body
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def full_url
|
59
|
+
if query_values.empty?
|
60
|
+
return url
|
61
|
+
end
|
62
|
+
|
63
|
+
full_url = Addressable::URI.parse(url)
|
64
|
+
full_url.query_values = query_values
|
65
|
+
full_url.to_s
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,100 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'addressable/uri'
|
3
|
+
require 'addressable/template'
|
4
|
+
require 'patron'
|
5
|
+
|
6
|
+
class Pillow::Resource
|
7
|
+
|
8
|
+
attr_reader :url
|
9
|
+
|
10
|
+
def initialize(url)
|
11
|
+
@url = if url.is_a?(Hash)
|
12
|
+
self.class.template.expand(url).to_s
|
13
|
+
else
|
14
|
+
url.to_s
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
class << self
|
19
|
+
def session
|
20
|
+
@session ||= Patron::Session.new
|
21
|
+
end
|
22
|
+
|
23
|
+
def query_values
|
24
|
+
@query_values ||= {}
|
25
|
+
end
|
26
|
+
|
27
|
+
def headers
|
28
|
+
@headers ||= {}
|
29
|
+
end
|
30
|
+
|
31
|
+
def template(template = nil)
|
32
|
+
@template = Addressable::Template.new(template) if template
|
33
|
+
@template
|
34
|
+
end
|
35
|
+
|
36
|
+
def options
|
37
|
+
@options ||= Pillow::Method.new(:options, self)
|
38
|
+
end
|
39
|
+
|
40
|
+
def get
|
41
|
+
@get ||= Pillow::Method.new(:get, self)
|
42
|
+
end
|
43
|
+
|
44
|
+
def head
|
45
|
+
@head ||= Pillow::Method.new(:head, self)
|
46
|
+
end
|
47
|
+
|
48
|
+
def post
|
49
|
+
@post ||= Pillow::Method.new(:post, self)
|
50
|
+
end
|
51
|
+
|
52
|
+
def put
|
53
|
+
@put ||= Pillow::Method.new(:put, self)
|
54
|
+
end
|
55
|
+
|
56
|
+
def delete
|
57
|
+
@delete ||= Pillow::Method.new(:delete, self)
|
58
|
+
end
|
59
|
+
|
60
|
+
def trace
|
61
|
+
@trace ||= Pillow::Method.new(:trace, self)
|
62
|
+
end
|
63
|
+
|
64
|
+
def patch
|
65
|
+
@patch ||= Pillow::Method.new(:patch, self)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def options(*args)
|
70
|
+
self.class.options.process(*args)
|
71
|
+
end
|
72
|
+
|
73
|
+
def get(*args)
|
74
|
+
self.class.get.process(*args)
|
75
|
+
end
|
76
|
+
|
77
|
+
def head(*args)
|
78
|
+
self.class.head.process(*args)
|
79
|
+
end
|
80
|
+
|
81
|
+
def post(*args)
|
82
|
+
self.class.post.process(*args)
|
83
|
+
end
|
84
|
+
|
85
|
+
def put(*args)
|
86
|
+
self.class.put.process(*args)
|
87
|
+
end
|
88
|
+
|
89
|
+
def delete(*args)
|
90
|
+
self.class.delete.process(*args)
|
91
|
+
end
|
92
|
+
|
93
|
+
def trace(*args)
|
94
|
+
self.class.trace.process(*args)
|
95
|
+
end
|
96
|
+
|
97
|
+
def patch(*args)
|
98
|
+
self.class.patch.process(*args)
|
99
|
+
end
|
100
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'json'
|
3
|
+
|
4
|
+
class Pillow::Response
|
5
|
+
|
6
|
+
attr_accessor :status, :headers, :body
|
7
|
+
attr_reader :raw_body
|
8
|
+
|
9
|
+
def raw_body=(raw_body)
|
10
|
+
@raw_body = raw_body
|
11
|
+
|
12
|
+
if headers['Content-Type'] == 'application/json'
|
13
|
+
@body = JSON.parse(raw_body)
|
14
|
+
else
|
15
|
+
@body = raw_body
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,228 @@
|
|
1
|
+
require 'spec/spec_helper'
|
2
|
+
|
3
|
+
describe Pillow::Method do
|
4
|
+
before do
|
5
|
+
@resource = stub('resource')
|
6
|
+
@session = mock('session')
|
7
|
+
@response = stub('response')
|
8
|
+
|
9
|
+
@resource.stub!(:session).and_return(@session)
|
10
|
+
@resource.stub!(:url).and_return('http://foo.com/')
|
11
|
+
@resource.stub!(:query_values).and_return('foo' => 'bar')
|
12
|
+
@resource.stub!(:headers).and_return('X-Foo' => 'Bar')
|
13
|
+
|
14
|
+
@session.stub!(:request).and_return(@response)
|
15
|
+
|
16
|
+
@response.stub!(:body).and_return('test')
|
17
|
+
@response.stub!(:headers).and_return('X-Foo' => 'Bar')
|
18
|
+
@response.stub!(:status).and_return(200)
|
19
|
+
|
20
|
+
@method = Pillow::Method.new(:get, @resource)
|
21
|
+
end
|
22
|
+
|
23
|
+
context 'upon creation' do
|
24
|
+
it 'should have a method' do
|
25
|
+
@method.method.should == :get
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'should have a resource' do
|
29
|
+
@method.resource.should == @resource
|
30
|
+
end
|
31
|
+
|
32
|
+
it 'should not have a before block' do
|
33
|
+
@method.before.should == nil
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'should not have an after block' do
|
37
|
+
@method.after.should == nil
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
describe 'before block' do
|
42
|
+
it 'should be settable with a block' do
|
43
|
+
before_block = Proc.new {}
|
44
|
+
@method.before &before_block
|
45
|
+
|
46
|
+
@method.before.should equal(before_block)
|
47
|
+
end
|
48
|
+
|
49
|
+
it 'should be overwritable' do
|
50
|
+
before_block = Proc.new {}
|
51
|
+
before_block_2 = Proc.new {}
|
52
|
+
@method.before &before_block
|
53
|
+
@method.before &before_block_2
|
54
|
+
|
55
|
+
@method.before.should equal(before_block_2)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
describe 'after block' do
|
60
|
+
it 'should be settable with a block' do
|
61
|
+
after_block = Proc.new {}
|
62
|
+
@method.after &after_block
|
63
|
+
|
64
|
+
@method.after.should equal(after_block)
|
65
|
+
end
|
66
|
+
|
67
|
+
it 'should be overwritable' do
|
68
|
+
after_block = Proc.new {}
|
69
|
+
after_block_2 = Proc.new {}
|
70
|
+
@method.after &after_block
|
71
|
+
@method.after &after_block_2
|
72
|
+
|
73
|
+
@method.after.should equal(after_block_2)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
describe '#process' do
|
78
|
+
context 'when there is no before block' do
|
79
|
+
it 'should not call the before block' do
|
80
|
+
allow_message_expectations_on_nil
|
81
|
+
@method.before.should_not_receive(:call)
|
82
|
+
|
83
|
+
@method.process
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
context 'when there is a before block' do
|
88
|
+
before do
|
89
|
+
@method.before do |request|
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
it 'should create a request with the method' do
|
94
|
+
@method.should_receive(:method).once
|
95
|
+
@method.process
|
96
|
+
end
|
97
|
+
|
98
|
+
it 'should create a request with the resource url' do
|
99
|
+
@resource.should_receive(:url).once
|
100
|
+
@method.process
|
101
|
+
end
|
102
|
+
|
103
|
+
it 'should receive a request with the resource query values' do
|
104
|
+
@method.before do |request|
|
105
|
+
request.query_values.should == {'foo' => 'bar'}
|
106
|
+
end
|
107
|
+
|
108
|
+
@method.process
|
109
|
+
end
|
110
|
+
|
111
|
+
it 'should receive a request with the resource headers' do
|
112
|
+
@method.before do |request|
|
113
|
+
request.headers.should == {'X-Foo' => 'Bar'}
|
114
|
+
end
|
115
|
+
|
116
|
+
@method.process
|
117
|
+
end
|
118
|
+
|
119
|
+
context 'when arguments are supplied' do
|
120
|
+
it 'should call the before block with the arguments' do
|
121
|
+
@method.before do |request, mock_1, mock_2|
|
122
|
+
mock_1.should == 'foo'
|
123
|
+
mock_2.should == 'bar'
|
124
|
+
end
|
125
|
+
|
126
|
+
@method.process('foo', 'bar')
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
it 'should request using the method' do
|
132
|
+
@session.should_receive(:request).with(:get, anything(), anything(), anything())
|
133
|
+
@method.process
|
134
|
+
end
|
135
|
+
|
136
|
+
it 'should request the generated url with the resource session' do
|
137
|
+
@session.should_receive(:request).with(anything(), 'http://foo.com/?foo=bar', anything(), anything())
|
138
|
+
@method.process
|
139
|
+
end
|
140
|
+
|
141
|
+
it 'should include headers with the request' do
|
142
|
+
@session.should_receive(:request).with(anything(), anything(), {'X-Foo' => 'Bar'}, anything())
|
143
|
+
@method.process
|
144
|
+
end
|
145
|
+
|
146
|
+
it 'should include the raw body with the request' do
|
147
|
+
@method = Pillow::Method.new(:put, @resource)
|
148
|
+
@method.before do |request|
|
149
|
+
request.should_receive(:raw_body).at_least(:once).and_return('foo')
|
150
|
+
end
|
151
|
+
|
152
|
+
@session.should_receive(:request).with(:put, anything(), anything(), :data => 'foo')
|
153
|
+
|
154
|
+
@method.process
|
155
|
+
end
|
156
|
+
|
157
|
+
context 'when there is no after block' do
|
158
|
+
it 'should not call the after block' do
|
159
|
+
allow_message_expectations_on_nil
|
160
|
+
@method.before.should_not_receive(:call)
|
161
|
+
|
162
|
+
@method.process
|
163
|
+
end
|
164
|
+
|
165
|
+
it 'should return the response' do
|
166
|
+
@method.process.should be_a_kind_of(Pillow::Response)
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
context 'when there is an after block' do
|
171
|
+
before do
|
172
|
+
@method.after do |response|
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
it 'should receive a response with the response status' do
|
177
|
+
@method.after do |response|
|
178
|
+
response.status.should == 200
|
179
|
+
end
|
180
|
+
|
181
|
+
@method.process
|
182
|
+
end
|
183
|
+
|
184
|
+
it 'should receive a response with the response headers' do
|
185
|
+
@method.after do |response|
|
186
|
+
response.headers.should == {'X-Foo' => 'Bar'}
|
187
|
+
end
|
188
|
+
|
189
|
+
@method.process
|
190
|
+
end
|
191
|
+
|
192
|
+
it 'should receive a response with the response raw body' do
|
193
|
+
@method.after do |response|
|
194
|
+
response.raw_body.should == 'test'
|
195
|
+
end
|
196
|
+
|
197
|
+
@method.process
|
198
|
+
end
|
199
|
+
|
200
|
+
it 'should receive a response with the response body' do
|
201
|
+
@method.after do |response|
|
202
|
+
response.body.should == 'test'
|
203
|
+
end
|
204
|
+
|
205
|
+
@method.process
|
206
|
+
end
|
207
|
+
|
208
|
+
it 'should return the output of the after block' do
|
209
|
+
@method.after do |response|
|
210
|
+
'test'
|
211
|
+
end
|
212
|
+
|
213
|
+
@method.process.should == 'test'
|
214
|
+
end
|
215
|
+
|
216
|
+
context 'when arguments are supplied' do
|
217
|
+
it 'should call the after block with the arguments' do
|
218
|
+
@method.after do |response, mock_1, mock_2|
|
219
|
+
mock_1.should == 'foo'
|
220
|
+
mock_2.should == 'bar'
|
221
|
+
end
|
222
|
+
|
223
|
+
@method.process('foo', 'bar')
|
224
|
+
end
|
225
|
+
end
|
226
|
+
end
|
227
|
+
end
|
228
|
+
end
|
@@ -0,0 +1,230 @@
|
|
1
|
+
require 'spec/spec_helper'
|
2
|
+
|
3
|
+
describe Pillow::Request do
|
4
|
+
before do
|
5
|
+
@request = Pillow::Request.new(:get, 'http://foo.com/')
|
6
|
+
end
|
7
|
+
|
8
|
+
it 'should have a url' do
|
9
|
+
@request.url.should == 'http://foo.com/'
|
10
|
+
end
|
11
|
+
|
12
|
+
describe '#method' do
|
13
|
+
it 'should have a method' do
|
14
|
+
@request.method.should == :get
|
15
|
+
end
|
16
|
+
|
17
|
+
context 'valid methods' do
|
18
|
+
it 'should allow the OPTIONS method' do
|
19
|
+
@request.method = :options
|
20
|
+
@request.method.should == :options
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'should allow the GET method' do
|
24
|
+
@request.method = :get
|
25
|
+
@request.method.should == :get
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'should allow the HEAD method' do
|
29
|
+
@request.method = :head
|
30
|
+
@request.method.should == :head
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'should allow the POST method' do
|
34
|
+
@request.method = :post
|
35
|
+
@request.method.should == :post
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'should allow the PUT method' do
|
39
|
+
@request.method = :put
|
40
|
+
@request.method.should == :put
|
41
|
+
end
|
42
|
+
|
43
|
+
it 'should allow the DELETE method' do
|
44
|
+
@request.method = :delete
|
45
|
+
@request.method.should == :delete
|
46
|
+
end
|
47
|
+
|
48
|
+
it 'should allow the TRACE method' do
|
49
|
+
@request.method = :trace
|
50
|
+
@request.method.should == :trace
|
51
|
+
end
|
52
|
+
|
53
|
+
it 'should allow the PATCH method' do
|
54
|
+
@request.method = :patch
|
55
|
+
@request.method.should == :patch
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
context 'invalid method' do
|
60
|
+
it 'should reset the method to GET' do
|
61
|
+
@request.method = :post
|
62
|
+
@request.method = :fake_method
|
63
|
+
@request.method = :get
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
describe 'query values' do
|
69
|
+
it 'should by default be empty' do
|
70
|
+
@request.query_values.should be_empty
|
71
|
+
end
|
72
|
+
|
73
|
+
it 'should have query values' do
|
74
|
+
@request.query_values['foo'] = 'bar'
|
75
|
+
@request.query_values['foo'].should == 'bar'
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
describe 'headers' do
|
80
|
+
it 'should by default be empty' do
|
81
|
+
@request.headers.should be_empty
|
82
|
+
end
|
83
|
+
|
84
|
+
it 'should have headers' do
|
85
|
+
@request.headers['foo'] = 'bar'
|
86
|
+
@request.headers['foo'].should == 'bar'
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
describe '#body' do
|
91
|
+
context 'when the method should contain a body' do
|
92
|
+
it 'should by default be a blank string' do
|
93
|
+
@request.method = :put
|
94
|
+
@request.body.should == ''
|
95
|
+
end
|
96
|
+
|
97
|
+
it 'should be settable for PUT' do
|
98
|
+
@request.method = :put
|
99
|
+
@request.body = 'foo'
|
100
|
+
@request.body.should == 'foo'
|
101
|
+
end
|
102
|
+
|
103
|
+
it 'should be settable for POST' do
|
104
|
+
@request.method = :post
|
105
|
+
@request.body = 'foo'
|
106
|
+
@request.body.should == 'foo'
|
107
|
+
end
|
108
|
+
|
109
|
+
it 'should be settable for PATCH' do
|
110
|
+
@request.method = :patch
|
111
|
+
@request.body = 'foo'
|
112
|
+
@request.body.should == 'foo'
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
context 'when the method should not contain a body' do
|
117
|
+
it 'should by default be nil' do
|
118
|
+
@request.body.should be_nil
|
119
|
+
end
|
120
|
+
|
121
|
+
it 'should not be settable' do
|
122
|
+
@request.method = :get
|
123
|
+
@request.body = 'foo'
|
124
|
+
@request.body.should be_nil
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
describe '#raw_body' do
|
130
|
+
context 'when the method should contain a body' do
|
131
|
+
it 'should by default be a blank string' do
|
132
|
+
@request.method = :put
|
133
|
+
@request.body.should == ''
|
134
|
+
end
|
135
|
+
|
136
|
+
it 'should be settable for PUT' do
|
137
|
+
@request.method = :put
|
138
|
+
@request.body = 'foo'
|
139
|
+
@request.body.should == 'foo'
|
140
|
+
end
|
141
|
+
|
142
|
+
it 'should be settable for POST' do
|
143
|
+
@request.method = :post
|
144
|
+
@request.body = 'foo'
|
145
|
+
@request.body.should == 'foo'
|
146
|
+
end
|
147
|
+
|
148
|
+
it 'should be settable for PATCH' do
|
149
|
+
@request.method = :patch
|
150
|
+
@request.body = 'foo'
|
151
|
+
@request.body.should == 'foo'
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
context 'when the method should not contain a body' do
|
156
|
+
describe 'raw body' do
|
157
|
+
it 'should by default be nil' do
|
158
|
+
@request.raw_body.should be_nil
|
159
|
+
end
|
160
|
+
|
161
|
+
it 'should not be settable' do
|
162
|
+
@request.method = :get
|
163
|
+
@request.raw_body = 'foo'
|
164
|
+
@request.raw_body.should be_nil
|
165
|
+
end
|
166
|
+
end
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
describe 'body parsing' do
|
171
|
+
before do
|
172
|
+
@request.method = :put
|
173
|
+
end
|
174
|
+
|
175
|
+
context 'when the Content-Type is not application/json' do
|
176
|
+
before do
|
177
|
+
@request.headers['Content-Type'] = 'application/xml'
|
178
|
+
end
|
179
|
+
|
180
|
+
it 'should be the same as the body' do
|
181
|
+
@request.body = 'foo'
|
182
|
+
@request.raw_body.should == 'foo'
|
183
|
+
end
|
184
|
+
|
185
|
+
it 'should be settable' do
|
186
|
+
@request.raw_body = 'foo'
|
187
|
+
@request.raw_body.should == 'foo'
|
188
|
+
end
|
189
|
+
|
190
|
+
it 'should be able to be set to change the body' do
|
191
|
+
@request.raw_body = 'foo'
|
192
|
+
@request.body.should == 'foo'
|
193
|
+
end
|
194
|
+
end
|
195
|
+
|
196
|
+
context 'when the Content-Type is application/json' do
|
197
|
+
before do
|
198
|
+
@request.headers['Content-Type'] = 'application/json'
|
199
|
+
end
|
200
|
+
|
201
|
+
it 'should convert the body from a hash to JSON' do
|
202
|
+
@request.body = {'foo' => 'bar'}
|
203
|
+
@request.raw_body.should == '{"foo":"bar"}'
|
204
|
+
end
|
205
|
+
|
206
|
+
it 'should keep the original body in body' do
|
207
|
+
@request.body = {'foo' => 'bar'}
|
208
|
+
@request.body.should == {'foo' => 'bar'}
|
209
|
+
end
|
210
|
+
end
|
211
|
+
end
|
212
|
+
|
213
|
+
describe '#full_url' do
|
214
|
+
context 'when there are no query values' do
|
215
|
+
it 'should be the same as the url' do
|
216
|
+
@request.full_url.should == @request.url
|
217
|
+
end
|
218
|
+
end
|
219
|
+
|
220
|
+
context 'when there are query values' do
|
221
|
+
before do
|
222
|
+
@request.query_values['foo'] = 'bar'
|
223
|
+
end
|
224
|
+
|
225
|
+
it 'should append the query values to the url' do
|
226
|
+
@request.full_url.should == @request.url + '?foo=bar'
|
227
|
+
end
|
228
|
+
end
|
229
|
+
end
|
230
|
+
end
|
@@ -0,0 +1,156 @@
|
|
1
|
+
require 'spec/spec_helper'
|
2
|
+
|
3
|
+
describe Pillow::Resource do
|
4
|
+
before do
|
5
|
+
@klass = Class.new(Pillow::Resource)
|
6
|
+
@resource = @klass.new('http://foo.com/')
|
7
|
+
end
|
8
|
+
|
9
|
+
describe '#self.session' do
|
10
|
+
subject { @klass.session }
|
11
|
+
it { should be_a_kind_of(Patron::Session) }
|
12
|
+
end
|
13
|
+
|
14
|
+
describe '#self.query_values' do
|
15
|
+
subject { @klass.query_values }
|
16
|
+
|
17
|
+
context 'when first created' do
|
18
|
+
it { should be_empty }
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'should store query values for the resource' do
|
22
|
+
@klass.query_values['foo'] = 'bar'
|
23
|
+
@klass.query_values['foo'].should == 'bar'
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
describe '#self.headers' do
|
28
|
+
subject { @klass.headers }
|
29
|
+
|
30
|
+
context 'when first created' do
|
31
|
+
it { should be_empty }
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'should store headers for the resource' do
|
35
|
+
@klass.headers['foo'] = 'bar'
|
36
|
+
@klass.headers['foo'].should == 'bar'
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
describe '#self.template' do
|
41
|
+
subject { @klass.template }
|
42
|
+
|
43
|
+
context 'when first created' do
|
44
|
+
it { should be_nil }
|
45
|
+
end
|
46
|
+
|
47
|
+
context 'when set to a template' do
|
48
|
+
before do
|
49
|
+
@klass.template 'http://example.com/{foo}'
|
50
|
+
end
|
51
|
+
|
52
|
+
it 'should store the template' do
|
53
|
+
@klass.template.should be_a_kind_of(Addressable::Template)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
describe '#initialize' do
|
59
|
+
context 'when given a url' do
|
60
|
+
before do
|
61
|
+
@resource = @klass.new('http://exmaple.com')
|
62
|
+
end
|
63
|
+
|
64
|
+
it 'should store the url' do
|
65
|
+
@resource.url.should == 'http://exmaple.com'
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
context 'when given a params list' do
|
70
|
+
before do
|
71
|
+
@klass.template 'http://example.com/{foo}'
|
72
|
+
@resource = @klass.new('foo' => 'test')
|
73
|
+
end
|
74
|
+
|
75
|
+
it 'should expand the parent template with the params' do
|
76
|
+
@resource.url.should == 'http://example.com/test'
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
describe 'methods definitions' do
|
82
|
+
it 'should have an OPTIONS method' do
|
83
|
+
@klass.options.method.should == :options
|
84
|
+
end
|
85
|
+
|
86
|
+
it 'should have a GET method' do
|
87
|
+
@klass.get.method.should == :get
|
88
|
+
end
|
89
|
+
|
90
|
+
it 'should have a HEAD method' do
|
91
|
+
@klass.head.method.should == :head
|
92
|
+
end
|
93
|
+
|
94
|
+
it 'should have a POST method' do
|
95
|
+
@klass.post.method.should == :post
|
96
|
+
end
|
97
|
+
|
98
|
+
it 'should have a PUT method' do
|
99
|
+
@klass.put.method.should == :put
|
100
|
+
end
|
101
|
+
|
102
|
+
it 'should have a DELETE method' do
|
103
|
+
@klass.delete.method.should == :delete
|
104
|
+
end
|
105
|
+
|
106
|
+
it 'should have a TRACE method' do
|
107
|
+
@klass.trace.method.should == :trace
|
108
|
+
end
|
109
|
+
|
110
|
+
it 'should have a PATCH method' do
|
111
|
+
@klass.patch.method.should == :patch
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
describe 'methods' do
|
116
|
+
it 'should be able to call OPTIONS' do
|
117
|
+
@klass.options.should_receive(:process).with('test').and_return(123)
|
118
|
+
@resource.options('test').should == 123
|
119
|
+
end
|
120
|
+
|
121
|
+
it 'should be able to call GET' do
|
122
|
+
@klass.get.should_receive(:process).with('test').and_return(123)
|
123
|
+
@resource.get('test').should == 123
|
124
|
+
end
|
125
|
+
|
126
|
+
it 'should be able to call HEAD' do
|
127
|
+
@klass.head.should_receive(:process).with('test').and_return(123)
|
128
|
+
@resource.head('test').should == 123
|
129
|
+
end
|
130
|
+
|
131
|
+
it 'should be able to call POST' do
|
132
|
+
@klass.post.should_receive(:process).with('test').and_return(123)
|
133
|
+
@resource.post('test').should == 123
|
134
|
+
end
|
135
|
+
|
136
|
+
it 'should be able to call PUT' do
|
137
|
+
@klass.put.should_receive(:process).with('test').and_return(123)
|
138
|
+
@resource.put('test').should == 123
|
139
|
+
end
|
140
|
+
|
141
|
+
it 'should be able to call DELETE' do
|
142
|
+
@klass.delete.should_receive(:process).with('test').and_return(123)
|
143
|
+
@resource.delete('test').should == 123
|
144
|
+
end
|
145
|
+
|
146
|
+
it 'should be able to call TRACE' do
|
147
|
+
@klass.trace.should_receive(:process).with('test').and_return(123)
|
148
|
+
@resource.trace('test').should == 123
|
149
|
+
end
|
150
|
+
|
151
|
+
it 'should be able to call PATCH' do
|
152
|
+
@klass.patch.should_receive(:process).with('test').and_return(123)
|
153
|
+
@resource.patch('test').should == 123
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'spec/spec_helper'
|
2
|
+
|
3
|
+
describe Pillow::Response do
|
4
|
+
before do
|
5
|
+
@response = Pillow::Response.new
|
6
|
+
@response.status = 200
|
7
|
+
@response.headers = {'X-Foo' => 'Bar'}
|
8
|
+
@response.raw_body = 'test'
|
9
|
+
end
|
10
|
+
|
11
|
+
it 'should store the status' do
|
12
|
+
@response.status.should == 200
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'should store the headers' do
|
16
|
+
@response.headers.should == {'X-Foo' => 'Bar'}
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'should store the body' do
|
20
|
+
@response.body.should == 'test'
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'should store the origin raw body' do
|
24
|
+
@response.raw_body.should == 'test'
|
25
|
+
end
|
26
|
+
|
27
|
+
context 'when the Content-Type is application/json' do
|
28
|
+
before do
|
29
|
+
@data = {'foo' => 'bar'}
|
30
|
+
@response.headers['Content-Type'] = 'application/json'
|
31
|
+
@response.raw_body = @data.to_json
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'should process the body' do
|
35
|
+
@response.body.should == @data
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'should store the origin body' do
|
39
|
+
@response.raw_body.should == @data.to_json
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
data/spec/spec.opts
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--color
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'spec'
|
2
|
+
require 'spec/autorun'
|
3
|
+
|
4
|
+
require File.join(File.dirname(__FILE__), '..', 'lib', 'pillow')
|
5
|
+
|
6
|
+
Spec::Runner.configure do |config|
|
7
|
+
end
|
8
|
+
|
9
|
+
def mock_response(status, headers, body)
|
10
|
+
response = Patron::Response.new
|
11
|
+
response.instance_eval do
|
12
|
+
@status = status
|
13
|
+
@headers = headers
|
14
|
+
@body = body
|
15
|
+
end
|
16
|
+
response
|
17
|
+
end
|
metadata
ADDED
@@ -0,0 +1,141 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: pillow
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 11
|
5
|
+
prerelease: false
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 5
|
9
|
+
- 0
|
10
|
+
version: 0.5.0
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Alexander Kern
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2010-05-19 00:00:00 -07:00
|
19
|
+
default_executable:
|
20
|
+
dependencies:
|
21
|
+
- !ruby/object:Gem::Dependency
|
22
|
+
name: patron
|
23
|
+
prerelease: false
|
24
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ">="
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
hash: 3
|
30
|
+
segments:
|
31
|
+
- 0
|
32
|
+
version: "0"
|
33
|
+
type: :runtime
|
34
|
+
version_requirements: *id001
|
35
|
+
- !ruby/object:Gem::Dependency
|
36
|
+
name: json
|
37
|
+
prerelease: false
|
38
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ">="
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
hash: 3
|
44
|
+
segments:
|
45
|
+
- 0
|
46
|
+
version: "0"
|
47
|
+
type: :runtime
|
48
|
+
version_requirements: *id002
|
49
|
+
- !ruby/object:Gem::Dependency
|
50
|
+
name: addressable
|
51
|
+
prerelease: false
|
52
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
53
|
+
none: false
|
54
|
+
requirements:
|
55
|
+
- - ">="
|
56
|
+
- !ruby/object:Gem::Version
|
57
|
+
hash: 3
|
58
|
+
segments:
|
59
|
+
- 0
|
60
|
+
version: "0"
|
61
|
+
type: :runtime
|
62
|
+
version_requirements: *id003
|
63
|
+
- !ruby/object:Gem::Dependency
|
64
|
+
name: rspec
|
65
|
+
prerelease: false
|
66
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
67
|
+
none: false
|
68
|
+
requirements:
|
69
|
+
- - ">="
|
70
|
+
- !ruby/object:Gem::Version
|
71
|
+
hash: 3
|
72
|
+
segments:
|
73
|
+
- 0
|
74
|
+
version: "0"
|
75
|
+
type: :development
|
76
|
+
version_requirements: *id004
|
77
|
+
description: Ruby HTTP client that takes full advantage of HTTP.
|
78
|
+
email: alex@kernul.com
|
79
|
+
executables: []
|
80
|
+
|
81
|
+
extensions: []
|
82
|
+
|
83
|
+
extra_rdoc_files:
|
84
|
+
- LICENSE
|
85
|
+
- README.md
|
86
|
+
files:
|
87
|
+
- LICENSE
|
88
|
+
- README.md
|
89
|
+
- Rakefile
|
90
|
+
- VERSION
|
91
|
+
- lib/pillow.rb
|
92
|
+
- lib/pillow/method.rb
|
93
|
+
- lib/pillow/request.rb
|
94
|
+
- lib/pillow/resource.rb
|
95
|
+
- lib/pillow/response.rb
|
96
|
+
- spec/pillow/method_spec.rb
|
97
|
+
- spec/pillow/request_spec.rb
|
98
|
+
- spec/pillow/resource_spec.rb
|
99
|
+
- spec/pillow/response_spec.rb
|
100
|
+
- spec/spec.opts
|
101
|
+
- spec/spec_helper.rb
|
102
|
+
has_rdoc: true
|
103
|
+
homepage:
|
104
|
+
licenses: []
|
105
|
+
|
106
|
+
post_install_message:
|
107
|
+
rdoc_options:
|
108
|
+
- --charset=UTF-8
|
109
|
+
require_paths:
|
110
|
+
- lib
|
111
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
112
|
+
none: false
|
113
|
+
requirements:
|
114
|
+
- - ">="
|
115
|
+
- !ruby/object:Gem::Version
|
116
|
+
hash: 3
|
117
|
+
segments:
|
118
|
+
- 0
|
119
|
+
version: "0"
|
120
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
121
|
+
none: false
|
122
|
+
requirements:
|
123
|
+
- - ">="
|
124
|
+
- !ruby/object:Gem::Version
|
125
|
+
hash: 3
|
126
|
+
segments:
|
127
|
+
- 0
|
128
|
+
version: "0"
|
129
|
+
requirements: []
|
130
|
+
|
131
|
+
rubyforge_project:
|
132
|
+
rubygems_version: 1.3.7
|
133
|
+
signing_key:
|
134
|
+
specification_version: 3
|
135
|
+
summary: Take a nap, Pillow lets you REST.
|
136
|
+
test_files:
|
137
|
+
- spec/pillow/method_spec.rb
|
138
|
+
- spec/pillow/request_spec.rb
|
139
|
+
- spec/pillow/resource_spec.rb
|
140
|
+
- spec/pillow/response_spec.rb
|
141
|
+
- spec/spec_helper.rb
|