puma 3.12.1 → 4.1.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of puma might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/History.md +75 -5
- data/README.md +90 -33
- data/docs/architecture.md +1 -0
- data/docs/deployment.md +24 -4
- data/docs/restart.md +4 -2
- data/docs/systemd.md +27 -9
- data/ext/puma_http11/PumaHttp11Service.java +2 -0
- data/ext/puma_http11/extconf.rb +8 -0
- data/ext/puma_http11/mini_ssl.c +78 -8
- data/ext/puma_http11/org/jruby/puma/IOBuffer.java +72 -0
- data/ext/puma_http11/org/jruby/puma/MiniSSL.java +15 -4
- data/lib/puma.rb +2 -0
- data/lib/puma/accept_nonblock.rb +2 -0
- data/lib/puma/app/status.rb +7 -2
- data/lib/puma/binder.rb +11 -1
- data/lib/puma/client.rb +64 -30
- data/lib/puma/cluster.rb +44 -17
- data/lib/puma/configuration.rb +4 -3
- data/lib/puma/const.rb +9 -2
- data/lib/puma/control_cli.rb +10 -2
- data/lib/puma/dsl.rb +280 -74
- data/lib/puma/events.rb +6 -3
- data/lib/puma/io_buffer.rb +1 -6
- data/lib/puma/launcher.rb +15 -14
- data/lib/puma/minissl.rb +35 -17
- data/lib/puma/plugin/tmp_restart.rb +2 -0
- data/lib/puma/rack/builder.rb +2 -0
- data/lib/puma/rack/urlmap.rb +2 -0
- data/lib/puma/rack_default.rb +2 -0
- data/lib/puma/reactor.rb +104 -53
- data/lib/puma/runner.rb +2 -1
- data/lib/puma/server.rb +44 -36
- data/lib/puma/single.rb +3 -3
- data/lib/puma/thread_pool.rb +5 -1
- data/lib/puma/util.rb +1 -6
- data/lib/rack/handler/puma.rb +3 -1
- data/tools/jungle/init.d/puma +6 -6
- metadata +22 -11
- data/lib/puma/compat.rb +0 -14
- data/lib/puma/java_io_buffer.rb +0 -47
- data/lib/puma/rack/backports/uri/common_193.rb +0 -33
data/lib/puma/runner.rb
CHANGED
@@ -14,6 +14,7 @@ module Puma
|
|
14
14
|
@options = cli.options
|
15
15
|
@app = nil
|
16
16
|
@control = nil
|
17
|
+
@started_at = Time.now
|
17
18
|
end
|
18
19
|
|
19
20
|
def daemon?
|
@@ -55,7 +56,7 @@ module Puma
|
|
55
56
|
app = Puma::App::Status.new @launcher
|
56
57
|
|
57
58
|
if token = @options[:control_auth_token]
|
58
|
-
app.auth_token = token unless token.empty?
|
59
|
+
app.auth_token = token unless token.empty? || token == 'none'
|
59
60
|
end
|
60
61
|
|
61
62
|
control = Puma::Server.new app, @launcher.events
|
data/lib/puma/server.rb
CHANGED
@@ -6,7 +6,6 @@ require 'puma/thread_pool'
|
|
6
6
|
require 'puma/const'
|
7
7
|
require 'puma/events'
|
8
8
|
require 'puma/null_io'
|
9
|
-
require 'puma/compat'
|
10
9
|
require 'puma/reactor'
|
11
10
|
require 'puma/client'
|
12
11
|
require 'puma/binder'
|
@@ -16,10 +15,6 @@ require 'puma/util'
|
|
16
15
|
|
17
16
|
require 'puma/puma_http11'
|
18
17
|
|
19
|
-
unless Puma.const_defined? "IOBuffer"
|
20
|
-
require 'puma/io_buffer'
|
21
|
-
end
|
22
|
-
|
23
18
|
require 'socket'
|
24
19
|
|
25
20
|
module Puma
|
@@ -28,7 +23,7 @@ module Puma
|
|
28
23
|
#
|
29
24
|
# This class is used by the `Puma::Single` and `Puma::Cluster` classes
|
30
25
|
# to generate one or more `Puma::Server` instances capable of handling requests.
|
31
|
-
# Each Puma process will contain one `Puma::Server`
|
26
|
+
# Each Puma process will contain one `Puma::Server` instance.
|
32
27
|
#
|
33
28
|
# The `Puma::Server` instance pulls requests from the socket, adds them to a
|
34
29
|
# `Puma::Reactor` where they get eventually passed to a `Puma::ThreadPool`.
|
@@ -79,7 +74,6 @@ module Puma
|
|
79
74
|
@first_data_timeout = options.fetch(:first_data_timeout, FIRST_DATA_TIMEOUT)
|
80
75
|
|
81
76
|
@binder = Binder.new(events)
|
82
|
-
@own_binder = true
|
83
77
|
|
84
78
|
@leak_stack_on_error = true
|
85
79
|
|
@@ -102,7 +96,6 @@ module Puma
|
|
102
96
|
|
103
97
|
def inherit_binder(bind)
|
104
98
|
@binder = bind
|
105
|
-
@own_binder = false
|
106
99
|
end
|
107
100
|
|
108
101
|
def tcp_mode!
|
@@ -270,10 +263,11 @@ module Puma
|
|
270
263
|
Thread.current.purge_interrupt_queue if Thread.current.respond_to? :purge_interrupt_queue
|
271
264
|
end
|
272
265
|
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
266
|
+
# Prevent can't modify frozen IOError (RuntimeError)
|
267
|
+
begin
|
268
|
+
@notify.close
|
269
|
+
rescue IOError
|
270
|
+
# no biggy
|
277
271
|
end
|
278
272
|
end
|
279
273
|
|
@@ -398,7 +392,10 @@ module Puma
|
|
398
392
|
end
|
399
393
|
|
400
394
|
pool << client
|
401
|
-
pool.wait_until_not_full
|
395
|
+
busy_threads = pool.wait_until_not_full
|
396
|
+
if busy_threads == 0
|
397
|
+
@options[:out_of_band].each(&:call) if @options[:out_of_band]
|
398
|
+
end
|
402
399
|
end
|
403
400
|
rescue SystemCallError
|
404
401
|
# nothing
|
@@ -430,10 +427,6 @@ module Puma
|
|
430
427
|
ensure
|
431
428
|
@check.close
|
432
429
|
@notify.close
|
433
|
-
|
434
|
-
if @status != :restart and @own_binder
|
435
|
-
@binder.close
|
436
|
-
end
|
437
430
|
end
|
438
431
|
|
439
432
|
@events.fire :state, :done
|
@@ -595,19 +588,26 @@ module Puma
|
|
595
588
|
end
|
596
589
|
|
597
590
|
def default_server_port(env)
|
598
|
-
|
599
|
-
|
591
|
+
if ['on', HTTPS].include?(env[HTTPS_KEY]) || env[HTTP_X_FORWARDED_PROTO].to_s[0...5] == HTTPS || env[HTTP_X_FORWARDED_SCHEME] == HTTPS || env[HTTP_X_FORWARDED_SSL] == "on"
|
592
|
+
PORT_443
|
593
|
+
else
|
594
|
+
PORT_80
|
595
|
+
end
|
600
596
|
end
|
601
597
|
|
602
|
-
#
|
603
|
-
#
|
604
|
-
# the rack app. Then construct the response and write it back to
|
605
|
-
# +client+
|
598
|
+
# Takes the request +req+, invokes the Rack application to construct
|
599
|
+
# the response and writes it back to +req.io+.
|
606
600
|
#
|
607
|
-
# +
|
608
|
-
#
|
609
|
-
# it up again.
|
601
|
+
# The second parameter +lines+ is a IO-like object unique to this thread.
|
602
|
+
# This is normally an instance of Puma::IOBuffer.
|
610
603
|
#
|
604
|
+
# It'll return +false+ when the connection is closed, this doesn't mean
|
605
|
+
# that the response wasn't successful.
|
606
|
+
#
|
607
|
+
# It'll return +:async+ if the connection remains open but will be handled
|
608
|
+
# elsewhere, i.e. the connection has been hijacked by the Rack application.
|
609
|
+
#
|
610
|
+
# Finally, it'll return +true+ on keep-alive connections.
|
611
611
|
def handle_request(req, lines)
|
612
612
|
env = req.env
|
613
613
|
client = req.io
|
@@ -630,23 +630,27 @@ module Puma
|
|
630
630
|
head = env[REQUEST_METHOD] == HEAD
|
631
631
|
|
632
632
|
env[RACK_INPUT] = body
|
633
|
-
env[RACK_URL_SCHEME] =
|
633
|
+
env[RACK_URL_SCHEME] = default_server_port(env) == PORT_443 ? HTTPS : HTTP
|
634
634
|
|
635
635
|
if @early_hints
|
636
636
|
env[EARLY_HINTS] = lambda { |headers|
|
637
|
-
|
637
|
+
begin
|
638
|
+
fast_write client, "HTTP/1.1 103 Early Hints\r\n".freeze
|
638
639
|
|
639
|
-
|
640
|
-
|
641
|
-
|
642
|
-
|
640
|
+
headers.each_pair do |k, vs|
|
641
|
+
if vs.respond_to?(:to_s) && !vs.to_s.empty?
|
642
|
+
vs.to_s.split(NEWLINE).each do |v|
|
643
|
+
fast_write client, "#{k}: #{v}\r\n"
|
644
|
+
end
|
645
|
+
else
|
646
|
+
fast_write client, "#{k}: #{vs}\r\n"
|
643
647
|
end
|
644
|
-
else
|
645
|
-
fast_write client, "#{k}: #{vs}\r\n"
|
646
648
|
end
|
647
|
-
end
|
648
649
|
|
649
|
-
|
650
|
+
fast_write client, "\r\n".freeze
|
651
|
+
rescue ConnectionError
|
652
|
+
# noop, if we lost the socket we just won't send the early hints
|
653
|
+
end
|
650
654
|
}
|
651
655
|
end
|
652
656
|
|
@@ -942,6 +946,10 @@ module Puma
|
|
942
946
|
@events.debug "Drained #{count} additional connections."
|
943
947
|
end
|
944
948
|
|
949
|
+
if @status != :restart
|
950
|
+
@binder.close
|
951
|
+
end
|
952
|
+
|
945
953
|
if @thread_pool
|
946
954
|
if timeout = @options[:force_shutdown_after]
|
947
955
|
@thread_pool.shutdown timeout.to_i
|
data/lib/puma/single.rb
CHANGED
@@ -18,7 +18,7 @@ module Puma
|
|
18
18
|
r = @server.running || 0
|
19
19
|
t = @server.pool_capacity || 0
|
20
20
|
m = @server.max_threads || 0
|
21
|
-
%Q!{ "backlog": #{b}, "running": #{r}, "pool_capacity": #{t}, "max_threads": #{m} }!
|
21
|
+
%Q!{ "started_at": "#{@started_at.utc.iso8601}", "backlog": #{b}, "running": #{r}, "pool_capacity": #{t}, "max_threads": #{m} }!
|
22
22
|
end
|
23
23
|
|
24
24
|
def restart
|
@@ -26,7 +26,7 @@ module Puma
|
|
26
26
|
end
|
27
27
|
|
28
28
|
def stop
|
29
|
-
@server.stop
|
29
|
+
@server.stop(false) if @server
|
30
30
|
end
|
31
31
|
|
32
32
|
def halt
|
@@ -36,7 +36,7 @@ module Puma
|
|
36
36
|
def stop_blocked
|
37
37
|
log "- Gracefully stopping, waiting for requests to finish"
|
38
38
|
@control.stop(true) if @control
|
39
|
-
@server.stop(true)
|
39
|
+
@server.stop(true) if @server
|
40
40
|
end
|
41
41
|
|
42
42
|
def jruby_daemon?
|
data/lib/puma/thread_pool.rb
CHANGED
@@ -194,6 +194,9 @@ module Puma
|
|
194
194
|
# method would not block and another request would be added into the reactor
|
195
195
|
# by the server. This would continue until a fully bufferend request
|
196
196
|
# makes it through the reactor and can then be processed by the thread pool.
|
197
|
+
#
|
198
|
+
# Returns the current number of busy threads, or +nil+ if shutting down.
|
199
|
+
#
|
197
200
|
def wait_until_not_full
|
198
201
|
@mutex.synchronize do
|
199
202
|
while true
|
@@ -203,7 +206,8 @@ module Puma
|
|
203
206
|
# is work queued that cannot be handled by waiting
|
204
207
|
# threads, then accept more work until we would
|
205
208
|
# spin up the max number of threads.
|
206
|
-
|
209
|
+
busy_threads = @spawned - @waiting + @todo.size
|
210
|
+
return busy_threads if @max > busy_threads
|
207
211
|
|
208
212
|
@not_full.wait @mutex
|
209
213
|
end
|
data/lib/puma/util.rb
CHANGED
@@ -1,11 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
-
major, minor, patch = RUBY_VERSION.split('.').map { |v| v.to_i }
|
3
2
|
|
4
|
-
|
5
|
-
require 'puma/rack/backports/uri/common_193'
|
6
|
-
else
|
7
|
-
require 'uri/common'
|
8
|
-
end
|
3
|
+
require 'uri/common'
|
9
4
|
|
10
5
|
module Puma
|
11
6
|
module Util
|
data/lib/rack/handler/puma.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'rack/handler'
|
2
4
|
|
3
5
|
module Rack
|
@@ -86,7 +88,7 @@ module Rack
|
|
86
88
|
"Verbose" => "Don't report each request (default: false)"
|
87
89
|
}
|
88
90
|
end
|
89
|
-
|
91
|
+
|
90
92
|
def self.set_host_port_to_config(host, port, config)
|
91
93
|
config.clear_binds! if host || port
|
92
94
|
|
data/tools/jungle/init.d/puma
CHANGED
@@ -47,11 +47,11 @@ do_start_one() {
|
|
47
47
|
PIDFILE=$1/tmp/puma/pid
|
48
48
|
if [ -e $PIDFILE ]; then
|
49
49
|
PID=`cat $PIDFILE`
|
50
|
-
# If the puma
|
50
|
+
# If the puma is running, restart it, otherwise run it.
|
51
51
|
if ps -p $PID > /dev/null; then
|
52
|
-
do_start_one_do $1
|
53
|
-
else
|
54
52
|
do_restart_one $1
|
53
|
+
else
|
54
|
+
do_start_one_do $1
|
55
55
|
fi
|
56
56
|
else
|
57
57
|
do_start_one_do $1
|
@@ -106,8 +106,6 @@ do_stop_one() {
|
|
106
106
|
if [ -e $PIDFILE ]; then
|
107
107
|
PID=`cat $PIDFILE`
|
108
108
|
if ps -p $PID > /dev/null; then
|
109
|
-
log_daemon_msg "---> Puma $1 isn't running."
|
110
|
-
else
|
111
109
|
log_daemon_msg "---> About to kill PID `cat $PIDFILE`"
|
112
110
|
if [ "$USE_LOCAL_BUNDLE" -eq 1 ]; then
|
113
111
|
cd $1 && bundle exec pumactl --state $STATEFILE stop
|
@@ -116,6 +114,8 @@ do_stop_one() {
|
|
116
114
|
fi
|
117
115
|
# Many daemons don't delete their pidfiles when they exit.
|
118
116
|
rm -f $PIDFILE $STATEFILE
|
117
|
+
else
|
118
|
+
log_daemon_msg "---> Puma $1 isn't running."
|
119
119
|
fi
|
120
120
|
else
|
121
121
|
log_daemon_msg "---> No puma here..."
|
@@ -398,7 +398,7 @@ case "$1" in
|
|
398
398
|
;;
|
399
399
|
remove)
|
400
400
|
if [ "$#" -lt 2 ]; then
|
401
|
-
echo "Please,
|
401
|
+
echo "Please, specify the app's directory to remove."
|
402
402
|
exit 1
|
403
403
|
else
|
404
404
|
do_remove $2
|
metadata
CHANGED
@@ -1,15 +1,29 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: puma
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 4.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Evan Phoenix
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-
|
12
|
-
dependencies:
|
11
|
+
date: 2019-08-08 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: nio4r
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '2.0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '2.0'
|
13
27
|
description: Puma is a simple, fast, threaded, and highly concurrent HTTP 1.1 server
|
14
28
|
for Ruby/Rack applications. Puma is intended for use in both development and production
|
15
29
|
environments. It's great for highly concurrent Ruby implementations such as Rubinius
|
@@ -51,6 +65,7 @@ files:
|
|
51
65
|
- ext/puma_http11/mini_ssl.c
|
52
66
|
- ext/puma_http11/org/jruby/puma/Http11.java
|
53
67
|
- ext/puma_http11/org/jruby/puma/Http11Parser.java
|
68
|
+
- ext/puma_http11/org/jruby/puma/IOBuffer.java
|
54
69
|
- ext/puma_http11/org/jruby/puma/MiniSSL.java
|
55
70
|
- ext/puma_http11/puma_http11.c
|
56
71
|
- lib/puma.rb
|
@@ -61,7 +76,6 @@ files:
|
|
61
76
|
- lib/puma/client.rb
|
62
77
|
- lib/puma/cluster.rb
|
63
78
|
- lib/puma/commonlogger.rb
|
64
|
-
- lib/puma/compat.rb
|
65
79
|
- lib/puma/configuration.rb
|
66
80
|
- lib/puma/const.rb
|
67
81
|
- lib/puma/control_cli.rb
|
@@ -72,14 +86,12 @@ files:
|
|
72
86
|
- lib/puma/dsl.rb
|
73
87
|
- lib/puma/events.rb
|
74
88
|
- lib/puma/io_buffer.rb
|
75
|
-
- lib/puma/java_io_buffer.rb
|
76
89
|
- lib/puma/jruby_restart.rb
|
77
90
|
- lib/puma/launcher.rb
|
78
91
|
- lib/puma/minissl.rb
|
79
92
|
- lib/puma/null_io.rb
|
80
93
|
- lib/puma/plugin.rb
|
81
94
|
- lib/puma/plugin/tmp_restart.rb
|
82
|
-
- lib/puma/rack/backports/uri/common_193.rb
|
83
95
|
- lib/puma/rack/builder.rb
|
84
96
|
- lib/puma/rack/urlmap.rb
|
85
97
|
- lib/puma/rack_default.rb
|
@@ -108,7 +120,7 @@ licenses:
|
|
108
120
|
- BSD-3-Clause
|
109
121
|
metadata:
|
110
122
|
msys2_mingw_dependencies: openssl
|
111
|
-
post_install_message:
|
123
|
+
post_install_message:
|
112
124
|
rdoc_options: []
|
113
125
|
require_paths:
|
114
126
|
- lib
|
@@ -123,9 +135,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
123
135
|
- !ruby/object:Gem::Version
|
124
136
|
version: '0'
|
125
137
|
requirements: []
|
126
|
-
|
127
|
-
|
128
|
-
signing_key:
|
138
|
+
rubygems_version: 3.0.3
|
139
|
+
signing_key:
|
129
140
|
specification_version: 4
|
130
141
|
summary: Puma is a simple, fast, threaded, and highly concurrent HTTP 1.1 server for
|
131
142
|
Ruby/Rack applications
|
data/lib/puma/compat.rb
DELETED
@@ -1,14 +0,0 @@
|
|
1
|
-
# Provides code to work properly on 1.8 and 1.9
|
2
|
-
|
3
|
-
class String
|
4
|
-
unless method_defined? :bytesize
|
5
|
-
alias_method :bytesize, :size
|
6
|
-
end
|
7
|
-
|
8
|
-
unless method_defined? :byteslice
|
9
|
-
def byteslice(*arg)
|
10
|
-
enc = self.encoding
|
11
|
-
self.dup.force_encoding(Encoding::ASCII_8BIT).slice(*arg).force_encoding(enc)
|
12
|
-
end
|
13
|
-
end
|
14
|
-
end
|
data/lib/puma/java_io_buffer.rb
DELETED
@@ -1,47 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'java'
|
4
|
-
|
5
|
-
# Conservative native JRuby/Java implementation of IOBuffer
|
6
|
-
# backed by a ByteArrayOutputStream and conversion between
|
7
|
-
# Ruby String and Java bytes
|
8
|
-
module Puma
|
9
|
-
class JavaIOBuffer < java.io.ByteArrayOutputStream
|
10
|
-
field_reader :buf
|
11
|
-
end
|
12
|
-
|
13
|
-
class IOBuffer
|
14
|
-
BUF_DEFAULT_SIZE = 4096
|
15
|
-
|
16
|
-
def initialize
|
17
|
-
@buf = JavaIOBuffer.new(BUF_DEFAULT_SIZE)
|
18
|
-
end
|
19
|
-
|
20
|
-
def reset
|
21
|
-
@buf.reset
|
22
|
-
end
|
23
|
-
|
24
|
-
def <<(str)
|
25
|
-
bytes = str.to_java_bytes
|
26
|
-
@buf.write(bytes, 0, bytes.length)
|
27
|
-
end
|
28
|
-
|
29
|
-
def append(*strs)
|
30
|
-
strs.each { |s| self << s; }
|
31
|
-
end
|
32
|
-
|
33
|
-
def to_s
|
34
|
-
String.from_java_bytes @buf.to_byte_array
|
35
|
-
end
|
36
|
-
|
37
|
-
alias_method :to_str, :to_s
|
38
|
-
|
39
|
-
def used
|
40
|
-
@buf.size
|
41
|
-
end
|
42
|
-
|
43
|
-
def capacity
|
44
|
-
@buf.buf.length
|
45
|
-
end
|
46
|
-
end
|
47
|
-
end
|