puma 5.5.1-java → 5.6.2-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 +67 -0
- data/LICENSE +0 -0
- data/README.md +5 -0
- data/bin/puma-wild +0 -0
- data/docs/architecture.md +4 -4
- data/docs/compile_options.md +0 -0
- data/docs/deployment.md +0 -0
- 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 +0 -0
- data/docs/rails_dev_mode.md +0 -0
- data/docs/restart.md +0 -0
- data/docs/signals.md +1 -0
- data/docs/stats.md +0 -0
- data/docs/systemd.md +0 -0
- 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 +22 -16
- 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 +19 -5
- data/lib/puma/cli.rb +9 -4
- data/lib/puma/client.rb +1 -1
- data/lib/puma/cluster/worker.rb +5 -5
- data/lib/puma/cluster/worker_handle.rb +4 -0
- data/lib/puma/cluster.rb +29 -11
- data/lib/puma/commonlogger.rb +0 -0
- data/lib/puma/configuration.rb +3 -0
- data/lib/puma/const.rb +2 -5
- data/lib/puma/control_cli.rb +0 -0
- data/lib/puma/detect.rb +8 -2
- data/lib/puma/dsl.rb +85 -8
- 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 +2 -1
- data/lib/puma/minissl/context_builder.rb +8 -6
- data/lib/puma/minissl.rb +18 -2
- 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 +10 -5
- data/lib/puma/runner.rb +3 -2
- data/lib/puma/server.rb +18 -24
- 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 +0 -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 +3 -3
|
@@ -6,6 +6,7 @@ import org.jruby.RubyModule;
|
|
|
6
6
|
import org.jruby.RubyObject;
|
|
7
7
|
import org.jruby.RubyString;
|
|
8
8
|
import org.jruby.anno.JRubyMethod;
|
|
9
|
+
import org.jruby.exceptions.RaiseException;
|
|
9
10
|
import org.jruby.javasupport.JavaEmbedUtils;
|
|
10
11
|
import org.jruby.runtime.Block;
|
|
11
12
|
import org.jruby.runtime.ObjectAllocator;
|
|
@@ -80,11 +81,11 @@ public class MiniSSL extends RubyObject {
|
|
|
80
81
|
/**
|
|
81
82
|
* Writes bytes to the buffer after ensuring there's room
|
|
82
83
|
*/
|
|
83
|
-
|
|
84
|
-
if (buffer.remaining() <
|
|
85
|
-
resize(buffer.limit() +
|
|
84
|
+
private void put(byte[] bytes, final int offset, final int length) {
|
|
85
|
+
if (buffer.remaining() < length) {
|
|
86
|
+
resize(buffer.limit() + length);
|
|
86
87
|
}
|
|
87
|
-
buffer.put(bytes);
|
|
88
|
+
buffer.put(bytes, offset, length);
|
|
88
89
|
}
|
|
89
90
|
|
|
90
91
|
/**
|
|
@@ -115,7 +116,7 @@ public class MiniSSL extends RubyObject {
|
|
|
115
116
|
|
|
116
117
|
buffer.get(bss);
|
|
117
118
|
buffer.clear();
|
|
118
|
-
return new ByteList(bss);
|
|
119
|
+
return new ByteList(bss, false);
|
|
119
120
|
}
|
|
120
121
|
|
|
121
122
|
@Override
|
|
@@ -174,8 +175,6 @@ public class MiniSSL extends RubyObject {
|
|
|
174
175
|
@JRubyMethod
|
|
175
176
|
public IRubyObject initialize(ThreadContext threadContext, IRubyObject miniSSLContext)
|
|
176
177
|
throws KeyStoreException, NoSuchAlgorithmException, KeyManagementException {
|
|
177
|
-
KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
|
|
178
|
-
KeyStore ts = KeyStore.getInstance(KeyStore.getDefaultType());
|
|
179
178
|
|
|
180
179
|
String keystoreFile = miniSSLContext.callMethod(threadContext, "keystore").convertToString().asJavaString();
|
|
181
180
|
KeyManagerFactory kmf = keyManagerFactoryMap.get(keystoreFile);
|
|
@@ -230,14 +229,9 @@ public class MiniSSL extends RubyObject {
|
|
|
230
229
|
|
|
231
230
|
@JRubyMethod
|
|
232
231
|
public IRubyObject inject(IRubyObject arg) {
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
return this;
|
|
237
|
-
} catch (Exception e) {
|
|
238
|
-
e.printStackTrace();
|
|
239
|
-
throw new RuntimeException(e);
|
|
240
|
-
}
|
|
232
|
+
ByteList bytes = arg.convertToString().getByteList();
|
|
233
|
+
inboundNetData.put(bytes.unsafeBytes(), bytes.getBegin(), bytes.getRealSize());
|
|
234
|
+
return this;
|
|
241
235
|
}
|
|
242
236
|
|
|
243
237
|
private enum SSLOperation {
|
|
@@ -297,7 +291,7 @@ public class MiniSSL extends RubyObject {
|
|
|
297
291
|
}
|
|
298
292
|
|
|
299
293
|
@JRubyMethod
|
|
300
|
-
public IRubyObject read()
|
|
294
|
+
public IRubyObject read() {
|
|
301
295
|
try {
|
|
302
296
|
inboundNetData.flip();
|
|
303
297
|
|
|
@@ -342,55 +336,46 @@ public class MiniSSL extends RubyObject {
|
|
|
342
336
|
return getRuntime().getNil();
|
|
343
337
|
}
|
|
344
338
|
|
|
345
|
-
RubyString
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
throw
|
|
339
|
+
return RubyString.newString(getRuntime(), appDataByteList);
|
|
340
|
+
} catch (SSLException e) {
|
|
341
|
+
RaiseException re = getRuntime().newEOFError(e.getMessage());
|
|
342
|
+
re.initCause(e);
|
|
343
|
+
throw re;
|
|
350
344
|
}
|
|
351
345
|
}
|
|
352
346
|
|
|
353
347
|
@JRubyMethod
|
|
354
348
|
public IRubyObject write(IRubyObject arg) {
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
outboundAppData = new MiniSSLBuffer(bls);
|
|
349
|
+
byte[] bls = arg.convertToString().getBytes();
|
|
350
|
+
outboundAppData = new MiniSSLBuffer(bls);
|
|
358
351
|
|
|
359
|
-
|
|
360
|
-
} catch (Exception e) {
|
|
361
|
-
e.printStackTrace();
|
|
362
|
-
throw new RuntimeException(e);
|
|
363
|
-
}
|
|
352
|
+
return getRuntime().newFixnum(bls.length);
|
|
364
353
|
}
|
|
365
354
|
|
|
366
355
|
@JRubyMethod
|
|
367
|
-
public IRubyObject extract()
|
|
356
|
+
public IRubyObject extract(ThreadContext context) {
|
|
368
357
|
try {
|
|
369
358
|
ByteList dataByteList = outboundNetData.asByteList();
|
|
370
359
|
if (dataByteList != null) {
|
|
371
|
-
RubyString
|
|
372
|
-
str.setValue(dataByteList);
|
|
373
|
-
return str;
|
|
360
|
+
return RubyString.newString(context.runtime, dataByteList);
|
|
374
361
|
}
|
|
375
362
|
|
|
376
363
|
if (!outboundAppData.hasRemaining()) {
|
|
377
|
-
return
|
|
364
|
+
return context.nil;
|
|
378
365
|
}
|
|
379
366
|
|
|
380
367
|
outboundNetData.clear();
|
|
381
368
|
doOp(SSLOperation.WRAP, outboundAppData, outboundNetData);
|
|
382
369
|
dataByteList = outboundNetData.asByteList();
|
|
383
370
|
if (dataByteList == null) {
|
|
384
|
-
return
|
|
371
|
+
return context.nil;
|
|
385
372
|
}
|
|
386
373
|
|
|
387
|
-
RubyString
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
e.printStackTrace();
|
|
393
|
-
throw new RuntimeException(e);
|
|
374
|
+
return RubyString.newString(context.runtime, dataByteList);
|
|
375
|
+
} catch (SSLException e) {
|
|
376
|
+
RaiseException ex = context.runtime.newRuntimeError(e.toString());
|
|
377
|
+
ex.initCause(e);
|
|
378
|
+
throw ex;
|
|
394
379
|
}
|
|
395
380
|
}
|
|
396
381
|
|
|
@@ -398,7 +383,7 @@ public class MiniSSL extends RubyObject {
|
|
|
398
383
|
public IRubyObject peercert() throws CertificateEncodingException {
|
|
399
384
|
try {
|
|
400
385
|
return JavaEmbedUtils.javaToRuby(getRuntime(), engine.getSession().getPeerCertificates()[0].getEncoded());
|
|
401
|
-
} catch (SSLPeerUnverifiedException
|
|
386
|
+
} catch (SSLPeerUnverifiedException e) {
|
|
402
387
|
return getRuntime().getNil();
|
|
403
388
|
}
|
|
404
389
|
}
|
data/lib/puma/app/status.rb
CHANGED
|
File without changes
|
data/lib/puma/binder.rb
CHANGED
|
@@ -30,6 +30,7 @@ module Puma
|
|
|
30
30
|
|
|
31
31
|
def initialize(events, conf = Configuration.new)
|
|
32
32
|
@events = events
|
|
33
|
+
@conf = conf
|
|
33
34
|
@listeners = []
|
|
34
35
|
@inherited_fds = {}
|
|
35
36
|
@activated_sockets = {}
|
|
@@ -167,9 +168,9 @@ module Puma
|
|
|
167
168
|
params = Util.parse_query uri.query
|
|
168
169
|
|
|
169
170
|
opt = params.key?('low_latency') && params['low_latency'] != 'false'
|
|
170
|
-
|
|
171
|
+
backlog = params.fetch('backlog', 1024).to_i
|
|
171
172
|
|
|
172
|
-
io = add_tcp_listener uri.host, uri.port, opt,
|
|
173
|
+
io = add_tcp_listener uri.host, uri.port, opt, backlog
|
|
173
174
|
|
|
174
175
|
@ios[ios_len..-1].each do |i|
|
|
175
176
|
addr = loc_addr_str i
|
|
@@ -232,9 +233,21 @@ module Puma
|
|
|
232
233
|
# If key and certs are not defined and localhost gem is required.
|
|
233
234
|
# localhost gem will be used for self signed
|
|
234
235
|
# Load localhost authority if not loaded.
|
|
235
|
-
|
|
236
|
+
if params.values_at('cert', 'key').all? { |v| v.to_s.empty? }
|
|
237
|
+
ctx = localhost_authority && localhost_authority_context
|
|
238
|
+
end
|
|
236
239
|
|
|
237
|
-
ctx ||=
|
|
240
|
+
ctx ||=
|
|
241
|
+
begin
|
|
242
|
+
# Extract cert_pem and key_pem from options[:store] if present
|
|
243
|
+
['cert', 'key'].each do |v|
|
|
244
|
+
if params[v] && params[v].start_with?('store:')
|
|
245
|
+
index = Integer(params.delete(v).split('store:').last)
|
|
246
|
+
params["#{v}_pem"] = @conf.options[:store][index]
|
|
247
|
+
end
|
|
248
|
+
end
|
|
249
|
+
MiniSSL::ContextBuilder.new(params, @events).context
|
|
250
|
+
end
|
|
238
251
|
|
|
239
252
|
if fd = @inherited_fds.delete(str)
|
|
240
253
|
logger.log "* Inherited #{str}"
|
|
@@ -244,7 +257,8 @@ module Puma
|
|
|
244
257
|
logger.log "* Activated #{str}"
|
|
245
258
|
else
|
|
246
259
|
ios_len = @ios.length
|
|
247
|
-
|
|
260
|
+
backlog = params.fetch('backlog', 1024).to_i
|
|
261
|
+
io = add_ssl_listener uri.host, uri.port, ctx, optimize_for_latency = true, backlog
|
|
248
262
|
|
|
249
263
|
@ios[ios_len..-1].each do |i|
|
|
250
264
|
addr = loc_addr_str i
|
data/lib/puma/cli.rb
CHANGED
|
@@ -11,16 +11,17 @@ require 'puma/events'
|
|
|
11
11
|
|
|
12
12
|
module Puma
|
|
13
13
|
class << self
|
|
14
|
-
# The CLI exports
|
|
15
|
-
# apps to pick it up. An app
|
|
16
|
-
#
|
|
17
|
-
#
|
|
14
|
+
# The CLI exports a Puma::Configuration instance here to allow
|
|
15
|
+
# apps to pick it up. An app must load this object conditionally
|
|
16
|
+
# because it is not set if the app is launched via any mechanism
|
|
17
|
+
# other than the CLI class.
|
|
18
18
|
attr_accessor :cli_config
|
|
19
19
|
end
|
|
20
20
|
|
|
21
21
|
# Handles invoke a Puma::Server in a command line style.
|
|
22
22
|
#
|
|
23
23
|
class CLI
|
|
24
|
+
# @deprecated 6.0.0
|
|
24
25
|
KEYS_NOT_TO_PERSIST_IN_STATE = Launcher::KEYS_NOT_TO_PERSIST_IN_STATE
|
|
25
26
|
|
|
26
27
|
# Create a new CLI object using +argv+ as the command line
|
|
@@ -184,6 +185,10 @@ module Puma
|
|
|
184
185
|
user_config.restart_command cmd
|
|
185
186
|
end
|
|
186
187
|
|
|
188
|
+
o.on "-s", "--silent", "Do not log prompt messages other than errors" do
|
|
189
|
+
@events = Events.new NullIO.new, $stderr
|
|
190
|
+
end
|
|
191
|
+
|
|
187
192
|
o.on "-S", "--state PATH", "Where to store the state details" do |arg|
|
|
188
193
|
user_config.state_path arg
|
|
189
194
|
end
|
data/lib/puma/client.rb
CHANGED
data/lib/puma/cluster/worker.rb
CHANGED
|
@@ -33,8 +33,8 @@ module Puma
|
|
|
33
33
|
Signal.trap "SIGINT", "IGNORE"
|
|
34
34
|
Signal.trap "SIGCHLD", "DEFAULT"
|
|
35
35
|
|
|
36
|
-
|
|
37
|
-
Puma.set_thread_name "
|
|
36
|
+
Thread.new do
|
|
37
|
+
Puma.set_thread_name "wrkr check"
|
|
38
38
|
@check_pipe.wait_readable
|
|
39
39
|
log "! Detected parent died, dying"
|
|
40
40
|
exit! 1
|
|
@@ -76,7 +76,7 @@ module Puma
|
|
|
76
76
|
end
|
|
77
77
|
|
|
78
78
|
Thread.new do
|
|
79
|
-
Puma.set_thread_name "
|
|
79
|
+
Puma.set_thread_name "wrkr fork"
|
|
80
80
|
while (idx = @fork_pipe.gets)
|
|
81
81
|
idx = idx.to_i
|
|
82
82
|
if idx == -1 # stop server
|
|
@@ -114,7 +114,7 @@ module Puma
|
|
|
114
114
|
while restart_server.pop
|
|
115
115
|
server_thread = server.run
|
|
116
116
|
stat_thread ||= Thread.new(@worker_write) do |io|
|
|
117
|
-
Puma.set_thread_name "stat
|
|
117
|
+
Puma.set_thread_name "stat pld"
|
|
118
118
|
base_payload = "p#{Process.pid}"
|
|
119
119
|
|
|
120
120
|
while true
|
|
@@ -130,7 +130,7 @@ module Puma
|
|
|
130
130
|
Puma::Util.purge_interrupt_queue
|
|
131
131
|
break
|
|
132
132
|
end
|
|
133
|
-
sleep
|
|
133
|
+
sleep @options[:worker_check_interval]
|
|
134
134
|
end
|
|
135
135
|
end
|
|
136
136
|
server_thread.join
|
data/lib/puma/cluster.rb
CHANGED
|
@@ -108,24 +108,42 @@ module Puma
|
|
|
108
108
|
def cull_workers
|
|
109
109
|
diff = @workers.size - @options[:workers]
|
|
110
110
|
return if diff < 1
|
|
111
|
+
debug "Culling #{diff} workers"
|
|
111
112
|
|
|
112
|
-
|
|
113
|
+
workers = workers_to_cull(diff)
|
|
114
|
+
debug "Workers to cull: #{workers.inspect}"
|
|
113
115
|
|
|
114
|
-
|
|
115
|
-
debug "Workers to cull: #{workers_to_cull.inspect}"
|
|
116
|
-
|
|
117
|
-
workers_to_cull.each do |worker|
|
|
116
|
+
workers.each do |worker|
|
|
118
117
|
log "- Worker #{worker.index} (PID: #{worker.pid}) terminating"
|
|
119
118
|
worker.term
|
|
120
119
|
end
|
|
121
120
|
end
|
|
122
121
|
|
|
122
|
+
def workers_to_cull(diff)
|
|
123
|
+
workers = @workers.sort_by(&:started_at)
|
|
124
|
+
|
|
125
|
+
# In fork_worker mode, worker 0 acts as our master process.
|
|
126
|
+
# We should avoid culling it to preserve copy-on-write memory gains.
|
|
127
|
+
workers.reject! { |w| w.index == 0 } if @options[:fork_worker]
|
|
128
|
+
|
|
129
|
+
workers[cull_start_index(diff), diff]
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
def cull_start_index(diff)
|
|
133
|
+
case @options[:worker_culling_strategy]
|
|
134
|
+
when :oldest
|
|
135
|
+
0
|
|
136
|
+
else # :youngest
|
|
137
|
+
-diff
|
|
138
|
+
end
|
|
139
|
+
end
|
|
140
|
+
|
|
123
141
|
# @!attribute [r] next_worker_index
|
|
124
142
|
def next_worker_index
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
143
|
+
occupied_positions = @workers.map(&:index)
|
|
144
|
+
idx = 0
|
|
145
|
+
idx += 1 until !occupied_positions.include?(idx)
|
|
146
|
+
idx
|
|
129
147
|
end
|
|
130
148
|
|
|
131
149
|
def all_workers_booted?
|
|
@@ -135,7 +153,7 @@ module Puma
|
|
|
135
153
|
def check_workers
|
|
136
154
|
return if @next_check >= Time.now
|
|
137
155
|
|
|
138
|
-
@next_check = Time.now +
|
|
156
|
+
@next_check = Time.now + @options[:worker_check_interval]
|
|
139
157
|
|
|
140
158
|
timeout_workers
|
|
141
159
|
wait_workers
|
|
@@ -440,7 +458,7 @@ module Puma
|
|
|
440
458
|
workers_not_booted -= 1
|
|
441
459
|
when "e"
|
|
442
460
|
# external term, see worker method, Signal.trap "SIGTERM"
|
|
443
|
-
w.
|
|
461
|
+
w.term!
|
|
444
462
|
when "t"
|
|
445
463
|
w.term unless w.term?
|
|
446
464
|
when "p"
|
data/lib/puma/commonlogger.rb
CHANGED
|
File without changes
|
data/lib/puma/configuration.rb
CHANGED
|
@@ -11,6 +11,7 @@ module Puma
|
|
|
11
11
|
|
|
12
12
|
DefaultTCPHost = "0.0.0.0"
|
|
13
13
|
DefaultTCPPort = 9292
|
|
14
|
+
DefaultWorkerCheckInterval = 5
|
|
14
15
|
DefaultWorkerTimeout = 60
|
|
15
16
|
DefaultWorkerShutdownTimeout = 30
|
|
16
17
|
end
|
|
@@ -195,9 +196,11 @@ module Puma
|
|
|
195
196
|
:workers => Integer(ENV['WEB_CONCURRENCY'] || 0),
|
|
196
197
|
:silence_single_worker_warning => false,
|
|
197
198
|
:mode => :http,
|
|
199
|
+
:worker_check_interval => DefaultWorkerCheckInterval,
|
|
198
200
|
:worker_timeout => DefaultWorkerTimeout,
|
|
199
201
|
:worker_boot_timeout => DefaultWorkerTimeout,
|
|
200
202
|
:worker_shutdown_timeout => DefaultWorkerShutdownTimeout,
|
|
203
|
+
:worker_culling_strategy => :youngest,
|
|
201
204
|
:remote_address => :socket,
|
|
202
205
|
:tag => method(:infer_tag),
|
|
203
206
|
:environment => -> { ENV['APP_ENV'] || ENV['RACK_ENV'] || ENV['RAILS_ENV'] || 'development' },
|
data/lib/puma/const.rb
CHANGED
|
@@ -100,8 +100,8 @@ module Puma
|
|
|
100
100
|
# too taxing on performance.
|
|
101
101
|
module Const
|
|
102
102
|
|
|
103
|
-
PUMA_VERSION = VERSION = "5.
|
|
104
|
-
CODE_NAME = "
|
|
103
|
+
PUMA_VERSION = VERSION = "5.6.2".freeze
|
|
104
|
+
CODE_NAME = "Birdie's Version".freeze
|
|
105
105
|
|
|
106
106
|
PUMA_SERVER_STRING = ['puma', PUMA_VERSION, CODE_NAME].join(' ').freeze
|
|
107
107
|
|
|
@@ -235,9 +235,6 @@ module Puma
|
|
|
235
235
|
|
|
236
236
|
EARLY_HINTS = "rack.early_hints".freeze
|
|
237
237
|
|
|
238
|
-
# Minimum interval to checks worker health
|
|
239
|
-
WORKER_CHECK_INTERVAL = 5
|
|
240
|
-
|
|
241
238
|
# Illegal character in the key or value of response header
|
|
242
239
|
DQUOTE = "\"".freeze
|
|
243
240
|
HTTP_HEADER_DELIMITER = Regexp.escape("(),/:;<=>?@[]{}\\").freeze
|
data/lib/puma/control_cli.rb
CHANGED
|
File without changes
|
data/lib/puma/detect.rb
CHANGED
|
@@ -10,8 +10,10 @@ module Puma
|
|
|
10
10
|
|
|
11
11
|
IS_JRUBY = Object.const_defined? :JRUBY_VERSION
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
|
|
13
|
+
IS_OSX = RUBY_PLATFORM.include? 'darwin'
|
|
14
|
+
|
|
15
|
+
IS_WINDOWS = !!(RUBY_PLATFORM =~ /mswin|ming|cygwin/) ||
|
|
16
|
+
IS_JRUBY && RUBY_DESCRIPTION.include?('mswin')
|
|
15
17
|
|
|
16
18
|
# @version 5.2.0
|
|
17
19
|
IS_MRI = (RUBY_ENGINE == 'ruby' || RUBY_ENGINE.nil?)
|
|
@@ -20,6 +22,10 @@ module Puma
|
|
|
20
22
|
IS_JRUBY
|
|
21
23
|
end
|
|
22
24
|
|
|
25
|
+
def self.osx?
|
|
26
|
+
IS_OSX
|
|
27
|
+
end
|
|
28
|
+
|
|
23
29
|
def self.windows?
|
|
24
30
|
IS_WINDOWS
|
|
25
31
|
end
|
data/lib/puma/dsl.rb
CHANGED
|
@@ -48,6 +48,8 @@ module Puma
|
|
|
48
48
|
|
|
49
49
|
ca_additions = "&ca=#{opts[:ca]}" if ['peer', 'force_peer'].include?(verify)
|
|
50
50
|
|
|
51
|
+
backlog_str = opts[:backlog] ? "&backlog=#{Integer(opts[:backlog])}" : ''
|
|
52
|
+
|
|
51
53
|
if defined?(JRUBY_VERSION)
|
|
52
54
|
ssl_cipher_list = opts[:ssl_cipher_list] ?
|
|
53
55
|
"&ssl_cipher_list=#{opts[:ssl_cipher_list]}" : nil
|
|
@@ -55,7 +57,7 @@ module Puma
|
|
|
55
57
|
keystore_additions = "keystore=#{opts[:keystore]}&keystore-pass=#{opts[:keystore_pass]}"
|
|
56
58
|
|
|
57
59
|
"ssl://#{host}:#{port}?#{keystore_additions}#{ssl_cipher_list}" \
|
|
58
|
-
"&verify_mode=#{verify}#{tls_str}#{ca_additions}"
|
|
60
|
+
"&verify_mode=#{verify}#{tls_str}#{ca_additions}#{backlog_str}"
|
|
59
61
|
else
|
|
60
62
|
ssl_cipher_filter = opts[:ssl_cipher_filter] ?
|
|
61
63
|
"&ssl_cipher_filter=#{opts[:ssl_cipher_filter]}" : nil
|
|
@@ -64,7 +66,7 @@ module Puma
|
|
|
64
66
|
"&verification_flags=#{Array(ary).join ','}" : nil
|
|
65
67
|
|
|
66
68
|
"ssl://#{host}:#{port}?cert=#{opts[:cert]}&key=#{opts[:key]}" \
|
|
67
|
-
"#{ssl_cipher_filter}&verify_mode=#{verify}#{tls_str}#{ca_additions}#{v_flags}"
|
|
69
|
+
"#{ssl_cipher_filter}&verify_mode=#{verify}#{tls_str}#{ca_additions}#{v_flags}#{backlog_str}"
|
|
68
70
|
end
|
|
69
71
|
end
|
|
70
72
|
|
|
@@ -191,7 +193,7 @@ module Puma
|
|
|
191
193
|
end
|
|
192
194
|
|
|
193
195
|
# Bind the server to +url+. "tcp://", "unix://" and "ssl://" are the only
|
|
194
|
-
# accepted protocols. Multiple urls can be bound to, calling
|
|
196
|
+
# accepted protocols. Multiple urls can be bound to, calling +bind+ does
|
|
195
197
|
# not overwrite previous bindings.
|
|
196
198
|
#
|
|
197
199
|
# The default is "tcp://0.0.0.0:9292".
|
|
@@ -436,8 +438,15 @@ module Puma
|
|
|
436
438
|
@options[:max_threads] = max
|
|
437
439
|
end
|
|
438
440
|
|
|
439
|
-
# Instead of
|
|
440
|
-
#
|
|
441
|
+
# Instead of using +bind+ and manually constructing a URI like:
|
|
442
|
+
#
|
|
443
|
+
# bind 'ssl://127.0.0.1:9292?key=key_path&cert=cert_path'
|
|
444
|
+
#
|
|
445
|
+
# you can use the this method.
|
|
446
|
+
#
|
|
447
|
+
# When binding on localhost you don't need to specify +cert+ and +key+,
|
|
448
|
+
# Puma will assume you are using the +localhost+ gem and try to load the
|
|
449
|
+
# appropriate files.
|
|
441
450
|
#
|
|
442
451
|
# @example
|
|
443
452
|
# ssl_bind '127.0.0.1', '9292', {
|
|
@@ -447,14 +456,25 @@ module Puma
|
|
|
447
456
|
# verify_mode: verify_mode, # default 'none'
|
|
448
457
|
# verification_flags: flags, # optional, not supported by JRuby
|
|
449
458
|
# }
|
|
450
|
-
#
|
|
459
|
+
#
|
|
460
|
+
# @example Using self-signed certificate with the +localhost+ gem:
|
|
461
|
+
# ssl_bind '127.0.0.1', '9292'
|
|
462
|
+
#
|
|
463
|
+
# @example Alternatively, you can provide +cert_pem+ and +key_pem+:
|
|
464
|
+
# ssl_bind '127.0.0.1', '9292', {
|
|
465
|
+
# cert_pem: File.read(path_to_cert),
|
|
466
|
+
# key_pem: File.read(path_to_key),
|
|
467
|
+
# }
|
|
468
|
+
#
|
|
469
|
+
# @example For JRuby, two keys are required: +keystore+ & +keystore_pass+
|
|
451
470
|
# ssl_bind '127.0.0.1', '9292', {
|
|
452
471
|
# keystore: path_to_keystore,
|
|
453
472
|
# keystore_pass: password,
|
|
454
473
|
# ssl_cipher_list: cipher_list, # optional
|
|
455
474
|
# verify_mode: verify_mode # default 'none'
|
|
456
475
|
# }
|
|
457
|
-
def ssl_bind(host, port, opts)
|
|
476
|
+
def ssl_bind(host, port, opts = {})
|
|
477
|
+
add_pem_values_to_options_store(opts)
|
|
458
478
|
bind self.class.ssl_bind_str(host, port, opts)
|
|
459
479
|
end
|
|
460
480
|
|
|
@@ -727,6 +747,19 @@ module Puma
|
|
|
727
747
|
@options[:tag] = string.to_s
|
|
728
748
|
end
|
|
729
749
|
|
|
750
|
+
# Change the default interval for checking workers.
|
|
751
|
+
#
|
|
752
|
+
# The default value is 5 seconds.
|
|
753
|
+
#
|
|
754
|
+
# @note Cluster mode only.
|
|
755
|
+
# @example
|
|
756
|
+
# worker_check_interval 5
|
|
757
|
+
# @see Puma::Cluster#check_workers
|
|
758
|
+
#
|
|
759
|
+
def worker_check_interval(interval)
|
|
760
|
+
@options[:worker_check_interval] = Integer(interval)
|
|
761
|
+
end
|
|
762
|
+
|
|
730
763
|
# Verifies that all workers have checked in to the master process within
|
|
731
764
|
# the given timeout. If not the worker process will be restarted. This is
|
|
732
765
|
# not a request timeout, it is to protect against a hung or dead process.
|
|
@@ -741,7 +774,7 @@ module Puma
|
|
|
741
774
|
#
|
|
742
775
|
def worker_timeout(timeout)
|
|
743
776
|
timeout = Integer(timeout)
|
|
744
|
-
min =
|
|
777
|
+
min = @options.fetch(:worker_check_interval, Puma::ConfigDefault::DefaultWorkerCheckInterval)
|
|
745
778
|
|
|
746
779
|
if timeout <= min
|
|
747
780
|
raise "The minimum worker_timeout must be greater than the worker reporting interval (#{min})"
|
|
@@ -773,6 +806,30 @@ module Puma
|
|
|
773
806
|
@options[:worker_shutdown_timeout] = Integer(timeout)
|
|
774
807
|
end
|
|
775
808
|
|
|
809
|
+
# Set the strategy for worker culling.
|
|
810
|
+
#
|
|
811
|
+
# There are two possible values:
|
|
812
|
+
#
|
|
813
|
+
# 1. **:youngest** - the youngest workers (i.e. the workers that were
|
|
814
|
+
# the most recently started) will be culled.
|
|
815
|
+
# 2. **:oldest** - the oldest workers (i.e. the workers that were started
|
|
816
|
+
# the longest time ago) will be culled.
|
|
817
|
+
#
|
|
818
|
+
# @note Cluster mode only.
|
|
819
|
+
# @example
|
|
820
|
+
# worker_culling_strategy :oldest
|
|
821
|
+
# @see Puma::Cluster#cull_workers
|
|
822
|
+
#
|
|
823
|
+
def worker_culling_strategy(strategy)
|
|
824
|
+
stategy = strategy.to_sym
|
|
825
|
+
|
|
826
|
+
if ![:youngest, :oldest].include?(strategy)
|
|
827
|
+
raise "Invalid value for worker_culling_strategy - #{stategy}"
|
|
828
|
+
end
|
|
829
|
+
|
|
830
|
+
@options[:worker_culling_strategy] = strategy
|
|
831
|
+
end
|
|
832
|
+
|
|
776
833
|
# When set to true (the default), workers accept all requests
|
|
777
834
|
# and queue them before passing them to the handlers.
|
|
778
835
|
# When set to false, each worker process accepts exactly as
|
|
@@ -927,5 +984,25 @@ module Puma
|
|
|
927
984
|
def mutate_stdout_and_stderr_to_sync_on_write(enabled=true)
|
|
928
985
|
@options[:mutate_stdout_and_stderr_to_sync_on_write] = enabled
|
|
929
986
|
end
|
|
987
|
+
|
|
988
|
+
private
|
|
989
|
+
|
|
990
|
+
# To avoid adding cert_pem and key_pem as URI params, we store them on the
|
|
991
|
+
# options[:store] from where Puma binder knows how to find and extract them.
|
|
992
|
+
def add_pem_values_to_options_store(opts)
|
|
993
|
+
return if defined?(JRUBY_VERSION)
|
|
994
|
+
|
|
995
|
+
@options[:store] ||= []
|
|
996
|
+
|
|
997
|
+
# Store cert_pem and key_pem to options[:store] if present
|
|
998
|
+
[:cert, :key].each do |v|
|
|
999
|
+
opt_key = :"#{v}_pem"
|
|
1000
|
+
if opts[opt_key]
|
|
1001
|
+
index = @options[:store].length
|
|
1002
|
+
@options[:store] << opts[opt_key]
|
|
1003
|
+
opts[v] = "store:#{index}"
|
|
1004
|
+
end
|
|
1005
|
+
end
|
|
1006
|
+
end
|
|
930
1007
|
end
|
|
931
1008
|
end
|
data/lib/puma/error_logger.rb
CHANGED
|
File without changes
|
data/lib/puma/events.rb
CHANGED
|
File without changes
|
data/lib/puma/io_buffer.rb
CHANGED
|
File without changes
|
data/lib/puma/jruby_restart.rb
CHANGED
|
File without changes
|
|
File without changes
|
data/lib/puma/launcher.rb
CHANGED
|
@@ -15,6 +15,7 @@ module Puma
|
|
|
15
15
|
# It is responsible for either launching a cluster of Puma workers or a single
|
|
16
16
|
# puma server.
|
|
17
17
|
class Launcher
|
|
18
|
+
# @deprecated 6.0.0
|
|
18
19
|
KEYS_NOT_TO_PERSIST_IN_STATE = [
|
|
19
20
|
:logger, :lowlevel_error_handler,
|
|
20
21
|
:before_worker_shutdown, :before_worker_boot, :before_worker_fork,
|
|
@@ -73,7 +74,7 @@ module Puma
|
|
|
73
74
|
|
|
74
75
|
generate_restart_data
|
|
75
76
|
|
|
76
|
-
if clustered? && !
|
|
77
|
+
if clustered? && !Puma.forkable?
|
|
77
78
|
unsupported "worker mode not supported on #{RUBY_ENGINE} on this platform"
|
|
78
79
|
end
|
|
79
80
|
|
|
@@ -23,17 +23,19 @@ module Puma
|
|
|
23
23
|
ctx.keystore_pass = params['keystore-pass']
|
|
24
24
|
ctx.ssl_cipher_list = params['ssl_cipher_list'] if params['ssl_cipher_list']
|
|
25
25
|
else
|
|
26
|
-
|
|
27
|
-
events.error "Please specify the SSL key via 'key='"
|
|
26
|
+
if params['key'].nil? && params['key_pem'].nil?
|
|
27
|
+
events.error "Please specify the SSL key via 'key=' or 'key_pem='"
|
|
28
28
|
end
|
|
29
29
|
|
|
30
|
-
ctx.key = params['key']
|
|
30
|
+
ctx.key = params['key'] if params['key']
|
|
31
|
+
ctx.key_pem = params['key_pem'] if params['key_pem']
|
|
31
32
|
|
|
32
|
-
|
|
33
|
-
events.error "Please specify the SSL cert via 'cert='"
|
|
33
|
+
if params['cert'].nil? && params['cert_pem'].nil?
|
|
34
|
+
events.error "Please specify the SSL cert via 'cert=' or 'cert_pem='"
|
|
34
35
|
end
|
|
35
36
|
|
|
36
|
-
ctx.cert = params['cert']
|
|
37
|
+
ctx.cert = params['cert'] if params['cert']
|
|
38
|
+
ctx.cert_pem = params['cert_pem'] if params['cert_pem']
|
|
37
39
|
|
|
38
40
|
if ['peer', 'force_peer'].include?(params['verify_mode'])
|
|
39
41
|
unless params['ca']
|