puma 5.4.0-java → 5.6.0-java
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 +4 -4
- data/History.md +96 -2
- data/LICENSE +0 -0
- data/README.md +47 -6
- data/bin/puma-wild +0 -0
- data/docs/architecture.md +49 -16
- data/docs/compile_options.md +4 -2
- data/docs/deployment.md +53 -52
- data/docs/fork_worker.md +0 -0
- data/docs/images/puma-connection-flow-no-reactor.png +0 -0
- data/docs/images/puma-connection-flow.png +0 -0
- data/docs/images/puma-general-arch.png +0 -0
- data/docs/jungle/README.md +0 -0
- data/docs/jungle/rc.d/README.md +0 -0
- data/docs/jungle/rc.d/puma.conf +0 -0
- data/docs/kubernetes.md +0 -0
- data/docs/nginx.md +0 -0
- data/docs/plugins.md +15 -15
- data/docs/rails_dev_mode.md +2 -3
- data/docs/restart.md +6 -6
- data/docs/signals.md +11 -10
- data/docs/stats.md +8 -8
- data/docs/systemd.md +64 -67
- data/ext/puma_http11/PumaHttp11Service.java +0 -0
- data/ext/puma_http11/ext_help.h +0 -0
- data/ext/puma_http11/extconf.rb +12 -6
- data/ext/puma_http11/http11_parser.c +23 -10
- data/ext/puma_http11/http11_parser.h +0 -0
- data/ext/puma_http11/http11_parser.java.rl +0 -0
- data/ext/puma_http11/http11_parser.rl +0 -0
- data/ext/puma_http11/http11_parser_common.rl +1 -1
- data/ext/puma_http11/mini_ssl.c +54 -9
- data/ext/puma_http11/no_ssl/PumaHttp11Service.java +0 -0
- data/ext/puma_http11/org/jruby/puma/Http11.java +0 -0
- data/ext/puma_http11/org/jruby/puma/Http11Parser.java +49 -47
- data/ext/puma_http11/org/jruby/puma/MiniSSL.java +28 -43
- data/ext/puma_http11/puma_http11.c +1 -1
- data/lib/puma/app/status.rb +0 -0
- data/lib/puma/binder.rb +46 -4
- data/lib/puma/cli.rb +14 -4
- data/lib/puma/client.rb +46 -4
- data/lib/puma/cluster/worker.rb +7 -17
- data/lib/puma/cluster/worker_handle.rb +4 -0
- data/lib/puma/cluster.rb +29 -21
- data/lib/puma/commonlogger.rb +0 -0
- data/lib/puma/configuration.rb +4 -1
- data/lib/puma/const.rb +4 -5
- data/lib/puma/control_cli.rb +1 -1
- data/lib/puma/detect.rb +8 -2
- data/lib/puma/dsl.rb +98 -11
- data/lib/puma/error_logger.rb +0 -0
- data/lib/puma/events.rb +0 -0
- data/lib/puma/io_buffer.rb +0 -0
- data/lib/puma/jruby_restart.rb +0 -0
- data/lib/puma/json_serialization.rb +0 -0
- data/lib/puma/launcher.rb +4 -1
- data/lib/puma/minissl/context_builder.rb +8 -6
- data/lib/puma/minissl.rb +24 -23
- data/lib/puma/null_io.rb +0 -0
- data/lib/puma/plugin/tmp_restart.rb +0 -0
- data/lib/puma/plugin.rb +1 -1
- data/lib/puma/puma_http11.jar +0 -0
- data/lib/puma/queue_close.rb +0 -0
- data/lib/puma/rack/builder.rb +0 -0
- data/lib/puma/rack/urlmap.rb +0 -0
- data/lib/puma/rack_default.rb +0 -0
- data/lib/puma/reactor.rb +0 -0
- data/lib/puma/request.rb +47 -29
- data/lib/puma/runner.rb +22 -8
- data/lib/puma/server.rb +40 -37
- data/lib/puma/single.rb +0 -0
- data/lib/puma/state_file.rb +41 -7
- data/lib/puma/systemd.rb +0 -0
- data/lib/puma/thread_pool.rb +2 -2
- data/lib/puma/util.rb +7 -0
- data/lib/puma.rb +0 -0
- data/lib/rack/handler/puma.rb +0 -0
- data/tools/Dockerfile +1 -1
- data/tools/trickletest.rb +0 -0
- metadata +6 -6
data/lib/puma/runner.rb
CHANGED
|
@@ -15,6 +15,16 @@ module Puma
|
|
|
15
15
|
@app = nil
|
|
16
16
|
@control = nil
|
|
17
17
|
@started_at = Time.now
|
|
18
|
+
@wakeup = nil
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def wakeup!
|
|
22
|
+
return unless @wakeup
|
|
23
|
+
|
|
24
|
+
@wakeup.write "!" unless @wakeup.closed?
|
|
25
|
+
|
|
26
|
+
rescue SystemCallError, IOError
|
|
27
|
+
Puma::Util.purge_interrupt_queue
|
|
18
28
|
end
|
|
19
29
|
|
|
20
30
|
def development?
|
|
@@ -59,7 +69,7 @@ module Puma
|
|
|
59
69
|
|
|
60
70
|
control.binder.parse [str], self, 'Starting control server'
|
|
61
71
|
|
|
62
|
-
control.run thread_name: '
|
|
72
|
+
control.run thread_name: 'ctl'
|
|
63
73
|
@control = control
|
|
64
74
|
end
|
|
65
75
|
|
|
@@ -84,12 +94,13 @@ module Puma
|
|
|
84
94
|
def output_header(mode)
|
|
85
95
|
min_t = @options[:min_threads]
|
|
86
96
|
max_t = @options[:max_threads]
|
|
97
|
+
environment = @options[:environment]
|
|
87
98
|
|
|
88
99
|
log "Puma starting in #{mode} mode..."
|
|
89
100
|
log "* Puma version: #{Puma::Const::PUMA_VERSION} (#{ruby_engine}) (\"#{Puma::Const::CODE_NAME}\")"
|
|
90
101
|
log "* Min threads: #{min_t}"
|
|
91
102
|
log "* Max threads: #{max_t}"
|
|
92
|
-
log "* Environment: #{
|
|
103
|
+
log "* Environment: #{environment}"
|
|
93
104
|
|
|
94
105
|
if mode == "cluster"
|
|
95
106
|
log "* Master PID: #{Process.pid}"
|
|
@@ -108,9 +119,7 @@ module Puma
|
|
|
108
119
|
append = @options[:redirect_append]
|
|
109
120
|
|
|
110
121
|
if stdout
|
|
111
|
-
|
|
112
|
-
raise "Cannot redirect STDOUT to #{stdout}"
|
|
113
|
-
end
|
|
122
|
+
ensure_output_directory_exists(stdout, 'STDOUT')
|
|
114
123
|
|
|
115
124
|
STDOUT.reopen stdout, (append ? "a" : "w")
|
|
116
125
|
STDOUT.puts "=== puma startup: #{Time.now} ==="
|
|
@@ -118,9 +127,7 @@ module Puma
|
|
|
118
127
|
end
|
|
119
128
|
|
|
120
129
|
if stderr
|
|
121
|
-
|
|
122
|
-
raise "Cannot redirect STDERR to #{stderr}"
|
|
123
|
-
end
|
|
130
|
+
ensure_output_directory_exists(stderr, 'STDERR')
|
|
124
131
|
|
|
125
132
|
STDERR.reopen stderr, (append ? "a" : "w")
|
|
126
133
|
STDERR.puts "=== puma startup: #{Time.now} ==="
|
|
@@ -159,5 +166,12 @@ module Puma
|
|
|
159
166
|
server.inherit_binder @launcher.binder
|
|
160
167
|
server
|
|
161
168
|
end
|
|
169
|
+
|
|
170
|
+
private
|
|
171
|
+
def ensure_output_directory_exists(path, io_name)
|
|
172
|
+
unless Dir.exist?(File.dirname(path))
|
|
173
|
+
raise "Cannot redirect #{io_name} to #{path}"
|
|
174
|
+
end
|
|
175
|
+
end
|
|
162
176
|
end
|
|
163
177
|
end
|
data/lib/puma/server.rb
CHANGED
|
@@ -146,7 +146,7 @@ module Puma
|
|
|
146
146
|
begin
|
|
147
147
|
skt.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_CORK, 1) if skt.kind_of? TCPSocket
|
|
148
148
|
rescue IOError, SystemCallError
|
|
149
|
-
|
|
149
|
+
Puma::Util.purge_interrupt_queue
|
|
150
150
|
end
|
|
151
151
|
end
|
|
152
152
|
|
|
@@ -155,7 +155,7 @@ module Puma
|
|
|
155
155
|
begin
|
|
156
156
|
skt.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_CORK, 0) if skt.kind_of? TCPSocket
|
|
157
157
|
rescue IOError, SystemCallError
|
|
158
|
-
|
|
158
|
+
Puma::Util.purge_interrupt_queue
|
|
159
159
|
end
|
|
160
160
|
end
|
|
161
161
|
else
|
|
@@ -176,7 +176,7 @@ module Puma
|
|
|
176
176
|
begin
|
|
177
177
|
tcp_info = skt.getsockopt(Socket::IPPROTO_TCP, Socket::TCP_INFO)
|
|
178
178
|
rescue IOError, SystemCallError
|
|
179
|
-
|
|
179
|
+
Puma::Util.purge_interrupt_queue
|
|
180
180
|
@precheck_closing = false
|
|
181
181
|
false
|
|
182
182
|
else
|
|
@@ -220,7 +220,7 @@ module Puma
|
|
|
220
220
|
# up in the background to handle requests. Otherwise requests
|
|
221
221
|
# are handled synchronously.
|
|
222
222
|
#
|
|
223
|
-
def run(background=true, thread_name: '
|
|
223
|
+
def run(background=true, thread_name: 'srv')
|
|
224
224
|
BasicSocket.do_not_reverse_lookup = true
|
|
225
225
|
|
|
226
226
|
@events.fire :state, :booting
|
|
@@ -315,14 +315,15 @@ module Puma
|
|
|
315
315
|
queue_requests = @queue_requests
|
|
316
316
|
drain = @options[:drain_on_shutdown] ? 0 : nil
|
|
317
317
|
|
|
318
|
-
|
|
319
|
-
remote_addr_header = nil
|
|
320
|
-
|
|
321
|
-
case @options[:remote_address]
|
|
318
|
+
addr_send_name, addr_value = case @options[:remote_address]
|
|
322
319
|
when :value
|
|
323
|
-
|
|
320
|
+
[:peerip=, @options[:remote_address_value]]
|
|
324
321
|
when :header
|
|
325
|
-
remote_addr_header
|
|
322
|
+
[:remote_addr_header=, @options[:remote_address_header]]
|
|
323
|
+
when :proxy_protocol
|
|
324
|
+
[:expect_proxy_proto=, @options[:remote_address_proxy_protocol]]
|
|
325
|
+
else
|
|
326
|
+
[nil, nil]
|
|
326
327
|
end
|
|
327
328
|
|
|
328
329
|
while @status == :run || (drain && shutting_down?)
|
|
@@ -342,17 +343,16 @@ module Puma
|
|
|
342
343
|
next
|
|
343
344
|
end
|
|
344
345
|
drain += 1 if shutting_down?
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
elsif remote_addr_header
|
|
350
|
-
client.remote_addr_header = remote_addr_header
|
|
351
|
-
end
|
|
352
|
-
pool << client
|
|
346
|
+
pool << Client.new(io, @binder.env(sock)).tap { |c|
|
|
347
|
+
c.listener = sock
|
|
348
|
+
c.send(addr_send_name, addr_value) if addr_value
|
|
349
|
+
}
|
|
353
350
|
end
|
|
354
351
|
end
|
|
355
|
-
rescue
|
|
352
|
+
rescue IOError, Errno::EBADF
|
|
353
|
+
# In the case that any of the sockets are unexpectedly close.
|
|
354
|
+
raise
|
|
355
|
+
rescue StandardError => e
|
|
356
356
|
@events.unknown_error e, nil, "Listen loop"
|
|
357
357
|
end
|
|
358
358
|
end
|
|
@@ -368,13 +368,14 @@ module Puma
|
|
|
368
368
|
rescue Exception => e
|
|
369
369
|
@events.unknown_error e, nil, "Exception handling servers"
|
|
370
370
|
ensure
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
371
|
+
# RuntimeError is Ruby 2.2 issue, can't modify frozen IOError
|
|
372
|
+
# Errno::EBADF is infrequently raised
|
|
373
|
+
[@check, @notify].each do |io|
|
|
374
|
+
begin
|
|
375
|
+
io.close unless io.closed?
|
|
376
|
+
rescue Errno::EBADF, RuntimeError
|
|
377
|
+
end
|
|
376
378
|
end
|
|
377
|
-
@notify.close
|
|
378
379
|
@notify = nil
|
|
379
380
|
@check = nil
|
|
380
381
|
end
|
|
@@ -475,7 +476,7 @@ module Puma
|
|
|
475
476
|
end
|
|
476
477
|
true
|
|
477
478
|
rescue StandardError => e
|
|
478
|
-
client_error(e, client)
|
|
479
|
+
client_error(e, client, buffer, requests)
|
|
479
480
|
# The ensure tries to close +client+ down
|
|
480
481
|
requests > 0
|
|
481
482
|
ensure
|
|
@@ -484,7 +485,7 @@ module Puma
|
|
|
484
485
|
begin
|
|
485
486
|
client.close if close_socket
|
|
486
487
|
rescue IOError, SystemCallError
|
|
487
|
-
|
|
488
|
+
Puma::Util.purge_interrupt_queue
|
|
488
489
|
# Already closed
|
|
489
490
|
rescue StandardError => e
|
|
490
491
|
@events.unknown_error e, nil, "Client"
|
|
@@ -503,34 +504,36 @@ module Puma
|
|
|
503
504
|
# :nocov:
|
|
504
505
|
|
|
505
506
|
# Handle various error types thrown by Client I/O operations.
|
|
506
|
-
def client_error(e, client)
|
|
507
|
+
def client_error(e, client, buffer = ::Puma::IOBuffer.new, requests = 1)
|
|
507
508
|
# Swallow, do not log
|
|
508
509
|
return if [ConnectionError, EOFError].include?(e.class)
|
|
509
510
|
|
|
510
|
-
lowlevel_error(e, client.env)
|
|
511
511
|
case e
|
|
512
512
|
when MiniSSL::SSLError
|
|
513
513
|
@events.ssl_error e, client.io
|
|
514
514
|
when HttpParserError
|
|
515
|
-
client.
|
|
515
|
+
status, headers, res_body = lowlevel_error(e, client.env, 400)
|
|
516
|
+
write_response(status, headers, res_body, buffer, requests, client)
|
|
516
517
|
@events.parse_error e, client
|
|
517
518
|
else
|
|
518
|
-
client.
|
|
519
|
+
status, headers, res_body = lowlevel_error(e, client.env)
|
|
520
|
+
write_response(status, headers, res_body, buffer, requests, client)
|
|
519
521
|
@events.unknown_error e, nil, "Read"
|
|
520
522
|
end
|
|
521
523
|
end
|
|
522
524
|
|
|
523
525
|
# A fallback rack response if +@app+ raises as exception.
|
|
524
526
|
#
|
|
525
|
-
def lowlevel_error(e, env, status=500)
|
|
527
|
+
def lowlevel_error(e, env, status = 500)
|
|
526
528
|
if handler = @options[:lowlevel_error_handler]
|
|
527
529
|
if handler.arity == 1
|
|
528
|
-
|
|
530
|
+
handler_status, headers, res_body = handler.call(e)
|
|
529
531
|
elsif handler.arity == 2
|
|
530
|
-
|
|
532
|
+
handler_status, headers, res_body = handler.call(e, env)
|
|
531
533
|
else
|
|
532
|
-
|
|
534
|
+
handler_status, headers, res_body = handler.call(e, env, status)
|
|
533
535
|
end
|
|
536
|
+
return [handler_status || status, headers || {}, res_body || []]
|
|
534
537
|
end
|
|
535
538
|
|
|
536
539
|
if @leak_stack_on_error
|
|
@@ -576,11 +579,11 @@ module Puma
|
|
|
576
579
|
@notify << message
|
|
577
580
|
rescue IOError, NoMethodError, Errno::EPIPE
|
|
578
581
|
# The server, in another thread, is shutting down
|
|
579
|
-
|
|
582
|
+
Puma::Util.purge_interrupt_queue
|
|
580
583
|
rescue RuntimeError => e
|
|
581
584
|
# Temporary workaround for https://bugs.ruby-lang.org/issues/13239
|
|
582
585
|
if e.message.include?('IOError')
|
|
583
|
-
|
|
586
|
+
Puma::Util.purge_interrupt_queue
|
|
584
587
|
else
|
|
585
588
|
raise e
|
|
586
589
|
end
|
data/lib/puma/single.rb
CHANGED
|
File without changes
|
data/lib/puma/state_file.rb
CHANGED
|
@@ -1,15 +1,40 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require 'yaml'
|
|
4
|
-
|
|
5
3
|
module Puma
|
|
4
|
+
|
|
5
|
+
# Puma::Launcher uses StateFile to write a yaml file for use with Puma::ControlCLI.
|
|
6
|
+
#
|
|
7
|
+
# In previous versions of Puma, YAML was used to read/write the state file.
|
|
8
|
+
# Since Puma is similar to Bundler/RubyGems in that it may load before one's app
|
|
9
|
+
# does, minimizing the dependencies that may be shared with the app is desired.
|
|
10
|
+
#
|
|
11
|
+
# At present, it only works with numeric and string values. It is still a valid
|
|
12
|
+
# yaml file, and the CI tests parse it with Psych.
|
|
13
|
+
#
|
|
6
14
|
class StateFile
|
|
15
|
+
|
|
16
|
+
ALLOWED_FIELDS = %w!control_url control_auth_token pid running_from!
|
|
17
|
+
|
|
18
|
+
# @deprecated 6.0.0
|
|
19
|
+
FIELDS = ALLOWED_FIELDS
|
|
20
|
+
|
|
7
21
|
def initialize
|
|
8
22
|
@options = {}
|
|
9
23
|
end
|
|
10
24
|
|
|
11
25
|
def save(path, permission = nil)
|
|
12
|
-
contents =
|
|
26
|
+
contents = "---\n".dup
|
|
27
|
+
@options.each do |k,v|
|
|
28
|
+
next unless ALLOWED_FIELDS.include? k
|
|
29
|
+
case v
|
|
30
|
+
when Numeric
|
|
31
|
+
contents << "#{k}: #{v}\n"
|
|
32
|
+
when String
|
|
33
|
+
next if v.strip.empty?
|
|
34
|
+
contents << (k == 'running_from' || v.to_s.include?(' ') ?
|
|
35
|
+
"#{k}: \"#{v}\"\n" : "#{k}: #{v}\n")
|
|
36
|
+
end
|
|
37
|
+
end
|
|
13
38
|
if permission
|
|
14
39
|
File.write path, contents, mode: 'wb:UTF-8'
|
|
15
40
|
else
|
|
@@ -18,12 +43,21 @@ module Puma
|
|
|
18
43
|
end
|
|
19
44
|
|
|
20
45
|
def load(path)
|
|
21
|
-
|
|
46
|
+
File.read(path).lines.each do |line|
|
|
47
|
+
next if line.start_with? '#'
|
|
48
|
+
k,v = line.split ':', 2
|
|
49
|
+
next unless v && ALLOWED_FIELDS.include?(k)
|
|
50
|
+
v = v.strip
|
|
51
|
+
@options[k] =
|
|
52
|
+
case v
|
|
53
|
+
when /\A\d+\z/ then v.to_i
|
|
54
|
+
when /\A\d+\.\d+\z/ then v.to_f
|
|
55
|
+
else v.gsub(/\A"|"\z/, '')
|
|
56
|
+
end
|
|
57
|
+
end
|
|
22
58
|
end
|
|
23
59
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
FIELDS.each do |f|
|
|
60
|
+
ALLOWED_FIELDS.each do |f|
|
|
27
61
|
define_method f do
|
|
28
62
|
@options[f]
|
|
29
63
|
end
|
data/lib/puma/systemd.rb
CHANGED
|
File without changes
|
data/lib/puma/thread_pool.rb
CHANGED
|
@@ -72,7 +72,7 @@ module Puma
|
|
|
72
72
|
attr_accessor :out_of_band_hook # @version 5.0.0
|
|
73
73
|
|
|
74
74
|
def self.clean_thread_locals
|
|
75
|
-
Thread.current.keys.each do |key| # rubocop: disable
|
|
75
|
+
Thread.current.keys.each do |key| # rubocop: disable Style/HashEachMethods
|
|
76
76
|
Thread.current[key] = nil unless key == :__recursive_key__
|
|
77
77
|
end
|
|
78
78
|
end
|
|
@@ -102,7 +102,7 @@ module Puma
|
|
|
102
102
|
@spawned += 1
|
|
103
103
|
|
|
104
104
|
th = Thread.new(@spawned) do |spawned|
|
|
105
|
-
Puma.set_thread_name '%s
|
|
105
|
+
Puma.set_thread_name '%s tp %03i' % [@name, spawned]
|
|
106
106
|
todo = @todo
|
|
107
107
|
block = @block
|
|
108
108
|
mutex = @mutex
|
data/lib/puma/util.rb
CHANGED
|
@@ -10,6 +10,13 @@ module Puma
|
|
|
10
10
|
IO.pipe
|
|
11
11
|
end
|
|
12
12
|
|
|
13
|
+
# An instance method on Thread has been provided to address https://bugs.ruby-lang.org/issues/13632,
|
|
14
|
+
# which currently effects some older versions of Ruby: 2.2.7 2.2.8 2.2.9 2.2.10 2.3.4 2.4.1
|
|
15
|
+
# Additional context: https://github.com/puma/puma/pull/1345
|
|
16
|
+
def purge_interrupt_queue
|
|
17
|
+
Thread.current.purge_interrupt_queue if Thread.current.respond_to? :purge_interrupt_queue
|
|
18
|
+
end
|
|
19
|
+
|
|
13
20
|
# Unescapes a URI escaped string with +encoding+. +encoding+ will be the
|
|
14
21
|
# target encoding of the string returned, and it defaults to UTF-8
|
|
15
22
|
if defined?(::Encoding)
|
data/lib/puma.rb
CHANGED
|
File without changes
|
data/lib/rack/handler/puma.rb
CHANGED
|
File without changes
|
data/tools/Dockerfile
CHANGED
data/tools/trickletest.rb
CHANGED
|
File without changes
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: puma
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 5.
|
|
4
|
+
version: 5.6.0
|
|
5
5
|
platform: java
|
|
6
6
|
authors:
|
|
7
7
|
- Evan Phoenix
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 1980-01-01 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -24,9 +24,9 @@ dependencies:
|
|
|
24
24
|
- - "~>"
|
|
25
25
|
- !ruby/object:Gem::Version
|
|
26
26
|
version: '2.0'
|
|
27
|
-
description: Puma is a simple, fast, threaded, and highly
|
|
27
|
+
description: Puma is a simple, fast, threaded, and highly parallel HTTP 1.1 server
|
|
28
28
|
for Ruby/Rack applications. Puma is intended for use in both development and production
|
|
29
|
-
environments. It's great for highly
|
|
29
|
+
environments. It's great for highly parallel Ruby implementations such as Rubinius
|
|
30
30
|
and JRuby as well as as providing process worker support to support CRuby well.
|
|
31
31
|
email:
|
|
32
32
|
- evan@phx.io
|
|
@@ -140,9 +140,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
140
140
|
- !ruby/object:Gem::Version
|
|
141
141
|
version: '0'
|
|
142
142
|
requirements: []
|
|
143
|
-
rubygems_version: 3.
|
|
143
|
+
rubygems_version: 3.2.29
|
|
144
144
|
signing_key:
|
|
145
145
|
specification_version: 4
|
|
146
|
-
summary: Puma is a simple, fast, threaded, and highly
|
|
146
|
+
summary: Puma is a simple, fast, threaded, and highly parallel HTTP 1.1 server for
|
|
147
147
|
Ruby/Rack applications
|
|
148
148
|
test_files: []
|