httpadapter 0.2.1 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,357 @@
1
+ # Copyright (C) 2010 Google Inc.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ require 'spec_helper'
16
+ require 'spec/httpadapter/adapter_type_checking_spec'
17
+
18
+ require 'httpadapter/adapters/rack'
19
+
20
+ describe HTTPAdapter::RackAdapter do
21
+ before do
22
+ @adapter = HTTPAdapter::RackAdapter.new
23
+ end
24
+
25
+ it_should_behave_like 'adapter type-checking example'
26
+
27
+ describe 'when adapting a request' do
28
+ describe 'from Rack::Request for GET' do
29
+ before do
30
+ @body_io = StringIO.new
31
+ @env = {
32
+ # PEP333 variables
33
+ 'REQUEST_METHOD' => 'GET',
34
+ 'SERVER_NAME' => 'www.example.com',
35
+ 'SERVER_PORT' => '80',
36
+ 'SCRIPT_NAME' => '',
37
+ 'PATH_INFO' => '/path/to/resource',
38
+ 'QUERY_STRING' => '',
39
+
40
+ # Rack-specific variables
41
+ 'rack.version' => Rack::VERSION,
42
+ 'rack.input' => @body_io,
43
+ 'rack.errors' => STDERR,
44
+ 'rack.multithread' => true,
45
+ 'rack.multiprocess' => true,
46
+ 'rack.run_once' => false,
47
+ 'rack.url_scheme' => 'http',
48
+
49
+ # HTTP headers
50
+ 'HTTP_ACCEPT' => 'application/json'
51
+ }
52
+ @request = Rack::Request.new(@env)
53
+ @result = @adapter.adapt_request(@request)
54
+ @method, @uri, @headers, @body = @result
55
+ end
56
+
57
+ it 'should convert the HTTP method properly' do
58
+ @method.should == 'GET'
59
+ end
60
+
61
+ it 'should convert the URI properly' do
62
+ @uri.should == 'http://www.example.com/path/to/resource'
63
+ end
64
+
65
+ it 'should convert the headers properly' do
66
+ accept = nil
67
+ @headers.each do |header, value|
68
+ header.should be_kind_of(String)
69
+ value.should be_kind_of(String)
70
+ accept = value if header == 'Accept'
71
+ end
72
+ accept.should == 'application/json'
73
+ end
74
+
75
+ it 'should convert the body properly' do
76
+ @body.each do |chunk|
77
+ chunk.should be_kind_of(String)
78
+ end
79
+ end
80
+ end
81
+
82
+ describe 'from Rack::Request for POST' do
83
+ before do
84
+ @body_io = StringIO.new('{"three":3,"two":2,"one":1}')
85
+ @env = {
86
+ # PEP333 variables
87
+ 'REQUEST_METHOD' => 'POST',
88
+ 'SERVER_NAME' => 'www.example.com',
89
+ 'SERVER_PORT' => '80',
90
+ 'SCRIPT_NAME' => '',
91
+ 'PATH_INFO' => '/path/to/resource',
92
+ 'QUERY_STRING' => '',
93
+
94
+ # Rack-specific variables
95
+ 'rack.version' => Rack::VERSION,
96
+ 'rack.input' => @body_io,
97
+ 'rack.errors' => STDERR,
98
+ 'rack.multithread' => true,
99
+ 'rack.multiprocess' => true,
100
+ 'rack.run_once' => false,
101
+ 'rack.url_scheme' => 'http',
102
+
103
+ # HTTP headers
104
+ 'HTTP_ACCEPT' => 'application/json',
105
+ 'HTTP_CONTENT_TYPE' => 'application/json; charset=utf-8'
106
+ }
107
+ @request = Rack::Request.new(@env)
108
+ @result = @adapter.adapt_request(@request)
109
+ @method, @uri, @headers, @body = @result
110
+ end
111
+
112
+ it 'should convert the HTTP method properly' do
113
+ @method.should == 'POST'
114
+ end
115
+
116
+ it 'should convert the URI properly' do
117
+ @uri.should == 'http://www.example.com/path/to/resource'
118
+ end
119
+
120
+ it 'should convert the headers properly' do
121
+ accept = nil
122
+ content_type = nil
123
+ @headers.each do |header, value|
124
+ header.should be_kind_of(String)
125
+ value.should be_kind_of(String)
126
+ accept = value if header == 'Accept'
127
+ content_type = value if header == 'Content-Type'
128
+ end
129
+ accept.should == 'application/json'
130
+ content_type.should == 'application/json; charset=utf-8'
131
+ end
132
+
133
+ it 'should convert the body properly' do
134
+ merged_body = ""
135
+ @body.each do |chunk|
136
+ chunk.should be_kind_of(String)
137
+ merged_body += chunk
138
+ end
139
+ merged_body.should == '{"three":3,"two":2,"one":1}'
140
+ end
141
+ end
142
+ end
143
+
144
+ describe 'when specializing a request' do
145
+ it 'should raise an error for converting from an invalid tuple' do
146
+ (lambda do
147
+ @adapter.specialize_request(['GET', '/', [], [42]])
148
+ end).should raise_error(TypeError)
149
+ end
150
+
151
+ describe 'from a GET tuple' do
152
+ before do
153
+ @tuple = [
154
+ 'GET',
155
+ 'http://www.example.com/path?query',
156
+ [
157
+ ['Accept', 'application/json']
158
+ ],
159
+ []
160
+ ]
161
+ @request = @adapter.specialize_request(@tuple)
162
+ end
163
+
164
+ it 'should convert the HTTP method properly' do
165
+ @request.request_method.should == 'GET'
166
+ end
167
+
168
+ it 'should convert the URI properly' do
169
+ @request.url.should == 'http://www.example.com/path?query'
170
+ end
171
+
172
+ it 'should convert the headers properly' do
173
+ @request.env['HTTP_ACCEPT'].should == 'application/json'
174
+ end
175
+
176
+ it 'should convert the body properly' do
177
+ @request.body.read.should == ''
178
+ end
179
+ end
180
+
181
+ describe 'from a POST tuple' do
182
+ before do
183
+ @tuple = [
184
+ 'POST',
185
+ 'http://www.example.com/path?query',
186
+ [
187
+ ['Accept', 'application/json'],
188
+ ['Content-Type', 'application/json; charset=utf-8'],
189
+ ['Content-Length', '27']
190
+ ],
191
+ ['{"three":3,', '"two":2,', '"one":1}']
192
+ ]
193
+ @request = @adapter.specialize_request(@tuple)
194
+ end
195
+
196
+ it 'should convert the HTTP method properly' do
197
+ @request.request_method.should == 'POST'
198
+ end
199
+
200
+ it 'should convert the URI properly' do
201
+ @request.url.should == 'http://www.example.com/path?query'
202
+ end
203
+
204
+ it 'should convert the headers properly' do
205
+ accept = nil
206
+ content_type = nil
207
+ @request.env['HTTP_ACCEPT'].should == 'application/json'
208
+ @request.env['HTTP_CONTENT_TYPE'].should ==
209
+ 'application/json; charset=utf-8'
210
+ end
211
+
212
+ it 'should convert the body properly' do
213
+ @request.body.read.should == '{"three":3,"two":2,"one":1}'
214
+ end
215
+ end
216
+ end
217
+
218
+ describe 'when adapting a response' do
219
+ it 'should raise an error for converting from an invalid response' do
220
+ (lambda do
221
+ @adapter.adapt_response(42)
222
+ end).should raise_error(TypeError)
223
+ end
224
+
225
+ describe 'from Rack::Response' do
226
+ before do
227
+ @response = Rack::Response.new(
228
+ ['{"three":3,"two":2,"one":1}'],
229
+ 200,
230
+ {
231
+ 'Content-Type' => 'application/json; charset=utf-8',
232
+ 'Content-Length' => '27'
233
+ }
234
+ )
235
+ @result = @adapter.adapt_response(@response)
236
+ @status, @headers, @body = @result
237
+ end
238
+
239
+ it 'should convert the HTTP status properly' do
240
+ @status.should == 200
241
+ end
242
+
243
+ it 'should convert the headers properly' do
244
+ content_type = nil
245
+ @headers.each do |header, value|
246
+ header.should be_kind_of(String)
247
+ value.should be_kind_of(String)
248
+ content_type = value if header == 'Content-Type'
249
+ end
250
+ content_type.should == 'application/json; charset=utf-8'
251
+ end
252
+
253
+ it 'should convert the body properly' do
254
+ merged_body = ""
255
+ @body.each do |chunk|
256
+ merged_body += chunk
257
+ chunk.should be_kind_of(String)
258
+ end
259
+ merged_body.should == '{"three":3,"two":2,"one":1}'
260
+ end
261
+ end
262
+ end
263
+
264
+ describe 'when specializing a response' do
265
+ it 'should raise an error for converting from an invalid tuple' do
266
+ (lambda do
267
+ @adapter.specialize_response(
268
+ [200, [], [42]]
269
+ )
270
+ end).should raise_error(TypeError)
271
+ end
272
+
273
+ describe 'from a 200 tuple' do
274
+ before do
275
+ @tuple = [
276
+ 200,
277
+ [
278
+ ['Content-Type', 'application/json; charset=utf-8'],
279
+ ['Content-Length', '27']
280
+ ],
281
+ ['{"three":3,"two":2,"one":1}']
282
+ ]
283
+ @response = @adapter.specialize_response(@tuple)
284
+ end
285
+
286
+ it 'should convert the HTTP status properly' do
287
+ @response.status.to_i.should == 200
288
+ end
289
+
290
+ it 'should parse the content length properly' do
291
+ @response.length.to_i.should == 27
292
+ end
293
+
294
+ it 'should convert the headers properly' do
295
+ content_type = nil
296
+ @response.header.each do |header, value|
297
+ header.should be_kind_of(String)
298
+ value.should be_kind_of(String)
299
+ content_type = value if header == 'Content-Type'
300
+ end
301
+ content_type.should == 'application/json; charset=utf-8'
302
+ end
303
+
304
+ it 'should convert the body properly' do
305
+ merged_body = ""
306
+ @response.body.each do |chunk|
307
+ merged_body += chunk
308
+ end
309
+ merged_body.should == '{"three":3,"two":2,"one":1}'
310
+ end
311
+ end
312
+
313
+ describe 'from a 200 tuple' do
314
+ before do
315
+ @tuple = [
316
+ 500,
317
+ [
318
+ ['Content-Type', 'text/html'],
319
+ ['Content-Length', '28']
320
+ ],
321
+ ['<html><body>', '42', '</body></html>']
322
+ ]
323
+ @response = @adapter.specialize_response(@tuple)
324
+ end
325
+
326
+ it 'should convert the HTTP status properly' do
327
+ @response.status.to_i.should == 500
328
+ end
329
+
330
+ it 'should convert the headers properly' do
331
+ content_type = nil
332
+ @response.header.each do |header, value|
333
+ header.should be_kind_of(String)
334
+ value.should be_kind_of(String)
335
+ content_type = value if header == 'Content-Type'
336
+ end
337
+ content_type.should == 'text/html'
338
+ end
339
+
340
+ it 'should convert the body properly' do
341
+ merged_body = ""
342
+ @response.body.each do |chunk|
343
+ merged_body += chunk
344
+ end
345
+ merged_body.should == '<html><body>42</body></html>'
346
+ end
347
+ end
348
+ end
349
+
350
+ describe 'when transmitting a request' do
351
+ it 'should raise an error indicating that transmission is not possible' do
352
+ (lambda do
353
+ @adapter.transmit(['GET', 'http://www.google.com/', [], ['']])
354
+ end).should raise_error(NotImplementedError)
355
+ end
356
+ end
357
+ end
@@ -0,0 +1,379 @@
1
+ # Copyright (C) 2010 Google Inc.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ require 'spec_helper'
16
+
17
+ require 'httpadapter/adapters/typhoeus'
18
+
19
+ describe HTTPAdapter::TyphoeusAdapter do
20
+ before do
21
+ @adapter = HTTPAdapter::TyphoeusAdapter.new
22
+ end
23
+
24
+ it_should_behave_like 'adapter type-checking example'
25
+
26
+ describe 'when adapting a request' do
27
+ describe 'from Typhoeus::Request for GET' do
28
+ before do
29
+ @request = Typhoeus::Request.new(
30
+ 'http://www.example.com/path/to/resource'
31
+ )
32
+ @request.headers['Accept'] = 'application/json'
33
+ @result = @adapter.adapt_request(@request)
34
+ @method, @uri, @headers, @body = @result
35
+ end
36
+
37
+ it 'should convert the HTTP method properly' do
38
+ @method.should == 'GET'
39
+ end
40
+
41
+ it 'should convert the URI properly' do
42
+ @uri.should == 'http://www.example.com/path/to/resource'
43
+ end
44
+
45
+ it 'should convert the headers properly' do
46
+ accept = nil
47
+ @headers.each do |header, value|
48
+ header.should be_kind_of(String)
49
+ value.should be_kind_of(String)
50
+ accept = value if header == 'Accept'
51
+ end
52
+ accept.should == 'application/json'
53
+ end
54
+
55
+ it 'should convert the body properly' do
56
+ @body.each do |chunk|
57
+ chunk.should be_kind_of(String)
58
+ end
59
+ end
60
+ end
61
+
62
+ describe 'from Typhoeus::Request for POST' do
63
+ before do
64
+ @request = Typhoeus::Request.new(
65
+ 'http://www.example.com/path/to/resource',
66
+ :method => :post
67
+ )
68
+ @request.headers['Accept'] = 'application/json'
69
+ @request.headers['Content-Type'] = 'application/json; charset=utf-8'
70
+ @request.body = '{"three":3,"two":2,"one":1}'
71
+ @result = @adapter.adapt_request(@request)
72
+ @method, @uri, @headers, @body = @result
73
+ end
74
+
75
+ it 'should convert the HTTP method properly' do
76
+ @method.should == 'POST'
77
+ end
78
+
79
+ it 'should convert the URI properly' do
80
+ @uri.should == 'http://www.example.com/path/to/resource'
81
+ end
82
+
83
+ it 'should convert the headers properly' do
84
+ accept = nil
85
+ content_type = nil
86
+ @headers.each do |header, value|
87
+ header.should be_kind_of(String)
88
+ value.should be_kind_of(String)
89
+ accept = value if header == 'Accept'
90
+ content_type = value if header == 'Content-Type'
91
+ end
92
+ accept.should == 'application/json'
93
+ content_type.should == 'application/json; charset=utf-8'
94
+ end
95
+
96
+ it 'should convert the body properly' do
97
+ merged_body = ""
98
+ @body.each do |chunk|
99
+ chunk.should be_kind_of(String)
100
+ merged_body += chunk
101
+ end
102
+ merged_body.should == '{"three":3,"two":2,"one":1}'
103
+ end
104
+ end
105
+ end
106
+
107
+ describe 'when specializing a request' do
108
+ it 'should raise an error for converting from an invalid tuple' do
109
+ (lambda do
110
+ @adapter.specialize_request(
111
+ ['GET', '/', [], [42]]
112
+ )
113
+ end).should raise_error(TypeError)
114
+ end
115
+
116
+ describe 'from a GET tuple' do
117
+ before do
118
+ @tuple = [
119
+ 'GET',
120
+ 'http://www.example.com/path?query',
121
+ [
122
+ ['Accept', 'application/json']
123
+ ],
124
+ []
125
+ ]
126
+ @request = @adapter.specialize_request(@tuple)
127
+ end
128
+
129
+ it 'should convert the HTTP method properly' do
130
+ @request.method.should == :get
131
+ end
132
+
133
+ it 'should convert the URI properly' do
134
+ @request.url.should == 'http://www.example.com/path?query'
135
+ end
136
+
137
+ it 'should convert the headers properly' do
138
+ accept = nil
139
+ @request.headers.each do |header, value|
140
+ header.should be_kind_of(String)
141
+ value.should be_kind_of(String)
142
+ accept = value if header == 'Accept'
143
+ end
144
+ accept.should == 'application/json'
145
+ end
146
+
147
+ it 'should convert the body properly' do
148
+ @request.body.should == nil
149
+ end
150
+ end
151
+
152
+ describe 'from a POST tuple' do
153
+ before do
154
+ @tuple = [
155
+ 'POST',
156
+ 'http://www.example.com/path?query',
157
+ [
158
+ ['Accept', 'application/json'],
159
+ ['Content-Type', 'application/json; charset=utf-8'],
160
+ ['Content-Length', '27']
161
+ ],
162
+ ['{"three":3,', '"two":2,', '"one":1}']
163
+ ]
164
+ @request = @adapter.specialize_request(@tuple)
165
+ end
166
+
167
+ it 'should convert the HTTP method properly' do
168
+ @request.method.should == :post
169
+ end
170
+
171
+ it 'should convert the URI properly' do
172
+ @request.url.should == 'http://www.example.com/path?query'
173
+ end
174
+
175
+ it 'should convert the headers properly' do
176
+ accept = nil
177
+ content_type = nil
178
+ @request.headers.each do |header, value|
179
+ header.should be_kind_of(String)
180
+ value.should be_kind_of(String)
181
+ accept = value if header == 'Accept'
182
+ content_type = value if header == 'Content-Type'
183
+ end
184
+ accept.should == 'application/json'
185
+ content_type.should == 'application/json; charset=utf-8'
186
+ end
187
+
188
+ it 'should convert the body properly' do
189
+ @request.body.should == '{"three":3,"two":2,"one":1}'
190
+ end
191
+ end
192
+ end
193
+
194
+ describe 'when adapting a response' do
195
+ describe 'from Typhoeus::Response' do
196
+ before do
197
+ @response = Typhoeus::Response.new(
198
+ :code => 200,
199
+ :headers => <<-HEADERS,
200
+ Content-Type: application/json; charset=utf-8
201
+ Content-Length: 27
202
+ HEADERS
203
+ :body => '{"three":3,"two":2,"one":1}'
204
+ )
205
+ @result = @adapter.adapt_response(@response)
206
+ @status, @headers, @body = @result
207
+ end
208
+
209
+ it 'should convert the HTTP status properly' do
210
+ @status.should == 200
211
+ end
212
+
213
+ it 'should convert the headers properly' do
214
+ content_type = nil
215
+ @headers.each do |header, value|
216
+ header.should be_kind_of(String)
217
+ value.should be_kind_of(String)
218
+ content_type = value if header == 'Content-Type'
219
+ end
220
+ content_type.should == 'application/json; charset=utf-8'
221
+ end
222
+
223
+ it 'should convert the body properly' do
224
+ merged_body = ""
225
+ @body.each do |chunk|
226
+ merged_body += chunk
227
+ chunk.should be_kind_of(String)
228
+ end
229
+ merged_body.should == '{"three":3,"two":2,"one":1}'
230
+ end
231
+ end
232
+ end
233
+
234
+ describe 'when specializing a response' do
235
+ it 'should raise an error for converting from an invalid tuple' do
236
+ (lambda do
237
+ @adapter.specialize_response(
238
+ [200, [], [42]]
239
+ )
240
+ end).should raise_error(TypeError)
241
+ end
242
+
243
+ describe 'from a 200 tuple' do
244
+ before do
245
+ @tuple = [
246
+ 200,
247
+ [
248
+ ['Content-Type', 'application/json; charset=utf-8'],
249
+ ['Content-Length', '27']
250
+ ],
251
+ ['{"three":3,"two":2,"one":1}']
252
+ ]
253
+ @response = @adapter.specialize_response(@tuple)
254
+ end
255
+
256
+ it 'should convert the HTTP status properly' do
257
+ @response.code.to_i.should == 200
258
+ end
259
+
260
+ it 'should convert the headers properly' do
261
+ content_type = nil
262
+ @response.headers_hash.each do |header, value|
263
+ header.should be_kind_of(String)
264
+ value.should be_kind_of(String)
265
+ content_type = value if header == 'Content-Type'
266
+ end
267
+ content_type.should == 'application/json; charset=utf-8'
268
+ end
269
+
270
+ it 'should convert the body properly' do
271
+ @response.body.should == '{"three":3,"two":2,"one":1}'
272
+ end
273
+ end
274
+
275
+ describe 'from a 200 tuple' do
276
+ before do
277
+ @tuple = [
278
+ 500,
279
+ [
280
+ ['Content-Type', 'text/html'],
281
+ ['Content-Length', '28']
282
+ ],
283
+ ['<html><body>', '42', '</body></html>']
284
+ ]
285
+ @response = @adapter.specialize_response(@tuple)
286
+ end
287
+
288
+ it 'should convert the HTTP status properly' do
289
+ @response.code.to_i.should == 500
290
+ end
291
+
292
+ it 'should convert the headers properly' do
293
+ content_type = nil
294
+ @response.headers_hash.each do |header, value|
295
+ header.should be_kind_of(String)
296
+ value.should be_kind_of(String)
297
+ content_type = value if header == 'Content-Type'
298
+ end
299
+ content_type.should == 'text/html'
300
+ end
301
+
302
+ it 'should convert the body properly' do
303
+ @response.body.should == '<html><body>42</body></html>'
304
+ end
305
+ end
306
+ end
307
+
308
+ describe 'when transmitting a request' do
309
+ describe 'with a GET tuple' do
310
+ before do
311
+ @tuple = [
312
+ 'GET',
313
+ 'http://www.google.com/',
314
+ [],
315
+ []
316
+ ]
317
+ @response = @adapter.transmit(@tuple)
318
+ @status, @headers, @chunked_body = @response
319
+ @body = ''
320
+ @chunked_body.each do |chunk|
321
+ @body += chunk
322
+ end
323
+ end
324
+
325
+ it 'should have the correct status' do
326
+ @status.should == 200
327
+ end
328
+
329
+ it 'should have response headers' do
330
+ @headers.should_not be_empty
331
+ end
332
+
333
+ it 'should have a response body' do
334
+ @body.length.should > 0
335
+ end
336
+ end
337
+
338
+ describe 'with connection' do
339
+ before do
340
+ @connection = HTTPAdapter::Connection.new(
341
+ 'www.google.com', 80,
342
+ Typhoeus::Hydra.new,
343
+ :join => [:run, [], nil]
344
+ )
345
+ @connection.open
346
+ @tuple = [
347
+ 'GET',
348
+ 'http://www.google.com/',
349
+ [],
350
+ []
351
+ ]
352
+ @response = @adapter.transmit(@tuple, @connection)
353
+ @status, @headers, @chunked_body = @response
354
+ @body = ''
355
+ @chunked_body.each do |chunk|
356
+ @body += chunk
357
+ end
358
+ end
359
+
360
+ after do
361
+ @connection.close
362
+ end
363
+
364
+ it 'should have the correct status' do
365
+ @status.should == 200
366
+ end
367
+
368
+ it 'should have response headers' do
369
+ @headers.should_not be_empty
370
+ end
371
+
372
+ it 'should have a response body' do
373
+ @body.length.should > 0
374
+ end
375
+ end
376
+ end
377
+ end
378
+
379
+