tipi 0.40 → 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 (63) hide show
  1. checksums.yaml +4 -4
  2. data/.github/FUNDING.yml +1 -0
  3. data/.github/workflows/test.yml +3 -1
  4. data/.gitignore +5 -1
  5. data/CHANGELOG.md +35 -0
  6. data/Gemfile +7 -1
  7. data/Gemfile.lock +55 -29
  8. data/README.md +184 -8
  9. data/Rakefile +1 -3
  10. data/benchmarks/bm_http1_parser.rb +85 -0
  11. data/bin/benchmark +37 -0
  12. data/bin/h1pd +6 -0
  13. data/bin/tipi +3 -21
  14. data/bm.png +0 -0
  15. data/df/agent.rb +1 -1
  16. data/df/sample_agent.rb +2 -2
  17. data/df/server.rb +16 -102
  18. data/df/server_utils.rb +175 -0
  19. data/examples/full_service.rb +13 -0
  20. data/examples/hello.rb +5 -0
  21. data/examples/http1_parser.rb +55 -0
  22. data/examples/http_server.js +1 -1
  23. data/examples/http_server.rb +15 -3
  24. data/examples/http_server_graceful.rb +1 -1
  25. data/examples/http_server_static.rb +6 -18
  26. data/examples/https_server.rb +41 -15
  27. data/examples/rack_server_forked.rb +26 -0
  28. data/examples/rack_server_https_forked.rb +1 -1
  29. data/examples/servername_cb.rb +37 -0
  30. data/examples/websocket_demo.rb +1 -1
  31. data/lib/tipi/acme.rb +315 -0
  32. data/lib/tipi/cli.rb +93 -0
  33. data/lib/tipi/config_dsl.rb +13 -13
  34. data/lib/tipi/configuration.rb +2 -2
  35. data/{e → lib/tipi/controller/bare_polyphony.rb} +0 -0
  36. data/lib/tipi/controller/bare_stock.rb +10 -0
  37. data/lib/tipi/controller/stock_http1_adapter.rb +15 -0
  38. data/lib/tipi/controller/web_polyphony.rb +351 -0
  39. data/lib/tipi/controller/web_stock.rb +631 -0
  40. data/lib/tipi/controller.rb +12 -0
  41. data/lib/tipi/digital_fabric/agent.rb +10 -8
  42. data/lib/tipi/digital_fabric/agent_proxy.rb +26 -12
  43. data/lib/tipi/digital_fabric/executive.rb +7 -3
  44. data/lib/tipi/digital_fabric/protocol.rb +19 -4
  45. data/lib/tipi/digital_fabric/request_adapter.rb +0 -4
  46. data/lib/tipi/digital_fabric/service.rb +84 -56
  47. data/lib/tipi/handler.rb +2 -2
  48. data/lib/tipi/http1_adapter.rb +86 -125
  49. data/lib/tipi/http2_adapter.rb +29 -16
  50. data/lib/tipi/http2_stream.rb +52 -56
  51. data/lib/tipi/rack_adapter.rb +2 -53
  52. data/lib/tipi/response_extensions.rb +2 -2
  53. data/lib/tipi/supervisor.rb +75 -0
  54. data/lib/tipi/version.rb +1 -1
  55. data/lib/tipi/websocket.rb +3 -3
  56. data/lib/tipi.rb +8 -5
  57. data/test/coverage.rb +2 -2
  58. data/test/helper.rb +60 -12
  59. data/test/test_http_server.rb +14 -41
  60. data/test/test_request.rb +2 -29
  61. data/tipi.gemspec +12 -8
  62. metadata +88 -28
  63. data/examples/automatic_certificate.rb +0 -193
@@ -4,69 +4,18 @@ require 'rack'
4
4
 
5
5
  module Tipi
6
6
  module RackAdapter
7
- # Implements a rack input stream:
8
- # https://www.rubydoc.info/github/rack/rack/master/file/SPEC#label-The+Input+Stream
9
- class InputStream
10
- def initialize(request)
11
- @request = request
12
- end
13
-
14
- def gets; end
15
-
16
- def read(length = nil, outbuf = nil); end
17
-
18
- def each(&block)
19
- @request.each_chunk(&block)
20
- end
21
-
22
- def rewind; end
23
- end
24
-
25
7
  class << self
26
8
  def run(app)
27
9
  ->(req) { respond(req, app.(env(req))) }
28
10
  end
29
-
11
+
30
12
  def load(path)
31
13
  src = IO.read(path)
32
14
  instance_eval(src, path, 1)
33
15
  end
34
16
 
35
- RACK_ENV = {
36
- 'SCRIPT_NAME' => '',
37
- 'rack.version' => Rack::VERSION,
38
- 'SERVER_PORT' => '80', # ?
39
- 'rack.url_scheme' => 'http', # ?
40
- 'rack.errors' => STDERR, # ?
41
- 'rack.multithread' => false,
42
- 'rack.run_once' => false,
43
- 'rack.hijack?' => false,
44
- 'rack.hijack' => nil,
45
- 'rack.hijack_io' => nil,
46
- 'rack.session' => nil,
47
- 'rack.logger' => nil,
48
- 'rack.multipart.buffer_size' => nil,
49
- 'rack.multipar.tempfile_factory' => nil
50
- }
51
-
52
17
  def env(request)
53
- Hash.new do |h, k|
54
- h[k] = env_value_from_request(request, k)
55
- end
56
- end
57
-
58
- HTTP_HEADER_RE = /^HTTP_(.+)$/.freeze
59
-
60
- def env_value_from_request(request, key)
61
- case key
62
- when 'REQUEST_METHOD' then request.method
63
- when 'PATH_INFO' then request.path
64
- when 'QUERY_STRING' then request.query_string || ''
65
- when 'SERVER_NAME' then request.headers['host']
66
- when 'rack.input' then InputStream.new(request)
67
- when HTTP_HEADER_RE then request.headers[$1.downcase]
68
- else RACK_ENV[key]
69
- end
18
+ Qeweney.rack_env_from_request(request)
70
19
  end
71
20
 
72
21
  def respond(request, (status_code, headers, body))
@@ -8,8 +8,8 @@ module Tipi
8
8
 
9
9
  def serve_io(io, opts)
10
10
  if !opts[:stat] || opts[:stat].size >= SPLICE_CHUNKS_SIZE_THRESHOLD
11
- @adapter.respond_from_io(self, io, opts[:headers])
12
- else
11
+ @adapter.respond_from_io(self, io, opts[:headers], opts[:chunk_size] || 2**14)
12
+ else
13
13
  respond(io.read, opts[:headers] || {})
14
14
  end
15
15
  end
@@ -0,0 +1,75 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'polyphony'
4
+ require 'json'
5
+
6
+ module Tipi
7
+ module Supervisor
8
+ class << self
9
+ def run(opts)
10
+ puts "Start supervisor pid: #{Process.pid}"
11
+ @opts = opts
12
+ @controller_watcher = start_controller_watcher
13
+ supervise_loop
14
+ end
15
+
16
+ def start_controller_watcher
17
+ spin do
18
+ cmd = controller_cmd
19
+ puts "Starting controller..."
20
+ pid = Kernel.spawn(*cmd)
21
+ @controller_pid = pid
22
+ puts "Controller pid: #{pid}"
23
+ _pid, status = Polyphony.backend_waitpid(pid)
24
+ puts "Controller has terminated with status: #{status.inspect}"
25
+ terminated = true
26
+ ensure
27
+ if pid && !terminated
28
+ puts "Terminate controller #{pid.inspect}"
29
+ Polyphony::Process.kill_process(pid)
30
+ end
31
+ Fiber.current.parent << pid
32
+ end
33
+ end
34
+
35
+ def controller_cmd
36
+ [
37
+ 'ruby',
38
+ File.join(__dir__, 'controller.rb'),
39
+ @opts.to_json
40
+ ]
41
+ end
42
+
43
+ def supervise_loop
44
+ this_fiber = Fiber.current
45
+ trap('SIGUSR2') { this_fiber << :replace_controller }
46
+ loop do
47
+ case (msg = receive)
48
+ when :replace_controller
49
+ replace_controller
50
+ when Integer
51
+ pid = msg
52
+ if pid == @controller_pid
53
+ puts 'Detected dead controller. Restarting...'
54
+ exit!
55
+ @controller_watcher.restart
56
+ end
57
+ else
58
+ raise "Invalid message received: #{msg.inspect}"
59
+ end
60
+ end
61
+ end
62
+
63
+ def replace_controller
64
+ puts "Replacing controller"
65
+ old_watcher = @controller_watcher
66
+ @controller_watcher = start_controller_watcher
67
+
68
+ # TODO: we'll want to get some kind of signal from the new controller once it's ready
69
+ sleep 1
70
+
71
+ old_watcher.terminate(true)
72
+ end
73
+ end
74
+ end
75
+ end
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.40'
4
+ VERSION = '0.45'
5
5
  end
@@ -20,12 +20,12 @@ module Tipi
20
20
  @version = headers['sec-websocket-version'].to_i
21
21
  @reader = ::WebSocket::Frame::Incoming::Server.new(version: @version)
22
22
  end
23
-
23
+
24
24
  def recv
25
25
  if (msg = @reader.next)
26
26
  return msg.to_s
27
27
  end
28
-
28
+
29
29
  @conn.recv_loop do |data|
30
30
  @reader << data
31
31
  if (msg = @reader.next)
@@ -48,7 +48,7 @@ module Tipi
48
48
  end
49
49
  end
50
50
  end
51
-
51
+
52
52
  OutgoingFrame = ::WebSocket::Frame::Outgoing::Server
53
53
 
54
54
  def send(data)
data/lib/tipi.rb CHANGED
@@ -1,10 +1,13 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'polyphony'
4
+
4
5
  require_relative './tipi/http1_adapter'
5
6
  require_relative './tipi/http2_adapter'
6
7
  require_relative './tipi/configuration'
7
8
  require_relative './tipi/response_extensions'
9
+ require_relative './tipi/acme'
10
+
8
11
  require 'qeweney/request'
9
12
 
10
13
  class Qeweney::Request
@@ -14,7 +17,7 @@ end
14
17
  module Tipi
15
18
  ALPN_PROTOCOLS = %w[h2 http/1.1].freeze
16
19
  H2_PROTOCOL = 'h2'
17
-
20
+
18
21
  class << self
19
22
  def serve(host, port, opts = {}, &handler)
20
23
  opts[:alpn_protocols] = ALPN_PROTOCOLS
@@ -23,7 +26,7 @@ module Tipi
23
26
  ensure
24
27
  server&.close
25
28
  end
26
-
29
+
27
30
  def listen(host, port, opts = {})
28
31
  opts[:alpn_protocols] = ALPN_PROTOCOLS
29
32
  Polyphony::Net.tcp_listen(host, port, opts).tap do |socket|
@@ -32,7 +35,7 @@ module Tipi
32
35
  end
33
36
  end
34
37
  end
35
-
38
+
36
39
  def accept_loop(server, opts, &handler)
37
40
  server.accept_loop do |client|
38
41
  spin { client_loop(client, opts, &handler) }
@@ -40,7 +43,7 @@ module Tipi
40
43
  # disregard
41
44
  end
42
45
  end
43
-
46
+
44
47
  def client_loop(client, opts, &handler)
45
48
  client.no_delay if client.respond_to?(:no_delay)
46
49
  adapter = protocol_adapter(client, opts)
@@ -48,7 +51,7 @@ module Tipi
48
51
  ensure
49
52
  client.close rescue nil
50
53
  end
51
-
54
+
52
55
  def protocol_adapter(socket, opts)
53
56
  use_http2 = socket.respond_to?(:alpn_protocol) &&
54
57
  socket.alpn_protocol == H2_PROTOCOL
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
data/test/helper.rb CHANGED
@@ -8,32 +8,29 @@ 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
 
15
14
  ::Exception.__disable_sanitized_backtrace__ = true
16
15
 
17
- Minitest::Reporters.use! [
18
- Minitest::Reporters::SpecReporter.new
19
- ]
20
-
21
16
  class MiniTest::Test
22
17
  def setup
23
- # puts "* setup #{self.name}"
24
- if Fiber.current.children.size > 0
25
- puts "Children left: #{Fiber.current.children.inspect}"
26
- exit!
27
- end
18
+ # trace "* setup #{self.name}"
28
19
  Fiber.current.setup_main_fiber
29
20
  Fiber.current.instance_variable_set(:@auto_watcher, nil)
21
+ Thread.current.backend.finalize
30
22
  Thread.current.backend = Polyphony::Backend.new
31
23
  sleep 0
32
24
  end
33
25
 
34
26
  def teardown
35
- # puts "* teardown #{self.name.inspect} Fiber.current: #{Fiber.current.inspect}"
27
+ # trace "* teardown #{self.name}"
36
28
  Fiber.current.shutdown_all_children
29
+ if Fiber.current.children.size > 0
30
+ puts "Children left after #{self.name}: #{Fiber.current.children.inspect}"
31
+ exit!
32
+ end
33
+ Fiber.current.instance_variable_set(:@auto_watcher, nil)
37
34
  rescue => e
38
35
  puts e
39
36
  puts e.backtrace.join("\n")
@@ -47,4 +44,55 @@ module Kernel
47
44
  rescue Exception => e
48
45
  e
49
46
  end
50
- end
47
+
48
+ def trace(*args)
49
+ STDOUT.orig_write(format_trace(args))
50
+ end
51
+
52
+ def format_trace(args)
53
+ if args.first.is_a?(String)
54
+ if args.size > 1
55
+ format("%s: %p\n", args.shift, args)
56
+ else
57
+ format("%s\n", args.first)
58
+ end
59
+ else
60
+ format("%p\n", args.size == 1 ? args.first : args)
61
+ end
62
+ end
63
+ end
64
+
65
+ class IO
66
+ # Creates two mockup sockets for simulating server-client communication
67
+ def self.server_client_mockup
68
+ server_in, client_out = IO.pipe
69
+ client_in, server_out = IO.pipe
70
+
71
+ server_connection = mockup_connection(server_in, server_out, client_out)
72
+ client_connection = mockup_connection(client_in, client_out, server_out)
73
+
74
+ [server_connection, client_connection]
75
+ end
76
+
77
+ def self.mockup_connection(input, output, output2)
78
+ eg(
79
+ __parser_read_method__: ->() { :readpartial },
80
+ read: ->(*args) { input.read(*args) },
81
+ read_loop: ->(*args, &block) { input.read_loop(*args, &block) },
82
+ recv_loop: ->(*args, &block) { input.read_loop(*args, &block) },
83
+ readpartial: ->(*args) { input.readpartial(*args) },
84
+ recv: ->(*args) { input.readpartial(*args) },
85
+ '<<': ->(*args) { output.write(*args) },
86
+ write: ->(*args) { output.write(*args) },
87
+ close: -> { output.close },
88
+ eof?: -> { output2.closed? }
89
+ )
90
+ end
91
+ end
92
+
93
+ module Minitest::Assertions
94
+ def assert_in_range exp_range, act
95
+ msg = message(msg) { "Expected #{mu_pp(act)} to be in range #{mu_pp(exp_range)}" }
96
+ assert exp_range.include?(act), msg
97
+ end
98
+ end
@@ -4,38 +4,11 @@ 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
11
11
 
12
- class IO
13
- # Creates two mockup sockets for simulating server-client communication
14
- def self.server_client_mockup
15
- server_in, client_out = IO.pipe
16
- client_in, server_out = IO.pipe
17
-
18
- server_connection = mockup_connection(server_in, server_out, client_out)
19
- client_connection = mockup_connection(client_in, client_out, server_out)
20
-
21
- [server_connection, client_connection]
22
- end
23
-
24
- def self.mockup_connection(input, output, output2)
25
- eg(
26
- :read => ->(*args) { input.read(*args) },
27
- :read_loop => ->(*args, &block) { input.read_loop(*args, &block) },
28
- :recv_loop => ->(*args, &block) { input.read_loop(*args, &block) },
29
- :readpartial => ->(*args) { input.readpartial(*args) },
30
- :recv => ->(*args) { input.readpartial(*args) },
31
- :<< => ->(*args) { output.write(*args) },
32
- :write => ->(*args) { output.write(*args) },
33
- :close => -> { output.close },
34
- :eof? => -> { output2.closed? }
35
- )
36
- end
37
- end
38
-
39
12
  class HTTP1ServerTest < MiniTest::Test
40
13
  def teardown
41
14
  @server&.interrupt if @server&.alive?
@@ -60,7 +33,7 @@ class HTTP1ServerTest < MiniTest::Test
60
33
  connection << "GET / HTTP/1.0\r\n\r\n"
61
34
 
62
35
  response = connection.readpartial(8192)
63
- expected = <<~HTTP.chomp.http_lines.chomp
36
+ expected = <<~HTTP.chomp.crlf_lines.chomp
64
37
  HTTP/1.1 200
65
38
  Content-Length: 13
66
39
 
@@ -78,7 +51,7 @@ class HTTP1ServerTest < MiniTest::Test
78
51
  connection << "GET / HTTP/1.1\r\n\r\n"
79
52
 
80
53
  response = connection.readpartial(8192)
81
- expected = <<~HTTP.http_lines.chomp
54
+ expected = <<~HTTP.crlf_lines.chomp
82
55
  HTTP/1.1 200
83
56
  Content-Length: 13
84
57
 
@@ -100,7 +73,7 @@ class HTTP1ServerTest < MiniTest::Test
100
73
  connection << "GET / HTTP/1.1\r\n\r\n"
101
74
  response = connection.readpartial(8192)
102
75
  assert !connection.eof?
103
- expected = <<~HTTP.http_lines.chomp
76
+ expected = <<~HTTP.crlf_lines.chomp
104
77
  HTTP/1.1 200
105
78
  Content-Length: 2
106
79
 
@@ -127,7 +100,7 @@ class HTTP1ServerTest < MiniTest::Test
127
100
  sleep 0.01
128
101
  response = connection.readpartial(8192)
129
102
 
130
- expected = <<~HTTP.http_lines.chomp
103
+ expected = <<~HTTP.crlf_lines.chomp
131
104
  HTTP/1.1 200
132
105
  Content-Length: 13
133
106
 
@@ -152,7 +125,7 @@ class HTTP1ServerTest < MiniTest::Test
152
125
  req.finish
153
126
  end
154
127
 
155
- connection << <<~HTTP.http_lines
128
+ connection << <<~HTTP.crlf_lines
156
129
  POST / HTTP/1.1
157
130
  Transfer-Encoding: chunked
158
131
 
@@ -178,7 +151,7 @@ class HTTP1ServerTest < MiniTest::Test
178
151
 
179
152
  response = connection.readpartial(8192)
180
153
 
181
- expected = <<~HTTP.http_lines
154
+ expected = <<~HTTP.crlf_lines
182
155
  HTTP/1.1 200
183
156
  Transfer-Encoding: chunked
184
157
 
@@ -199,7 +172,7 @@ class HTTP1ServerTest < MiniTest::Test
199
172
  upgrade: {
200
173
  echo: lambda do |adapter, _headers|
201
174
  conn = adapter.conn
202
- conn << <<~HTTP.http_lines
175
+ conn << <<~HTTP.crlf_lines
203
176
  HTTP/1.1 101 Switching Protocols
204
177
  Upgrade: echo
205
178
  Connection: Upgrade
@@ -219,7 +192,7 @@ class HTTP1ServerTest < MiniTest::Test
219
192
  connection << "GET / HTTP/1.1\r\n\r\n"
220
193
  response = connection.readpartial(8192)
221
194
  assert !connection.eof?
222
- expected = <<~HTTP.http_lines.chomp
195
+ expected = <<~HTTP.crlf_lines.chomp
223
196
  HTTP/1.1 200
224
197
  Content-Length: 2
225
198
 
@@ -227,7 +200,7 @@ class HTTP1ServerTest < MiniTest::Test
227
200
  HTTP
228
201
  assert_equal(expected, response)
229
202
 
230
- connection << <<~HTTP.http_lines
203
+ connection << <<~HTTP.crlf_lines
231
204
  GET / HTTP/1.1
232
205
  Upgrade: echo
233
206
  Connection: upgrade
@@ -237,7 +210,7 @@ class HTTP1ServerTest < MiniTest::Test
237
210
  snooze
238
211
  response = connection.readpartial(8192)
239
212
  assert !connection.eof?
240
- expected = <<~HTTP.http_lines
213
+ expected = <<~HTTP.crlf_lines
241
214
  HTTP/1.1 101 Switching Protocols
242
215
  Upgrade: echo
243
216
  Connection: Upgrade
@@ -255,7 +228,7 @@ class HTTP1ServerTest < MiniTest::Test
255
228
 
256
229
  connection.close
257
230
  assert !done
258
-
231
+
259
232
  sleep 0.01
260
233
  assert done
261
234
  end
@@ -278,7 +251,7 @@ class HTTP1ServerTest < MiniTest::Test
278
251
  count = 0
279
252
 
280
253
  connection << "GET / HTTP/1.1\r\n\r\n"
281
-
254
+
282
255
  while (data = connection.read(chunk_size))
283
256
  response << data
284
257
  count += 1
@@ -286,7 +259,7 @@ class HTTP1ServerTest < MiniTest::Test
286
259
  end
287
260
 
288
261
  chunks = "#{chunk_size.to_s(16)}\n#{'*' * chunk_size}\n" * chunk_count
289
- expected = <<~HTTP.http_lines
262
+ expected = <<~HTTP.crlf_lines
290
263
  HTTP/1.1 200
291
264
  Transfer-Encoding: chunked
292
265
 
data/test/test_request.rb CHANGED
@@ -9,33 +9,6 @@ class String
9
9
  end
10
10
  end
11
11
 
12
- class IO
13
- # Creates two mockup sockets for simulating server-client communication
14
- def self.server_client_mockup
15
- server_in, client_out = IO.pipe
16
- client_in, server_out = IO.pipe
17
-
18
- server_connection = mockup_connection(server_in, server_out, client_out)
19
- client_connection = mockup_connection(client_in, client_out, server_out)
20
-
21
- [server_connection, client_connection]
22
- end
23
-
24
- def self.mockup_connection(input, output, output2)
25
- eg(
26
- :read => ->(*args) { input.read(*args) },
27
- :read_loop => ->(*args, &block) { input.read_loop(*args, &block) },
28
- :recv_loop => ->(*args, &block) { input.read_loop(*args, &block) },
29
- :readpartial => ->(*args) { input.readpartial(*args) },
30
- :recv => ->(*args) { input.readpartial(*args) },
31
- :<< => ->(*args) { output.write(*args) },
32
- :write => ->(*args) { output.write(*args) },
33
- :close => -> { output.close },
34
- :eof? => -> { output2.closed? }
35
- )
36
- end
37
- end
38
-
39
12
  class RequestHeadersTest < MiniTest::Test
40
13
  def teardown
41
14
  @server&.interrupt if @server&.alive?
@@ -65,8 +38,8 @@ class RequestHeadersTest < MiniTest::Test
65
38
  assert_kind_of Qeweney::Request, req
66
39
  assert_equal 'blah.com', req.headers['host']
67
40
  assert_equal 'bar', req.headers['foo']
68
- assert_equal ['1', '3', '2'], req.headers['hi']
69
- assert_equal 'get', req.headers[':method']
41
+ assert_equal ['1', '2', '3'], req.headers['hi']
42
+ assert_equal 'GET', req.headers[':method']
70
43
  assert_equal '/titi', req.headers[':path']
71
44
  end
72
45
 
data/tipi.gemspec CHANGED
@@ -19,21 +19,25 @@ Gem::Specification.new do |s|
19
19
 
20
20
  s.executables = ['tipi']
21
21
 
22
- s.add_runtime_dependency 'polyphony', '~>0.57.0'
23
- s.add_runtime_dependency 'qeweney', '~>0.10.0'
24
-
25
- s.add_runtime_dependency 'http_parser.rb', '~>0.6.0'
26
- s.add_runtime_dependency 'http-2', '~>0.10.0'
22
+ s.add_runtime_dependency 'polyphony', '~>0.71'
23
+ s.add_runtime_dependency 'ever', '~>0.1'
24
+ s.add_runtime_dependency 'qeweney', '~>0.14'
25
+ s.add_runtime_dependency 'extralite', '~>1.2'
26
+ s.add_runtime_dependency 'h1p', '~>0.2'
27
+
28
+ s.add_runtime_dependency 'http-2', '~>0.11'
27
29
  s.add_runtime_dependency 'rack', '>=2.0.8', '<2.3.0'
28
30
  s.add_runtime_dependency 'websocket', '~>1.2.8'
29
31
  s.add_runtime_dependency 'acme-client', '~>2.0.8'
32
+ s.add_runtime_dependency 'localhost', '~>1.1.4'
30
33
 
31
34
  # for digital fabric
32
35
  s.add_runtime_dependency 'msgpack', '~>1.4.2'
33
36
 
34
- s.add_development_dependency 'rake', '~>12.3.3'
35
- s.add_development_dependency 'localhost', '~>1.1.4'
37
+ s.add_development_dependency 'rake', '~>13.0.6'
36
38
  s.add_development_dependency 'minitest', '~>5.11.3'
37
- s.add_development_dependency 'minitest-reporters', '~>1.4.2'
38
39
  s.add_development_dependency 'simplecov', '~>0.17.1'
40
+ s.add_development_dependency 'memory_profiler', '~>1.0.0'
41
+
42
+ s.add_development_dependency 'cuba', '~>3.9.3'
39
43
  end