em-http-request 0.2.9 → 0.3.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/spec/request_spec.rb CHANGED
@@ -1,19 +1,19 @@
1
- require 'spec/helper'
2
- require 'spec/stallion'
3
- require 'spec/stub_server'
1
+ require 'helper'
2
+ require 'stallion'
3
+ require 'stub_server'
4
4
 
5
5
  describe EventMachine::HttpRequest do
6
6
 
7
- def failed
7
+ def failed(http=nil)
8
8
  EventMachine.stop
9
- fail
9
+ http ? fail(http.error) : fail
10
10
  end
11
11
 
12
12
  it "should fail GET on DNS timeout" do
13
13
  EventMachine.run {
14
14
  EventMachine.heartbeat_interval = 0.1
15
15
  http = EventMachine::HttpRequest.new('http://127.1.1.1/').get :timeout => 1
16
- http.callback { failed }
16
+ http.callback { failed(http) }
17
17
  http.errback {
18
18
  http.response_header.status.should == 0
19
19
  EventMachine.stop
@@ -25,20 +25,31 @@ describe EventMachine::HttpRequest do
25
25
  EventMachine.run {
26
26
  EventMachine.heartbeat_interval = 0.1
27
27
  http = EventMachine::HttpRequest.new('http://somethinglocal/').get :timeout => 1
28
- http.callback { failed }
28
+ http.callback { failed(http) }
29
29
  http.errback {
30
30
  http.response_header.status.should == 0
31
31
  http.error.should match(/unable to resolve server address/)
32
+ http.uri.to_s.should match('http://somethinglocal:80/')
32
33
  EventMachine.stop
33
34
  }
34
35
  }
35
36
  end
36
37
 
37
- it "should fail GET on missing path" do
38
+ it "should raise error on invalid URL" do
38
39
  EventMachine.run {
39
40
  lambda {
40
- EventMachine::HttpRequest.new('http://www.google.com').get
41
- }.should raise_error(ArgumentError)
41
+ EventMachine::HttpRequest.new('random?text').get
42
+ }.should raise_error
43
+
44
+ EM.stop
45
+ }
46
+ end
47
+
48
+ it "should succeed GET on missing path" do
49
+ EventMachine.run {
50
+ lambda {
51
+ EventMachine::HttpRequest.new('http://127.0.0.1:8080').get
52
+ }.should_not raise_error(ArgumentError)
42
53
 
43
54
  EventMachine.stop
44
55
  }
@@ -48,7 +59,7 @@ describe EventMachine::HttpRequest do
48
59
  EventMachine.run {
49
60
  http = EventMachine::HttpRequest.new('http://127.0.0.1:8080/').get
50
61
 
51
- http.errback { failed }
62
+ http.errback { failed(http) }
52
63
  http.callback {
53
64
  http.response_header.status.should == 200
54
65
  http.response.should match(/Hello/)
@@ -57,12 +68,90 @@ describe EventMachine::HttpRequest do
57
68
  }
58
69
  end
59
70
 
71
+ context "host override" do
72
+
73
+ it "should accept optional host" do
74
+ EventMachine.run {
75
+ http = EventMachine::HttpRequest.new('http://google.com:8080/').get :host => '127.0.0.1'
76
+
77
+ http.errback { failed(http) }
78
+ http.callback {
79
+ http.response_header.status.should == 200
80
+ http.response.should match(/Hello/)
81
+ EventMachine.stop
82
+ }
83
+ }
84
+ end
85
+
86
+ it "should reset host on redirect" do
87
+ EventMachine.run {
88
+ http = EventMachine::HttpRequest.new('http://127.0.0.1:8080/redirect').get :redirects => 1, :host => '127.0.0.1'
89
+
90
+ http.errback { failed(http) }
91
+ http.callback {
92
+ http.response_header.status.should == 200
93
+ http.response_header["CONTENT_ENCODING"].should == "gzip"
94
+ http.response.should == "compressed"
95
+ http.last_effective_url.to_s.should == 'http://127.0.0.1:8080/gzip'
96
+ http.redirects.should == 1
97
+
98
+ EM.stop
99
+ }
100
+ }
101
+ end
102
+
103
+ it "should redirect with missing content-length" do
104
+ EventMachine.run {
105
+ @s = StubServer.new("HTTP/1.0 301 MOVED PERMANENTLY\r\nlocation: http://127.0.0.1:8080/redirect\r\n\r\n")
106
+
107
+ http = EventMachine::HttpRequest.new('http://127.0.0.1:8081/').get :redirects => 2
108
+ http.errback { failed(http) }
109
+
110
+ http.callback {
111
+ http.response_header.status.should == 200
112
+ http.response_header["CONTENT_ENCODING"].should == "gzip"
113
+ http.response.should == "compressed"
114
+ http.last_effective_url.to_s.should == 'http://127.0.0.1:8080/gzip'
115
+ http.redirects.should == 2
116
+
117
+ @s.stop
118
+ EM.stop
119
+ }
120
+ }
121
+ end
122
+
123
+ it "should follow redirects on HEAD method" do
124
+ EventMachine.run {
125
+ http = EventMachine::HttpRequest.new('http://127.0.0.1:8080/redirect/head').head :redirects => 1
126
+ http.errback { failed(http) }
127
+ http.callback {
128
+ http.response_header.status.should == 200
129
+ http.last_effective_url.to_s.should == 'http://127.0.0.1:8080/'
130
+ EM.stop
131
+ }
132
+ }
133
+ end
134
+
135
+ it "should follow redirects on HEAD method (external)" do
136
+
137
+ EventMachine.run {
138
+ http = EventMachine::HttpRequest.new('http://www.google.com/').head :redirects => 1
139
+ http.errback { failed(http) }
140
+ http.callback {
141
+ http.response_header.status.should == 200
142
+ EM.stop
143
+ }
144
+ }
145
+ end
146
+
147
+ end
148
+
60
149
  it "should perform successfull GET with a URI passed as argument" do
61
150
  EventMachine.run {
62
151
  uri = URI.parse('http://127.0.0.1:8080/')
63
152
  http = EventMachine::HttpRequest.new(uri).get
64
153
 
65
- http.errback { failed }
154
+ http.errback { failed(http) }
66
155
  http.callback {
67
156
  http.response_header.status.should == 200
68
157
  http.response.should match(/Hello/)
@@ -76,7 +165,7 @@ describe EventMachine::HttpRequest do
76
165
  uri = URI.parse('http://127.0.0.1:8080/')
77
166
  http = EventMachine::HttpRequest.new(uri).head
78
167
 
79
- http.errback { p http; failed }
168
+ http.errback { failed(http) }
80
169
  http.callback {
81
170
  http.response_header.status.should == 200
82
171
  http.response.should == ""
@@ -91,7 +180,7 @@ describe EventMachine::HttpRequest do
91
180
  uri = URI.parse('http://127.0.0.1:8080/')
92
181
  http = EventMachine::HttpRequest.new(uri).delete
93
182
 
94
- http.errback { failed }
183
+ http.errback { failed(http) }
95
184
  http.callback {
96
185
  http.response_header.status.should == 200
97
186
  http.response.should == ""
@@ -104,7 +193,7 @@ describe EventMachine::HttpRequest do
104
193
  EventMachine.run {
105
194
  http = EventMachine::HttpRequest.new('http://127.0.0.1:8080/fail').get
106
195
 
107
- http.errback { failed }
196
+ http.errback { failed(http) }
108
197
  http.callback {
109
198
  http.response_header.status.should == 404
110
199
  EventMachine.stop
@@ -116,7 +205,7 @@ describe EventMachine::HttpRequest do
116
205
  EventMachine.run {
117
206
  http = EventMachine::HttpRequest.new('http://127.0.0.1:8080/').get :query => {:q => 'test'}
118
207
 
119
- http.errback { failed }
208
+ http.errback { failed(http) }
120
209
  http.callback {
121
210
  http.response_header.status.should == 200
122
211
  http.response.should match(/test/)
@@ -129,7 +218,7 @@ describe EventMachine::HttpRequest do
129
218
  EventMachine.run {
130
219
  http = EventMachine::HttpRequest.new('http://127.0.0.1:8080/').get :query => "q=test"
131
220
 
132
- http.errback { failed }
221
+ http.errback { failed(http) }
133
222
  http.callback {
134
223
  http.response_header.status.should == 200
135
224
  http.response.should match(/test/)
@@ -142,7 +231,7 @@ describe EventMachine::HttpRequest do
142
231
  EventMachine.run {
143
232
  http = EventMachine::HttpRequest.new('http://127.0.0.1:8080/echo_query').get :query => {:hash => ['value1', 'value2']}
144
233
 
145
- http.errback { failed }
234
+ http.errback { failed(http) }
146
235
  http.callback {
147
236
  http.response_header.status.should == 200
148
237
  http.response.should match(/hash\[\]=value1&hash\[\]=value2/)
@@ -156,7 +245,7 @@ describe EventMachine::HttpRequest do
156
245
  EventMachine.run {
157
246
  http = EventMachine::HttpRequest.new('http://127.0.0.1:8080/').put :body => "data"
158
247
 
159
- http.errback { failed }
248
+ http.errback { failed(http) }
160
249
  http.callback {
161
250
  http.response_header.status.should == 200
162
251
  http.response.should match(/data/)
@@ -169,7 +258,7 @@ describe EventMachine::HttpRequest do
169
258
  EventMachine.run {
170
259
  http = EventMachine::HttpRequest.new('http://127.0.0.1:8080/').post :body => "data"
171
260
 
172
- http.errback { failed }
261
+ http.errback { failed(http) }
173
262
  http.callback {
174
263
  http.response_header.status.should == 200
175
264
  http.response.should match(/data/)
@@ -178,11 +267,24 @@ describe EventMachine::HttpRequest do
178
267
  }
179
268
  end
180
269
 
270
+ it "should escape body on POST" do
271
+ EventMachine.run {
272
+ http = EventMachine::HttpRequest.new('http://127.0.0.1:8080/').post :body => {:stuff => 'string&string'}
273
+
274
+ http.errback { failed(http) }
275
+ http.callback {
276
+ http.response_header.status.should == 200
277
+ http.response.should == "stuff=string%26string"
278
+ EventMachine.stop
279
+ }
280
+ }
281
+ end
282
+
181
283
  it "should perform successfull POST with Ruby Hash/Array as params" do
182
284
  EventMachine.run {
183
285
  http = EventMachine::HttpRequest.new('http://127.0.0.1:8080/').post :body => {"key1" => 1, "key2" => [2,3]}
184
286
 
185
- http.errback { failed }
287
+ http.errback { failed(http) }
186
288
  http.callback {
187
289
  http.response_header.status.should == 200
188
290
 
@@ -196,7 +298,7 @@ describe EventMachine::HttpRequest do
196
298
  EventMachine.run {
197
299
  http = EventMachine::HttpRequest.new('http://127.0.0.1:8080/echo_content_length').post :body => {"key1" => "data1"}
198
300
 
199
- http.errback { failed }
301
+ http.errback { failed(http) }
200
302
  http.callback {
201
303
  http.response_header.status.should == 200
202
304
 
@@ -210,7 +312,7 @@ describe EventMachine::HttpRequest do
210
312
  EventMachine.run {
211
313
  http = EventMachine::HttpRequest.new('http://127.0.0.1:8080/').get :head => {'if-none-match' => 'evar!'}
212
314
 
213
- http.errback { failed }
315
+ http.errback { failed(http) }
214
316
  http.callback {
215
317
  http.response_header.status.should == 304
216
318
  EventMachine.stop
@@ -222,9 +324,9 @@ describe EventMachine::HttpRequest do
222
324
  EventMachine.run {
223
325
 
224
326
  # digg.com uses chunked encoding
225
- http = EventMachine::HttpRequest.new('http://digg.com/').get
327
+ http = EventMachine::HttpRequest.new('http://digg.com/news').get
226
328
 
227
- http.errback { failed }
329
+ http.errback { failed(http) }
228
330
  http.callback {
229
331
  http.response_header.status.should == 200
230
332
  EventMachine.stop
@@ -237,7 +339,7 @@ describe EventMachine::HttpRequest do
237
339
 
238
340
  http = EventMachine::HttpRequest.new('http://127.0.0.1:8080/').get :head => {'authorization' => ['user', 'pass']}
239
341
 
240
- http.errback { failed }
342
+ http.errback { failed(http) }
241
343
  http.callback {
242
344
  http.response_header.status.should == 200
243
345
  EventMachine.stop
@@ -250,7 +352,7 @@ describe EventMachine::HttpRequest do
250
352
  oauth_header = 'OAuth oauth_nonce="oqwgSYFUD87MHmJJDv7bQqOF2EPnVus7Wkqj5duNByU", b=c, d=e'
251
353
  http = EventMachine::HttpRequest.new('http://127.0.0.1:8080/oauth_auth').get :head => {'authorization' => oauth_header}
252
354
 
253
- http.errback { failed }
355
+ http.errback { failed(http) }
254
356
  http.callback {
255
357
  http.response_header.status.should == 200
256
358
  http.response.should == oauth_header
@@ -259,14 +361,43 @@ describe EventMachine::HttpRequest do
259
361
  }
260
362
  end
261
363
 
262
- it "should work with keep-alive servers" do
263
- EventMachine.run {
364
+ context "keepalive" do
365
+ it "should default to non-keepalive" do
366
+ EventMachine.run {
367
+ headers = {'If-Modified-Since' => 'Thu, 05 Aug 2010 22:54:44 GMT'}
368
+ http = EventMachine::HttpRequest.new('http://www.google.com/images/logos/ps_logo2.png').get :head => headers
264
369
 
265
- http = EventMachine::HttpRequest.new('http://mexicodiario.com/touch.public.json.php').get
370
+ http.errback { fail }
371
+ start = Time.now.to_i
372
+ http.callback {
373
+ (start - Time.now.to_i).should be_within(1).of(0)
374
+ EventMachine.stop
375
+ }
376
+ }
377
+ end
378
+
379
+ it "should work with keep-alive servers" do
380
+ EventMachine.run {
381
+ http = EventMachine::HttpRequest.new('http://mexicodiario.com/touch.public.json.php').get :keepalive => true
266
382
 
267
- http.errback { failed }
383
+ http.errback { failed(http) }
384
+ http.callback {
385
+ http.response_header.status.should == 200
386
+ EventMachine.stop
387
+ }
388
+ }
389
+ end
390
+ end
391
+
392
+ it "should return ETag and Last-Modified headers" do
393
+ EventMachine.run {
394
+ http = EventMachine::HttpRequest.new('http://127.0.0.1:8080/echo_query').get
395
+
396
+ http.errback { failed(http) }
268
397
  http.callback {
269
398
  http.response_header.status.should == 200
399
+ http.response_header.etag.should match('abcdefg')
400
+ http.response_header.last_modified.should match('Fri, 13 Aug 2010 17:31:21 GMT')
270
401
  EventMachine.stop
271
402
  }
272
403
  }
@@ -277,7 +408,7 @@ describe EventMachine::HttpRequest do
277
408
 
278
409
  http = EventMachine::HttpRequest.new('http://127.0.0.1:8080/deflate').get :head => {"accept-encoding" => "deflate"}
279
410
 
280
- http.errback { failed }
411
+ http.errback { failed(http) }
281
412
  http.callback {
282
413
  http.response_header.status.should == 200
283
414
  http.response_header["CONTENT_ENCODING"].should == "deflate"
@@ -293,7 +424,7 @@ describe EventMachine::HttpRequest do
293
424
 
294
425
  http = EventMachine::HttpRequest.new('http://127.0.0.1:8080/gzip').get :head => {"accept-encoding" => "gzip, compressed"}
295
426
 
296
- http.errback { failed }
427
+ http.errback { failed(http) }
297
428
  http.callback {
298
429
  http.response_header.status.should == 200
299
430
  http.response_header["CONTENT_ENCODING"].should == "gzip"
@@ -314,51 +445,98 @@ describe EventMachine::HttpRequest do
314
445
  (Time.now.to_i - t).should <= 5
315
446
  EventMachine.stop
316
447
  }
317
- http.callback { failed }
448
+ http.callback { failed(http) }
318
449
  }
319
450
  end
320
451
 
321
- it "should report last_effective_url" do
322
- EventMachine.run {
323
- http = EventMachine::HttpRequest.new('http://127.0.0.1:8080/').get
324
- http.errback { failed }
325
- http.callback {
326
- http.response_header.status.should == 200
327
- http.last_effective_url.to_s.should == 'http://127.0.0.1:8080/'
452
+ context "redirect" do
453
+ it "should report last_effective_url" do
454
+ EventMachine.run {
455
+ http = EventMachine::HttpRequest.new('http://127.0.0.1:8080/').get
456
+ http.errback { failed(http) }
457
+ http.callback {
458
+ http.response_header.status.should == 200
459
+ http.last_effective_url.to_s.should == 'http://127.0.0.1:8080/'
328
460
 
329
- EM.stop
461
+ EM.stop
462
+ }
330
463
  }
331
- }
332
- end
464
+ end
333
465
 
334
- it "should follow location redirects" do
335
- EventMachine.run {
336
- http = EventMachine::HttpRequest.new('http://127.0.0.1:8080/redirect').get :redirects => 1
337
- http.errback { failed }
338
- http.callback {
339
- http.response_header.status.should == 200
340
- http.response_header["CONTENT_ENCODING"].should == "gzip"
341
- http.response.should == "compressed"
342
- http.last_effective_url.to_s.should == 'http://127.0.0.1:8080/gzip'
343
- http.redirects.should == 1
466
+ it "should follow location redirects" do
467
+ EventMachine.run {
468
+ http = EventMachine::HttpRequest.new('http://127.0.0.1:8080/redirect').get :redirects => 1
469
+ http.errback { failed(http) }
470
+ http.callback {
471
+ http.response_header.status.should == 200
472
+ http.response_header["CONTENT_ENCODING"].should == "gzip"
473
+ http.response.should == "compressed"
474
+ http.last_effective_url.to_s.should == 'http://127.0.0.1:8080/gzip'
475
+ http.redirects.should == 1
344
476
 
345
- EM.stop
477
+ EM.stop
478
+ }
346
479
  }
347
- }
348
- end
480
+ end
349
481
 
350
- it "should default to 0 redirects" do
351
- EventMachine.run {
352
- http = EventMachine::HttpRequest.new('http://127.0.0.1:8080/redirect').get
353
- http.errback { failed }
354
- http.callback {
355
- http.response_header.status.should == 301
356
- http.last_effective_url.to_s.should == 'http://127.0.0.1:8080/gzip'
357
- http.redirects.should == 0
482
+ it "should default to 0 redirects" do
483
+ EventMachine.run {
484
+ http = EventMachine::HttpRequest.new('http://127.0.0.1:8080/redirect').get
485
+ http.errback { failed(http) }
486
+ http.callback {
487
+ http.response_header.status.should == 301
488
+ http.last_effective_url.to_s.should == 'http://127.0.0.1:8080/gzip'
489
+ http.redirects.should == 0
358
490
 
359
- EM.stop
491
+ EM.stop
492
+ }
360
493
  }
361
- }
494
+ end
495
+
496
+ it "should not invoke redirect logic on failed(http) connections" do
497
+ EventMachine.run {
498
+ http = EventMachine::HttpRequest.new('http://127.0.0.1:8081/').get :timeout => 0.1, :redirects => 5
499
+ http.callback { failed(http) }
500
+ http.errback {
501
+ http.redirects.should == 0
502
+ EM.stop
503
+ }
504
+ }
505
+ end
506
+
507
+ it "should normalize redirect urls" do
508
+ EventMachine.run {
509
+ http = EventMachine::HttpRequest.new('http://127.0.0.1:8080/redirect/bad').get :redirects => 1
510
+ http.errback { failed(http) }
511
+ http.callback {
512
+ http.last_effective_url.to_s.should match('http://127.0.0.1:8080/')
513
+ http.response.should match('Hello, World!')
514
+ EM.stop
515
+ }
516
+ }
517
+ end
518
+
519
+ it "should fail gracefully on a missing host in absolute Location header" do
520
+ EventMachine.run {
521
+ http = EventMachine::HttpRequest.new('http://127.0.0.1:8080/redirect/nohost').get :redirects => 1
522
+ http.callback { failed(http) }
523
+ http.errback {
524
+ http.error.should == 'Location header format error'
525
+ EM.stop
526
+ }
527
+ }
528
+ end
529
+
530
+ it "should fail gracefully on an invalid host in Location header" do
531
+ EventMachine.run {
532
+ http = EventMachine::HttpRequest.new('http://127.0.0.1:8080/redirect/badhost').get :redirects => 1
533
+ http.callback { failed(http) }
534
+ http.errback {
535
+ http.error.should == 'unable to resolve server address'
536
+ EM.stop
537
+ }
538
+ }
539
+ end
362
540
  end
363
541
 
364
542
  it "should optionally pass the response body progressively" do
@@ -366,7 +544,7 @@ describe EventMachine::HttpRequest do
366
544
  body = ''
367
545
  http = EventMachine::HttpRequest.new('http://127.0.0.1:8080/').get
368
546
 
369
- http.errback { failed }
547
+ http.errback { failed(http) }
370
548
  http.stream { |chunk| body += chunk }
371
549
 
372
550
  http.callback {
@@ -378,12 +556,55 @@ describe EventMachine::HttpRequest do
378
556
  }
379
557
  end
380
558
 
559
+ context "optional header callback" do
560
+ it "should optionally pass the response headers" do
561
+ EventMachine.run {
562
+ http = EventMachine::HttpRequest.new('http://127.0.0.1:8080/').get
563
+
564
+ http.errback { failed(http) }
565
+ http.headers { |hash|
566
+ hash.should be_an_kind_of Hash
567
+ hash.should include 'CONNECTION'
568
+ hash.should include 'CONTENT_LENGTH'
569
+ }
570
+
571
+ http.callback {
572
+ http.response_header.status.should == 200
573
+ http.response.should match(/Hello/)
574
+ EventMachine.stop
575
+ }
576
+ }
577
+ end
578
+
579
+ it "should allow to terminate current connection from header callback" do
580
+ EventMachine.run {
581
+ http = EventMachine::HttpRequest.new('http://127.0.0.1:8080/').get
582
+
583
+ http.callback { failed(http) }
584
+ http.headers { |hash|
585
+ hash.should be_an_kind_of Hash
586
+ hash.should include 'CONNECTION'
587
+ hash.should include 'CONTENT_LENGTH'
588
+
589
+ http.close('header callback terminated connection')
590
+ }
591
+
592
+ http.errback { |e|
593
+ http.response_header.status.should == 200
594
+ http.error.should == 'header callback terminated connection'
595
+ http.response.should == ''
596
+ EventMachine.stop
597
+ }
598
+ }
599
+ end
600
+ end
601
+
381
602
  it "should optionally pass the deflate-encoded response body progressively" do
382
603
  EventMachine.run {
383
604
  body = ''
384
605
  http = EventMachine::HttpRequest.new('http://127.0.0.1:8080/deflate').get :head => {"accept-encoding" => "deflate, compressed"}
385
606
 
386
- http.errback { failed }
607
+ http.errback { failed(http) }
387
608
  http.stream { |chunk| body += chunk }
388
609
 
389
610
  http.callback {
@@ -400,7 +621,7 @@ describe EventMachine::HttpRequest do
400
621
  EventMachine.run {
401
622
  http = EventMachine::HttpRequest.new('https://mail.google.com:443/mail/').get
402
623
 
403
- http.errback { failed }
624
+ http.errback { failed(http) }
404
625
  http.callback {
405
626
  http.response_header.status.should == 302
406
627
  EventMachine.stop
@@ -412,7 +633,7 @@ describe EventMachine::HttpRequest do
412
633
  EventMachine.run {
413
634
  http = EventMachine::HttpRequest.new('http://127.0.0.1:8080/set_cookie').get
414
635
 
415
- http.errback { failed }
636
+ http.errback { failed(http) }
416
637
  http.callback {
417
638
  http.response_header.status.should == 200
418
639
  http.response_header.cookie.should == "id=1; expires=Tue, 09-Aug-2011 17:53:39 GMT; path=/;"
@@ -425,7 +646,7 @@ describe EventMachine::HttpRequest do
425
646
  EventMachine.run {
426
647
  http = EventMachine::HttpRequest.new('http://127.0.0.1:8080/echo_cookie').get :head => {'cookie' => 'id=2;'}
427
648
 
428
- http.errback { failed }
649
+ http.errback { failed(http) }
429
650
  http.callback {
430
651
  http.response.should == "id=2;"
431
652
  EventMachine.stop
@@ -437,7 +658,7 @@ describe EventMachine::HttpRequest do
437
658
  EventMachine.run {
438
659
  http = EventMachine::HttpRequest.new('http://127.0.0.1:8080/echo_cookie').get :head => {'cookie' => {'id' => 2}}
439
660
 
440
- http.errback { failed }
661
+ http.errback { failed(http) }
441
662
  http.callback {
442
663
  http.response.should == "id=2;"
443
664
  EventMachine.stop
@@ -451,7 +672,7 @@ describe EventMachine::HttpRequest do
451
672
  @s = StubServer.new("HTTP/1.0 200 OK\r\nConnection: close\r\n\r\nFoo")
452
673
 
453
674
  http = EventMachine::HttpRequest.new('http://127.0.0.1:8081/').get
454
- http.errback { failed }
675
+ http.errback { failed(http) }
455
676
  http.callback {
456
677
  http.response.should match(/Foo/)
457
678
  http.response_header['CONTENT_LENGTH'].should_not == 0
@@ -467,7 +688,7 @@ describe EventMachine::HttpRequest do
467
688
  @s = StubServer.new("HTTP/1.0 200 OK\nContent-Type: text/plain\nContent-Length: 3\nConnection: close\n\nFoo")
468
689
 
469
690
  http = EventMachine::HttpRequest.new('http://127.0.0.1:8081/').get
470
- http.errback { failed }
691
+ http.errback { failed(http) }
471
692
  http.callback {
472
693
  http.response_header.status.should == 200
473
694
  http.response_header['CONTENT_TYPE'].should == 'text/plain'
@@ -485,7 +706,7 @@ describe EventMachine::HttpRequest do
485
706
  EventMachine.run {
486
707
  http = EventMachine::HttpRequest.new('http://127.0.0.1:8080/echo_content_type').post :body => "data"
487
708
 
488
- http.errback { failed }
709
+ http.errback { failed(http) }
489
710
  http.callback {
490
711
  http.response_header.status.should == 200
491
712
  http.response.should be_empty
@@ -498,7 +719,7 @@ describe EventMachine::HttpRequest do
498
719
  EventMachine.run {
499
720
  http = EventMachine::HttpRequest.new('http://127.0.0.1:8080/echo_content_type').post :body => {:a => :b}
500
721
 
501
- http.errback { failed }
722
+ http.errback { failed(http) }
502
723
  http.callback {
503
724
  http.response_header.status.should == 200
504
725
  http.response.should match("application/x-www-form-urlencoded")
@@ -509,24 +730,59 @@ describe EventMachine::HttpRequest do
509
730
 
510
731
  it "should not override content-type when passing in ruby hash/array for body" do
511
732
  EventMachine.run {
733
+ ct = 'text; charset=utf-8'
734
+ http = EventMachine::HttpRequest.new('http://127.0.0.1:8080/echo_content_type').post({
735
+ :body => {:a => :b}, :head => {'content-type' => ct}})
736
+
737
+ http.errback { failed(http) }
738
+ http.callback {
739
+ http.response_header.status.should == 200
740
+ http.content_charset.should == Encoding.find('utf-8')
741
+ http.response_header["CONTENT_TYPE"].should == ct
742
+ EventMachine.stop
743
+ }
744
+ }
745
+ end
746
+
747
+ it "should default to external encoding on invalid encoding" do
748
+ EventMachine.run {
749
+ ct = 'text/html; charset=utf-8lias'
512
750
  http = EventMachine::HttpRequest.new('http://127.0.0.1:8080/echo_content_type').post({
513
- :body => {:a => :b}, :head => {'content-type' => 'text'}})
751
+ :body => {:a => :b}, :head => {'content-type' => ct}})
514
752
 
515
- http.errback { failed }
753
+ http.errback { failed(http) }
516
754
  http.callback {
517
755
  http.response_header.status.should == 200
518
- http.response.should match("text")
756
+ http.content_charset.should == Encoding.find('utf-8')
757
+ http.response_header["CONTENT_TYPE"].should == ct
519
758
  EventMachine.stop
520
759
  }
521
760
  }
522
761
  end
762
+
763
+ it "should processed escaped content-type" do
764
+ EventMachine.run {
765
+ ct = "text/html; charset=\"ISO-8859-4\""
766
+ http = EventMachine::HttpRequest.new('http://127.0.0.1:8080/echo_content_type').post({
767
+ :body => {:a => :b}, :head => {'content-type' => ct}})
768
+
769
+ http.errback { failed(http) }
770
+ http.callback {
771
+ http.response_header.status.should == 200
772
+ http.content_charset.should == Encoding.find('ISO-8859-4')
773
+ http.response_header["CONTENT_TYPE"].should == ct
774
+ EventMachine.stop
775
+ }
776
+ }
777
+ end
778
+
523
779
  end
524
780
 
525
781
  it "should complete a Location: with a relative path" do
526
782
  EventMachine.run {
527
783
  http = EventMachine::HttpRequest.new('http://127.0.0.1:8080/relative-location').get
528
784
 
529
- http.errback { failed }
785
+ http.errback { failed(http) }
530
786
  http.callback {
531
787
  http.response_header['LOCATION'].should == 'http://127.0.0.1:8080/forwarded'
532
788
  EventMachine.stop
@@ -538,7 +794,7 @@ describe EventMachine::HttpRequest do
538
794
  EventMachine.run {
539
795
  http = EventMachine::HttpRequest.new('http://127.0.0.1:8080/').post :file => 'spec/fixtures/google.ca'
540
796
 
541
- http.errback { failed }
797
+ http.errback { failed(http) }
542
798
  http.callback {
543
799
  http.response.should match('google')
544
800
  EventMachine.stop
@@ -554,7 +810,7 @@ describe EventMachine::HttpRequest do
554
810
  c.options[:body] = {:callback_run => 'yes'}
555
811
  client = c
556
812
  }
557
- http.errback { failed }
813
+ http.errback { failed(http) }
558
814
  http.callback {
559
815
  client.should be_kind_of(EventMachine::HttpClient)
560
816
  http.response_header.status.should == 200
@@ -571,8 +827,8 @@ describe EventMachine::HttpRequest do
571
827
  http = EventMachine::MockHttpRequest.new('http://www.google.ca/').get
572
828
  http.errback { fail }
573
829
  http.callback {
574
- c1 = "PREF=ID=9454187d21c4a6a6:TM=1258403955:LM=1258403955:S=2-mf1n5oV5yAeT9-; expires=Wed, 16-Nov-2011 20:39:15 GMT; path=/; domain=.google.ca"
575
- c2 = "NID=28=lvxxVdiBQkCetu_WFaUxLyB7qPlHXS5OdAGYTqge_laVlCKVN8VYYeVBh4bNZiK_Oan2gm8oP9GA-FrZfMPC3ZMHeNq37MG2JH8AIW9LYucU8brOeuggMEbLNNXuiWg4; expires=Tue, 18-May-2010 20:39:15 GMT; path=/; domain=.google.ca; HttpOnly"
830
+ c1 = "PREF=ID=11955ae9690fd292:TM=1281823106:LM=1281823106:S=wHdloFqGQ_OLSE92; expires=Mon, 13-Aug-2012 21:58:26 GMT; path=/; domain=.google.ca"
831
+ c2 = "NID=37=USTdOsxOSMbLjphkJ3S5Ueua3Yc23COXuK_pbztcHx7JoyhomwQySrvebCf3_u8eyrBiLWssVzaZcEOiKGEJbNdy8lRhnq_mfrdz693LaMjNPh__ccW4sgn1ZO6nQltE; expires=Sun, 13-Feb-2011 21:58:26 GMT; path=/; domain=.google.ca; HttpOnly"
576
832
  http.response_header.cookie.should == [c1, c2]
577
833
 
578
834
  EventMachine.stop
@@ -582,35 +838,93 @@ describe EventMachine::HttpRequest do
582
838
  EventMachine::MockHttpRequest.count('http://www.google.ca:80/', :get, {}).should == 1
583
839
  end
584
840
 
585
- context "connections via proxy" do
841
+ context "connections via" do
842
+ context "direct proxy" do
843
+ it "should default to skip CONNECT" do
844
+ EventMachine.run {
586
845
 
587
- it "should work with proxy servers" do
588
- EventMachine.run {
846
+ http = EventMachine::HttpRequest.new('http://127.0.0.1:8080/?q=test').get :proxy => {
847
+ :host => '127.0.0.1', :port => 8083
848
+ }
589
849
 
590
- http = EventMachine::HttpRequest.new('http://127.0.0.1:8080/').get :proxy => {:host => '127.0.0.1', :port => 8082}
850
+ http.errback { failed(http) }
851
+ http.callback {
852
+ http.response_header.status.should == 200
853
+ http.response.should match('test')
854
+ EventMachine.stop
855
+ }
856
+ }
857
+ end
591
858
 
592
- http.errback { p http.inspect; failed }
593
- http.callback {
594
- http.response_header.status.should == 200
595
- http.response.should == 'Hello, World!'
596
- EventMachine.stop
859
+ it "should send absolute URIs to the proxy server" do
860
+ EventMachine.run {
861
+
862
+ http = EventMachine::HttpRequest.new('http://127.0.0.1:8080/?q=test').get :proxy => {
863
+ :host => '127.0.0.1', :port => 8083
864
+ }
865
+
866
+ http.errback { failed(http) }
867
+ http.callback {
868
+ http.response_header.status.should == 200
869
+ # The test proxy server gives the requested uri back in this header
870
+ http.response_header['X_THE_REQUESTED_URI'].should == 'http://127.0.0.1:8080/?q=test'
871
+ http.response_header['X_THE_REQUESTED_URI'].should_not == '/?q=test'
872
+ http.response.should match('test')
873
+ EventMachine.stop
874
+ }
597
875
  }
598
- }
876
+ end
877
+
878
+ it "should include query parameters specified in the options" do
879
+ EventMachine.run {
880
+
881
+ http = EventMachine::HttpRequest.new('http://127.0.0.1:8080/').get(
882
+ :proxy => { :host => '127.0.0.1', :port => 8083 },
883
+ :query => { 'q' => 'test' }
884
+ )
885
+
886
+ http.errback { failed(http) }
887
+ http.callback {
888
+ http.response_header.status.should == 200
889
+ http.response.should match('test')
890
+ EventMachine.stop
891
+ }
892
+ }
893
+ end
599
894
  end
600
895
 
601
- it "should proxy POST data" do
602
- EventMachine.run {
896
+ context "CONNECT proxy" do
897
+ it "should work with CONNECT proxy servers" do
898
+ EventMachine.run {
603
899
 
604
- http = EventMachine::HttpRequest.new('http://127.0.0.1:8080/').post({
605
- :body => "data", :proxy => {:host => '127.0.0.1', :port => 8082}})
900
+ http = EventMachine::HttpRequest.new('http://127.0.0.1:8080/').get({
901
+ :proxy => {:host => '127.0.0.1', :port => 8082, :use_connect => true}
902
+ })
606
903
 
607
- http.errback { failed }
608
- http.callback {
609
- http.response_header.status.should == 200
610
- http.response.should match(/data/)
611
- EventMachine.stop
904
+ http.errback { failed(http) }
905
+ http.callback {
906
+ http.response_header.status.should == 200
907
+ http.response.should == 'Hello, World!'
908
+ EventMachine.stop
909
+ }
612
910
  }
613
- }
911
+ end
912
+
913
+ it "should proxy POST data" do
914
+ EventMachine.run {
915
+
916
+ http = EventMachine::HttpRequest.new('http://127.0.0.1:8080/').post({
917
+ :body => "data", :proxy => {:host => '127.0.0.1', :port => 8082, :use_connect => true}
918
+ })
919
+
920
+ http.errback { failed(http) }
921
+ http.callback {
922
+ http.response_header.status.should == 200
923
+ http.response.should match(/data/)
924
+ EventMachine.stop
925
+ }
926
+ }
927
+ end
614
928
  end
615
929
  end
616
930
 
@@ -626,7 +940,7 @@ describe EventMachine::HttpRequest do
626
940
  EventMachine.run {
627
941
  http = EventMachine::HttpRequest.new('ws://127.0.0.1:8080/').get :timeout => 0
628
942
 
629
- http.callback { failed }
943
+ http.callback { failed(http) }
630
944
  http.errback {
631
945
  http.response_header.status.should == 200
632
946
  EventMachine.stop
@@ -643,7 +957,7 @@ describe EventMachine::HttpRequest do
643
957
  end
644
958
 
645
959
  http = EventMachine::HttpRequest.new('ws://127.0.0.1:8085/').get :timeout => 1
646
- http.errback { failed }
960
+ http.errback { failed(http) }
647
961
  http.callback {
648
962
  http.response_header.status.should == 101
649
963
  http.response_header['CONNECTION'].should match(/Upgrade/)
@@ -674,7 +988,7 @@ describe EventMachine::HttpRequest do
674
988
 
675
989
  EventMachine.add_timer(0.1) do
676
990
  http = EventMachine::HttpRequest.new('ws://127.0.0.1:8085/').get :timeout => 0
677
- http.errback { failed }
991
+ http.errback { failed(http) }
678
992
  http.callback { http.response_header.status.should == 101 }
679
993
  http.stream {|msg|
680
994
  msg.should == messages[recieved.size]