tipi 0.43 → 0.45

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.
Files changed (51) hide show
  1. checksums.yaml +4 -4
  2. data/.github/FUNDING.yml +1 -0
  3. data/.github/workflows/test.yml +1 -3
  4. data/CHANGELOG.md +12 -0
  5. data/Gemfile +3 -1
  6. data/Gemfile.lock +14 -7
  7. data/README.md +184 -8
  8. data/Rakefile +1 -7
  9. data/benchmarks/bm_http1_parser.rb +1 -1
  10. data/bin/benchmark +0 -0
  11. data/bin/h1pd +0 -0
  12. data/bm.png +0 -0
  13. data/df/agent.rb +1 -1
  14. data/df/sample_agent.rb +2 -2
  15. data/df/server_utils.rb +1 -1
  16. data/examples/hello.rb +5 -0
  17. data/examples/http_server.js +1 -1
  18. data/examples/http_server_graceful.rb +1 -1
  19. data/examples/https_server.rb +41 -18
  20. data/examples/rack_server_forked.rb +26 -0
  21. data/examples/rack_server_https_forked.rb +1 -1
  22. data/examples/websocket_demo.rb +1 -1
  23. data/lib/tipi/acme.rb +46 -39
  24. data/lib/tipi/cli.rb +79 -16
  25. data/lib/tipi/config_dsl.rb +13 -13
  26. data/lib/tipi/configuration.rb +2 -2
  27. data/lib/tipi/controller/bare_polyphony.rb +0 -0
  28. data/lib/tipi/controller/bare_stock.rb +10 -0
  29. data/lib/tipi/controller/stock_http1_adapter.rb +15 -0
  30. data/lib/tipi/controller/web_polyphony.rb +351 -0
  31. data/lib/tipi/controller/web_stock.rb +631 -0
  32. data/lib/tipi/controller.rb +12 -0
  33. data/lib/tipi/digital_fabric/agent.rb +3 -3
  34. data/lib/tipi/digital_fabric/agent_proxy.rb +11 -5
  35. data/lib/tipi/digital_fabric/executive.rb +1 -1
  36. data/lib/tipi/digital_fabric/protocol.rb +1 -1
  37. data/lib/tipi/digital_fabric/service.rb +8 -8
  38. data/lib/tipi/handler.rb +2 -2
  39. data/lib/tipi/http1_adapter.rb +32 -27
  40. data/lib/tipi/http2_adapter.rb +10 -10
  41. data/lib/tipi/http2_stream.rb +14 -14
  42. data/lib/tipi/rack_adapter.rb +2 -2
  43. data/lib/tipi/response_extensions.rb +1 -1
  44. data/lib/tipi/supervisor.rb +75 -0
  45. data/lib/tipi/version.rb +1 -1
  46. data/lib/tipi/websocket.rb +3 -3
  47. data/lib/tipi.rb +4 -83
  48. data/test/coverage.rb +2 -2
  49. data/test/test_http_server.rb +14 -14
  50. data/tipi.gemspec +3 -2
  51. metadata +30 -5
data/lib/tipi.rb CHANGED
@@ -17,7 +17,7 @@ end
17
17
  module Tipi
18
18
  ALPN_PROTOCOLS = %w[h2 http/1.1].freeze
19
19
  H2_PROTOCOL = 'h2'
20
-
20
+
21
21
  class << self
22
22
  def serve(host, port, opts = {}, &handler)
23
23
  opts[:alpn_protocols] = ALPN_PROTOCOLS
@@ -26,7 +26,7 @@ module Tipi
26
26
  ensure
27
27
  server&.close
28
28
  end
29
-
29
+
30
30
  def listen(host, port, opts = {})
31
31
  opts[:alpn_protocols] = ALPN_PROTOCOLS
32
32
  Polyphony::Net.tcp_listen(host, port, opts).tap do |socket|
@@ -35,7 +35,7 @@ module Tipi
35
35
  end
36
36
  end
37
37
  end
38
-
38
+
39
39
  def accept_loop(server, opts, &handler)
40
40
  server.accept_loop do |client|
41
41
  spin { client_loop(client, opts, &handler) }
@@ -43,7 +43,7 @@ module Tipi
43
43
  # disregard
44
44
  end
45
45
  end
46
-
46
+
47
47
  def client_loop(client, opts, &handler)
48
48
  client.no_delay if client.respond_to?(:no_delay)
49
49
  adapter = protocol_adapter(client, opts)
@@ -62,84 +62,5 @@ module Tipi
62
62
  def route(&block)
63
63
  proc { |req| req.route(&block) }
64
64
  end
65
-
66
- CERTIFICATE_STORE_DEFAULT_DIR = File.expand_path('~/.tipi')
67
- CERTIFICATE_STORE_DEFAULT_DB_PATH = File.join(
68
- CERTIFICATE_STORE_DEFAULT_DIR, 'certificates.db'
69
- )
70
-
71
- def default_certificate_store
72
- FileUtils.mkdir(CERTIFICATE_STORE_DEFAULT_DIR) rescue nil
73
- Tipi::ACME::SQLiteCertificateStore.new(CERTIFICATE_STORE_DEFAULT_DB_PATH)
74
- end
75
-
76
- def full_service(
77
- http_port: 10080,
78
- https_port: 10443,
79
- certificate_store: default_certificate_store,
80
- app: nil, &block
81
- )
82
- app ||= block
83
- raise "No app given" unless app
84
-
85
- http_handler = ->(r) { r.redirect("https://#{r.host}#{r.path}") }
86
-
87
- ctx = OpenSSL::SSL::SSLContext.new
88
- # ctx.ciphers = 'ECDH+aRSA'
89
- Polyphony::Net.setup_alpn(ctx, Tipi::ALPN_PROTOCOLS)
90
-
91
- challenge_handler = Tipi::ACME::HTTPChallengeHandler.new
92
- certificate_manager = Tipi::ACME::CertificateManager.new(
93
- master_ctx: ctx,
94
- store: certificate_store,
95
- challenge_handler: challenge_handler
96
- )
97
-
98
- http_listener = spin do
99
- opts = {
100
- reuse_addr: true,
101
- reuse_port: true,
102
- dont_linger: true,
103
- }
104
- puts "Listening for HTTP on localhost:#{http_port}"
105
- server = Polyphony::Net.tcp_listen('0.0.0.0', http_port, opts)
106
- wrapped_handler = certificate_manager.challenge_routing_app(http_handler)
107
- server.accept_loop do |client|
108
- spin do
109
- Tipi.client_loop(client, opts, &wrapped_handler)
110
- rescue => e
111
- puts "Uncaught error in HTTP listener: #{e.inspect}"
112
- end
113
- end
114
- ensure
115
- server.close
116
- end
117
-
118
- https_listener = spin do
119
- opts = {
120
- reuse_addr: true,
121
- reuse_port: true,
122
- dont_linger: true,
123
- secure_context: ctx,
124
- }
125
-
126
- puts "Listening for HTTPS on localhost:#{https_port}"
127
- server = Polyphony::Net.tcp_listen('0.0.0.0', https_port, opts)
128
- loop do
129
- client = server.accept
130
- spin do
131
- Tipi.client_loop(client, opts, &app)
132
- rescue => e
133
- puts "Uncaught error in HTTPS listener: #{e.inspect}"
134
- end
135
- rescue OpenSSL::SSL::SSLError, SystemCallError, TypeError
136
- # ignore
137
- end
138
- ensure
139
- server.close
140
- end
141
-
142
- Fiber.await(http_listener, https_listener)
143
- end
144
65
  end
145
66
  end
data/test/coverage.rb CHANGED
@@ -26,10 +26,10 @@ module Coverage
26
26
  @result = {}
27
27
  trace = TracePoint.new(:line) do |tp|
28
28
  next if tp.path =~ /\(/
29
-
29
+
30
30
  absolute = File.expand_path(tp.path)
31
31
  next unless LIB_FILES.include?(absolute)# =~ /^#{LIB_DIR}/
32
-
32
+
33
33
  @result[absolute] ||= relevant_lines_for_filename(absolute)
34
34
  @result[absolute][tp.lineno - 1] = 1
35
35
  end
@@ -4,7 +4,7 @@ require_relative 'helper'
4
4
  require 'tipi'
5
5
 
6
6
  class String
7
- def http_lines
7
+ def crlf_lines
8
8
  gsub "\n", "\r\n"
9
9
  end
10
10
  end
@@ -33,7 +33,7 @@ class HTTP1ServerTest < MiniTest::Test
33
33
  connection << "GET / HTTP/1.0\r\n\r\n"
34
34
 
35
35
  response = connection.readpartial(8192)
36
- expected = <<~HTTP.chomp.http_lines.chomp
36
+ expected = <<~HTTP.chomp.crlf_lines.chomp
37
37
  HTTP/1.1 200
38
38
  Content-Length: 13
39
39
 
@@ -51,7 +51,7 @@ class HTTP1ServerTest < MiniTest::Test
51
51
  connection << "GET / HTTP/1.1\r\n\r\n"
52
52
 
53
53
  response = connection.readpartial(8192)
54
- expected = <<~HTTP.http_lines.chomp
54
+ expected = <<~HTTP.crlf_lines.chomp
55
55
  HTTP/1.1 200
56
56
  Content-Length: 13
57
57
 
@@ -73,7 +73,7 @@ class HTTP1ServerTest < MiniTest::Test
73
73
  connection << "GET / HTTP/1.1\r\n\r\n"
74
74
  response = connection.readpartial(8192)
75
75
  assert !connection.eof?
76
- expected = <<~HTTP.http_lines.chomp
76
+ expected = <<~HTTP.crlf_lines.chomp
77
77
  HTTP/1.1 200
78
78
  Content-Length: 2
79
79
 
@@ -100,7 +100,7 @@ class HTTP1ServerTest < MiniTest::Test
100
100
  sleep 0.01
101
101
  response = connection.readpartial(8192)
102
102
 
103
- expected = <<~HTTP.http_lines.chomp
103
+ expected = <<~HTTP.crlf_lines.chomp
104
104
  HTTP/1.1 200
105
105
  Content-Length: 13
106
106
 
@@ -125,7 +125,7 @@ class HTTP1ServerTest < MiniTest::Test
125
125
  req.finish
126
126
  end
127
127
 
128
- connection << <<~HTTP.http_lines
128
+ connection << <<~HTTP.crlf_lines
129
129
  POST / HTTP/1.1
130
130
  Transfer-Encoding: chunked
131
131
 
@@ -151,7 +151,7 @@ class HTTP1ServerTest < MiniTest::Test
151
151
 
152
152
  response = connection.readpartial(8192)
153
153
 
154
- expected = <<~HTTP.http_lines
154
+ expected = <<~HTTP.crlf_lines
155
155
  HTTP/1.1 200
156
156
  Transfer-Encoding: chunked
157
157
 
@@ -172,7 +172,7 @@ class HTTP1ServerTest < MiniTest::Test
172
172
  upgrade: {
173
173
  echo: lambda do |adapter, _headers|
174
174
  conn = adapter.conn
175
- conn << <<~HTTP.http_lines
175
+ conn << <<~HTTP.crlf_lines
176
176
  HTTP/1.1 101 Switching Protocols
177
177
  Upgrade: echo
178
178
  Connection: Upgrade
@@ -192,7 +192,7 @@ class HTTP1ServerTest < MiniTest::Test
192
192
  connection << "GET / HTTP/1.1\r\n\r\n"
193
193
  response = connection.readpartial(8192)
194
194
  assert !connection.eof?
195
- expected = <<~HTTP.http_lines.chomp
195
+ expected = <<~HTTP.crlf_lines.chomp
196
196
  HTTP/1.1 200
197
197
  Content-Length: 2
198
198
 
@@ -200,7 +200,7 @@ class HTTP1ServerTest < MiniTest::Test
200
200
  HTTP
201
201
  assert_equal(expected, response)
202
202
 
203
- connection << <<~HTTP.http_lines
203
+ connection << <<~HTTP.crlf_lines
204
204
  GET / HTTP/1.1
205
205
  Upgrade: echo
206
206
  Connection: upgrade
@@ -210,7 +210,7 @@ class HTTP1ServerTest < MiniTest::Test
210
210
  snooze
211
211
  response = connection.readpartial(8192)
212
212
  assert !connection.eof?
213
- expected = <<~HTTP.http_lines
213
+ expected = <<~HTTP.crlf_lines
214
214
  HTTP/1.1 101 Switching Protocols
215
215
  Upgrade: echo
216
216
  Connection: Upgrade
@@ -228,7 +228,7 @@ class HTTP1ServerTest < MiniTest::Test
228
228
 
229
229
  connection.close
230
230
  assert !done
231
-
231
+
232
232
  sleep 0.01
233
233
  assert done
234
234
  end
@@ -251,7 +251,7 @@ class HTTP1ServerTest < MiniTest::Test
251
251
  count = 0
252
252
 
253
253
  connection << "GET / HTTP/1.1\r\n\r\n"
254
-
254
+
255
255
  while (data = connection.read(chunk_size))
256
256
  response << data
257
257
  count += 1
@@ -259,7 +259,7 @@ class HTTP1ServerTest < MiniTest::Test
259
259
  end
260
260
 
261
261
  chunks = "#{chunk_size.to_s(16)}\n#{'*' * chunk_size}\n" * chunk_count
262
- expected = <<~HTTP.http_lines
262
+ expected = <<~HTTP.crlf_lines
263
263
  HTTP/1.1 200
264
264
  Transfer-Encoding: chunked
265
265
 
data/tipi.gemspec CHANGED
@@ -19,11 +19,12 @@ Gem::Specification.new do |s|
19
19
 
20
20
  s.executables = ['tipi']
21
21
 
22
- s.add_runtime_dependency 'polyphony', '~>0.69'
22
+ s.add_runtime_dependency 'polyphony', '~>0.71'
23
+ s.add_runtime_dependency 'ever', '~>0.1'
23
24
  s.add_runtime_dependency 'qeweney', '~>0.14'
24
25
  s.add_runtime_dependency 'extralite', '~>1.2'
25
26
  s.add_runtime_dependency 'h1p', '~>0.2'
26
-
27
+
27
28
  s.add_runtime_dependency 'http-2', '~>0.11'
28
29
  s.add_runtime_dependency 'rack', '>=2.0.8', '<2.3.0'
29
30
  s.add_runtime_dependency 'websocket', '~>1.2.8'
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.43'
4
+ version: '0.45'
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-20 00:00:00.000000000 Z
11
+ date: 2021-10-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: polyphony
@@ -16,14 +16,28 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '0.69'
19
+ version: '0.71'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: '0.69'
26
+ version: '0.71'
27
+ - !ruby/object:Gem::Dependency
28
+ name: ever
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '0.1'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '0.1'
27
41
  - !ruby/object:Gem::Dependency
28
42
  name: qeweney
29
43
  requirement: !ruby/object:Gem::Requirement
@@ -234,6 +248,7 @@ extensions: []
234
248
  extra_rdoc_files:
235
249
  - README.md
236
250
  files:
251
+ - ".github/FUNDING.yml"
237
252
  - ".github/workflows/test.yml"
238
253
  - ".gitignore"
239
254
  - CHANGELOG.md
@@ -247,6 +262,7 @@ files:
247
262
  - bin/benchmark
248
263
  - bin/h1pd
249
264
  - bin/tipi
265
+ - bm.png
250
266
  - df/agent.rb
251
267
  - df/etc_benchmark.rb
252
268
  - df/multi_agent_supervisor.rb
@@ -263,6 +279,7 @@ files:
263
279
  - examples/cuba.ru
264
280
  - examples/full_service.rb
265
281
  - examples/hanami-api.ru
282
+ - examples/hello.rb
266
283
  - examples/hello.ru
267
284
  - examples/http1_parser.rb
268
285
  - examples/http_request_ws_server.rb
@@ -283,6 +300,7 @@ files:
283
300
  - examples/https_server_forked.rb
284
301
  - examples/https_wss_server.rb
285
302
  - examples/rack_server.rb
303
+ - examples/rack_server_forked.rb
286
304
  - examples/rack_server_https.rb
287
305
  - examples/rack_server_https_forked.rb
288
306
  - examples/routing_server.rb
@@ -298,6 +316,12 @@ files:
298
316
  - lib/tipi/cli.rb
299
317
  - lib/tipi/config_dsl.rb
300
318
  - lib/tipi/configuration.rb
319
+ - lib/tipi/controller.rb
320
+ - lib/tipi/controller/bare_polyphony.rb
321
+ - lib/tipi/controller/bare_stock.rb
322
+ - lib/tipi/controller/stock_http1_adapter.rb
323
+ - lib/tipi/controller/web_polyphony.rb
324
+ - lib/tipi/controller/web_stock.rb
301
325
  - lib/tipi/digital_fabric.rb
302
326
  - lib/tipi/digital_fabric/agent.rb
303
327
  - lib/tipi/digital_fabric/agent_proxy.rb
@@ -312,6 +336,7 @@ files:
312
336
  - lib/tipi/http2_stream.rb
313
337
  - lib/tipi/rack_adapter.rb
314
338
  - lib/tipi/response_extensions.rb
339
+ - lib/tipi/supervisor.rb
315
340
  - lib/tipi/version.rb
316
341
  - lib/tipi/websocket.rb
317
342
  - test/coverage.rb
@@ -345,7 +370,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
345
370
  - !ruby/object:Gem::Version
346
371
  version: '0'
347
372
  requirements: []
348
- rubygems_version: 3.1.4
373
+ rubygems_version: 3.1.2
349
374
  signing_key:
350
375
  specification_version: 4
351
376
  summary: Tipi - the All-in-one Web Server for Ruby Apps