tipi 0.43 → 0.45

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