puma 6.0.0 → 6.2.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 +88 -5
- data/README.md +15 -3
- data/docs/nginx.md +1 -1
- data/docs/systemd.md +1 -2
- data/lib/puma/binder.rb +4 -3
- data/lib/puma/cli.rb +1 -1
- data/lib/puma/client.rb +32 -4
- data/lib/puma/cluster/worker.rb +5 -0
- data/lib/puma/cluster.rb +5 -5
- data/lib/puma/commonlogger.rb +21 -14
- data/lib/puma/configuration.rb +2 -0
- data/lib/puma/const.rb +76 -84
- data/lib/puma/detect.rb +2 -0
- data/lib/puma/dsl.rb +62 -2
- data/lib/puma/error_logger.rb +2 -1
- data/lib/puma/io_buffer.rb +10 -0
- data/lib/puma/launcher.rb +9 -22
- data/lib/puma/log_writer.rb +13 -3
- data/lib/puma/plugin/systemd.rb +90 -0
- data/lib/puma/rack_default.rb +18 -3
- data/lib/puma/reactor.rb +1 -1
- data/lib/puma/request.rb +170 -119
- data/lib/puma/runner.rb +11 -0
- data/lib/puma/sd_notify.rb +149 -0
- data/lib/puma/server.rb +6 -7
- data/lib/puma/single.rb +3 -1
- data/lib/puma/thread_pool.rb +1 -4
- data/lib/puma.rb +1 -3
- data/lib/rack/handler/puma.rb +117 -94
- metadata +4 -3
- data/lib/puma/systemd.rb +0 -47
data/lib/puma/server.rb
CHANGED
@@ -11,7 +11,6 @@ require_relative 'reactor'
|
|
11
11
|
require_relative 'client'
|
12
12
|
require_relative 'binder'
|
13
13
|
require_relative 'util'
|
14
|
-
require_relative 'io_buffer'
|
15
14
|
require_relative 'request'
|
16
15
|
|
17
16
|
require 'socket'
|
@@ -96,6 +95,7 @@ module Puma
|
|
96
95
|
@queue_requests = @options[:queue_requests]
|
97
96
|
@max_fast_inline = @options[:max_fast_inline]
|
98
97
|
@io_selector_backend = @options[:io_selector_backend]
|
98
|
+
@http_content_length_limit = @options[:http_content_length_limit]
|
99
99
|
|
100
100
|
temp = !!(@options[:environment] =~ /\A(development|test)\z/)
|
101
101
|
@leak_stack_on_error = @options[:environment] ? temp : true
|
@@ -230,7 +230,7 @@ module Puma
|
|
230
230
|
|
231
231
|
@status = :run
|
232
232
|
|
233
|
-
@thread_pool = ThreadPool.new(thread_name, @options) { |
|
233
|
+
@thread_pool = ThreadPool.new(thread_name, @options) { |client| process_client client }
|
234
234
|
|
235
235
|
if @queue_requests
|
236
236
|
@reactor = Reactor.new(@io_selector_backend) { |c| reactor_wakeup c }
|
@@ -335,6 +335,7 @@ module Puma
|
|
335
335
|
drain += 1 if shutting_down?
|
336
336
|
pool << Client.new(io, @binder.env(sock)).tap { |c|
|
337
337
|
c.listener = sock
|
338
|
+
c.http_content_length_limit = @http_content_length_limit
|
338
339
|
c.send(addr_send_name, addr_value) if addr_value
|
339
340
|
}
|
340
341
|
end
|
@@ -401,7 +402,7 @@ module Puma
|
|
401
402
|
# returning.
|
402
403
|
#
|
403
404
|
# Return true if one or more requests were processed.
|
404
|
-
def process_client(client
|
405
|
+
def process_client(client)
|
405
406
|
# Advertise this server into the thread
|
406
407
|
Thread.current[ThreadLocalKey] = self
|
407
408
|
|
@@ -427,15 +428,13 @@ module Puma
|
|
427
428
|
|
428
429
|
while true
|
429
430
|
@requests_count += 1
|
430
|
-
case handle_request(client,
|
431
|
+
case handle_request(client, requests + 1)
|
431
432
|
when false
|
432
433
|
break
|
433
434
|
when :async
|
434
435
|
close_socket = false
|
435
436
|
break
|
436
437
|
when true
|
437
|
-
buffer.reset
|
438
|
-
|
439
438
|
ThreadPool.clean_thread_locals if clean_thread_locals
|
440
439
|
|
441
440
|
requests += 1
|
@@ -469,7 +468,7 @@ module Puma
|
|
469
468
|
# The ensure tries to close +client+ down
|
470
469
|
requests > 0
|
471
470
|
ensure
|
472
|
-
|
471
|
+
client.io_buffer.reset
|
473
472
|
|
474
473
|
begin
|
475
474
|
client.close if close_socket
|
data/lib/puma/single.rb
CHANGED
@@ -16,7 +16,7 @@ module Puma
|
|
16
16
|
# @!attribute [r] stats
|
17
17
|
def stats
|
18
18
|
{
|
19
|
-
started_at: @started_at
|
19
|
+
started_at: utc_iso8601(@started_at)
|
20
20
|
}.merge(@server.stats).merge(super)
|
21
21
|
end
|
22
22
|
|
@@ -57,6 +57,8 @@ module Puma
|
|
57
57
|
|
58
58
|
@events.fire_on_booted!
|
59
59
|
|
60
|
+
debug_loaded_extensions("Loaded Extensions:") if @log_writer.debug?
|
61
|
+
|
60
62
|
begin
|
61
63
|
server_thread.join
|
62
64
|
rescue Interrupt
|
data/lib/puma/thread_pool.rb
CHANGED
@@ -45,7 +45,6 @@ module Puma
|
|
45
45
|
@min = Integer(options[:min_threads])
|
46
46
|
@max = Integer(options[:max_threads])
|
47
47
|
@block = block
|
48
|
-
@extra = [::Puma::IOBuffer]
|
49
48
|
@out_of_band = options[:out_of_band]
|
50
49
|
@clean_thread_locals = options[:clean_thread_locals]
|
51
50
|
@reaping_time = options[:reaping_time]
|
@@ -112,8 +111,6 @@ module Puma
|
|
112
111
|
not_empty = @not_empty
|
113
112
|
not_full = @not_full
|
114
113
|
|
115
|
-
extra = @extra.map { |i| i.new }
|
116
|
-
|
117
114
|
while true
|
118
115
|
work = nil
|
119
116
|
|
@@ -147,7 +144,7 @@ module Puma
|
|
147
144
|
end
|
148
145
|
|
149
146
|
begin
|
150
|
-
@out_of_band_pending = true if block.call(work
|
147
|
+
@out_of_band_pending = true if block.call(work)
|
151
148
|
rescue Exception => e
|
152
149
|
STDERR.puts "Error reached top of thread-pool: #{e.message} (#{e.class})"
|
153
150
|
end
|
data/lib/puma.rb
CHANGED
@@ -3,8 +3,6 @@
|
|
3
3
|
# Standard libraries
|
4
4
|
require 'socket'
|
5
5
|
require 'tempfile'
|
6
|
-
require 'time'
|
7
|
-
require 'etc'
|
8
6
|
require 'uri'
|
9
7
|
require 'stringio'
|
10
8
|
|
@@ -28,7 +26,7 @@ module Puma
|
|
28
26
|
# not in minissl.rb
|
29
27
|
HAS_SSL = const_defined?(:MiniSSL, false) && MiniSSL.const_defined?(:Engine, false)
|
30
28
|
|
31
|
-
HAS_UNIX_SOCKET = Object.const_defined?
|
29
|
+
HAS_UNIX_SOCKET = Object.const_defined?(:UNIXSocket) && !IS_WINDOWS
|
32
30
|
|
33
31
|
if HAS_SSL
|
34
32
|
require_relative 'puma/minissl'
|
data/lib/rack/handler/puma.rb
CHANGED
@@ -1,114 +1,137 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
module
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
(options.keys - user_supplied_options).each do |k|
|
28
|
-
default_options[k] = options.delete(k)
|
29
|
-
end
|
3
|
+
# This module is used as an 'include' file in code at bottom of file
|
4
|
+
module Puma
|
5
|
+
module RackHandler
|
6
|
+
DEFAULT_OPTIONS = {
|
7
|
+
:Verbose => false,
|
8
|
+
:Silent => false
|
9
|
+
}
|
10
|
+
|
11
|
+
def config(app, options = {})
|
12
|
+
require_relative '../../puma'
|
13
|
+
require_relative '../../puma/configuration'
|
14
|
+
require_relative '../../puma/log_writer'
|
15
|
+
require_relative '../../puma/launcher'
|
16
|
+
|
17
|
+
default_options = DEFAULT_OPTIONS.dup
|
18
|
+
|
19
|
+
# Libraries pass in values such as :Port and there is no way to determine
|
20
|
+
# if it is a default provided by the library or a special value provided
|
21
|
+
# by the user. A special key `user_supplied_options` can be passed. This
|
22
|
+
# contains an array of all explicitly defined user options. We then
|
23
|
+
# know that all other values are defaults
|
24
|
+
if user_supplied_options = options.delete(:user_supplied_options)
|
25
|
+
(options.keys - user_supplied_options).each do |k|
|
26
|
+
default_options[k] = options.delete(k)
|
30
27
|
end
|
28
|
+
end
|
29
|
+
|
30
|
+
@events = options[:events] || ::Puma::Events.new
|
31
31
|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
end
|
37
|
-
|
38
|
-
if options[:environment]
|
39
|
-
user_config.environment options[:environment]
|
40
|
-
end
|
41
|
-
|
42
|
-
if options[:Threads]
|
43
|
-
min, max = options.delete(:Threads).split(':', 2)
|
44
|
-
user_config.threads min, max
|
45
|
-
end
|
46
|
-
|
47
|
-
if options[:Host] || options[:Port]
|
48
|
-
host = options[:Host] || default_options[:Host]
|
49
|
-
port = options[:Port] || default_options[:Port]
|
50
|
-
self.set_host_port_to_config(host, port, user_config)
|
51
|
-
end
|
52
|
-
|
53
|
-
if default_options[:Host]
|
54
|
-
file_config.set_default_host(default_options[:Host])
|
55
|
-
end
|
56
|
-
self.set_host_port_to_config(default_options[:Host], default_options[:Port], default_config)
|
57
|
-
|
58
|
-
user_config.app app
|
32
|
+
conf = ::Puma::Configuration.new(options, default_options.merge({events: @events})) do |user_config, file_config, default_config|
|
33
|
+
if options.delete(:Verbose)
|
34
|
+
require 'rack/common_logger'
|
35
|
+
app = Rack::CommonLogger.new(app, STDOUT)
|
59
36
|
end
|
60
|
-
conf
|
61
|
-
end
|
62
37
|
|
63
|
-
|
64
|
-
|
38
|
+
if options[:environment]
|
39
|
+
user_config.environment options[:environment]
|
40
|
+
end
|
65
41
|
|
66
|
-
|
42
|
+
if options[:Threads]
|
43
|
+
min, max = options.delete(:Threads).split(':', 2)
|
44
|
+
user_config.threads min, max
|
45
|
+
end
|
67
46
|
|
68
|
-
|
47
|
+
if options[:Host] || options[:Port]
|
48
|
+
host = options[:Host] || default_options[:Host]
|
49
|
+
port = options[:Port] || default_options[:Port]
|
50
|
+
self.set_host_port_to_config(host, port, user_config)
|
51
|
+
end
|
69
52
|
|
70
|
-
|
71
|
-
|
72
|
-
launcher.run
|
73
|
-
rescue Interrupt
|
74
|
-
puts "* Gracefully stopping, waiting for requests to finish"
|
75
|
-
launcher.stop
|
76
|
-
puts "* Goodbye!"
|
53
|
+
if default_options[:Host]
|
54
|
+
file_config.set_default_host(default_options[:Host])
|
77
55
|
end
|
56
|
+
self.set_host_port_to_config(default_options[:Host], default_options[:Port], default_config)
|
57
|
+
|
58
|
+
user_config.app app
|
78
59
|
end
|
60
|
+
conf
|
61
|
+
end
|
62
|
+
|
63
|
+
def run(app, **options)
|
64
|
+
conf = self.config(app, options)
|
65
|
+
|
66
|
+
log_writer = options.delete(:Silent) ? ::Puma::LogWriter.strings : ::Puma::LogWriter.stdio
|
79
67
|
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
68
|
+
launcher = ::Puma::Launcher.new(conf, :log_writer => log_writer, events: @events)
|
69
|
+
|
70
|
+
yield launcher if block_given?
|
71
|
+
begin
|
72
|
+
launcher.run
|
73
|
+
rescue Interrupt
|
74
|
+
puts "* Gracefully stopping, waiting for requests to finish"
|
75
|
+
launcher.stop
|
76
|
+
puts "* Goodbye!"
|
87
77
|
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def valid_options
|
81
|
+
{
|
82
|
+
"Host=HOST" => "Hostname to listen on (default: localhost)",
|
83
|
+
"Port=PORT" => "Port to listen on (default: 8080)",
|
84
|
+
"Threads=MIN:MAX" => "min:max threads to use (default 0:16)",
|
85
|
+
"Verbose" => "Don't report each request (default: false)"
|
86
|
+
}
|
87
|
+
end
|
88
|
+
|
89
|
+
def set_host_port_to_config(host, port, config)
|
90
|
+
config.clear_binds! if host || port
|
91
|
+
|
92
|
+
if host && (host[0,1] == '.' || host[0,1] == '/')
|
93
|
+
config.bind "unix://#{host}"
|
94
|
+
elsif host && host =~ /^ssl:\/\//
|
95
|
+
uri = URI.parse(host)
|
96
|
+
uri.port ||= port || ::Puma::Configuration::DEFAULTS[:tcp_port]
|
97
|
+
config.bind uri.to_s
|
98
|
+
else
|
88
99
|
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
uri.port ||= port || ::Puma::Configuration::DEFAULTS[:tcp_port]
|
97
|
-
config.bind uri.to_s
|
98
|
-
else
|
99
|
-
|
100
|
-
if host
|
101
|
-
port ||= ::Puma::Configuration::DEFAULTS[:tcp_port]
|
102
|
-
end
|
103
|
-
|
104
|
-
if port
|
105
|
-
host ||= ::Puma::Configuration::DEFAULTS[:tcp_host]
|
106
|
-
config.port port, host
|
107
|
-
end
|
100
|
+
if host
|
101
|
+
port ||= ::Puma::Configuration::DEFAULTS[:tcp_port]
|
102
|
+
end
|
103
|
+
|
104
|
+
if port
|
105
|
+
host ||= ::Puma::Configuration::DEFAULTS[:tcp_host]
|
106
|
+
config.port port, host
|
108
107
|
end
|
109
108
|
end
|
110
109
|
end
|
110
|
+
end
|
111
|
+
end
|
111
112
|
|
112
|
-
|
113
|
+
# rackup was removed in Rack 3, it is now a separate gem
|
114
|
+
if Object.const_defined? :Rackup
|
115
|
+
module Rackup
|
116
|
+
module Handler
|
117
|
+
module Puma
|
118
|
+
class << self
|
119
|
+
include ::Puma::RackHandler
|
120
|
+
end
|
121
|
+
end
|
122
|
+
register :puma, Puma
|
123
|
+
end
|
124
|
+
end
|
125
|
+
else
|
126
|
+
do_register = Object.const_defined?(:Rack) && Rack::RELEASE < '3'
|
127
|
+
module Rack
|
128
|
+
module Handler
|
129
|
+
module Puma
|
130
|
+
class << self
|
131
|
+
include ::Puma::RackHandler
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
113
135
|
end
|
136
|
+
::Rack::Handler.register(:puma, ::Rack::Handler::Puma) if do_register
|
114
137
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: puma
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 6.
|
4
|
+
version: 6.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Evan Phoenix
|
@@ -104,6 +104,7 @@ files:
|
|
104
104
|
- lib/puma/minissl/context_builder.rb
|
105
105
|
- lib/puma/null_io.rb
|
106
106
|
- lib/puma/plugin.rb
|
107
|
+
- lib/puma/plugin/systemd.rb
|
107
108
|
- lib/puma/plugin/tmp_restart.rb
|
108
109
|
- lib/puma/rack/builder.rb
|
109
110
|
- lib/puma/rack/urlmap.rb
|
@@ -111,10 +112,10 @@ files:
|
|
111
112
|
- lib/puma/reactor.rb
|
112
113
|
- lib/puma/request.rb
|
113
114
|
- lib/puma/runner.rb
|
115
|
+
- lib/puma/sd_notify.rb
|
114
116
|
- lib/puma/server.rb
|
115
117
|
- lib/puma/single.rb
|
116
118
|
- lib/puma/state_file.rb
|
117
|
-
- lib/puma/systemd.rb
|
118
119
|
- lib/puma/thread_pool.rb
|
119
120
|
- lib/puma/util.rb
|
120
121
|
- lib/rack/handler/puma.rb
|
@@ -144,7 +145,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
144
145
|
- !ruby/object:Gem::Version
|
145
146
|
version: '0'
|
146
147
|
requirements: []
|
147
|
-
rubygems_version: 3.
|
148
|
+
rubygems_version: 3.3.20
|
148
149
|
signing_key:
|
149
150
|
specification_version: 4
|
150
151
|
summary: Puma is a simple, fast, threaded, and highly parallel HTTP 1.1 server for
|
data/lib/puma/systemd.rb
DELETED
@@ -1,47 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'sd_notify'
|
4
|
-
|
5
|
-
module Puma
|
6
|
-
class Systemd
|
7
|
-
def initialize(log_writer, events)
|
8
|
-
@log_writer = log_writer
|
9
|
-
@events = events
|
10
|
-
end
|
11
|
-
|
12
|
-
def hook_events
|
13
|
-
@events.on_booted { SdNotify.ready }
|
14
|
-
@events.on_stopped { SdNotify.stopping }
|
15
|
-
@events.on_restart { SdNotify.reloading }
|
16
|
-
end
|
17
|
-
|
18
|
-
def start_watchdog
|
19
|
-
return unless SdNotify.watchdog?
|
20
|
-
|
21
|
-
ping_f = watchdog_sleep_time
|
22
|
-
|
23
|
-
log "Pinging systemd watchdog every #{ping_f.round(1)} sec"
|
24
|
-
Thread.new do
|
25
|
-
loop do
|
26
|
-
sleep ping_f
|
27
|
-
SdNotify.watchdog
|
28
|
-
end
|
29
|
-
end
|
30
|
-
end
|
31
|
-
|
32
|
-
private
|
33
|
-
|
34
|
-
def watchdog_sleep_time
|
35
|
-
usec = Integer(ENV["WATCHDOG_USEC"])
|
36
|
-
|
37
|
-
sec_f = usec / 1_000_000.0
|
38
|
-
# "It is recommended that a daemon sends a keep-alive notification message
|
39
|
-
# to the service manager every half of the time returned here."
|
40
|
-
sec_f / 2
|
41
|
-
end
|
42
|
-
|
43
|
-
def log(str)
|
44
|
-
@log_writer.log(str)
|
45
|
-
end
|
46
|
-
end
|
47
|
-
end
|