tipi 0.42 → 0.43

Sign up to get free protection for your applications and to get access to all the features.
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