em-http-request 0.2.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of em-http-request might be problematic. Click here for more details.

@@ -0,0 +1,22 @@
1
+ class StubServer
2
+ module Server
3
+ def receive_data(data)
4
+ send_data @response
5
+ close_connection_after_writing
6
+ end
7
+
8
+ def response=(response)
9
+ @response = response
10
+ end
11
+ end
12
+
13
+ def initialize(response, port=8081)
14
+ @sig = EventMachine::start_server("127.0.0.1", port, Server) { |s|
15
+ s.response = response
16
+ }
17
+ end
18
+
19
+ def stop
20
+ EventMachine.stop_server @sig
21
+ end
22
+ end
@@ -0,0 +1,19 @@
1
+ require 'test/helper'
2
+
3
+ describe Hash do
4
+
5
+ describe ".to_params" do
6
+ it "should transform a basic hash into HTTP POST Params" do
7
+ {:a => "alpha", :b => "beta"}.to_params.should == "a=alpha&b=beta"
8
+ end
9
+
10
+ it "should transform a more complex hash into HTTP POST Params" do
11
+ {:a => "a", :b => ["c", "d", "e"]}.to_params.should == "a=a&b[0]=c&b[1]=d&b[2]=e"
12
+ end
13
+
14
+ # Ruby 1.8 Hash is not sorted, so this test breaks randomly. Maybe once we're all on 1.9. ;-)
15
+ # it "should transform a very complex hash into HTTP POST Params" do
16
+ # {:a => "a", :b => [{:c => "c", :d => "d"}, {:e => "e", :f => "f"}]}.to_params.should == "a=a&b[0][d]=d&b[0][c]=c&b[1][f]=f&b[1][e]=e"
17
+ # end
18
+ end
19
+ end
@@ -0,0 +1,29 @@
1
+ require 'test/helper'
2
+ require 'test/stallion'
3
+
4
+ describe EventMachine::MultiRequest do
5
+
6
+ it "should submit multiple requests in parallel and return once all of them are complete" do
7
+ EventMachine.run {
8
+
9
+ # create an instance of multi-request handler, and the requests themselves
10
+ multi = EventMachine::MultiRequest.new
11
+
12
+ # add multiple requests to the multi-handler
13
+ multi.add(EventMachine::HttpRequest.new('http://127.0.0.1:8080/').get(:query => {:q => 'test'}))
14
+ multi.add(EventMachine::HttpRequest.new('http://0.0.0.0/').get(:timeout => 1))
15
+
16
+ multi.callback {
17
+ # verify successfull request
18
+ multi.responses[:succeeded].size.should == 1
19
+ multi.responses[:succeeded].first.response.should match(/test/)
20
+
21
+ # verify invalid requests
22
+ multi.responses[:failed].size.should == 1
23
+ multi.responses[:failed].first.response_header.status.should == 0
24
+
25
+ EventMachine.stop
26
+ }
27
+ }
28
+ end
29
+ end
@@ -0,0 +1,393 @@
1
+ require 'test/helper'
2
+ require 'test/stallion'
3
+ require 'test/stub_server'
4
+
5
+ describe EventMachine::HttpRequest do
6
+
7
+ def failed
8
+ EventMachine.stop
9
+ fail
10
+ end
11
+
12
+ it "should fail GET on DNS timeout" do
13
+ EventMachine.run {
14
+ http = EventMachine::HttpRequest.new('http://127.1.1.1/').get :timeout => 1
15
+ http.callback { failed }
16
+ http.errback {
17
+ http.response_header.status.should == 0
18
+ EventMachine.stop
19
+ }
20
+ }
21
+ end
22
+
23
+ it "should fail GET on invalid host" do
24
+ EventMachine.run {
25
+ http = EventMachine::HttpRequest.new('http://somethinglocal/').get :timeout => 1
26
+ http.callback { failed }
27
+ http.errback {
28
+ http.response_header.status.should == 0
29
+ http.errors.should match(/no connection/)
30
+ EventMachine.stop
31
+ }
32
+ }
33
+ end
34
+
35
+ it "should fail GET on missing path" do
36
+ EventMachine.run {
37
+ lambda {
38
+ EventMachine::HttpRequest.new('http://www.google.com').get
39
+ }.should raise_error(ArgumentError)
40
+
41
+ EventMachine.stop
42
+ }
43
+ end
44
+
45
+ it "should perform successfull GET" do
46
+ EventMachine.run {
47
+ http = EventMachine::HttpRequest.new('http://127.0.0.1:8080/').get
48
+
49
+ http.errback { failed }
50
+ http.callback {
51
+ http.response_header.status.should == 200
52
+ http.response.should match(/Hello/)
53
+ EventMachine.stop
54
+ }
55
+ }
56
+ end
57
+
58
+ it "should perform successfull GET with a URI passed as argument" do
59
+ EventMachine.run {
60
+ uri = URI.parse('http://127.0.0.1:8080/')
61
+ http = EventMachine::HttpRequest.new(uri).get
62
+
63
+ http.errback { failed }
64
+ http.callback {
65
+ http.response_header.status.should == 200
66
+ http.response.should match(/Hello/)
67
+ EventMachine.stop
68
+ }
69
+ }
70
+ end
71
+
72
+ it "should perform successfull HEAD with a URI passed as argument" do
73
+ EventMachine.run {
74
+ uri = URI.parse('http://127.0.0.1:8080/')
75
+ http = EventMachine::HttpRequest.new(uri).head
76
+
77
+ http.errback { failed }
78
+ http.callback {
79
+ http.response_header.status.should == 200
80
+ http.response.should == ""
81
+ EventMachine.stop
82
+ }
83
+ }
84
+ end
85
+
86
+ it "should return 404 on invalid path" do
87
+ EventMachine.run {
88
+ http = EventMachine::HttpRequest.new('http://127.0.0.1:8080/fail').get
89
+
90
+ http.errback { failed }
91
+ http.callback {
92
+ http.response_header.status.should == 404
93
+ EventMachine.stop
94
+ }
95
+ }
96
+ end
97
+
98
+ it "should build query parameters from Hash" do
99
+ EventMachine.run {
100
+ http = EventMachine::HttpRequest.new('http://127.0.0.1:8080/').get :query => {:q => 'test'}
101
+
102
+ http.errback { failed }
103
+ http.callback {
104
+ http.response_header.status.should == 200
105
+ http.response.should match(/test/)
106
+ EventMachine.stop
107
+ }
108
+ }
109
+ end
110
+
111
+ it "should pass query parameters string" do
112
+ EventMachine.run {
113
+ http = EventMachine::HttpRequest.new('http://127.0.0.1:8080/').get :query => "q=test"
114
+
115
+ http.errback { failed }
116
+ http.callback {
117
+ http.response_header.status.should == 200
118
+ http.response.should match(/test/)
119
+ EventMachine.stop
120
+ }
121
+ }
122
+ end
123
+
124
+ it "should encode an array of query parameters" do
125
+ EventMachine.run {
126
+ http = EventMachine::HttpRequest.new('http://127.0.0.1:8080/echo_query').get :query => {:hash => ['value1', 'value2']}
127
+
128
+ http.errback { failed }
129
+ http.callback {
130
+ http.response_header.status.should == 200
131
+ http.response.should match(/hash\[\]=value1&hash\[\]=value2/)
132
+ EventMachine.stop
133
+ }
134
+ }
135
+ end
136
+
137
+ it "should perform successfull POST" do
138
+ EventMachine.run {
139
+ http = EventMachine::HttpRequest.new('http://127.0.0.1:8080/').post :body => "data"
140
+
141
+ http.errback { failed }
142
+ http.callback {
143
+ http.response_header.status.should == 200
144
+ http.response.should match(/data/)
145
+ EventMachine.stop
146
+ }
147
+ }
148
+ end
149
+
150
+ it "should perform successfull POST with Ruby Hash/Array as params" do
151
+ EventMachine.run {
152
+ http = EventMachine::HttpRequest.new('http://127.0.0.1:8080/').post :body => {"key1" => 1, "key2" => [2,3]}
153
+
154
+ http.errback { failed }
155
+ http.callback {
156
+ http.response_header.status.should == 200
157
+
158
+ http.response.should match(/key1=1&key2\[0\]=2&key2\[1\]=3/)
159
+ EventMachine.stop
160
+ }
161
+ }
162
+ end
163
+
164
+ it "should perform successfull POST with Ruby Hash/Array as params and with the correct content length" do
165
+ EventMachine.run {
166
+ http = EventMachine::HttpRequest.new('http://127.0.0.1:8080/echo_content_length').post :body => {"key1" => "data1"}
167
+
168
+ http.errback { failed }
169
+ http.callback {
170
+ http.response_header.status.should == 200
171
+
172
+ http.response.to_i.should == 10
173
+ EventMachine.stop
174
+ }
175
+ }
176
+ end
177
+
178
+ it "should perform successfull GET with custom header" do
179
+ EventMachine.run {
180
+ http = EventMachine::HttpRequest.new('http://127.0.0.1:8080/').get :head => {'if-none-match' => 'evar!'}
181
+
182
+ http.errback { failed }
183
+ http.callback {
184
+ http.response_header.status.should == 304
185
+ EventMachine.stop
186
+ }
187
+ }
188
+ end
189
+
190
+ it "should perform a streaming GET" do
191
+ EventMachine.run {
192
+
193
+ # digg.com uses chunked encoding
194
+ http = EventMachine::HttpRequest.new('http://digg.com/').get
195
+
196
+ http.errback { failed }
197
+ http.callback {
198
+ http.response_header.status.should == 200
199
+ EventMachine.stop
200
+ }
201
+ }
202
+ end
203
+
204
+ it "should perform basic auth" do
205
+ EventMachine.run {
206
+
207
+ http = EventMachine::HttpRequest.new('http://127.0.0.1:8080/').get :head => {'authorization' => ['user', 'pass']}
208
+
209
+ http.errback { failed }
210
+ http.callback {
211
+ http.response_header.status.should == 200
212
+ EventMachine.stop
213
+ }
214
+ }
215
+ end
216
+
217
+ it "should work with keep-alive servers" do
218
+ EventMachine.run {
219
+
220
+ http = EventMachine::HttpRequest.new('http://mexicodiario.com/touch.public.json.php').get
221
+
222
+ http.errback { failed }
223
+ http.callback {
224
+ http.response_header.status.should == 200
225
+ EventMachine.stop
226
+ }
227
+ }
228
+ end
229
+
230
+ it "should detect deflate encoding" do
231
+ EventMachine.run {
232
+
233
+ http = EventMachine::HttpRequest.new('http://127.0.0.1:8080/deflate').get :head => {"accept-encoding" => "deflate"}
234
+
235
+ http.errback { failed }
236
+ http.callback {
237
+ http.response_header.status.should == 200
238
+ http.response_header["CONTENT_ENCODING"].should == "deflate"
239
+ http.response.should == "compressed"
240
+
241
+ EventMachine.stop
242
+ }
243
+ }
244
+ end
245
+
246
+ it "should detect gzip encoding" do
247
+ EventMachine.run {
248
+
249
+ http = EventMachine::HttpRequest.new('http://127.0.0.1:8080/gzip').get :head => {"accept-encoding" => "gzip, compressed"}
250
+
251
+ http.errback { failed }
252
+ http.callback {
253
+ http.response_header.status.should == 200
254
+ http.response_header["CONTENT_ENCODING"].should == "gzip"
255
+ http.response.should == "compressed"
256
+
257
+ EventMachine.stop
258
+ }
259
+ }
260
+ end
261
+
262
+ it "should timeout after 10 seconds" do
263
+ EventMachine.run {
264
+ t = Time.now.to_i
265
+ http = EventMachine::HttpRequest.new('http://127.0.0.1:8080/timeout').get :timeout => 1
266
+
267
+ http.errback {
268
+ (Time.now.to_i - t).should >= 2
269
+ EventMachine.stop
270
+ }
271
+ http.callback { failed }
272
+ }
273
+ end
274
+
275
+ it "should optionally pass the response body progressively" do
276
+ EventMachine.run {
277
+ body = ''
278
+ http = EventMachine::HttpRequest.new('http://127.0.0.1:8080/').get
279
+
280
+ http.errback { failed }
281
+ http.stream { |chunk| body += chunk }
282
+
283
+ http.callback {
284
+ http.response_header.status.should == 200
285
+ http.response.should == ''
286
+ body.should match(/Hello/)
287
+ EventMachine.stop
288
+ }
289
+ }
290
+ end
291
+
292
+ it "should optionally pass the deflate-encoded response body progressively" do
293
+ EventMachine.run {
294
+ body = ''
295
+ http = EventMachine::HttpRequest.new('http://127.0.0.1:8080/deflate').get :head => {"accept-encoding" => "deflate, compressed"}
296
+
297
+ http.errback { failed }
298
+ http.stream { |chunk| body += chunk }
299
+
300
+ http.callback {
301
+ http.response_header.status.should == 200
302
+ http.response_header["CONTENT_ENCODING"].should == "deflate"
303
+ http.response.should == ''
304
+ body.should == "compressed"
305
+ EventMachine.stop
306
+ }
307
+ }
308
+ end
309
+
310
+ it "should initiate SSL/TLS on HTTPS connections" do
311
+ EventMachine.run {
312
+ http = EventMachine::HttpRequest.new('https://mail.google.com:443/mail/').get
313
+
314
+ http.errback { failed }
315
+ http.callback {
316
+ http.response_header.status.should == 302
317
+ EventMachine.stop
318
+ }
319
+ }
320
+ end
321
+
322
+ it "should accept & return cookie header to user" do
323
+ EventMachine.run {
324
+ http = EventMachine::HttpRequest.new('http://127.0.0.1:8080/set_cookie').get
325
+
326
+ http.errback { failed }
327
+ http.callback {
328
+ http.response_header.status.should == 200
329
+ http.response_header.cookie.should == "id=1; expires=Tue, 09-Aug-2011 17:53:39 GMT; path=/;"
330
+ EventMachine.stop
331
+ }
332
+ }
333
+ end
334
+
335
+ it "should pass cookie header to server from string" do
336
+ EventMachine.run {
337
+ http = EventMachine::HttpRequest.new('http://127.0.0.1:8080/echo_cookie').get :head => {'cookie' => 'id=2;'}
338
+
339
+ http.errback { failed }
340
+ http.callback {
341
+ http.response.should == "id=2;"
342
+ EventMachine.stop
343
+ }
344
+ }
345
+ end
346
+
347
+ it "should pass cookie header to server from Hash" do
348
+ EventMachine.run {
349
+ http = EventMachine::HttpRequest.new('http://127.0.0.1:8080/echo_cookie').get :head => {'cookie' => {'id' => 2}}
350
+
351
+ http.errback { failed }
352
+ http.callback {
353
+ http.response.should == "id=2;"
354
+ EventMachine.stop
355
+ }
356
+ }
357
+ end
358
+
359
+ context "when talking to a stub HTTP/1.0 server" do
360
+ it "should get the body without Content-Length" do
361
+ EventMachine.run {
362
+ @s = StubServer.new("HTTP/1.0 200 OK\r\nConnection: close\r\n\r\nFoo")
363
+
364
+ http = EventMachine::HttpRequest.new('http://127.0.0.1:8081/').get
365
+ http.errback { failed }
366
+ http.callback {
367
+ http.response.should match(/Foo/)
368
+ http.response_header['CONTENT_LENGTH'].should_not == 0
369
+
370
+ @s.stop
371
+ EventMachine.stop
372
+ }
373
+ }
374
+ end
375
+
376
+ it "should work with \\n instead of \\r\\n" do
377
+ EventMachine.run {
378
+ @s = StubServer.new("HTTP/1.0 200 OK\nContent-Type: text/plain\nContent-Length: 3\nConnection: close\n\nFoo")
379
+
380
+ http = EventMachine::HttpRequest.new('http://127.0.0.1:8081/').get
381
+ http.errback { failed }
382
+ http.callback {
383
+ http.response_header.status.should == 200
384
+ http.response_header['CONTENT_TYPE'].should == 'text/plain'
385
+ http.response.should match(/Foo/)
386
+
387
+ @s.stop
388
+ EventMachine.stop
389
+ }
390
+ }
391
+ end
392
+ end
393
+ end