tipi 0.42 → 0.43

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 82155f4b86223d3fb32dc8c314abfeb75fda951747e63832ed5c15bc3b1f43cc
4
- data.tar.gz: 721b98fb8d330d1bc38f8f236f82ddd909235d31f5875c1b4f89895e4e3926da
3
+ metadata.gz: c7a42c93f436a24b74aef2fc9de54d7f01b587ec42b2897d0b0c24a9090776d8
4
+ data.tar.gz: 1fa532504e9c79d620306b4ddfbd01bf1d1dc39b563ec2a2c3cfec9cb00a1b64
5
5
  SHA512:
6
- metadata.gz: 10389779975234d90c968626b4f9d6b168491f9a32ecf1be71683c37cf11f58f1bac52a36478691e72328236a16d309a8462104bda556772e25cebe52b2b0d53
7
- data.tar.gz: 99db2c15278cdfc286ffad05f266f5d62eec6a3bb1363f8dfa4c302549a308a691496ee60ec085ede59e3b594533e8e196bbca144878e5a6dccf2ecfc962151c
6
+ metadata.gz: 93282cde73eca46289cf212e76c90e7390dcd9e48e8594bd756d5f59ae3bc5fed41e61d216c85cca9c9d2c8fca1061ee0159f8cc0ca575fe0b7149a21b1edc24
7
+ data.tar.gz: 6fd1dc4de05351d0b7da91a7344798145f31659f4663f451355222ce63bb8504fb123c562199820b4f217bc14d064bb529fcc0c9ea495863856bd79f073a491b
data/CHANGELOG.md CHANGED
@@ -1,3 +1,8 @@
1
+ ## 0.43 2021-08-20
2
+
3
+ - Extract HTTP/1 parser into a separate gem:
4
+ [H1P](https://github.com/digital-fabric/h1p)
5
+
1
6
  ## 0.42 2021-08-16
2
7
 
3
8
  - HTTP/1 parser: disable UTF-8 parsing for all but header values
data/Gemfile CHANGED
@@ -1,7 +1,7 @@
1
1
  source 'https://rubygems.org'
2
2
 
3
3
  gemspec
4
- %w{polyphony qeweney}.each do |dep|
4
+ %w{polyphony qeweney h1p}.each do |dep|
5
5
  dir = "../#{dep}"
6
6
  gem(dep, path: dir) if File.directory?(dir)
7
7
  end
data/Gemfile.lock CHANGED
@@ -1,7 +1,12 @@
1
+ PATH
2
+ remote: ../h1p
3
+ specs:
4
+ h1p (0.2)
5
+
1
6
  PATH
2
7
  remote: ../polyphony
3
8
  specs:
4
- polyphony (0.69)
9
+ polyphony (0.70)
5
10
 
6
11
  PATH
7
12
  remote: ../qeweney
@@ -12,9 +17,10 @@ PATH
12
17
  PATH
13
18
  remote: .
14
19
  specs:
15
- tipi (0.42)
20
+ tipi (0.43)
16
21
  acme-client (~> 2.0.8)
17
22
  extralite (~> 1.2)
23
+ h1p (~> 0.2)
18
24
  http-2 (~> 0.11)
19
25
  localhost (~> 1.1.4)
20
26
  msgpack (~> 1.4.2)
@@ -28,13 +34,11 @@ GEM
28
34
  specs:
29
35
  acme-client (2.0.8)
30
36
  faraday (>= 0.17, < 2.0.0)
31
- ansi (1.5.0)
32
- builder (3.2.4)
33
37
  cuba (3.9.3)
34
38
  rack (>= 1.6.0)
35
39
  docile (1.4.0)
36
40
  escape_utils (1.2.1)
37
- extralite (1.2)
41
+ extralite (1.3)
38
42
  faraday (1.7.0)
39
43
  faraday-em_http (~> 1.0)
40
44
  faraday-em_synchrony (~> 1.0)
@@ -55,22 +59,14 @@ GEM
55
59
  faraday-patron (1.0.0)
56
60
  faraday-rack (1.0.0)
57
61
  http-2 (0.11.0)
58
- http_parser.rb (0.7.0)
59
62
  json (2.5.1)
60
63
  localhost (1.1.8)
64
+ memory_profiler (1.0.0)
61
65
  minitest (5.11.3)
62
- minitest-reporters (1.4.3)
63
- ansi
64
- builder
65
- minitest (>= 5.0)
66
- ruby-progressbar
67
66
  msgpack (1.4.2)
68
67
  multipart-post (2.1.1)
69
68
  rack (2.2.3)
70
- rake (12.3.3)
71
- rake-compiler (1.1.1)
72
- rake
73
- ruby-progressbar (1.11.0)
69
+ rake (13.0.6)
74
70
  ruby2_keywords (0.0.5)
75
71
  simplecov (0.17.1)
76
72
  docile (~> 1.1)
@@ -84,13 +80,12 @@ PLATFORMS
84
80
 
85
81
  DEPENDENCIES
86
82
  cuba (~> 3.9.3)
87
- http_parser.rb (= 0.7.0)
83
+ h1p!
84
+ memory_profiler (~> 1.0.0)
88
85
  minitest (~> 5.11.3)
89
- minitest-reporters (~> 1.4.2)
90
86
  polyphony!
91
87
  qeweney!
92
- rake (~> 12.3.3)
93
- rake-compiler (= 1.1.1)
88
+ rake (~> 13.0.6)
94
89
  simplecov (~> 0.17.1)
95
90
  tipi!
96
91
 
@@ -4,6 +4,25 @@ require 'bundler/setup'
4
4
 
5
5
  HTTP_REQUEST = "GET /foo HTTP/1.1\r\nHost: example.com\r\nAccept: */*\r\n\r\n"
6
6
 
7
+ def measure_time_and_allocs
8
+ 4.times { GC.start }
9
+ GC.disable
10
+
11
+ t0 = Time.now
12
+ a0 = object_count
13
+ yield
14
+ t1 = Time.now
15
+ a1 = object_count
16
+ [t1 - t0, a1 - a0]
17
+ ensure
18
+ GC.enable
19
+ end
20
+
21
+ def object_count
22
+ count = ObjectSpace.count_objects
23
+ count[:TOTAL] - count[:FREE]
24
+ end
25
+
7
26
  def benchmark_other_http1_parser(iterations)
8
27
  STDOUT << "http_parser.rb: "
9
28
  require 'http_parser.rb'
@@ -16,21 +35,20 @@ def benchmark_other_http1_parser(iterations)
16
35
  headers = h
17
36
  headers[':method'] = parser.http_method
18
37
  headers[':path'] = parser.request_url
19
- headers[':protocol'] = parser.http_version
20
38
  end
21
39
  parser.on_message_complete = proc { done = true }
22
40
 
23
- t0 = Time.now
24
- iterations.times do
25
- o << HTTP_REQUEST
26
- done = false
27
- while !done
28
- msg = i.readpartial(4096)
29
- parser << msg
41
+ elapsed, allocated = measure_time_and_allocs do
42
+ iterations.times do
43
+ o << HTTP_REQUEST
44
+ done = false
45
+ while !done
46
+ msg = i.readpartial(4096)
47
+ parser << msg
48
+ end
30
49
  end
31
50
  end
32
- t1 = Time.now
33
- puts "#{iterations / (t1 - t0)} ips"
51
+ puts(format('elapsed: %f, allocated: %d (%f/req), rate: %f ips', elapsed, allocated, allocated.to_f / iterations, iterations / elapsed))
34
52
  end
35
53
 
36
54
  def benchmark_tipi_http1_parser(iterations)
@@ -40,22 +58,28 @@ def benchmark_tipi_http1_parser(iterations)
40
58
  reader = proc { |len| i.readpartial(len) }
41
59
  parser = Tipi::HTTP1Parser.new(reader)
42
60
 
43
- t0 = Time.now
44
- iterations.times do
45
- o << HTTP_REQUEST
46
- headers = parser.parse_headers
61
+ elapsed, allocated = measure_time_and_allocs do
62
+ iterations.times do
63
+ o << HTTP_REQUEST
64
+ headers = parser.parse_headers
65
+ end
47
66
  end
48
- t1 = Time.now
49
- puts "#{iterations / (t1 - t0)} ips"
67
+ puts(format('elapsed: %f, allocated: %d (%f/req), rate: %f ips', elapsed, allocated, allocated.to_f / iterations, iterations / elapsed))
50
68
  end
51
69
 
52
70
  def fork_benchmark(method, iterations)
53
- pid = fork { send(method, iterations) }
71
+ pid = fork do
72
+ send(method, iterations)
73
+ rescue Exception => e
74
+ p e
75
+ p e.backtrace
76
+ exit!
77
+ end
54
78
  Process.wait(pid)
55
79
  end
56
80
 
57
81
  x = 500000
58
- fork_benchmark(:benchmark_other_http1_parser, x)
59
- fork_benchmark(:benchmark_tipi_http1_parser, x)
82
+ # fork_benchmark(:benchmark_other_http1_parser, x)
83
+ # fork_benchmark(:benchmark_tipi_http1_parser, x)
60
84
 
61
- # benchmark_tipi_http1_parser(x)
85
+ benchmark_tipi_http1_parser(x)
data/df/server.rb CHANGED
@@ -8,6 +8,8 @@ listeners = [
8
8
  listen_unix
9
9
  ]
10
10
 
11
+ spin_loop(interval: 60) { GC.compact } if GC.respond_to?(:compact)
12
+
11
13
  begin
12
14
  log('Starting DF server')
13
15
  Fiber.await(*listeners)
data/df/server_utils.rb CHANGED
@@ -64,17 +64,14 @@ def listen_https
64
64
  c = IO.read('../../reality/ssl/cacert.pem')
65
65
  certificates = c.scan(CERTIFICATE_REGEXP).map { |p| OpenSSL::X509::Certificate.new(p.first) }
66
66
  ctx = OpenSSL::SSL::SSLContext.new
67
+ ctx.security_level = 0
67
68
  cert = certificates.shift
68
69
  log "SSL Certificate expires: #{cert.not_after.inspect}"
69
70
  ctx.add_certificate(cert, private_key, certificates)
70
71
  ctx.ciphers = 'ECDH+aRSA'
71
- ctx.send(
72
- :set_minmax_proto_version,
73
- OpenSSL::SSL::SSL3_VERSION,
74
- OpenSSL::SSL::TLS1_3_VERSION
75
- )
76
- # ctx.min_version = OpenSSL::SSL::SSL3_VERSION #OpenSSL::SSL::TLS1_VERSION
77
- # ctx.max_version = OpenSSL::SSL::TLS1_3_VERSION
72
+ ctx.max_version = OpenSSL::SSL::TLS1_3_VERSION
73
+ ctx.min_version = OpenSSL::SSL::SSL3_VERSION
74
+ ctx.verify_mode = OpenSSL::SSL::VERIFY_NONE
78
75
 
79
76
  # TODO: further limit ciphers
80
77
  # ref: https://github.com/socketry/falcon/blob/3ec805b3ceda0a764a2c5eb68cde33897b6a35ff/lib/falcon/environments/tls.rb
@@ -91,10 +88,10 @@ def listen_https
91
88
  server = Polyphony::Net.tcp_listen('0.0.0.0', 10443, opts)
92
89
  id = 0
93
90
  loop do
94
- log('Before HTTPS server.accept')
95
- client = server.accept
96
- log('After HTTPS server.accept')
97
- log('Accept HTTPS client connection', client: client)
91
+ client = server.accept rescue nil
92
+ next unless client
93
+
94
+ # log('Accept HTTPS client connection', client: client)
98
95
  spin("https#{id += 1}") do
99
96
  @service.incr_connection_count
100
97
  Tipi.client_loop(client, opts) { |req| @service.http_request(req) }
@@ -104,12 +101,12 @@ def listen_https
104
101
  # log("Done with HTTP connection", client: client)
105
102
  @service.decr_connection_count
106
103
  end
107
- rescue OpenSSL::SSL::SSLError, SystemCallError, TypeError => e
108
- log('HTTPS accept error', error: e)
104
+ # rescue OpenSSL::SSL::SSLError, SystemCallError, TypeError => e
105
+ # log('HTTPS accept error', error: e)
109
106
  rescue Polyphony::BaseException
110
107
  raise
111
108
  rescue Exception => e
112
- log 'HTTPS accept (unknown) error', error: e, backtrace: e.backtrace
109
+ log 'HTTPS listener error: ', error: e, backtrace: e.backtrace
113
110
  end
114
111
  end
115
112
  end
@@ -50,6 +50,8 @@ module DigitalFabric
50
50
  switch_rate = backend_stats[:switch_count] / elapsed
51
51
  poll_rate = backend_stats[:poll_count] / elapsed
52
52
 
53
+ object_space_stats = ObjectSpace.count_objects
54
+
53
55
  {
54
56
  service: {
55
57
  agent_count: @agents.size,
@@ -73,6 +75,8 @@ module DigitalFabric
73
75
  process: {
74
76
  cpu_usage: cpu,
75
77
  rss: rss.to_f / 1024,
78
+ objects_total: object_space_stats[:TOTAL],
79
+ objects_free: object_space_stats[:FREE]
76
80
  }
77
81
  }
78
82
  end
@@ -1,9 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'tipi_ext'
4
- require_relative './http2_adapter'
3
+ require 'h1p'
5
4
  require 'qeweney/request'
6
5
 
6
+ require_relative './http2_adapter'
7
+
7
8
  module Tipi
8
9
  # HTTP1 protocol implementation
9
10
  class HTTP1Adapter
@@ -14,7 +15,7 @@ module Tipi
14
15
  @conn = conn
15
16
  @opts = opts
16
17
  @first = true
17
- @parser = Tipi::HTTP1Parser.new(@conn)
18
+ @parser = H1P::Parser.new(@conn)
18
19
  end
19
20
 
20
21
  def each(&block)
@@ -26,7 +27,7 @@ module Tipi
26
27
  # upgraded
27
28
  break if handle_request(headers, &block)
28
29
  end
29
- rescue Tipi::HTTP1Parser::Error
30
+ rescue H1P::Error
30
31
  # ignore
31
32
  rescue SystemCallError, IOError
32
33
  # ignore
data/lib/tipi/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Tipi
4
- VERSION = '0.42'
4
+ VERSION = '0.43'
5
5
  end
data/test/helper.rb CHANGED
@@ -8,7 +8,6 @@ require_relative './eg'
8
8
  require_relative './coverage' if ENV['COVERAGE']
9
9
 
10
10
  require 'minitest/autorun'
11
- require 'minitest/reporters'
12
11
 
13
12
  require 'polyphony'
14
13
 
data/test/test_request.rb CHANGED
@@ -39,7 +39,7 @@ class RequestHeadersTest < MiniTest::Test
39
39
  assert_equal 'blah.com', req.headers['host']
40
40
  assert_equal 'bar', req.headers['foo']
41
41
  assert_equal ['1', '2', '3'], req.headers['hi']
42
- assert_equal 'get', req.headers[':method']
42
+ assert_equal 'GET', req.headers[':method']
43
43
  assert_equal '/titi', req.headers[':path']
44
44
  end
45
45
 
data/tipi.gemspec CHANGED
@@ -14,7 +14,6 @@ Gem::Specification.new do |s|
14
14
  }
15
15
  s.rdoc_options = ["--title", "tipi", "--main", "README.md"]
16
16
  s.extra_rdoc_files = ["README.md"]
17
- s.extensions = ["ext/tipi/extconf.rb"]
18
17
  s.require_paths = ["lib"]
19
18
  s.required_ruby_version = '>= 2.6'
20
19
 
@@ -23,6 +22,7 @@ Gem::Specification.new do |s|
23
22
  s.add_runtime_dependency 'polyphony', '~>0.69'
24
23
  s.add_runtime_dependency 'qeweney', '~>0.14'
25
24
  s.add_runtime_dependency 'extralite', '~>1.2'
25
+ s.add_runtime_dependency 'h1p', '~>0.2'
26
26
 
27
27
  s.add_runtime_dependency 'http-2', '~>0.11'
28
28
  s.add_runtime_dependency 'rack', '>=2.0.8', '<2.3.0'
@@ -33,12 +33,10 @@ Gem::Specification.new do |s|
33
33
  # for digital fabric
34
34
  s.add_runtime_dependency 'msgpack', '~>1.4.2'
35
35
 
36
- s.add_development_dependency 'rake-compiler', '1.1.1'
37
- s.add_development_dependency 'rake', '~>12.3.3'
36
+ s.add_development_dependency 'rake', '~>13.0.6'
38
37
  s.add_development_dependency 'minitest', '~>5.11.3'
39
- s.add_development_dependency 'minitest-reporters', '~>1.4.2'
40
38
  s.add_development_dependency 'simplecov', '~>0.17.1'
39
+ s.add_development_dependency 'memory_profiler', '~>1.0.0'
41
40
 
42
41
  s.add_development_dependency 'cuba', '~>3.9.3'
43
- s.add_development_dependency 'http_parser.rb', '0.7.0'
44
42
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tipi
3
3
  version: !ruby/object:Gem::Version
4
- version: '0.42'
4
+ version: '0.43'
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sharon Rosner
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-08-16 00:00:00.000000000 Z
11
+ date: 2021-08-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: polyphony
@@ -52,6 +52,20 @@ dependencies:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
54
  version: '1.2'
55
+ - !ruby/object:Gem::Dependency
56
+ name: h1p
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '0.2'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '0.2'
55
69
  - !ruby/object:Gem::Dependency
56
70
  name: http-2
57
71
  requirement: !ruby/object:Gem::Requirement
@@ -142,34 +156,20 @@ dependencies:
142
156
  - - "~>"
143
157
  - !ruby/object:Gem::Version
144
158
  version: 1.4.2
145
- - !ruby/object:Gem::Dependency
146
- name: rake-compiler
147
- requirement: !ruby/object:Gem::Requirement
148
- requirements:
149
- - - '='
150
- - !ruby/object:Gem::Version
151
- version: 1.1.1
152
- type: :development
153
- prerelease: false
154
- version_requirements: !ruby/object:Gem::Requirement
155
- requirements:
156
- - - '='
157
- - !ruby/object:Gem::Version
158
- version: 1.1.1
159
159
  - !ruby/object:Gem::Dependency
160
160
  name: rake
161
161
  requirement: !ruby/object:Gem::Requirement
162
162
  requirements:
163
163
  - - "~>"
164
164
  - !ruby/object:Gem::Version
165
- version: 12.3.3
165
+ version: 13.0.6
166
166
  type: :development
167
167
  prerelease: false
168
168
  version_requirements: !ruby/object:Gem::Requirement
169
169
  requirements:
170
170
  - - "~>"
171
171
  - !ruby/object:Gem::Version
172
- version: 12.3.3
172
+ version: 13.0.6
173
173
  - !ruby/object:Gem::Dependency
174
174
  name: minitest
175
175
  requirement: !ruby/object:Gem::Requirement
@@ -185,33 +185,33 @@ dependencies:
185
185
  - !ruby/object:Gem::Version
186
186
  version: 5.11.3
187
187
  - !ruby/object:Gem::Dependency
188
- name: minitest-reporters
188
+ name: simplecov
189
189
  requirement: !ruby/object:Gem::Requirement
190
190
  requirements:
191
191
  - - "~>"
192
192
  - !ruby/object:Gem::Version
193
- version: 1.4.2
193
+ version: 0.17.1
194
194
  type: :development
195
195
  prerelease: false
196
196
  version_requirements: !ruby/object:Gem::Requirement
197
197
  requirements:
198
198
  - - "~>"
199
199
  - !ruby/object:Gem::Version
200
- version: 1.4.2
200
+ version: 0.17.1
201
201
  - !ruby/object:Gem::Dependency
202
- name: simplecov
202
+ name: memory_profiler
203
203
  requirement: !ruby/object:Gem::Requirement
204
204
  requirements:
205
205
  - - "~>"
206
206
  - !ruby/object:Gem::Version
207
- version: 0.17.1
207
+ version: 1.0.0
208
208
  type: :development
209
209
  prerelease: false
210
210
  version_requirements: !ruby/object:Gem::Requirement
211
211
  requirements:
212
212
  - - "~>"
213
213
  - !ruby/object:Gem::Version
214
- version: 0.17.1
214
+ version: 1.0.0
215
215
  - !ruby/object:Gem::Dependency
216
216
  name: cuba
217
217
  requirement: !ruby/object:Gem::Requirement
@@ -226,26 +226,11 @@ dependencies:
226
226
  - - "~>"
227
227
  - !ruby/object:Gem::Version
228
228
  version: 3.9.3
229
- - !ruby/object:Gem::Dependency
230
- name: http_parser.rb
231
- requirement: !ruby/object:Gem::Requirement
232
- requirements:
233
- - - '='
234
- - !ruby/object:Gem::Version
235
- version: 0.7.0
236
- type: :development
237
- prerelease: false
238
- version_requirements: !ruby/object:Gem::Requirement
239
- requirements:
240
- - - '='
241
- - !ruby/object:Gem::Version
242
- version: 0.7.0
243
229
  description:
244
230
  email: sharon@noteflakes.com
245
231
  executables:
246
232
  - tipi
247
- extensions:
248
- - ext/tipi/extconf.rb
233
+ extensions: []
249
234
  extra_rdoc_files:
250
235
  - README.md
251
236
  files:
@@ -308,10 +293,6 @@ files:
308
293
  - examples/websocket_server.rb
309
294
  - examples/ws_page.html
310
295
  - examples/wss_page.html
311
- - ext/tipi/extconf.rb
312
- - ext/tipi/http1_parser.c
313
- - ext/tipi/http1_parser.h
314
- - ext/tipi/tipi_ext.c
315
296
  - lib/tipi.rb
316
297
  - lib/tipi/acme.rb
317
298
  - lib/tipi/cli.rb
@@ -333,12 +314,10 @@ files:
333
314
  - lib/tipi/response_extensions.rb
334
315
  - lib/tipi/version.rb
335
316
  - lib/tipi/websocket.rb
336
- - security/http1.rb
337
317
  - test/coverage.rb
338
318
  - test/eg.rb
339
319
  - test/helper.rb
340
320
  - test/run.rb
341
- - test/test_http1_parser.rb
342
321
  - test/test_http_server.rb
343
322
  - test/test_request.rb
344
323
  - tipi.gemspec
@@ -366,7 +345,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
366
345
  - !ruby/object:Gem::Version
367
346
  version: '0'
368
347
  requirements: []
369
- rubygems_version: 3.1.6
348
+ rubygems_version: 3.1.4
370
349
  signing_key:
371
350
  specification_version: 4
372
351
  summary: Tipi - the All-in-one Web Server for Ruby Apps