http_tools 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -8,18 +8,31 @@ class ResponseTest < Test::Unit::TestCase
8
8
  parser = HTTPTools::Parser.new
9
9
  version = nil
10
10
 
11
- parser.add_listener(:version) {|v| version = v}
11
+ parser.add_listener(:header) {version = parser.version}
12
12
 
13
- parser << "HTTP/1.1 "
13
+ parser << "HTTP/1.1 200 OK\r\n\r\n"
14
14
 
15
15
  assert_equal("1.1", version)
16
16
  end
17
17
 
18
+ def test_one_dot_x_version
19
+ parser = HTTPTools::Parser.new
20
+ version = nil
21
+
22
+ parser.add_listener(:header) {version = parser.version}
23
+
24
+ parser << "HTTP/1.x 200 OK\r\n\r\n"
25
+
26
+ assert_equal("1.x", version)
27
+ end
28
+
18
29
  def test_ok
19
30
  parser = HTTPTools::Parser.new
20
31
  code, message = nil
21
32
 
22
- parser.add_listener(:status) {|c, m| code, message = c, m}
33
+ parser.add_listener(:header) do
34
+ code, message = parser.status_code, parser.message
35
+ end
23
36
 
24
37
  parser << "HTTP/1.1 200 OK\r\n\r\n"
25
38
 
@@ -32,7 +45,9 @@ class ResponseTest < Test::Unit::TestCase
32
45
  parser = HTTPTools::Parser.new
33
46
  code, message = nil
34
47
 
35
- parser.add_listener(:status) {|c, m| code, message = c, m}
48
+ parser.add_listener(:header) do
49
+ code, message = parser.status_code, parser.message
50
+ end
36
51
 
37
52
  parser << "HTTP/1.1 404 Not Found\r\n\r\n"
38
53
 
@@ -41,11 +56,61 @@ class ResponseTest < Test::Unit::TestCase
41
56
  assert(!parser.finished?, "parser should not be finished")
42
57
  end
43
58
 
59
+ def test_missing_message
60
+ parser = HTTPTools::Parser.new
61
+ code, message = nil
62
+
63
+ parser.add_listener(:header) do
64
+ code, message = parser.status_code, parser.message
65
+ end
66
+
67
+ parser << "HTTP/1.1 302\r\n\r\n"
68
+
69
+ assert_equal(302, code)
70
+ assert_equal("", message)
71
+ assert(!parser.finished?, "parser should not be finished")
72
+ end
73
+
74
+ def test_non_standard_message
75
+ parser = HTTPTools::Parser.new
76
+ version, code, message = nil
77
+
78
+ parser.add_listener(:header) do
79
+ version = parser.version
80
+ code = parser.status_code
81
+ message = parser.message
82
+ end
83
+
84
+ parser << "HTTP/1.0 200 (OK)\r\n\r\n"
85
+
86
+ assert_equal("1.0", version)
87
+ assert_equal(200, code)
88
+ assert_equal("(OK)", message)
89
+ assert(!parser.finished?, "parser should not be finished")
90
+ end
91
+
92
+ def test_status_message_with_accent
93
+ parser = HTTPTools::Parser.new
94
+ code, message = nil
95
+
96
+ parser.add_listener(:header) do
97
+ code, message = parser.status_code, parser.message
98
+ end
99
+
100
+ parser << "HTTP/1.1 403 Accès interdit\r\n\r\n"
101
+
102
+ assert_equal(403, code)
103
+ assert_equal("Accès interdit", message)
104
+ assert(!parser.finished?, "parser should not be finished")
105
+ end
106
+
44
107
  def test_no_content
45
108
  parser = HTTPTools::Parser.new
46
109
  code, message = nil
47
110
 
48
- parser.add_listener(:status) {|c, m| code, message = c, m}
111
+ parser.add_listener(:header) do
112
+ code, message = parser.status_code, parser.message
113
+ end
49
114
 
50
115
  parser << "HTTP/1.1 204 No Content\r\n\r\n"
51
116
 
@@ -58,7 +123,9 @@ class ResponseTest < Test::Unit::TestCase
58
123
  parser = HTTPTools::Parser.new
59
124
  code, message = nil
60
125
 
61
- parser.add_listener(:status) {|c, m| code, message = c, m}
126
+ parser.add_listener(:header) do
127
+ code, message = parser.status_code, parser.message
128
+ end
62
129
 
63
130
  parser << "HTTP/1.1 304 Not Modified\r\n\r\n"
64
131
 
@@ -72,7 +139,7 @@ class ResponseTest < Test::Unit::TestCase
72
139
  parser.force_no_body = true
73
140
  headers = nil
74
141
 
75
- parser.add_listener(:headers) {|h| headers = h}
142
+ parser.add_listener(:header) {headers = parser.header}
76
143
 
77
144
  parser << "HTTP/1.1 200 OK\r\n"
78
145
  parser << "Content-Length: 20\r\n"
@@ -82,12 +149,178 @@ class ResponseTest < Test::Unit::TestCase
82
149
  assert(parser.finished?, "parser should be finished")
83
150
  end
84
151
 
152
+ def test_messed_up_iis_headers
153
+ parser = HTTPTools::Parser.new
154
+ headers = nil
155
+
156
+ parser.add_listener(:header) {headers = parser.header}
157
+
158
+ parser << "HTTP/1.1 200 OK\r\n"
159
+ parser << "Server:: Harris Associates L.P.\r\n"
160
+ parser << "X-DIP:202\r\n"
161
+ parser << "\r\n"
162
+
163
+ assert_equal({
164
+ "Server" => ": Harris Associates L.P.",
165
+ "X-DIP" => "202"}, headers)
166
+ end
167
+
168
+ def test_space_in_header_key
169
+ parser = HTTPTools::Parser.new
170
+ headers = nil
171
+
172
+ parser.add_listener(:header) {headers = parser.header}
173
+
174
+ parser << "HTTP/1.1 200 OK\r\n"
175
+ parser << "X-Powered-By: PHP/5.3.5\r\n"
176
+ parser << "HTTP Status Code: HTTP/1.1 404 Not Found\r\n"
177
+ parser << "\r\n"
178
+
179
+ assert_equal({
180
+ "X-Powered-By" => "PHP/5.3.5",
181
+ "HTTP Status Code" => "HTTP/1.1 404 Not Found"}, headers)
182
+ end
183
+
184
+ def test_header_empty_value
185
+ parser = HTTPTools::Parser.new
186
+ headers = nil
187
+
188
+ parser.add_listener(:header) {headers = parser.header}
189
+
190
+ parser << "HTTP/1.1 200 OK\r\n"
191
+ parser << "X-Empty: \r\n"
192
+ parser << "Content-Type: text/html\r\n\r\n"
193
+
194
+ assert_equal({
195
+ "X-Empty" => "",
196
+ "Content-Type" => "text/html"}, headers)
197
+ end
198
+
199
+ def test_weird_iis_content_header
200
+ parser = HTTPTools::Parser.new
201
+ code, message, headers = nil
202
+ body = ""
203
+
204
+ parser.add_listener(:header) do
205
+ code = parser.status_code
206
+ message = parser.message
207
+ headers = parser.header
208
+ end
209
+ parser.add_listener(:stream) {|chunk| body << chunk}
210
+
211
+ parser << "HTTP/1.1 200 OK\r\n"
212
+ parser << "Content-Length: 20\r\n"
213
+ parser << "Content:\r\n"
214
+ parser << "\r\n"
215
+ parser << "<h1>Hello world</h1>"
216
+
217
+ assert_equal(200, code)
218
+ assert_equal("OK", message)
219
+ assert_equal({"Content-Length" => "20", "Content" => ""}, headers)
220
+ assert_equal("<h1>Hello world</h1>", body)
221
+ assert(parser.finished?, "parser should be finished")
222
+ end
223
+
224
+ def test_multiple_set_cookie_headers
225
+ parser = HTTPTools::Parser.new
226
+ headers = nil
227
+
228
+ parser.add_listener(:header) {headers = parser.header}
229
+
230
+ parser << "HTTP/1.1 200 OK\r\n"
231
+ parser << "Set-Cookie: foo=bar\r\n"
232
+ parser << "Set-Cookie: baz=qux\r\n\r\n"
233
+
234
+ assert_equal({"Set-Cookie" => ["foo=bar", "baz=qux"]}, headers)
235
+ end
236
+
237
+ def test_skip_junk_headers_at_end
238
+ parser = HTTPTools::Parser.new
239
+ code, message, headers = nil
240
+ body = ""
241
+
242
+ parser.add_listener(:header) do
243
+ code = parser.status_code
244
+ message = parser.message
245
+ headers = parser.header
246
+ end
247
+ parser.add_listener(:stream) {|chunk| body << chunk}
248
+
249
+ parser << "HTTP/1.1 301 Redirect\r\n"
250
+ parser << "Location: /index.html\r\n"
251
+ parser << "Content-Length: 74\r\n"
252
+ parser << "301 Moved Permanently\r\n\r\n"
253
+ parser << "You should have been redirected to\n"
254
+ parser << "<a href=\"/index.html\">/index.html</a>.\n"
255
+
256
+ assert_equal(301, code)
257
+ assert_equal("Redirect", message)
258
+ assert_equal({"Location" => "/index.html", "Content-Length" => "74"}, headers)
259
+ assert_equal("You should have been redirected to\n<a href=\"/index.html\">/index.html</a>.\n", body)
260
+ assert(parser.finished?, "parser should be finished")
261
+ end
262
+
263
+ def test_skip_junk_headers_at_start
264
+ parser = HTTPTools::Parser.new
265
+ code, message, headers = nil
266
+ body = ""
267
+
268
+ parser.add_listener(:header) do
269
+ code = parser.status_code
270
+ message = parser.message
271
+ headers = parser.header
272
+ end
273
+ parser.add_listener(:stream) {|chunk| body << chunk}
274
+
275
+ parser << "HTTP/1.0 200 OK\r\n"
276
+ parser << "QWEBS/1.0 (HP 3000)\r\n"
277
+ parser << "Content-Type: text/html\r\n\r\n"
278
+ parser << "<h1>Hello world</h1>"
279
+ parser.finish
280
+
281
+ assert_equal(200, code)
282
+ assert_equal("OK", message)
283
+ assert_equal({"Content-Type" => "text/html"}, headers)
284
+ assert_equal("<h1>Hello world</h1>", body)
285
+ assert(parser.finished?, "parser should be finished")
286
+ end
287
+
288
+ def test_skip_junk_headers_in_the_middle
289
+ parser = HTTPTools::Parser.new
290
+ code, message, headers = nil
291
+ body = ""
292
+
293
+ parser.add_listener(:header) do
294
+ code = parser.status_code
295
+ message = parser.message
296
+ headers = parser.header
297
+ end
298
+ parser.add_listener(:stream) {|chunk| body << chunk}
299
+
300
+ parser << "HTTP/1.1 200 OK\r\n"
301
+ parser << "Content-Length: 20\r\n"
302
+ parser << "random\t"
303
+ parser << "garbage\n"
304
+ parser << "Content-Type: text/html\r\n"
305
+ parser << "\r\n"
306
+ parser << "<h1>Hello world</h1>"
307
+
308
+ assert_equal(200, code)
309
+ assert_equal("OK", message)
310
+ assert_equal({"Content-Length" => "20", "Content-Type" => "text/html"}, headers)
311
+ assert_equal("<h1>Hello world</h1>", body)
312
+ assert(parser.finished?, "parser should be finished")
313
+ end
314
+
85
315
  def test_apple_dot_com
86
316
  parser = HTTPTools::Parser.new
87
317
  code, message, headers = nil
88
318
 
89
- parser.add_listener(:status) {|c, m| code, message = c, m}
90
- parser.add_listener(:headers) {|h| headers = h}
319
+ parser.add_listener(:header) do
320
+ code = parser.status_code
321
+ message = parser.message
322
+ headers = parser.header
323
+ end
91
324
 
92
325
  parser << "HTTP/1.1 200 OK\r\n"
93
326
  parser << "Server: Apache/2.2.11 (Unix)\r\n"
@@ -114,9 +347,12 @@ class ResponseTest < Test::Unit::TestCase
114
347
  code, message, headers = nil
115
348
  body = []
116
349
 
117
- parser.add_listener(:status) {|c, m| code, message = c, m}
118
- parser.add_listener(:headers) {|h| headers = h}
119
- parser.add_listener(:stream) {|b| body << b}
350
+ parser.add_listener(:header) do
351
+ code = parser.status_code
352
+ message = parser.message
353
+ headers = parser.header
354
+ end
355
+ parser.add_listener(:stream) {|chunk| body << chunk}
120
356
 
121
357
  parser << "HTTP/1.1 200 OK\r\n"
122
358
  parser << "Content-Length: 20\r\n"
@@ -133,11 +369,15 @@ class ResponseTest < Test::Unit::TestCase
133
369
 
134
370
  def test_body
135
371
  parser = HTTPTools::Parser.new
136
- code, message, headers, body = nil
372
+ code, message, headers = nil
373
+ body = ""
137
374
 
138
- parser.add_listener(:status) {|c, m| code, message = c, m}
139
- parser.add_listener(:headers) {|h| headers = h}
140
- parser.add_listener(:body) {|b| body = b}
375
+ parser.add_listener(:header) do
376
+ code = parser.status_code
377
+ message = parser.message
378
+ headers = parser.header
379
+ end
380
+ parser.add_listener(:stream) {|chunk| body << chunk}
141
381
 
142
382
  parser << "HTTP/1.1 200 OK\r\n"
143
383
  parser << "Content-Length: 20\r\n"
@@ -152,13 +392,67 @@ class ResponseTest < Test::Unit::TestCase
152
392
  assert(parser.finished?, "parser should be finished")
153
393
  end
154
394
 
155
- def test_sub_line_chunks
395
+ def test_zero_length_body
396
+ parser = HTTPTools::Parser.new
397
+ code, message, headers, body = nil
398
+ stream = []
399
+ body = ""
400
+
401
+ parser.add_listener(:header) do
402
+ code = parser.status_code
403
+ message = parser.message
404
+ headers = parser.header
405
+ end
406
+ parser.add_listener(:stream) {|chunk| body << chunk; stream.push(chunk)}
407
+
408
+ parser << "HTTP/1.1 302 Moved Temporarily\r\n"
409
+ parser << "Location: http://www.example.com/\r\n"
410
+ parser << "Content-Length: 0\r\n\r\n"
411
+
412
+ assert_equal(302, code)
413
+ assert_equal("Moved Temporarily", message)
414
+ assert_equal({"Location" => "http://www.example.com/", "Content-Length" => "0"}, headers)
415
+ assert_equal([""], stream)
416
+ assert_equal("", body)
417
+ assert(parser.finished?, "parser should be finished")
418
+ end
419
+
420
+ def test_zero_length_body_terminated_by_close
156
421
  parser = HTTPTools::Parser.new
157
422
  code, message, headers, body = nil
423
+ stream = []
424
+ body = ""
425
+
426
+ parser.add_listener(:header) do
427
+ code = parser.status_code
428
+ message = parser.message
429
+ headers = parser.header
430
+ end
431
+ parser.add_listener(:stream) {|chunk| body << chunk; stream.push(chunk)}
432
+
433
+ parser << "HTTP/1.1 302 Moved Temporarily\r\n"
434
+ parser << "Location: http://www.example.com/\r\n\r\n"
435
+ parser.finish # notify parser the connection has closed
436
+
437
+ assert_equal(302, code)
438
+ assert_equal("Moved Temporarily", message)
439
+ assert_equal({"Location" => "http://www.example.com/"}, headers)
440
+ assert_equal([""], stream)
441
+ assert_equal("", body)
442
+ assert(parser.finished?, "parser should be finished")
443
+ end
444
+
445
+ def test_sub_line_chunks
446
+ parser = HTTPTools::Parser.new
447
+ code, message, headers = nil
448
+ body = ""
158
449
 
159
- parser.add_listener(:status) {|c, m| code, message = c, m}
160
- parser.add_listener(:headers) {|h| headers = h}
161
- parser.add_listener(:body) {|b| body = b}
450
+ parser.add_listener(:header) do
451
+ code = parser.status_code
452
+ message = parser.message
453
+ headers = parser.header
454
+ end
455
+ parser.add_listener(:stream) {|chunk| body << chunk}
162
456
 
163
457
  parser << "HTTP/"
164
458
  parser << "1."
@@ -177,13 +471,60 @@ class ResponseTest < Test::Unit::TestCase
177
471
  assert(parser.finished?, "parser should be finished")
178
472
  end
179
473
 
474
+ def test_break_between_crlf
475
+ parser = HTTPTools::Parser.new
476
+ code, message, headers = nil
477
+ body = ""
478
+
479
+ parser.add_listener(:header) do
480
+ code = parser.status_code
481
+ message = parser.message
482
+ headers = parser.header
483
+ end
484
+ parser.add_listener(:stream) {|chunk| body << chunk}
485
+
486
+ parser << "HTTP/1.1 200 OK\r"
487
+ parser << "\nContent-Length: 20\r"
488
+ parser << "\n\r"
489
+ parser << "\n<h1>Hello world</h1>"
490
+
491
+ assert_equal(200, code)
492
+ assert_equal("OK", message)
493
+ assert_equal({"Content-Length" => "20"}, headers)
494
+ assert_equal("<h1>Hello world</h1>", body)
495
+ assert(parser.finished?, "parser should be finished")
496
+ end
497
+
498
+ def test_double_cr
499
+ parser = HTTPTools::Parser.new
500
+ headers = nil
501
+ body = ""
502
+
503
+ parser.add_listener(:header) {headers = parser.header}
504
+ parser.add_listener(:stream) {|chunk| body << chunk}
505
+
506
+ parser << "HTTP/1.1 200 OK\r\n"
507
+ parser << "Page-Completion-Status: Normal\r\r\n"
508
+ parser << "Content-Length: 20\r\n"
509
+ parser << "\r\n"
510
+ parser << "<h1>Hello world</h1>"
511
+
512
+ assert_equal({"Page-Completion-Status" => "Normal\r", "Content-Length" => "20"}, headers)
513
+ assert_equal("<h1>Hello world</h1>", body)
514
+ assert(parser.finished?, "parser should be finished")
515
+ end
516
+
180
517
  def test_body_with_key_terminator_like_value
181
518
  parser = HTTPTools::Parser.new
182
- code, message, headers, body = nil
519
+ code, message, headers = nil
520
+ body = ""
183
521
 
184
- parser.add_listener(:status) {|c, m| code, message = c, m}
185
- parser.add_listener(:headers) {|h| headers = h}
186
- parser.add_listener(:body) {|b| body = b}
522
+ parser.add_listener(:header) do
523
+ code = parser.status_code
524
+ message = parser.message
525
+ headers = parser.header
526
+ end
527
+ parser.add_listener(:stream) {|chunk| body << chunk}
187
528
 
188
529
  parser << "HTTP/1.1 200 OK\r\n"
189
530
  parser << "Content-Length: 21\r\n"
@@ -198,11 +539,15 @@ class ResponseTest < Test::Unit::TestCase
198
539
 
199
540
  def test_lazy_server
200
541
  parser = HTTPTools::Parser.new
201
- code, message, headers, body = nil
542
+ code, message, headers = nil
543
+ body = ""
202
544
 
203
- parser.add_listener(:status) {|c, m| code, message = c, m}
204
- parser.add_listener(:headers) {|h| headers = h}
205
- parser.add_listener(:body) {|b| body = b}
545
+ parser.add_listener(:header) do
546
+ code = parser.status_code
547
+ message = parser.message
548
+ headers = parser.header
549
+ end
550
+ parser.add_listener(:stream) {|chunk| body << chunk}
206
551
 
207
552
  parser << "HTTP/1.1 200 OK\n"
208
553
  parser << "Content-Type: text/html; charset=utf-8\n"
@@ -219,11 +564,15 @@ class ResponseTest < Test::Unit::TestCase
219
564
 
220
565
  def test_chunked
221
566
  parser = HTTPTools::Parser.new
222
- code, message, headers, body = nil
567
+ code, message, headers = nil
568
+ body = ""
223
569
 
224
- parser.add_listener(:status) {|c, m| code, message = c, m}
225
- parser.add_listener(:headers) {|h| headers = h}
226
- parser.add_listener(:body) {|b| body = b}
570
+ parser.add_listener(:header) do
571
+ code = parser.status_code
572
+ message = parser.message
573
+ headers = parser.header
574
+ end
575
+ parser.add_listener(:stream) {|chunk| body << chunk}
227
576
 
228
577
  parser << "HTTP/1.1 200 OK\r\n"
229
578
  parser << "Transfer-Encoding: chunked\r\n"
@@ -244,9 +593,12 @@ class ResponseTest < Test::Unit::TestCase
244
593
  code, message, headers = nil
245
594
  body = []
246
595
 
247
- parser.add_listener(:status) {|c, m| code, message = c, m}
248
- parser.add_listener(:headers) {|h| headers = h}
249
- parser.add_listener(:stream) {|b| body << b}
596
+ parser.add_listener(:header) do
597
+ code = parser.status_code
598
+ message = parser.message
599
+ headers = parser.header
600
+ end
601
+ parser.add_listener(:stream) {|chunk| body << chunk}
250
602
 
251
603
  parser << "HTTP/1.1 200 OK\r\n"
252
604
  parser << "Transfer-Encoding: chunked\r\n"
@@ -267,9 +619,12 @@ class ResponseTest < Test::Unit::TestCase
267
619
  code, message, headers = nil
268
620
  body = []
269
621
 
270
- parser.add_listener(:status) {|c, m| code, message = c, m}
271
- parser.add_listener(:headers) {|h| headers = h}
272
- parser.add_listener(:stream) {|b| body << b}
622
+ parser.add_listener(:header) do
623
+ code = parser.status_code
624
+ message = parser.message
625
+ headers = parser.header
626
+ end
627
+ parser.add_listener(:stream) {|chunk| body << chunk}
273
628
 
274
629
  parser << "HTTP/1.1 200 OK\r\n"
275
630
  parser << "Transfer-Encoding: chunked\r\n"
@@ -285,13 +640,82 @@ class ResponseTest < Test::Unit::TestCase
285
640
  assert(parser.finished?, "parser should be finished")
286
641
  end
287
642
 
643
+ # shouldn't really be allowed, but IIS can't do chunked encoding properly
644
+ def test_chunked_terminated_by_close
645
+ parser = HTTPTools::Parser.new
646
+ code, message, headers = nil
647
+ body = []
648
+
649
+ parser.add_listener(:header) do
650
+ code = parser.status_code
651
+ message = parser.message
652
+ headers = parser.header
653
+ end
654
+ parser.add_listener(:stream) {|chunk| body << chunk}
655
+
656
+ parser << "HTTP/1.1 200 OK\r\n"
657
+ parser << "Connection: close\r\n"
658
+ parser << "Transfer-Encoding: chunked\r\n"
659
+ parser << "\r\n"
660
+ parser << "9\r\n<h1>Hello\r\n"
661
+ parser << "b\r\n world</h1>\r\n"
662
+ parser.finish # notify parser the connection has closed
663
+
664
+ assert_equal(200, code)
665
+ assert_equal("OK", message)
666
+ assert_equal({
667
+ "Transfer-Encoding" => "chunked",
668
+ "Connection" => "close"}, headers)
669
+ assert_equal(["<h1>Hello", " world</h1>"], body)
670
+ assert(parser.finished?, "parser should be finished")
671
+ end
672
+
673
+ def test_html_body_only_not_allowed
674
+ parser = HTTPTools::Parser.new
675
+
676
+ assert_raise(HTTPTools::ParseError) do
677
+ parser << "<html><p>HTTP is hard</p></html>"
678
+ end
679
+ end
680
+
681
+ def test_html_body_only_allowed
682
+ parser = HTTPTools::Parser.new
683
+ version, code, message, headers = nil
684
+ body = ""
685
+
686
+ parser.allow_html_without_header = true
687
+
688
+ parser.add_listener(:header) do
689
+ version = parser.version
690
+ code = parser.status_code
691
+ message = parser.message
692
+ headers = parser.header
693
+ end
694
+ parser.add_listener(:stream) {|chunk| body << chunk}
695
+
696
+ parser << "<html><p>HTTP is hard</p></html>"
697
+ parser.finish
698
+
699
+ assert_equal("0.0", version)
700
+ assert_equal(200, code)
701
+ assert_equal("", message)
702
+ assert_equal({}, headers)
703
+ assert_equal("<html><p>HTTP is hard</p></html>", body)
704
+ assert(parser.finished?, "parser should be finished")
705
+ end
706
+
288
707
  def test_finished
289
708
  parser = HTTPTools::Parser.new
290
- code, message, body, remainder = nil
709
+ code, message, remainder = nil
710
+ body = ""
291
711
 
292
- parser.add_listener(:status) {|c, m| code, message = c, m}
293
- parser.add_listener(:body) {|b| body = b}
294
- parser.add_listener(:finished) {|r| remainder = r}
712
+ parser.add_listener(:header) do
713
+ code = parser.status_code
714
+ message = parser.message
715
+ headers = parser.header
716
+ end
717
+ parser.add_listener(:stream) {|chunk| body << chunk}
718
+ parser.add_listener(:finish) {|r| remainder = r}
295
719
 
296
720
  parser << "HTTP/1.1 200 OK\r\nContent-Length: 20\r\n\r\n"
297
721
  parser << "<h1>Hello world</h1>HTTP/1.1 404 Not Found\r\n"
@@ -305,11 +729,16 @@ class ResponseTest < Test::Unit::TestCase
305
729
 
306
730
  def test_finished_chunked
307
731
  parser = HTTPTools::Parser.new
308
- code, message, body, remainder = nil
732
+ code, message, remainder = nil
733
+ body = ""
309
734
 
310
- parser.add_listener(:status) {|c, m| code, message = c, m}
311
- parser.add_listener(:body) {|b| body = b}
312
- parser.add_listener(:finished) {|r| remainder = r}
735
+ parser.add_listener(:header) do
736
+ code = parser.status_code
737
+ message = parser.message
738
+ headers = parser.header
739
+ end
740
+ parser.add_listener(:stream) {|chunk| body << chunk}
741
+ parser.add_listener(:finish) {|r| remainder = r}
313
742
 
314
743
  parser << "HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n"
315
744
  parser << "14\r\n<h1>Hello world</h1>\r\n0\r\nHTTP/1.1 404 Not Found\r\n"
@@ -325,7 +754,7 @@ class ResponseTest < Test::Unit::TestCase
325
754
  parser = HTTPTools::Parser.new
326
755
  trailer = nil
327
756
 
328
- parser.add_listener(:trailer) {|t| trailer = t}
757
+ parser.add_listener(:trailer) {trailer = parser.trailer}
329
758
 
330
759
  parser << "HTTP/1.1 200 OK\r\n"
331
760
  parser << "Transfer-Encoding: chunked\r\nTrailer: X-Checksum\r\n\r\n"
@@ -340,7 +769,7 @@ class ResponseTest < Test::Unit::TestCase
340
769
  parser = HTTPTools::Parser.new
341
770
  trailer = nil
342
771
 
343
- parser.add_listener(:trailer) {|t| trailer = t}
772
+ parser.add_listener(:trailer) {trailer = parser.trailer}
344
773
 
345
774
  parser << "HTTP/1.1 200 OK\r\n"
346
775
  parser << "Transfer-Encoding: chunked\r\nTrailer: X-Checksum\r\n\r\n"
@@ -356,7 +785,7 @@ class ResponseTest < Test::Unit::TestCase
356
785
  parser = HTTPTools::Parser.new
357
786
  trailer = nil
358
787
 
359
- parser.add_listener(:trailer) {|t| trailer = t}
788
+ parser.add_listener(:trailer) {trailer = parser.trailer}
360
789
 
361
790
  parser.force_trailer = true
362
791
 
@@ -369,6 +798,39 @@ class ResponseTest < Test::Unit::TestCase
369
798
  assert(parser.finished?, "parser should be finished")
370
799
  end
371
800
 
801
+ def test_messed_up_iis_header_style_trailer_1
802
+ parser = HTTPTools::Parser.new
803
+ trailer = nil
804
+
805
+ parser.add_listener(:trailer) {trailer = parser.trailer}
806
+
807
+ parser << "HTTP/1.1 200 OK\r\n"
808
+ parser << "Server: Microsoft-IIS/6.0\r\n"
809
+ parser << "Transfer-Encoding: chunked\r\nTrailer: Server::\r\n\r\n"
810
+ parser << "14\r\n<h1>Hello world</h1>\r\n0\r\n"
811
+ parser << "Server:: Harris Associates L.P.\r\n"
812
+ parser << "\r\n"
813
+
814
+ assert_equal({"Server" => ": Harris Associates L.P."}, trailer)
815
+ assert(parser.finished?, "parser should be finished")
816
+ end
817
+
818
+ def test_messed_up_iis_header_style_trailer_2
819
+ parser = HTTPTools::Parser.new
820
+ trailer = nil
821
+
822
+ parser.add_listener(:trailer) {trailer = parser.trailer}
823
+
824
+ parser << "HTTP/1.1 200 OK\r\n"
825
+ parser << "Transfer-Encoding: chunked\r\nTrailer: Server::\r\n\r\n"
826
+ parser << "14\r\n<h1>Hello world</h1>\r\n0\r\n"
827
+ parser << "X-DIP:202\r\n"
828
+ parser << "\r\n"
829
+
830
+ assert_equal({"X-DIP" => "202"}, trailer)
831
+ assert(parser.finished?, "parser should be finished")
832
+ end
833
+
372
834
  def test_error_on_unallowed_trailer
373
835
  parser = HTTPTools::Parser.new
374
836
 
@@ -397,14 +859,14 @@ class ResponseTest < Test::Unit::TestCase
397
859
  parser = HTTPTools::Parser.new
398
860
  trailer = nil
399
861
 
400
- parser.add_listener(:trailer) {|t| trailer = t}
862
+ parser.add_listener(:trailer) {trailer = parser.trailer}
401
863
 
402
864
  parser << "HTTP/1.1 200 OK\r\n"
403
865
  parser << "Transfer-Encoding: chunked\r\nTrailer: X-Checksum\r\n\r\n"
404
866
  parser << "14\r\n<h1>Hello world</h1>\r\n0\r\n"
405
867
 
406
868
  assert_raise(HTTPTools::ParseError) do
407
- parser << "x-invalid key: value\r\n\r\n"
869
+ parser << "x-invalid\0key: value\r\n\r\n"
408
870
  end
409
871
  end
410
872
 
@@ -412,7 +874,7 @@ class ResponseTest < Test::Unit::TestCase
412
874
  parser = HTTPTools::Parser.new
413
875
  trailer = nil
414
876
 
415
- parser.add_listener(:trailer) {|t| trailer = t}
877
+ parser.add_listener(:trailer) {trailer = parser.trailer}
416
878
 
417
879
  parser << "HTTP/1.1 200 OK\r\n"
418
880
  parser << "Transfer-Encoding: chunked\r\nTrailer: X-Checksum\r\n\r\n"
@@ -443,4 +905,10 @@ class ResponseTest < Test::Unit::TestCase
443
905
  assert_raise(HTTPTools::MessageIncompleteError) {parser.finish}
444
906
  end
445
907
 
908
+ def test_empty
909
+ parser = HTTPTools::Parser.new
910
+
911
+ assert_raise(HTTPTools::EmptyMessageError) {parser.finish}
912
+ end
913
+
446
914
  end