em-http-request 0.2.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.

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