h1p 0.2 → 0.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -5,13 +5,13 @@ require 'h1p'
5
5
  require 'socket'
6
6
  require_relative '../ext/h1p/limits'
7
7
 
8
- class H1PTest < MiniTest::Test
8
+ class H1PRequestTest < MiniTest::Test
9
9
  Error = H1P::Error
10
10
 
11
11
  def setup
12
12
  super
13
13
  @i, @o = IO.pipe
14
- @parser = H1P::Parser.new(@i)
14
+ @parser = H1P::Parser.new(@i, :server)
15
15
  end
16
16
  alias_method :reset_parser, :setup
17
17
 
@@ -75,7 +75,7 @@ class H1PTest < MiniTest::Test
75
75
  @o.close
76
76
 
77
77
  assert_raises(Error) { @parser.parse_headers }
78
-
78
+
79
79
  max_length = H1P_LIMITS[:max_method_length]
80
80
 
81
81
  reset_parser
@@ -96,7 +96,7 @@ class H1PTest < MiniTest::Test
96
96
  def test_bad_path
97
97
  @o << "GET HTTP/1.1\r\n\r\n"
98
98
  assert_raises(Error) { @parser.parse_headers }
99
-
99
+
100
100
  max_length = H1P_LIMITS[:max_path_length]
101
101
 
102
102
  reset_parser
@@ -149,26 +149,26 @@ class H1PTest < MiniTest::Test
149
149
  assert_raises(Error) { @parser.parse_headers }
150
150
 
151
151
  reset_parser
152
- @o << "GET / http/1.1.1\r\n\r\n"
152
+ @o << "GET / HTTP/1.1.1\r\n\r\n"
153
153
  assert_raises(Error) { @parser.parse_headers }
154
154
  end
155
155
 
156
156
  def test_headers_eof
157
157
  @o << "GET / HTTP/1.1\r\na"
158
158
  @o.close
159
-
159
+
160
160
  assert_nil @parser.parse_headers
161
161
 
162
162
  reset_parser
163
163
  @o << "GET / HTTP/1.1\r\na:"
164
164
  @o.close
165
-
165
+
166
166
  assert_nil @parser.parse_headers
167
167
 
168
168
  reset_parser
169
169
  @o << "GET / HTTP/1.1\r\na: "
170
170
  @o.close
171
-
171
+
172
172
  assert_nil @parser.parse_headers
173
173
  end
174
174
 
@@ -197,46 +197,46 @@ class H1PTest < MiniTest::Test
197
197
  end
198
198
 
199
199
  def test_bad_headers
200
- @o << "GET / http/1.1\r\n a: b\r\n\r\n"
200
+ @o << "GET / HTTP/1.1\r\n a: b\r\n\r\n"
201
201
  assert_raises(Error) { @parser.parse_headers }
202
202
 
203
203
  reset_parser
204
- @o << "GET / http/1.1\r\na b\r\n\r\n"
204
+ @o << "GET / HTTP/1.1\r\na b\r\n\r\n"
205
205
  assert_raises(Error) { @parser.parse_headers }
206
206
 
207
207
  max_key_length = H1P_LIMITS[:max_header_key_length]
208
208
 
209
209
  reset_parser
210
- @o << "GET / http/1.1\r\n#{'a' * max_key_length}: b\r\n\r\n"
210
+ @o << "GET / HTTP/1.1\r\n#{'a' * max_key_length}: b\r\n\r\n"
211
211
  headers = @parser.parse_headers
212
212
  assert_equal 'b', headers['a' * max_key_length]
213
213
 
214
214
  reset_parser
215
- @o << "GET / http/1.1\r\n#{'a' * (max_key_length + 1)}: b\r\n\r\n"
215
+ @o << "GET / HTTP/1.1\r\n#{'a' * (max_key_length + 1)}: b\r\n\r\n"
216
216
  assert_raises(Error) { @parser.parse_headers }
217
217
 
218
218
  max_value_length = H1P_LIMITS[:max_header_value_length]
219
219
 
220
220
  reset_parser
221
- @o << "GET / http/1.1\r\nfoo: #{'a' * max_value_length}\r\n\r\n"
221
+ @o << "GET / HTTP/1.1\r\nfoo: #{'a' * max_value_length}\r\n\r\n"
222
222
  headers = @parser.parse_headers
223
223
  assert_equal 'a' * max_value_length, headers['foo']
224
224
 
225
225
  reset_parser
226
- @o << "GET / http/1.1\r\nfoo: #{'a' * (max_value_length + 1)}\r\n\r\n"
226
+ @o << "GET / HTTP/1.1\r\nfoo: #{'a' * (max_value_length + 1)}\r\n\r\n"
227
227
  assert_raises(Error) { @parser.parse_headers }
228
228
 
229
229
  max_header_count = H1P_LIMITS[:max_header_count]
230
230
 
231
231
  reset_parser
232
232
  hdrs = (1..max_header_count).map { |i| "foo#{i}: bar\r\n" }.join
233
- @o << "GET / http/1.1\r\n#{hdrs}\r\n"
233
+ @o << "GET / HTTP/1.1\r\n#{hdrs}\r\n"
234
234
  headers = @parser.parse_headers
235
235
  assert_equal (max_header_count + 4), headers.size
236
236
 
237
237
  reset_parser
238
238
  hdrs = (1..(max_header_count + 1)).map { |i| "foo#{i}: bar\r\n" }.join
239
- @o << "GET / http/1.1\r\n#{hdrs}\r\n"
239
+ @o << "GET / HTTP/1.1\r\n#{hdrs}\r\n"
240
240
  assert_raises(Error) { @parser.parse_headers }
241
241
  end
242
242
 
@@ -256,7 +256,7 @@ class H1PTest < MiniTest::Test
256
256
  def test_read_body_with_content_length
257
257
  10.times do
258
258
  data = ' ' * rand(20..60000)
259
- msg = "POST /foo HTTP/1.1\r\nContent-Length: #{data.bytesize}\r\n\r\n#{data}"
259
+ msg = "GET / HTTP/1.1\r\nContent-Length: #{data.bytesize}\r\n\r\n#{data}"
260
260
  Thread.new { @o << msg }
261
261
 
262
262
  headers = @parser.parse_headers
@@ -270,7 +270,7 @@ class H1PTest < MiniTest::Test
270
270
 
271
271
  def test_read_body_chunk_with_content_length
272
272
  data = 'abc' * 20000
273
- msg = "POST /foo HTTP/1.1\r\nContent-Length: #{data.bytesize}\r\n\r\n#{data}"
273
+ msg = "GET / HTTP/1.1\r\nContent-Length: #{data.bytesize}\r\n\r\n#{data}"
274
274
  Thread.new { @o << msg }
275
275
  headers = @parser.parse_headers
276
276
  assert_equal data.bytesize.to_s, headers['content-length']
@@ -290,7 +290,7 @@ class H1PTest < MiniTest::Test
290
290
  def test_read_body_with_content_length_incomplete
291
291
  data = ' ' * rand(20..60000)
292
292
  Thread.new do
293
- @o << "POST /foo HTTP/1.1\r\nContent-Length: #{data.bytesize + 1}\r\n\r\n#{data}"
293
+ @o << "GET / HTTP/1.1\r\nContent-Length: #{data.bytesize + 1}\r\n\r\n#{data}"
294
294
  @o.close # !!! otherwise the parser will keep waiting
295
295
  end
296
296
  headers = @parser.parse_headers
@@ -300,7 +300,7 @@ class H1PTest < MiniTest::Test
300
300
 
301
301
  def test_read_body_chunk_with_content_length_incomplete
302
302
  data = 'abc' * 50
303
- @o << "POST /foo HTTP/1.1\r\nContent-Length: #{data.bytesize + 1}\r\n\r\n#{data}"
303
+ @o << "GET / HTTP/1.1\r\nContent-Length: #{data.bytesize + 1}\r\n\r\n#{data}"
304
304
  @o.close
305
305
  headers = @parser.parse_headers
306
306
 
@@ -311,7 +311,7 @@ class H1PTest < MiniTest::Test
311
311
  chunks = []
312
312
  total_sent = 0
313
313
  Thread.new do
314
- msg = "POST /foo HTTP/1.1\r\nTransfer-Encoding: chunked\r\n\r\n"
314
+ msg = "GET / HTTP/1.1\r\nTransfer-Encoding: chunked\r\n\r\n"
315
315
  @o << msg
316
316
  total_sent += msg.bytesize
317
317
  rand(8..16).times do |i|
@@ -324,7 +324,7 @@ class H1PTest < MiniTest::Test
324
324
  msg = "0\r\n\r\n"
325
325
  @o << msg
326
326
  total_sent += msg.bytesize
327
- end
327
+ end
328
328
  headers = @parser.parse_headers
329
329
  assert_equal 'chunked', headers['transfer-encoding']
330
330
 
@@ -337,7 +337,7 @@ class H1PTest < MiniTest::Test
337
337
  chunks = []
338
338
  total_sent = 0
339
339
  Thread.new do
340
- msg = "POST /foo HTTP/1.1\r\nTransfer-Encoding: chunked\r\n\r\n"
340
+ msg = "GET / HTTP/1.1\r\nTransfer-Encoding: chunked\r\n\r\n"
341
341
  @o << msg
342
342
  total_sent += msg.bytesize
343
343
  rand(8..16).times do |i|
@@ -350,7 +350,7 @@ class H1PTest < MiniTest::Test
350
350
  msg = "0\r\n\r\n"
351
351
  @o << msg
352
352
  total_sent += msg.bytesize
353
- end
353
+ end
354
354
  headers = @parser.parse_headers
355
355
  assert_equal 'chunked', headers['transfer-encoding']
356
356
 
@@ -364,7 +364,7 @@ class H1PTest < MiniTest::Test
364
364
 
365
365
  def test_read_body_with_chunked_encoding_malformed
366
366
  Thread.new do
367
- @o << "POST /foo HTTP/1.1\r\nTransfer-Encoding: chunked\r\n\r\n"
367
+ @o << "GET / HTTP/1.1\r\nTransfer-Encoding: chunked\r\n\r\n"
368
368
  chunk = ' '.to_s * rand(40000..360000)
369
369
  @o << "#{chunk.bytesize.to_s(16)}\r\n#{chunk}\r\n3"
370
370
  @o << "0\r\n\r\n"
@@ -376,22 +376,22 @@ class H1PTest < MiniTest::Test
376
376
  reset_parser
377
377
  # missing last empty chunk
378
378
  Thread.new do
379
- @o << "POST /foo HTTP/1.1\r\nTransfer-Encoding: chunked\r\n\r\n"
379
+ @o << "GET / HTTP/1.1\r\nTransfer-Encoding: chunked\r\n\r\n"
380
380
  chunk = ' '.to_s * rand(40000..360000)
381
381
  @o << "#{chunk.bytesize.to_s(16)}\r\n#{chunk}\r\n"
382
382
  @o.close
383
- end
383
+ end
384
384
  headers = @parser.parse_headers
385
385
  assert_raises(H1P::Error) { @parser.read_body }
386
386
 
387
387
  reset_parser
388
388
  # bad chunk size
389
389
  Thread.new do
390
- @o << "POST /foo HTTP/1.1\r\nTransfer-Encoding: chunked\r\n\r\n"
390
+ @o << "GET / HTTP/1.1\r\nTransfer-Encoding: chunked\r\n\r\n"
391
391
  chunk = ' '.to_s * rand(40000..360000)
392
392
  @o << "-#{chunk.bytesize.to_s(16)}\r\n#{chunk}\r\n"
393
393
  @o.close
394
- end
394
+ end
395
395
  headers = @parser.parse_headers
396
396
  assert_raises(H1P::Error) { @parser.read_body }
397
397
  end
@@ -399,7 +399,7 @@ class H1PTest < MiniTest::Test
399
399
  def test_read_body_chunk_with_chunked_encoding_malformed
400
400
  chunk = nil
401
401
  Thread.new do
402
- @o << "POST /foo HTTP/1.1\r\nTransfer-Encoding: chunked\r\n\r\n"
402
+ @o << "GET / HTTP/1.1\r\nTransfer-Encoding: chunked\r\n\r\n"
403
403
  chunk = ' ' * rand(40000..360000)
404
404
  @o << "#{chunk.bytesize.to_s(16)}\r\n#{chunk}\r\n3"
405
405
  @o << "0\r\n\r\n"
@@ -415,7 +415,7 @@ class H1PTest < MiniTest::Test
415
415
  # missing last empty chunk
416
416
  chunk = nil
417
417
  Thread.new do
418
- @o << "POST /foo HTTP/1.1\r\nTransfer-Encoding: chunked\r\n\r\n"
418
+ @o << "GET / HTTP/1.1\r\nTransfer-Encoding: chunked\r\n\r\n"
419
419
  chunk = ' '.to_s * rand(20..1600)
420
420
  @o << "#{chunk.bytesize.to_s(16)}\r\n#{chunk}\r\n"
421
421
  @o.close
@@ -429,18 +429,18 @@ class H1PTest < MiniTest::Test
429
429
 
430
430
  # bad chunk size
431
431
  Thread.new do
432
- @o << "POST /foo HTTP/1.1\r\nTransfer-Encoding: chunked\r\n\r\n"
432
+ @o << "GET / HTTP/1.1\r\nTransfer-Encoding: chunked\r\n\r\n"
433
433
  chunk = ' '.to_s * rand(20..1600)
434
434
  @o << "-#{chunk.bytesize.to_s(16)}\r\n#{chunk}\r\n"
435
435
  @o.close
436
- end
436
+ end
437
437
  headers = @parser.parse_headers
438
438
  assert_raises(H1P::Error) { @parser.read_body_chunk(false) }
439
439
 
440
440
  reset_parser
441
441
 
442
442
  # missing body
443
- @o << "POST /foo HTTP/1.1\r\nTransfer-Encoding: chunked\r\n\r\n"
443
+ @o << "GET / HTTP/1.1\r\nTransfer-Encoding: chunked\r\n\r\n"
444
444
  @o.close
445
445
  headers = @parser.parse_headers
446
446
  assert_raises(H1P::Error) { @parser.read_body_chunk(false) }
@@ -519,7 +519,7 @@ class H1PTest < MiniTest::Test
519
519
  server_thread = Thread.new do
520
520
  while (socket = server.accept)
521
521
  Thread.new do
522
- parser = H1P::Parser.new(socket)
522
+ parser = H1P::Parser.new(socket, :server)
523
523
  headers = parser.parse_headers
524
524
  socket << headers.inspect
525
525
  socket.shutdown
@@ -556,7 +556,7 @@ class H1PTest < MiniTest::Test
556
556
  request
557
557
  end
558
558
 
559
- parser = H1P::Parser.new(callable)
559
+ parser = H1P::Parser.new(callable, :server)
560
560
 
561
561
  headers = parser.parse_headers
562
562
  assert_equal({
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: h1p
3
3
  version: !ruby/object:Gem::Version
4
- version: '0.2'
4
+ version: '0.3'
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sharon Rosner
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-08-20 00:00:00.000000000 Z
11
+ date: 2022-02-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake-compiler
@@ -52,7 +52,7 @@ dependencies:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
54
  version: 5.14.4
55
- description:
55
+ description:
56
56
  email: sharon@noteflakes.com
57
57
  executables: []
58
58
  extensions:
@@ -70,6 +70,7 @@ files:
70
70
  - Rakefile
71
71
  - TODO.md
72
72
  - benchmarks/bm_http1_parser.rb
73
+ - benchmarks/pipelined.rb
73
74
  - examples/callable.rb
74
75
  - examples/http_server.rb
75
76
  - ext/h1p/extconf.rb
@@ -80,13 +81,15 @@ files:
80
81
  - lib/h1p.rb
81
82
  - lib/h1p/version.rb
82
83
  - test/helper.rb
83
- - test/test_h1p.rb
84
+ - test/run.rb
85
+ - test/test_h1p_client.rb
86
+ - test/test_h1p_server.rb
84
87
  homepage: http://github.com/digital-fabric/h1p
85
88
  licenses:
86
89
  - MIT
87
90
  metadata:
88
91
  source_code_uri: https://github.com/digital-fabric/h1p
89
- post_install_message:
92
+ post_install_message:
90
93
  rdoc_options:
91
94
  - "--title"
92
95
  - h1p
@@ -105,8 +108,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
105
108
  - !ruby/object:Gem::Version
106
109
  version: '0'
107
110
  requirements: []
108
- rubygems_version: 3.1.4
109
- signing_key:
111
+ rubygems_version: 3.3.3
112
+ signing_key:
110
113
  specification_version: 4
111
114
  summary: H1P is a blocking HTTP/1 parser for Ruby
112
115
  test_files: []