em-http-request 1.0.1 → 1.0.2

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.

data/spec/client_spec.rb CHANGED
@@ -1,734 +1,763 @@
1
- require 'helper'
2
-
3
- describe EventMachine::HttpRequest do
4
-
5
- def failed(http=nil)
6
- EventMachine.stop
7
- http ? fail(http.error) : fail
8
- end
9
-
10
- it "should perform successful GET" do
11
- EventMachine.run {
12
- http = EventMachine::HttpRequest.new('http://127.0.0.1:8090/').get
13
-
14
- http.errback { failed(http) }
15
- http.callback {
16
- http.response_header.status.should == 200
17
- http.response.should match(/Hello/)
18
- EventMachine.stop
19
- }
20
- }
21
- end
22
-
23
- it "should perform successful GET with a URI passed as argument" do
24
- EventMachine.run {
25
- uri = URI.parse('http://127.0.0.1:8090/')
26
- http = EventMachine::HttpRequest.new(uri).get
27
-
28
- http.errback { failed(http) }
29
- http.callback {
30
- http.response_header.status.should == 200
31
- http.response.should match(/Hello/)
32
- EventMachine.stop
33
- }
34
- }
35
- end
36
-
37
- it "should succeed GET on missing path" do
38
- EventMachine.run {
39
- lambda {
40
- http = EventMachine::HttpRequest.new('http://127.0.0.1:8090').get
41
- http.callback {
42
- http.response.should match(/Hello/)
43
- EventMachine.stop
44
- }
45
- }.should_not raise_error(ArgumentError)
46
-
47
- }
48
- end
49
-
50
- it "should raise error on invalid URL" do
51
- EventMachine.run {
52
- lambda {
53
- EventMachine::HttpRequest.new('random?text').get
54
- }.should raise_error
55
-
56
- EM.stop
57
- }
58
- end
59
-
60
- it "should perform successful HEAD with a URI passed as argument" do
61
- EventMachine.run {
62
- uri = URI.parse('http://127.0.0.1:8090/')
63
- http = EventMachine::HttpRequest.new(uri).head
64
-
65
- http.errback { failed(http) }
66
- http.callback {
67
- http.response_header.status.should == 200
68
- http.response.should == ""
69
- EventMachine.stop
70
- }
71
- }
72
- end
73
-
74
- it "should perform successful DELETE with a URI passed as argument" do
75
- EventMachine.run {
76
- uri = URI.parse('http://127.0.0.1:8090/')
77
- http = EventMachine::HttpRequest.new(uri).delete
78
-
79
- http.errback { failed(http) }
80
- http.callback {
81
- http.response_header.status.should == 200
82
- http.response.should == ""
83
- EventMachine.stop
84
- }
85
- }
86
- end
87
-
88
- it "should return 404 on invalid path" do
89
- EventMachine.run {
90
- http = EventMachine::HttpRequest.new('http://127.0.0.1:8090/fail').get
91
-
92
- http.errback { failed(http) }
93
- http.callback {
94
- http.response_header.status.should == 404
95
- EventMachine.stop
96
- }
97
- }
98
- end
99
-
100
- it "should return HTTP reason" do
101
- EventMachine.run {
102
- http = EventMachine::HttpRequest.new('http://127.0.0.1:8090/fail').get
103
-
104
- http.errback { failed(http) }
105
- http.callback {
106
- http.response_header.status.should == 404
107
- http.response_header.http_reason.should == 'Not Found'
108
- EventMachine.stop
109
- }
110
- }
111
- end
112
-
113
- it "should return HTTP reason 'unknown' on a non-standard status code" do
114
- EventMachine.run {
115
- http = EventMachine::HttpRequest.new('http://127.0.0.1:8090/fail_with_nonstandard_response').get
116
-
117
- http.errback { failed(http) }
118
- http.callback {
119
- http.response_header.status.should == 420
120
- http.response_header.http_reason.should == 'unknown'
121
- EventMachine.stop
122
- }
123
- }
124
- end
125
-
126
- it "should build query parameters from Hash" do
127
- EventMachine.run {
128
- http = EventMachine::HttpRequest.new('http://127.0.0.1:8090/').get :query => {:q => 'test'}
129
-
130
- http.errback { failed(http) }
131
- http.callback {
132
- http.response_header.status.should == 200
133
- http.response.should match(/test/)
134
- EventMachine.stop
135
- }
136
- }
137
- end
138
-
139
- it "should pass query parameters string" do
140
- EventMachine.run {
141
- http = EventMachine::HttpRequest.new('http://127.0.0.1:8090/').get :query => "q=test"
142
-
143
- http.errback { failed(http) }
144
- http.callback {
145
- http.response_header.status.should == 200
146
- http.response.should match(/test/)
147
- EventMachine.stop
148
- }
149
- }
150
- end
151
-
152
- it "should encode an array of query parameters" do
153
- EventMachine.run {
154
- http = EventMachine::HttpRequest.new('http://127.0.0.1:8090/echo_query').get :query => {:hash =>['value1','value2']}
155
-
156
- http.errback { failed(http) }
157
- http.callback {
158
- http.response_header.status.should == 200
159
- http.response.should match(/hash\[\]=value1&hash\[\]=value2/)
160
- EventMachine.stop
161
- }
162
- }
163
- end
164
-
165
- it "should perform successful PUT" do
166
- EventMachine.run {
167
- http = EventMachine::HttpRequest.new('http://127.0.0.1:8090/').put :body => "data"
168
-
169
- http.errback { failed(http) }
170
- http.callback {
171
- http.response_header.status.should == 200
172
- http.response.should match(/data/)
173
- EventMachine.stop
174
- }
175
- }
176
- end
177
-
178
- it "should perform successful POST" do
179
- EventMachine.run {
180
- http = EventMachine::HttpRequest.new('http://127.0.0.1:8090/').post :body => "data"
181
-
182
- http.errback { failed(http) }
183
- http.callback {
184
- http.response_header.status.should == 200
185
- http.response.should match(/data/)
186
- EventMachine.stop
187
- }
188
- }
189
- end
190
-
191
- it "should escape body on POST" do
192
- EventMachine.run {
193
- http = EventMachine::HttpRequest.new('http://127.0.0.1:8090/').post :body => {:stuff => 'string&string'}
194
-
195
- http.errback { failed(http) }
196
- http.callback {
197
- http.response_header.status.should == 200
198
- http.response.should == "stuff=string%26string"
199
- EventMachine.stop
200
- }
201
- }
202
- end
203
-
204
- it "should perform successful POST with Ruby Hash/Array as params" do
205
- EventMachine.run {
206
- http = EventMachine::HttpRequest.new('http://127.0.0.1:8090/').post :body => {"key1" => 1, "key2" => [2,3]}
207
-
208
- http.errback { failed(http) }
209
- http.callback {
210
- http.response_header.status.should == 200
211
-
212
- http.response.should match(/key1=1&key2\[0\]=2&key2\[1\]=3/)
213
- EventMachine.stop
214
- }
215
- }
216
- end
217
-
218
- it "should set content-length to 0 on posts with empty bodies" do
219
- EventMachine.run {
220
- http = EventMachine::HttpRequest.new('http://127.0.0.1:8090/echo_content_length_from_header').post
221
-
222
- http.errback { failed(http) }
223
- http.callback {
224
- http.response_header.status.should == 200
225
-
226
- http.response.strip.split(':')[1].should == '0'
227
- EventMachine.stop
228
- }
229
- }
230
- end
231
-
232
- it "should perform successful POST with Ruby Hash/Array as params and with the correct content length" do
233
- EventMachine.run {
234
- http = EventMachine::HttpRequest.new('http://127.0.0.1:8090/echo_content_length').post :body => {"key1" => "data1"}
235
-
236
- http.errback { failed(http) }
237
- http.callback {
238
- http.response_header.status.should == 200
239
-
240
- http.response.to_i.should == 10
241
- EventMachine.stop
242
- }
243
- }
244
- end
245
-
246
- it "should perform successful GET with custom header" do
247
- EventMachine.run {
248
- http = EventMachine::HttpRequest.new('http://127.0.0.1:8090/').get :head => {'if-none-match' => 'evar!'}
249
-
250
- http.errback { p http; failed(http) }
251
- http.callback {
252
- http.response_header.status.should == 304
253
- EventMachine.stop
254
- }
255
- }
256
- end
257
-
258
- it "should perform basic auth" do
259
- EventMachine.run {
260
-
261
- http = EventMachine::HttpRequest.new('http://127.0.0.1:8090/').get :head => {'authorization' => ['user', 'pass']}
262
-
263
- http.errback { failed(http) }
264
- http.callback {
265
- http.response_header.status.should == 200
266
- EventMachine.stop
267
- }
268
- }
269
- end
270
-
271
- it "should return peer's IP address" do
272
- EventMachine.run {
273
-
274
- conn = EventMachine::HttpRequest.new('http://127.0.0.1:8090/')
275
- conn.peer.should be_nil
276
-
277
- http = conn.get
278
- http.peer.should be_nil
279
-
280
- http.errback { failed(http) }
281
- http.callback {
282
- conn.peer.should == '127.0.0.1'
283
- http.peer.should == '127.0.0.1'
284
-
285
- EventMachine.stop
286
- }
287
- }
288
- end
289
-
290
- it "should remove all newlines from long basic auth header" do
291
- EventMachine.run {
292
- auth = {'authorization' => ['aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', 'zzzzzzzzzzzzzzzzzzzzzzzzzzzzzz']}
293
- http = EventMachine::HttpRequest.new('http://127.0.0.1:8090/auth').get :head => auth
294
- http.errback { failed(http) }
295
- http.callback {
296
- http.response_header.status.should == 200
297
- http.response.should == "Basic YWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhOnp6enp6enp6enp6enp6enp6enp6enp6enp6enp6eg=="
298
- EventMachine.stop
299
- }
300
- }
301
- end
302
-
303
- it "should send proper OAuth auth header" do
304
- EventMachine.run {
305
- oauth_header = 'OAuth oauth_nonce="oqwgSYFUD87MHmJJDv7bQqOF2EPnVus7Wkqj5duNByU", b=c, d=e'
306
- http = EventMachine::HttpRequest.new('http://127.0.0.1:8090/auth').get :head => {
307
- 'authorization' => oauth_header
308
- }
309
-
310
- http.errback { failed(http) }
311
- http.callback {
312
- http.response_header.status.should == 200
313
- http.response.should == oauth_header
314
- EventMachine.stop
315
- }
316
- }
317
- end
318
-
319
- it "should return ETag and Last-Modified headers" do
320
- EventMachine.run {
321
- http = EventMachine::HttpRequest.new('http://127.0.0.1:8090/echo_query').get
322
-
323
- http.errback { failed(http) }
324
- http.callback {
325
- http.response_header.status.should == 200
326
- http.response_header.etag.should match('abcdefg')
327
- http.response_header.last_modified.should match('Fri, 13 Aug 2010 17:31:21 GMT')
328
- EventMachine.stop
329
- }
330
- }
331
- end
332
-
333
- it "should detect deflate encoding" do
334
- EventMachine.run {
335
-
336
- http = EventMachine::HttpRequest.new('http://127.0.0.1:8090/deflate').get :head => {"accept-encoding" => "deflate"}
337
-
338
- http.errback { failed(http) }
339
- http.callback {
340
- http.response_header.status.should == 200
341
- http.response_header["CONTENT_ENCODING"].should == "deflate"
342
- http.response.should == "compressed"
343
-
344
- EventMachine.stop
345
- }
346
- }
347
- end
348
-
349
- it "should detect gzip encoding" do
350
- EventMachine.run {
351
-
352
- http = EventMachine::HttpRequest.new('http://127.0.0.1:8090/gzip').get :head => {
353
- "accept-encoding" => "gzip, compressed"
354
- }
355
-
356
- http.errback { failed(http) }
357
- http.callback {
358
- http.response_header.status.should == 200
359
- http.response_header["CONTENT_ENCODING"].should == "gzip"
360
- http.response.should == "compressed"
361
-
362
- EventMachine.stop
363
- }
364
- }
365
- end
366
-
367
- it "should not decode the response when configured so" do
368
- EventMachine.run {
369
-
370
- http = EventMachine::HttpRequest.new('http://127.0.0.1:8090/gzip').get :head => {
371
- "accept-encoding" => "gzip, compressed"
372
- }, :decoding => false
373
-
374
- http.errback { failed(http) }
375
- http.callback {
376
- http.response_header.status.should == 200
377
- http.response_header["CONTENT_ENCODING"].should == "gzip"
378
-
379
- raw = http.response
380
- Zlib::GzipReader.new(StringIO.new(raw)).read.should == "compressed"
381
-
382
- EventMachine.stop
383
- }
384
- }
385
- end
386
-
387
- it "should timeout after 0.1 seconds of inactivity" do
388
- EventMachine.run {
389
- t = Time.now.to_i
390
- EventMachine.heartbeat_interval = 0.1
391
- http = EventMachine::HttpRequest.new('http://127.0.0.1:8090/timeout', :inactivity_timeout => 0.1).get
392
-
393
- http.errback {
394
- (Time.now.to_i - t).should <= 1
395
- EventMachine.stop
396
- }
397
- http.callback { failed(http) }
398
- }
399
- end
400
-
401
- it "should complete a Location: with a relative path" do
402
- EventMachine.run {
403
- http = EventMachine::HttpRequest.new('http://127.0.0.1:8090/relative-location').get
404
-
405
- http.errback { failed(http) }
406
- http.callback {
407
- http.response_header['LOCATION'].should == 'http://127.0.0.1:8090/forwarded'
408
- EventMachine.stop
409
- }
410
- }
411
- end
412
-
413
- context "body content-type encoding" do
414
- it "should not set content type on string in body" do
415
- EventMachine.run {
416
- http = EventMachine::HttpRequest.new('http://127.0.0.1:8090/echo_content_type').post :body => "data"
417
-
418
- http.errback { failed(http) }
419
- http.callback {
420
- http.response_header.status.should == 200
421
- http.response.should be_empty
422
- EventMachine.stop
423
- }
424
- }
425
- end
426
-
427
- it "should set content-type automatically when passed a ruby hash/array for body" do
428
- EventMachine.run {
429
- http = EventMachine::HttpRequest.new('http://127.0.0.1:8090/echo_content_type').post :body => {:a => :b}
430
-
431
- http.errback { failed(http) }
432
- http.callback {
433
- http.response_header.status.should == 200
434
- http.response.should match("application/x-www-form-urlencoded")
435
- EventMachine.stop
436
- }
437
- }
438
- end
439
-
440
- it "should not override content-type when passing in ruby hash/array for body" do
441
- EventMachine.run {
442
- ct = 'text; charset=utf-8'
443
- http = EventMachine::HttpRequest.new('http://127.0.0.1:8090/echo_content_type').post({
444
- :body => {:a => :b}, :head => {'content-type' => ct}})
445
-
446
- http.errback { failed(http) }
447
- http.callback {
448
- http.response_header.status.should == 200
449
- http.content_charset.should == Encoding.find('utf-8') if defined? Encoding
450
- http.response_header["CONTENT_TYPE"].should == ct
451
- EventMachine.stop
452
- }
453
- }
454
- end
455
-
456
- it "should default to external encoding on invalid encoding" do
457
- EventMachine.run {
458
- ct = 'text/html; charset=utf-8lias'
459
- http = EventMachine::HttpRequest.new('http://127.0.0.1:8090/echo_content_type').post({
460
- :body => {:a => :b}, :head => {'content-type' => ct}})
461
-
462
- http.errback { failed(http) }
463
- http.callback {
464
- http.response_header.status.should == 200
465
- http.content_charset.should == Encoding.find('utf-8') if defined? Encoding
466
- http.response_header["CONTENT_TYPE"].should == ct
467
- EventMachine.stop
468
- }
469
- }
470
- end
471
-
472
- it "should processed escaped content-type" do
473
- EventMachine.run {
474
- ct = "text/html; charset=\"ISO-8859-4\""
475
- http = EventMachine::HttpRequest.new('http://127.0.0.1:8090/echo_content_type').post({
476
- :body => {:a => :b}, :head => {'content-type' => ct}})
477
-
478
- http.errback { failed(http) }
479
- http.callback {
480
- http.response_header.status.should == 200
481
- http.content_charset.should == Encoding.find('ISO-8859-4') if defined? Encoding
482
- http.response_header["CONTENT_TYPE"].should == ct
483
- EventMachine.stop
484
- }
485
- }
486
- end
487
- end
488
-
489
- context "optional header callback" do
490
- it "should optionally pass the response headers" do
491
- EventMachine.run {
492
- http = EventMachine::HttpRequest.new('http://127.0.0.1:8090/').get
493
-
494
- http.errback { failed(http) }
495
- http.headers { |hash|
496
- hash.should be_an_kind_of Hash
497
- hash.should include 'CONNECTION'
498
- hash.should include 'CONTENT_LENGTH'
499
- }
500
-
501
- http.callback {
502
- http.response_header.status.should == 200
503
- http.response.should match(/Hello/)
504
- EventMachine.stop
505
- }
506
- }
507
- end
508
-
509
- it "should allow to terminate current connection from header callback" do
510
- EventMachine.run {
511
- http = EventMachine::HttpRequest.new('http://127.0.0.1:8090/').get
512
-
513
- http.callback { failed(http) }
514
- http.headers { |hash|
515
- hash.should be_an_kind_of Hash
516
- hash.should include 'CONNECTION'
517
- hash.should include 'CONTENT_LENGTH'
518
-
519
- http.close('header callback terminated connection')
520
- }
521
-
522
- http.errback { |e|
523
- http.response_header.status.should == 200
524
- http.error.should == 'header callback terminated connection'
525
- http.response.should == ''
526
- EventMachine.stop
527
- }
528
- }
529
- end
530
- end
531
-
532
- it "should optionally pass the response body progressively" do
533
- EventMachine.run {
534
- body = ''
535
- http = EventMachine::HttpRequest.new('http://127.0.0.1:8090/').get
536
-
537
- http.errback { failed(http) }
538
- http.stream { |chunk| body += chunk }
539
-
540
- http.callback {
541
- http.response_header.status.should == 200
542
- http.response.should == ''
543
- body.should match(/Hello/)
544
- EventMachine.stop
545
- }
546
- }
547
- end
548
-
549
- it "should optionally pass the deflate-encoded response body progressively" do
550
- EventMachine.run {
551
- body = ''
552
- http = EventMachine::HttpRequest.new('http://127.0.0.1:8090/deflate').get :head => {
553
- "accept-encoding" => "deflate, compressed"
554
- }
555
-
556
- http.errback { failed(http) }
557
- http.stream { |chunk| body += chunk }
558
-
559
- http.callback {
560
- http.response_header.status.should == 200
561
- http.response_header["CONTENT_ENCODING"].should == "deflate"
562
- http.response.should == ''
563
- body.should == "compressed"
564
- EventMachine.stop
565
- }
566
- }
567
- end
568
-
569
- it "should accept & return cookie header to user" do
570
- EventMachine.run {
571
- http = EventMachine::HttpRequest.new('http://127.0.0.1:8090/set_cookie').get
572
-
573
- http.errback { failed(http) }
574
- http.callback {
575
- http.response_header.status.should == 200
576
- http.response_header.cookie.should == "id=1; expires=Sat, 09 Aug 2031 17:53:39 GMT; path=/;"
577
- EventMachine.stop
578
- }
579
- }
580
- end
581
-
582
- it "should return array of cookies on multiple Set-Cookie headers" do
583
- EventMachine.run {
584
- http = EventMachine::HttpRequest.new('http://127.0.0.1:8090/set_multiple_cookies').get
585
-
586
- http.errback { failed(http) }
587
- http.callback {
588
- http.response_header.status.should == 200
589
- http.response_header.cookie.size.should == 2
590
- http.response_header.cookie.first.should == "id=1; expires=Sat, 09 Aug 2031 17:53:39 GMT; path=/;"
591
- http.response_header.cookie.last.should == "id=2;"
592
-
593
- EventMachine.stop
594
- }
595
- }
596
- end
597
-
598
- it "should pass cookie header to server from string" do
599
- EventMachine.run {
600
- http = EventMachine::HttpRequest.new('http://127.0.0.1:8090/echo_cookie').get :head => {'cookie' => 'id=2;'}
601
-
602
- http.errback { failed(http) }
603
- http.callback {
604
- http.response.should == "id=2;"
605
- EventMachine.stop
606
- }
607
- }
608
- end
609
-
610
- it "should pass cookie header to server from Hash" do
611
- EventMachine.run {
612
- http = EventMachine::HttpRequest.new('http://127.0.0.1:8090/echo_cookie').get :head => {'cookie' => {'id' => 2}}
613
-
614
- http.errback { failed(http) }
615
- http.callback {
616
- http.response.should == "id=2;"
617
- EventMachine.stop
618
- }
619
- }
620
- end
621
-
622
- context "when talking to a stub HTTP/1.0 server" do
623
- it "should get the body without Content-Length" do
624
-
625
- EventMachine.run {
626
- @s = StubServer.new("HTTP/1.0 200 OK\r\nConnection: close\r\n\r\nFoo")
627
-
628
- http = EventMachine::HttpRequest.new('http://127.0.0.1:8081/').get
629
- http.errback { failed(http) }
630
- http.callback {
631
- http.response.should match(/Foo/)
632
- http.response_header['CONTENT_LENGTH'].should_not == 0
633
-
634
- @s.stop
635
- EventMachine.stop
636
- }
637
- }
638
- end
639
-
640
- it "should work with \\n instead of \\r\\n" do
641
- EventMachine.run {
642
- @s = StubServer.new("HTTP/1.0 200 OK\nContent-Type: text/plain\nContent-Length: 3\nConnection: close\n\nFoo")
643
-
644
- http = EventMachine::HttpRequest.new('http://127.0.0.1:8081/').get
645
- http.errback { failed(http) }
646
- http.callback {
647
- http.response_header.status.should == 200
648
- http.response_header['CONTENT_TYPE'].should == 'text/plain'
649
- http.response.should match(/Foo/)
650
-
651
- @s.stop
652
- EventMachine.stop
653
- }
654
- }
655
- end
656
-
657
- it "should handle invalid HTTP response" do
658
- EventMachine.run {
659
- @s = StubServer.new("<html></html>")
660
-
661
- http = EventMachine::HttpRequest.new('http://127.0.0.1:8081/').get
662
- http.callback { failed(http) }
663
- http.errback {
664
- http.error.should_not be_nil
665
- EM.stop
666
- }
667
- }
668
- end
669
- end
670
-
671
- it "should stream a file off disk" do
672
- EventMachine.run {
673
- http = EventMachine::HttpRequest.new('http://127.0.0.1:8090/').post :file => 'spec/fixtures/google.ca'
674
-
675
- http.errback { failed(http) }
676
- http.callback {
677
- http.response.should match('google')
678
- EventMachine.stop
679
- }
680
- }
681
- end
682
-
683
- it 'should handle malformed Content-Type header repetitions' do
684
- EventMachine.run {
685
- response =<<-HTTP.gsub(/^ +/, '').strip
686
- HTTP/1.0 200 OK
687
- Content-Type: text/plain; charset=iso-8859-1
688
- Content-Type: text/plain; charset=utf-8
689
- Content-Length: 5
690
- Connection: close
691
-
692
- Hello
693
- HTTP
694
-
695
- @s = StubServer.new(response)
696
- http = EventMachine::HttpRequest.new('http://127.0.0.1:8081/').get
697
- http.errback { failed(http) }
698
- http.callback {
699
- http.content_charset.should == Encoding::ISO_8859_1 if defined? Encoding
700
- EventMachine.stop
701
- }
702
- }
703
- end
704
-
705
- it "should allow indifferent access to headers" do
706
- EventMachine.run {
707
- response =<<-HTTP.gsub(/^ +/, '').strip
708
- HTTP/1.0 200 OK
709
- Content-Type: text/plain; charset=utf-8
710
- X-Custom-Header: foo
711
- Content-Length: 5
712
- Connection: close
713
-
714
- Hello
715
- HTTP
716
-
717
- @s = StubServer.new(response)
718
- http = EventMachine::HttpRequest.new('http://127.0.0.1:8081/').get
719
- http.errback { failed(http) }
720
- http.callback {
721
- http.response_header["Content-Type"].should == "text/plain; charset=utf-8"
722
- http.response_header["CONTENT_TYPE"].should == "text/plain; charset=utf-8"
723
-
724
- http.response_header["Content-Length"].should == "5"
725
- http.response_header["CONTENT_LENGTH"].should == "5"
726
-
727
- http.response_header["X-Custom-Header"].should == "foo"
728
- http.response_header["X_CUSTOM_HEADER"].should == "foo"
729
-
730
- EventMachine.stop
731
- }
732
- }
733
- end
734
- end
1
+ require 'helper'
2
+
3
+ describe EventMachine::HttpRequest do
4
+
5
+ def failed(http=nil)
6
+ EventMachine.stop
7
+ http ? fail(http.error) : fail
8
+ end
9
+
10
+ it "should perform successful GET" do
11
+ EventMachine.run {
12
+ http = EventMachine::HttpRequest.new('http://127.0.0.1:8090/').get
13
+
14
+ http.errback { failed(http) }
15
+ http.callback {
16
+ http.response_header.status.should == 200
17
+ http.response.should match(/Hello/)
18
+ EventMachine.stop
19
+ }
20
+ }
21
+ end
22
+
23
+ it "should perform successful GET with a URI passed as argument" do
24
+ EventMachine.run {
25
+ uri = URI.parse('http://127.0.0.1:8090/')
26
+ http = EventMachine::HttpRequest.new(uri).get
27
+
28
+ http.errback { failed(http) }
29
+ http.callback {
30
+ http.response_header.status.should == 200
31
+ http.response.should match(/Hello/)
32
+ EventMachine.stop
33
+ }
34
+ }
35
+ end
36
+
37
+ it "should succeed GET on missing path" do
38
+ EventMachine.run {
39
+ lambda {
40
+ http = EventMachine::HttpRequest.new('http://127.0.0.1:8090').get
41
+ http.callback {
42
+ http.response.should match(/Hello/)
43
+ EventMachine.stop
44
+ }
45
+ }.should_not raise_error(ArgumentError)
46
+
47
+ }
48
+ end
49
+
50
+ it "should raise error on invalid URL" do
51
+ EventMachine.run {
52
+ lambda {
53
+ EventMachine::HttpRequest.new('random?text').get
54
+ }.should raise_error
55
+
56
+ EM.stop
57
+ }
58
+ end
59
+
60
+ it "should perform successful HEAD with a URI passed as argument" do
61
+ EventMachine.run {
62
+ uri = URI.parse('http://127.0.0.1:8090/')
63
+ http = EventMachine::HttpRequest.new(uri).head
64
+
65
+ http.errback { failed(http) }
66
+ http.callback {
67
+ http.response_header.status.should == 200
68
+ http.response.should == ""
69
+ EventMachine.stop
70
+ }
71
+ }
72
+ end
73
+
74
+ it "should perform successful DELETE with a URI passed as argument" do
75
+ EventMachine.run {
76
+ uri = URI.parse('http://127.0.0.1:8090/')
77
+ http = EventMachine::HttpRequest.new(uri).delete
78
+
79
+ http.errback { failed(http) }
80
+ http.callback {
81
+ http.response_header.status.should == 200
82
+ http.response.should == ""
83
+ EventMachine.stop
84
+ }
85
+ }
86
+ end
87
+
88
+ it "should return 404 on invalid path" do
89
+ EventMachine.run {
90
+ http = EventMachine::HttpRequest.new('http://127.0.0.1:8090/fail').get
91
+
92
+ http.errback { failed(http) }
93
+ http.callback {
94
+ http.response_header.status.should == 404
95
+ EventMachine.stop
96
+ }
97
+ }
98
+ end
99
+
100
+ it "should return HTTP reason" do
101
+ EventMachine.run {
102
+ http = EventMachine::HttpRequest.new('http://127.0.0.1:8090/fail').get
103
+
104
+ http.errback { failed(http) }
105
+ http.callback {
106
+ http.response_header.status.should == 404
107
+ http.response_header.http_reason.should == 'Not Found'
108
+ EventMachine.stop
109
+ }
110
+ }
111
+ end
112
+
113
+ it "should return HTTP reason 'unknown' on a non-standard status code" do
114
+ EventMachine.run {
115
+ http = EventMachine::HttpRequest.new('http://127.0.0.1:8090/fail_with_nonstandard_response').get
116
+
117
+ http.errback { failed(http) }
118
+ http.callback {
119
+ http.response_header.status.should == 420
120
+ http.response_header.http_reason.should == 'unknown'
121
+ EventMachine.stop
122
+ }
123
+ }
124
+ end
125
+
126
+ it "should build query parameters from Hash" do
127
+ EventMachine.run {
128
+ http = EventMachine::HttpRequest.new('http://127.0.0.1:8090/').get :query => {:q => 'test'}
129
+
130
+ http.errback { failed(http) }
131
+ http.callback {
132
+ http.response_header.status.should == 200
133
+ http.response.should match(/test/)
134
+ EventMachine.stop
135
+ }
136
+ }
137
+ end
138
+
139
+ it "should pass query parameters string" do
140
+ EventMachine.run {
141
+ http = EventMachine::HttpRequest.new('http://127.0.0.1:8090/').get :query => "q=test"
142
+
143
+ http.errback { failed(http) }
144
+ http.callback {
145
+ http.response_header.status.should == 200
146
+ http.response.should match(/test/)
147
+ EventMachine.stop
148
+ }
149
+ }
150
+ end
151
+
152
+ it "should encode an array of query parameters" do
153
+ EventMachine.run {
154
+ http = EventMachine::HttpRequest.new('http://127.0.0.1:8090/echo_query').get :query => {:hash =>['value1','value2']}
155
+
156
+ http.errback { failed(http) }
157
+ http.callback {
158
+ http.response_header.status.should == 200
159
+ http.response.should match(/hash\[\]=value1&hash\[\]=value2/)
160
+ EventMachine.stop
161
+ }
162
+ }
163
+ end
164
+
165
+ it "should perform successful PUT" do
166
+ EventMachine.run {
167
+ http = EventMachine::HttpRequest.new('http://127.0.0.1:8090/').put :body => "data"
168
+
169
+ http.errback { failed(http) }
170
+ http.callback {
171
+ http.response_header.status.should == 200
172
+ http.response.should match(/data/)
173
+ EventMachine.stop
174
+ }
175
+ }
176
+ end
177
+
178
+ it "should perform successful POST" do
179
+ EventMachine.run {
180
+ http = EventMachine::HttpRequest.new('http://127.0.0.1:8090/').post :body => "data"
181
+
182
+ http.errback { failed(http) }
183
+ http.callback {
184
+ http.response_header.status.should == 200
185
+ http.response.should match(/data/)
186
+ EventMachine.stop
187
+ }
188
+ }
189
+ end
190
+
191
+ it "should escape body on POST" do
192
+ EventMachine.run {
193
+ http = EventMachine::HttpRequest.new('http://127.0.0.1:8090/').post :body => {:stuff => 'string&string'}
194
+
195
+ http.errback { failed(http) }
196
+ http.callback {
197
+ http.response_header.status.should == 200
198
+ http.response.should == "stuff=string%26string"
199
+ EventMachine.stop
200
+ }
201
+ }
202
+ end
203
+
204
+ it "should perform successful POST with Ruby Hash/Array as params" do
205
+ EventMachine.run {
206
+ http = EventMachine::HttpRequest.new('http://127.0.0.1:8090/').post :body => {"key1" => 1, "key2" => [2,3]}
207
+
208
+ http.errback { failed(http) }
209
+ http.callback {
210
+ http.response_header.status.should == 200
211
+
212
+ http.response.should match(/key1=1&key2\[0\]=2&key2\[1\]=3/)
213
+ EventMachine.stop
214
+ }
215
+ }
216
+ end
217
+
218
+ it "should set content-length to 0 on posts with empty bodies" do
219
+ EventMachine.run {
220
+ http = EventMachine::HttpRequest.new('http://127.0.0.1:8090/echo_content_length_from_header').post
221
+
222
+ http.errback { failed(http) }
223
+ http.callback {
224
+ http.response_header.status.should == 200
225
+
226
+ http.response.strip.split(':')[1].should == '0'
227
+ EventMachine.stop
228
+ }
229
+ }
230
+ end
231
+
232
+ it "should perform successful POST with Ruby Hash/Array as params and with the correct content length" do
233
+ EventMachine.run {
234
+ http = EventMachine::HttpRequest.new('http://127.0.0.1:8090/echo_content_length').post :body => {"key1" => "data1"}
235
+
236
+ http.errback { failed(http) }
237
+ http.callback {
238
+ http.response_header.status.should == 200
239
+
240
+ http.response.to_i.should == 10
241
+ EventMachine.stop
242
+ }
243
+ }
244
+ end
245
+
246
+ it "should perform successful GET with custom header" do
247
+ EventMachine.run {
248
+ http = EventMachine::HttpRequest.new('http://127.0.0.1:8090/').get :head => {'if-none-match' => 'evar!'}
249
+
250
+ http.errback { p http; failed(http) }
251
+ http.callback {
252
+ http.response_header.status.should == 304
253
+ EventMachine.stop
254
+ }
255
+ }
256
+ end
257
+
258
+ it "should perform basic auth" do
259
+ EventMachine.run {
260
+
261
+ http = EventMachine::HttpRequest.new('http://127.0.0.1:8090/authtest').get :head => {'authorization' => ['user', 'pass']}
262
+
263
+ http.errback { failed(http) }
264
+ http.callback {
265
+ http.response_header.status.should == 200
266
+ EventMachine.stop
267
+ }
268
+ }
269
+ end
270
+
271
+ it "should perform basic auth via the URL" do
272
+ EventMachine.run {
273
+
274
+ http = EventMachine::HttpRequest.new('http://user:pass@127.0.0.1:8090/authtest').get
275
+
276
+ http.errback { failed(http) }
277
+ http.callback {
278
+ http.response_header.status.should == 200
279
+ EventMachine.stop
280
+ }
281
+ }
282
+ end
283
+
284
+ it "should return peer's IP address" do
285
+ EventMachine.run {
286
+
287
+ conn = EventMachine::HttpRequest.new('http://127.0.0.1:8090/')
288
+ conn.peer.should be_nil
289
+
290
+ http = conn.get
291
+ http.peer.should be_nil
292
+
293
+ http.errback { failed(http) }
294
+ http.callback {
295
+ conn.peer.should == '127.0.0.1'
296
+ http.peer.should == '127.0.0.1'
297
+
298
+ EventMachine.stop
299
+ }
300
+ }
301
+ end
302
+
303
+ it "should remove all newlines from long basic auth header" do
304
+ EventMachine.run {
305
+ auth = {'authorization' => ['aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', 'zzzzzzzzzzzzzzzzzzzzzzzzzzzzzz']}
306
+ http = EventMachine::HttpRequest.new('http://127.0.0.1:8090/auth').get :head => auth
307
+ http.errback { failed(http) }
308
+ http.callback {
309
+ http.response_header.status.should == 200
310
+ http.response.should == "Basic YWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhOnp6enp6enp6enp6enp6enp6enp6enp6enp6enp6eg=="
311
+ EventMachine.stop
312
+ }
313
+ }
314
+ end
315
+
316
+ it "should send proper OAuth auth header" do
317
+ EventMachine.run {
318
+ oauth_header = 'OAuth oauth_nonce="oqwgSYFUD87MHmJJDv7bQqOF2EPnVus7Wkqj5duNByU", b=c, d=e'
319
+ http = EventMachine::HttpRequest.new('http://127.0.0.1:8090/auth').get :head => {
320
+ 'authorization' => oauth_header
321
+ }
322
+
323
+ http.errback { failed(http) }
324
+ http.callback {
325
+ http.response_header.status.should == 200
326
+ http.response.should == oauth_header
327
+ EventMachine.stop
328
+ }
329
+ }
330
+ end
331
+
332
+ it "should return ETag and Last-Modified headers" do
333
+ EventMachine.run {
334
+ http = EventMachine::HttpRequest.new('http://127.0.0.1:8090/echo_query').get
335
+
336
+ http.errback { failed(http) }
337
+ http.callback {
338
+ http.response_header.status.should == 200
339
+ http.response_header.etag.should match('abcdefg')
340
+ http.response_header.last_modified.should match('Fri, 13 Aug 2010 17:31:21 GMT')
341
+ EventMachine.stop
342
+ }
343
+ }
344
+ end
345
+
346
+ it "should detect deflate encoding" do
347
+ EventMachine.run {
348
+
349
+ http = EventMachine::HttpRequest.new('http://127.0.0.1:8090/deflate').get :head => {"accept-encoding" => "deflate"}
350
+
351
+ http.errback { failed(http) }
352
+ http.callback {
353
+ http.response_header.status.should == 200
354
+ http.response_header["CONTENT_ENCODING"].should == "deflate"
355
+ http.response.should == "compressed"
356
+
357
+ EventMachine.stop
358
+ }
359
+ }
360
+ end
361
+
362
+ it "should detect gzip encoding" do
363
+ EventMachine.run {
364
+
365
+ http = EventMachine::HttpRequest.new('http://127.0.0.1:8090/gzip').get :head => {
366
+ "accept-encoding" => "gzip, compressed"
367
+ }
368
+
369
+ http.errback { failed(http) }
370
+ http.callback {
371
+ http.response_header.status.should == 200
372
+ http.response_header["CONTENT_ENCODING"].should == "gzip"
373
+ http.response.should == "compressed"
374
+
375
+ EventMachine.stop
376
+ }
377
+ }
378
+ end
379
+
380
+ it "should not decode the response when configured so" do
381
+ EventMachine.run {
382
+
383
+ http = EventMachine::HttpRequest.new('http://127.0.0.1:8090/gzip').get :head => {
384
+ "accept-encoding" => "gzip, compressed"
385
+ }, :decoding => false
386
+
387
+ http.errback { failed(http) }
388
+ http.callback {
389
+ http.response_header.status.should == 200
390
+ http.response_header["CONTENT_ENCODING"].should == "gzip"
391
+
392
+ raw = http.response
393
+ Zlib::GzipReader.new(StringIO.new(raw)).read.should == "compressed"
394
+
395
+ EventMachine.stop
396
+ }
397
+ }
398
+ end
399
+
400
+ it "should timeout after 0.1 seconds of inactivity" do
401
+ EventMachine.run {
402
+ t = Time.now.to_i
403
+ EventMachine.heartbeat_interval = 0.1
404
+ http = EventMachine::HttpRequest.new('http://127.0.0.1:8090/timeout', :inactivity_timeout => 0.1).get
405
+
406
+ http.errback {
407
+ (Time.now.to_i - t).should <= 1
408
+ EventMachine.stop
409
+ }
410
+ http.callback { failed(http) }
411
+ }
412
+ end
413
+
414
+ it "should complete a Location: with a relative path" do
415
+ EventMachine.run {
416
+ http = EventMachine::HttpRequest.new('http://127.0.0.1:8090/relative-location').get
417
+
418
+ http.errback { failed(http) }
419
+ http.callback {
420
+ http.response_header['LOCATION'].should == 'http://127.0.0.1:8090/forwarded'
421
+ EventMachine.stop
422
+ }
423
+ }
424
+ end
425
+
426
+ context "body content-type encoding" do
427
+ it "should not set content type on string in body" do
428
+ EventMachine.run {
429
+ http = EventMachine::HttpRequest.new('http://127.0.0.1:8090/echo_content_type').post :body => "data"
430
+
431
+ http.errback { failed(http) }
432
+ http.callback {
433
+ http.response_header.status.should == 200
434
+ http.response.should be_empty
435
+ EventMachine.stop
436
+ }
437
+ }
438
+ end
439
+
440
+ it "should set content-type automatically when passed a ruby hash/array for body" do
441
+ EventMachine.run {
442
+ http = EventMachine::HttpRequest.new('http://127.0.0.1:8090/echo_content_type').post :body => {:a => :b}
443
+
444
+ http.errback { failed(http) }
445
+ http.callback {
446
+ http.response_header.status.should == 200
447
+ http.response.should match("application/x-www-form-urlencoded")
448
+ EventMachine.stop
449
+ }
450
+ }
451
+ end
452
+
453
+ it "should not override content-type when passing in ruby hash/array for body" do
454
+ EventMachine.run {
455
+ ct = 'text; charset=utf-8'
456
+ http = EventMachine::HttpRequest.new('http://127.0.0.1:8090/echo_content_type').post({
457
+ :body => {:a => :b}, :head => {'content-type' => ct}})
458
+
459
+ http.errback { failed(http) }
460
+ http.callback {
461
+ http.response_header.status.should == 200
462
+ http.content_charset.should == Encoding.find('utf-8') if defined? Encoding
463
+ http.response_header["CONTENT_TYPE"].should == ct
464
+ EventMachine.stop
465
+ }
466
+ }
467
+ end
468
+
469
+ it "should default to external encoding on invalid encoding" do
470
+ EventMachine.run {
471
+ ct = 'text/html; charset=utf-8lias'
472
+ http = EventMachine::HttpRequest.new('http://127.0.0.1:8090/echo_content_type').post({
473
+ :body => {:a => :b}, :head => {'content-type' => ct}})
474
+
475
+ http.errback { failed(http) }
476
+ http.callback {
477
+ http.response_header.status.should == 200
478
+ http.content_charset.should == Encoding.find('utf-8') if defined? Encoding
479
+ http.response_header["CONTENT_TYPE"].should == ct
480
+ EventMachine.stop
481
+ }
482
+ }
483
+ end
484
+
485
+ it "should processed escaped content-type" do
486
+ EventMachine.run {
487
+ ct = "text/html; charset=\"ISO-8859-4\""
488
+ http = EventMachine::HttpRequest.new('http://127.0.0.1:8090/echo_content_type').post({
489
+ :body => {:a => :b}, :head => {'content-type' => ct}})
490
+
491
+ http.errback { failed(http) }
492
+ http.callback {
493
+ http.response_header.status.should == 200
494
+ http.content_charset.should == Encoding.find('ISO-8859-4') if defined? Encoding
495
+ http.response_header["CONTENT_TYPE"].should == ct
496
+ EventMachine.stop
497
+ }
498
+ }
499
+ end
500
+ end
501
+
502
+ context "optional header callback" do
503
+ it "should optionally pass the response headers" do
504
+ EventMachine.run {
505
+ http = EventMachine::HttpRequest.new('http://127.0.0.1:8090/').get
506
+
507
+ http.errback { failed(http) }
508
+ http.headers { |hash|
509
+ hash.should be_an_kind_of Hash
510
+ hash.should include 'CONNECTION'
511
+ hash.should include 'CONTENT_LENGTH'
512
+ }
513
+
514
+ http.callback {
515
+ http.response_header.status.should == 200
516
+ http.response.should match(/Hello/)
517
+ EventMachine.stop
518
+ }
519
+ }
520
+ end
521
+
522
+ it "should allow to terminate current connection from header callback" do
523
+ EventMachine.run {
524
+ http = EventMachine::HttpRequest.new('http://127.0.0.1:8090/').get
525
+
526
+ http.callback { failed(http) }
527
+ http.headers { |hash|
528
+ hash.should be_an_kind_of Hash
529
+ hash.should include 'CONNECTION'
530
+ hash.should include 'CONTENT_LENGTH'
531
+
532
+ http.close('header callback terminated connection')
533
+ }
534
+
535
+ http.errback { |e|
536
+ http.response_header.status.should == 200
537
+ http.error.should == 'header callback terminated connection'
538
+ http.response.should == ''
539
+ EventMachine.stop
540
+ }
541
+ }
542
+ end
543
+ end
544
+
545
+ it "should optionally pass the response body progressively" do
546
+ EventMachine.run {
547
+ body = ''
548
+ http = EventMachine::HttpRequest.new('http://127.0.0.1:8090/').get
549
+
550
+ http.errback { failed(http) }
551
+ http.stream { |chunk| body += chunk }
552
+
553
+ http.callback {
554
+ http.response_header.status.should == 200
555
+ http.response.should == ''
556
+ body.should match(/Hello/)
557
+ EventMachine.stop
558
+ }
559
+ }
560
+ end
561
+
562
+ it "should optionally pass the deflate-encoded response body progressively" do
563
+ EventMachine.run {
564
+ body = ''
565
+ http = EventMachine::HttpRequest.new('http://127.0.0.1:8090/deflate').get :head => {
566
+ "accept-encoding" => "deflate, compressed"
567
+ }
568
+
569
+ http.errback { failed(http) }
570
+ http.stream { |chunk| body += chunk }
571
+
572
+ http.callback {
573
+ http.response_header.status.should == 200
574
+ http.response_header["CONTENT_ENCODING"].should == "deflate"
575
+ http.response.should == ''
576
+ body.should == "compressed"
577
+ EventMachine.stop
578
+ }
579
+ }
580
+ end
581
+
582
+ it "should accept & return cookie header to user" do
583
+ EventMachine.run {
584
+ http = EventMachine::HttpRequest.new('http://127.0.0.1:8090/set_cookie').get
585
+
586
+ http.errback { failed(http) }
587
+ http.callback {
588
+ http.response_header.status.should == 200
589
+ http.response_header.cookie.should == "id=1; expires=Sat, 09 Aug 2031 17:53:39 GMT; path=/;"
590
+ EventMachine.stop
591
+ }
592
+ }
593
+ end
594
+
595
+ it "should return array of cookies on multiple Set-Cookie headers" do
596
+ EventMachine.run {
597
+ http = EventMachine::HttpRequest.new('http://127.0.0.1:8090/set_multiple_cookies').get
598
+
599
+ http.errback { failed(http) }
600
+ http.callback {
601
+ http.response_header.status.should == 200
602
+ http.response_header.cookie.size.should == 2
603
+ http.response_header.cookie.first.should == "id=1; expires=Sat, 09 Aug 2031 17:53:39 GMT; path=/;"
604
+ http.response_header.cookie.last.should == "id=2;"
605
+
606
+ EventMachine.stop
607
+ }
608
+ }
609
+ end
610
+
611
+ it "should pass cookie header to server from string" do
612
+ EventMachine.run {
613
+ http = EventMachine::HttpRequest.new('http://127.0.0.1:8090/echo_cookie').get :head => {'cookie' => 'id=2;'}
614
+
615
+ http.errback { failed(http) }
616
+ http.callback {
617
+ http.response.should == "id=2;"
618
+ EventMachine.stop
619
+ }
620
+ }
621
+ end
622
+
623
+ it "should pass cookie header to server from Hash" do
624
+ EventMachine.run {
625
+ http = EventMachine::HttpRequest.new('http://127.0.0.1:8090/echo_cookie').get :head => {'cookie' => {'id' => 2}}
626
+
627
+ http.errback { failed(http) }
628
+ http.callback {
629
+ http.response.should == "id=2;"
630
+ EventMachine.stop
631
+ }
632
+ }
633
+ end
634
+
635
+ it "should get the body without Content-Length" do
636
+ EventMachine.run {
637
+ @s = StubServer.new("HTTP/1.1 200 OK\r\n\r\nFoo")
638
+
639
+ http = EventMachine::HttpRequest.new('http://127.0.0.1:8081/').get
640
+ http.errback { failed(http) }
641
+ http.callback {
642
+ http.response.should match(/Foo/)
643
+ http.response_header['CONTENT_LENGTH'].should be_nil
644
+
645
+ @s.stop
646
+ EventMachine.stop
647
+ }
648
+ }
649
+ end
650
+
651
+ context "when talking to a stub HTTP/1.0 server" do
652
+ it "should get the body without Content-Length" do
653
+
654
+ EventMachine.run {
655
+ @s = StubServer.new("HTTP/1.0 200 OK\r\nConnection: close\r\n\r\nFoo")
656
+
657
+ http = EventMachine::HttpRequest.new('http://127.0.0.1:8081/').get
658
+ http.errback { failed(http) }
659
+ http.callback {
660
+ http.response.should match(/Foo/)
661
+ http.response_header['CONTENT_LENGTH'].should be_nil
662
+
663
+ @s.stop
664
+ EventMachine.stop
665
+ }
666
+ }
667
+ end
668
+
669
+ it "should work with \\n instead of \\r\\n" do
670
+ EventMachine.run {
671
+ @s = StubServer.new("HTTP/1.0 200 OK\nContent-Type: text/plain\nContent-Length: 3\nConnection: close\n\nFoo")
672
+
673
+ http = EventMachine::HttpRequest.new('http://127.0.0.1:8081/').get
674
+ http.errback { failed(http) }
675
+ http.callback {
676
+ http.response_header.status.should == 200
677
+ http.response_header['CONTENT_TYPE'].should == 'text/plain'
678
+ http.response.should match(/Foo/)
679
+
680
+ @s.stop
681
+ EventMachine.stop
682
+ }
683
+ }
684
+ end
685
+
686
+ it "should handle invalid HTTP response" do
687
+ EventMachine.run {
688
+ @s = StubServer.new("<html></html>")
689
+
690
+ http = EventMachine::HttpRequest.new('http://127.0.0.1:8081/').get
691
+ http.callback { failed(http) }
692
+ http.errback {
693
+ http.error.should_not be_nil
694
+ EM.stop
695
+ }
696
+ }
697
+ end
698
+ end
699
+
700
+ it "should stream a file off disk" do
701
+ EventMachine.run {
702
+ http = EventMachine::HttpRequest.new('http://127.0.0.1:8090/').post :file => 'spec/fixtures/google.ca'
703
+
704
+ http.errback { failed(http) }
705
+ http.callback {
706
+ http.response.should match('google')
707
+ EventMachine.stop
708
+ }
709
+ }
710
+ end
711
+
712
+ it 'should handle malformed Content-Type header repetitions' do
713
+ EventMachine.run {
714
+ response =<<-HTTP.gsub(/^ +/, '').strip
715
+ HTTP/1.0 200 OK
716
+ Content-Type: text/plain; charset=iso-8859-1
717
+ Content-Type: text/plain; charset=utf-8
718
+ Content-Length: 5
719
+ Connection: close
720
+
721
+ Hello
722
+ HTTP
723
+
724
+ @s = StubServer.new(response)
725
+ http = EventMachine::HttpRequest.new('http://127.0.0.1:8081/').get
726
+ http.errback { failed(http) }
727
+ http.callback {
728
+ http.content_charset.should == Encoding::ISO_8859_1 if defined? Encoding
729
+ EventMachine.stop
730
+ }
731
+ }
732
+ end
733
+
734
+ it "should allow indifferent access to headers" do
735
+ EventMachine.run {
736
+ response =<<-HTTP.gsub(/^ +/, '').strip
737
+ HTTP/1.0 200 OK
738
+ Content-Type: text/plain; charset=utf-8
739
+ X-Custom-Header: foo
740
+ Content-Length: 5
741
+ Connection: close
742
+
743
+ Hello
744
+ HTTP
745
+
746
+ @s = StubServer.new(response)
747
+ http = EventMachine::HttpRequest.new('http://127.0.0.1:8081/').get
748
+ http.errback { failed(http) }
749
+ http.callback {
750
+ http.response_header["Content-Type"].should == "text/plain; charset=utf-8"
751
+ http.response_header["CONTENT_TYPE"].should == "text/plain; charset=utf-8"
752
+
753
+ http.response_header["Content-Length"].should == "5"
754
+ http.response_header["CONTENT_LENGTH"].should == "5"
755
+
756
+ http.response_header["X-Custom-Header"].should == "foo"
757
+ http.response_header["X_CUSTOM_HEADER"].should == "foo"
758
+
759
+ EventMachine.stop
760
+ }
761
+ }
762
+ end
763
+ end