puma 5.0.0.beta2-java → 5.0.0-java

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 35a07b62e45c13573cba434caa78d336c981104d65448bf2cba63cc7fe87ebe5
4
- data.tar.gz: d05d3e5a89a5dec3f71a133024d596975bb5fb0a8b4e2a8c0342479f061132fc
3
+ metadata.gz: 57175cfb98319685a496220e92303e6c7827421de8569d0c1128b2f7d04d7a2a
4
+ data.tar.gz: 29c2a8c29628ca7732999005bad47ebcf071f1758dbf604a4bfa9ac5c063669d
5
5
  SHA512:
6
- metadata.gz: 18498ab4e516ea2b386a8515c5ced3f2f5572e72f6281c87433f24f69b0ad94b55db2466a8f77df24b611c054353641ecce50b397b9cd698370bf81e3ba66369
7
- data.tar.gz: 82efab2a81aebbd2eb50de04f906bb5f607f83121fe484f31feacd09cd481433d3f008278e8dcaf844a9b8ed3915e5985fa1a11fcf6d4f556eef24c87e9c6b3d
6
+ metadata.gz: 402feb9a877783c892bf9d1c441f7486961061c9de7182965ac50b60bc93de91ccb3e99bae102a3d0f337dd228017c69542d7812edad79515557ea2266ddb3bb
7
+ data.tar.gz: 2499c2971fd885aa8121076f1f4f8079add4eeed8dbb4157ac789747dc68794ef83f98222b8cc645542bfaa51379bee038bff64a514d1b1bfe1df4c7c3078e06
data/History.md CHANGED
@@ -1,6 +1,7 @@
1
1
  ## 5.0.0
2
2
 
3
3
  * Features
4
+ * Allow compiling without OpenSSL and dynamically load files needed for SSL, add 'no ssl' CI (#2305)
4
5
  * EXPERIMENTAL: Add `fork_worker` option and `refork` command for reduced memory usage by forking from a worker process instead of the master process. (#2099)
5
6
  * EXPERIMENTAL: Added `wait_for_less_busy_worker` config. This may reduce latency on MRI through inserting a small delay before re-listening on the socket if worker is busy (#2079).
6
7
  * EXPERIMENTAL: Added `nakayoshi_fork` option. Reduce memory usage in preloaded cluster-mode apps by GCing before fork and compacting, where available. (#2093, #2256)
@@ -58,6 +59,7 @@
58
59
  * Fix recursive `prune_bundler` (#2319).
59
60
  * Ensure that TCP_CORK is usable
60
61
  * Fix corner case when request body is chunked (#2326)
62
+ * Fix filehandle leak in MiniSSL (#2299)
61
63
 
62
64
  * Refactor
63
65
  * Remove unused loader argument from Plugin initializer (#2095)
@@ -70,6 +72,12 @@
70
72
  * Support parallel tests in verbose progress reporting (#2223)
71
73
  * Refactor error handling in server accept loop (#2239)
72
74
 
75
+ ## 4.3.6 / 2020-09-05
76
+
77
+ * Bugfixes
78
+ * Explicitly include ctype.h to fix compilation warning and build error on macOS with Xcode 12 (#2304)
79
+ * Don't require json at boot (#2269)
80
+
73
81
  ## 4.3.4/4.3.5 and 3.12.5/3.12.6 / 2020-05-22
74
82
 
75
83
  Each patchlevel release contains a separate security fix. We recommend simply upgrading to 4.3.5/3.12.6.
data/README.md CHANGED
@@ -5,7 +5,6 @@
5
5
  # Puma: A Ruby Web Server Built For Concurrency
6
6
 
7
7
  [![Actions Build Status](https://github.com/puma/puma/workflows/CI/badge.svg?branch=master)](https://github.com/puma/puma/actions)
8
-
9
8
  [![Code Climate](https://codeclimate.com/github/puma/puma.svg)](https://codeclimate.com/github/puma/puma)
10
9
  [![SemVer](https://api.dependabot.com/badges/compatibility_score?dependency-name=puma&package-manager=bundler&version-scheme=semver)](https://dependabot.com/compatibility-score.html?dependency-name=puma&package-manager=bundler&version-scheme=semver)
11
10
  [![StackOverflow](https://img.shields.io/badge/stackoverflow-Puma-blue.svg)]( https://stackoverflow.com/questions/tagged/puma )
@@ -30,6 +29,14 @@ $ puma
30
29
  Without arguments, puma will look for a rackup (.ru) file in
31
30
  working directory called `config.ru`.
32
31
 
32
+ ## SSL Connection Support
33
+
34
+ Puma will install/compile with support for ssl sockets, assuming OpenSSL
35
+ development files are installed on the system.
36
+
37
+ If the system does not have OpenSSL development files installed, Puma will
38
+ install/compile, but it will not allow ssl connections.
39
+
33
40
  ## Frameworks
34
41
 
35
42
  ### Rails
@@ -38,10 +38,10 @@ Puma cluster responds to these signals:
38
38
  - `TERM` send `TERM` to worker. Worker will attempt to finish then exit.
39
39
  - `USR2` restart workers. This also reloads puma configuration file, if there is one.
40
40
  - `USR1` restart workers in phases, a rolling restart. This will not reload configuration file.
41
- - `HUP` reopen log files defined in stdout_redirect configuration parameter. If there is no stdout_redirect option provided it will behave like `INT`
42
- - `INT` equivalent of sending Ctrl-C to cluster. Will attempt to finish then exit.
41
+ - `HUP ` reopen log files defined in stdout_redirect configuration parameter. If there is no stdout_redirect option provided it will behave like `INT`
42
+ - `INT ` equivalent of sending Ctrl-C to cluster. Will attempt to finish then exit.
43
43
  - `CHLD`
44
- - `URG` refork workers in phases from worker 0, if `fork_workers` option is enabled.
44
+ - `URG ` refork workers in phases from worker 0, if `fork_workers` option is enabled.
45
45
 
46
46
  ## Callbacks order in case of different signals
47
47
 
@@ -463,6 +463,9 @@ VALUE engine_peercert(VALUE self) {
463
463
  return rb_cert_buf;
464
464
  }
465
465
 
466
+ /* @see Puma::MiniSSL::Socket#ssl_version_state
467
+ * @version 5.0.0
468
+ */
466
469
  static VALUE
467
470
  engine_ssl_vers_st(VALUE self) {
468
471
  ms_conn* conn;
@@ -0,0 +1,15 @@
1
+ package puma;
2
+
3
+ import java.io.IOException;
4
+
5
+ import org.jruby.Ruby;
6
+ import org.jruby.runtime.load.BasicLibraryService;
7
+
8
+ import org.jruby.puma.Http11;
9
+
10
+ public class PumaHttp11Service implements BasicLibraryService {
11
+ public boolean basicLoad(final Ruby runtime) throws IOException {
12
+ Http11.createHttp11(runtime);
13
+ return true;
14
+ }
15
+ }
@@ -22,6 +22,7 @@ import javax.net.ssl.SSLException;
22
22
  import javax.net.ssl.SSLPeerUnverifiedException;
23
23
  import javax.net.ssl.SSLSession;
24
24
  import java.io.FileInputStream;
25
+ import java.io.InputStream;
25
26
  import java.io.IOException;
26
27
  import java.nio.Buffer;
27
28
  import java.nio.ByteBuffer;
@@ -32,6 +33,8 @@ import java.security.NoSuchAlgorithmException;
32
33
  import java.security.UnrecoverableKeyException;
33
34
  import java.security.cert.CertificateEncodingException;
34
35
  import java.security.cert.CertificateException;
36
+ import java.util.concurrent.ConcurrentHashMap;
37
+ import java.util.Map;
35
38
 
36
39
  import static javax.net.ssl.SSLEngineResult.Status;
37
40
  import static javax.net.ssl.SSLEngineResult.HandshakeStatus;
@@ -130,10 +133,39 @@ public class MiniSSL extends RubyObject {
130
133
  super(runtime, klass);
131
134
  }
132
135
 
136
+ private static Map<String, KeyManagerFactory> keyManagerFactoryMap = new ConcurrentHashMap<String, KeyManagerFactory>();
137
+ private static Map<String, TrustManagerFactory> trustManagerFactoryMap = new ConcurrentHashMap<String, TrustManagerFactory>();
138
+
133
139
  @JRubyMethod(meta = true)
134
- public static IRubyObject server(ThreadContext context, IRubyObject recv, IRubyObject miniSSLContext) {
135
- RubyClass klass = (RubyClass) recv;
140
+ public static synchronized IRubyObject server(ThreadContext context, IRubyObject recv, IRubyObject miniSSLContext)
141
+ throws KeyStoreException, IOException, CertificateException, NoSuchAlgorithmException, UnrecoverableKeyException {
142
+ // Create the KeyManagerFactory and TrustManagerFactory for this server
143
+ String keystoreFile = miniSSLContext.callMethod(context, "keystore").convertToString().asJavaString();
144
+ char[] password = miniSSLContext.callMethod(context, "keystore_pass").convertToString().asJavaString().toCharArray();
145
+
146
+ KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
147
+ InputStream is = new FileInputStream(keystoreFile);
148
+ try {
149
+ ks.load(is, password);
150
+ } finally {
151
+ is.close();
152
+ }
153
+ KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
154
+ kmf.init(ks, password);
155
+ keyManagerFactoryMap.put(keystoreFile, kmf);
156
+
157
+ KeyStore ts = KeyStore.getInstance(KeyStore.getDefaultType());
158
+ is = new FileInputStream(keystoreFile);
159
+ try {
160
+ ts.load(is, password);
161
+ } finally {
162
+ is.close();
163
+ }
164
+ TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
165
+ tmf.init(ts);
166
+ trustManagerFactoryMap.put(keystoreFile, tmf);
136
167
 
168
+ RubyClass klass = (RubyClass) recv;
137
169
  return klass.newInstance(context,
138
170
  new IRubyObject[] { miniSSLContext },
139
171
  Block.NULL_BLOCK);
@@ -141,20 +173,16 @@ public class MiniSSL extends RubyObject {
141
173
 
142
174
  @JRubyMethod
143
175
  public IRubyObject initialize(ThreadContext threadContext, IRubyObject miniSSLContext)
144
- throws KeyStoreException, IOException, CertificateException, NoSuchAlgorithmException, UnrecoverableKeyException, KeyManagementException {
176
+ throws KeyStoreException, NoSuchAlgorithmException, KeyManagementException {
145
177
  KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
146
178
  KeyStore ts = KeyStore.getInstance(KeyStore.getDefaultType());
147
179
 
148
- char[] password = miniSSLContext.callMethod(threadContext, "keystore_pass").convertToString().asJavaString().toCharArray();
149
180
  String keystoreFile = miniSSLContext.callMethod(threadContext, "keystore").convertToString().asJavaString();
150
- ks.load(new FileInputStream(keystoreFile), password);
151
- ts.load(new FileInputStream(keystoreFile), password);
152
-
153
- KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
154
- kmf.init(ks, password);
155
-
156
- TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
157
- tmf.init(ts);
181
+ KeyManagerFactory kmf = keyManagerFactoryMap.get(keystoreFile);
182
+ TrustManagerFactory tmf = trustManagerFactoryMap.get(keystoreFile);
183
+ if(kmf == null || tmf == null) {
184
+ throw new KeyStoreException("Could not find KeyManagerFactory/TrustManagerFactory for keystore: " + keystoreFile);
185
+ }
158
186
 
159
187
  SSLContext sslCtx = SSLContext.getInstance("TLS");
160
188
 
@@ -434,7 +434,9 @@ VALUE HttpParser_body(VALUE self) {
434
434
  return http->body;
435
435
  }
436
436
 
437
+ #ifdef HAVE_OPENSSL_BIO_H
437
438
  void Init_mini_ssl(VALUE mod);
439
+ #endif
438
440
 
439
441
  void Init_puma_http11()
440
442
  {
@@ -463,5 +465,7 @@ void Init_puma_http11()
463
465
  rb_define_method(cHttpParser, "body", HttpParser_body, 0);
464
466
  init_common_fields();
465
467
 
468
+ #ifdef HAVE_OPENSSL_BIO_H
466
469
  Init_mini_ssl(mPuma);
470
+ #endif
467
471
  }
@@ -10,6 +10,9 @@ require 'stringio'
10
10
 
11
11
  require 'thread'
12
12
 
13
+ require_relative 'puma/puma_http11'
14
+ require_relative 'puma/detect'
15
+
13
16
  module Puma
14
17
  autoload :Const, 'puma/const'
15
18
  autoload :Server, 'puma/server'
@@ -24,6 +27,7 @@ module Puma
24
27
  @get_stats.stats.to_json
25
28
  end
26
29
 
30
+ # @version 5.0.0
27
31
  def self.stats_hash
28
32
  @get_stats.stats
29
33
  end
@@ -33,4 +37,12 @@ module Puma
33
37
  return unless Thread.current.respond_to?(:name=)
34
38
  Thread.current.name = "puma #{name}"
35
39
  end
40
+
41
+ unless HAS_SSL
42
+ module MiniSSL
43
+ # this class is defined so that it exists when Puma is compiled
44
+ # without ssl support, as Server and Reactor use it in rescue statements.
45
+ class SSLError < StandardError ; end
46
+ end
47
+ end
36
48
  end
@@ -5,10 +5,16 @@ require 'socket'
5
5
 
6
6
  require 'puma/const'
7
7
  require 'puma/util'
8
- require 'puma/minissl/context_builder'
9
8
  require 'puma/configuration'
10
9
 
11
10
  module Puma
11
+
12
+ if HAS_SSL
13
+ require 'puma/minissl'
14
+ require 'puma/minissl/context_builder'
15
+ require 'puma/accept_nonblock'
16
+ end
17
+
12
18
  class Binder
13
19
  include Puma::Const
14
20
 
@@ -44,7 +50,12 @@ module Puma
44
50
  @ios = []
45
51
  end
46
52
 
47
- attr_reader :ios, :listeners, :unix_paths, :proto_env, :envs, :activated_sockets, :inherited_fds
53
+ attr_reader :ios
54
+
55
+ # @version 5.0.0
56
+ attr_reader :activated_sockets, :envs, :inherited_fds, :listeners, :proto_env, :unix_paths
57
+
58
+ # @version 5.0.0
48
59
  attr_writer :ios, :listeners
49
60
 
50
61
  def env(sock)
@@ -55,10 +66,12 @@ module Puma
55
66
  @ios.each { |i| i.close }
56
67
  end
57
68
 
69
+ # @version 5.0.0
58
70
  def connected_ports
59
71
  ios.map { |io| io.addr[1] }.uniq
60
72
  end
61
73
 
74
+ # @version 5.0.0
62
75
  def create_inherited_fds(env_hash)
63
76
  env_hash.select {|k,v| k =~ /PUMA_INHERIT_\d+/}.each do |_k, v|
64
77
  fd, url = v.split(":", 2)
@@ -69,7 +82,9 @@ module Puma
69
82
  # systemd socket activation.
70
83
  # LISTEN_FDS = number of listening sockets. e.g. 2 means accept on 2 sockets w/descriptors 3 and 4.
71
84
  # LISTEN_PID = PID of the service process, aka us
72
- # see https://www.freedesktop.org/software/systemd/man/systemd-socket-activate.html
85
+ # @see https://www.freedesktop.org/software/systemd/man/systemd-socket-activate.html
86
+ # @version 5.0.0
87
+ #
73
88
  def create_activated_fds(env_hash)
74
89
  return [] unless env_hash['LISTEN_FDS'] && env_hash['LISTEN_PID'].to_i == $$
75
90
  env_hash['LISTEN_FDS'].to_i.times do |index|
@@ -155,6 +170,9 @@ module Puma
155
170
 
156
171
  @listeners << [str, io]
157
172
  when "ssl"
173
+
174
+ raise "Puma compiled without SSL support" unless HAS_SSL
175
+
158
176
  params = Util.parse_query uri.query
159
177
  ctx = MiniSSL::ContextBuilder.new(params, @events).context
160
178
 
@@ -245,9 +263,8 @@ module Puma
245
263
 
246
264
  def add_ssl_listener(host, port, ctx,
247
265
  optimize_for_latency=true, backlog=1024)
248
- require 'puma/minissl'
249
266
 
250
- MiniSSL.check
267
+ raise "Puma compiled without SSL support" unless HAS_SSL
251
268
 
252
269
  if host == "localhost"
253
270
  loopback_addresses.each do |addr|
@@ -264,7 +281,6 @@ module Puma
264
281
  s.setsockopt(Socket::SOL_SOCKET,Socket::SO_REUSEADDR, true)
265
282
  s.listen backlog
266
283
 
267
-
268
284
  ssl = MiniSSL::Server.new s, ctx
269
285
  env = @proto_env.dup
270
286
  env[HTTPS_KEY] = HTTPS
@@ -275,8 +291,7 @@ module Puma
275
291
  end
276
292
 
277
293
  def inherit_ssl_listener(fd, ctx)
278
- require 'puma/minissl'
279
- MiniSSL.check
294
+ raise "Puma compiled without SSL support" unless HAS_SSL
280
295
 
281
296
  if fd.kind_of? TCPServer
282
297
  s = fd
@@ -367,6 +382,7 @@ module Puma
367
382
  redirects
368
383
  end
369
384
 
385
+ # @version 5.0.0
370
386
  def redirects_for_restart_env
371
387
  listeners.each_with_object({}).with_index do |(listen, memo), i|
372
388
  memo["PUMA_INHERIT_#{i}"] = "#{listen[1].to_i}:#{listen[0]}"
@@ -381,6 +397,7 @@ module Puma
381
397
  end.map { |addrinfo| addrinfo.ip_address }.uniq
382
398
  end
383
399
 
400
+ # @version 5.0.0
384
401
  def socket_activation_fd(int)
385
402
  int + 3 # 3 is the magic number you add to follow the SA protocol
386
403
  end
@@ -280,6 +280,8 @@ module Puma
280
280
 
281
281
  # Returns true if the persistent connection can be closed immediately
282
282
  # without waiting for the configured idle/shutdown timeout.
283
+ # @version 5.0.0
284
+ #
283
285
  def can_close?
284
286
  # Allow connection to close if it's received at least one full request
285
287
  # and hasn't received any data for a future request.
@@ -443,6 +445,7 @@ module Puma
443
445
  end
444
446
  end
445
447
 
448
+ # @version 5.0.0
446
449
  def write_chunk(str)
447
450
  @chunked_content_length += @body.write(str)
448
451
  end
@@ -77,6 +77,8 @@ module Puma
77
77
  end
78
78
 
79
79
  attr_reader :index, :pid, :phase, :signal, :last_checkin, :last_status, :started_at
80
+
81
+ # @version 5.0.0
80
82
  attr_writer :pid, :phase
81
83
 
82
84
  def booted?
@@ -98,6 +100,8 @@ module Puma
98
100
  @last_status = JSON.parse(status, symbolize_names: true)
99
101
  end
100
102
 
103
+ # @see Puma::Cluster#check_workers
104
+ # @version 5.0.0
101
105
  def ping_timeout
102
106
  @last_checkin +
103
107
  (booted? ?
@@ -160,6 +164,7 @@ module Puma
160
164
  end
161
165
  end
162
166
 
167
+ # @version 5.0.0
163
168
  def spawn_worker(idx, master)
164
169
  @launcher.config.run_hooks :before_worker_fork, idx, @launcher.events
165
170
 
@@ -419,6 +424,7 @@ module Puma
419
424
  @options[:preload_app]
420
425
  end
421
426
 
427
+ # @version 5.0.0
422
428
  def fork_worker!
423
429
  if (worker = @workers.find { |w| w.index == 0 })
424
430
  worker.phase += 1
@@ -640,6 +646,7 @@ module Puma
640
646
  end
641
647
  end
642
648
 
649
+ # @version 5.0.0
643
650
  def timeout_workers
644
651
  @workers.each do |w|
645
652
  if !w.term? && w.ping_timeout <= Time.now
@@ -649,6 +656,7 @@ module Puma
649
656
  end
650
657
  end
651
658
 
659
+ # @version 5.0.0
652
660
  def nakayoshi_gc
653
661
  return unless @options[:nakayoshi_fork]
654
662
  log "! Promoting existing objects to old generation..."
@@ -173,6 +173,7 @@ module Puma
173
173
  self
174
174
  end
175
175
 
176
+ # @version 5.0.0
176
177
  def default_max_threads
177
178
  Puma.mri? ? 5 : 16
178
179
  end
@@ -100,8 +100,9 @@ module Puma
100
100
  # too taxing on performance.
101
101
  module Const
102
102
 
103
- PUMA_VERSION = VERSION = "5.0.0.beta2".freeze
103
+ PUMA_VERSION = VERSION = "5.0.0".freeze
104
104
  CODE_NAME = "Spoony Bard".freeze
105
+
105
106
  PUMA_SERVER_STRING = ['puma', PUMA_VERSION, CODE_NAME].join(' ').freeze
106
107
 
107
108
  FAST_TRACK_KA_TIMEOUT = 0.2
@@ -12,6 +12,8 @@ module Puma
12
12
  class ControlCLI
13
13
 
14
14
  COMMANDS = %w{halt restart phased-restart start stats status stop reload-worker-directory gc gc-stats thread-backtraces refork}
15
+
16
+ # @version 5.0.0
15
17
  PRINTABLE_COMMANDS = %w{gc-stats stats thread-backtraces}
16
18
 
17
19
  def initialize(argv, stdout=STDOUT, stderr=STDERR)
@@ -1,6 +1,13 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Puma
4
+ # at present, MiniSSL::Engine is only defined in extension code, not in minissl.rb
5
+ HAS_SSL = const_defined?(:MiniSSL, false) && MiniSSL.const_defined?(:Engine, false)
6
+
7
+ def self.ssl?
8
+ HAS_SSL
9
+ end
10
+
4
11
  IS_JRUBY = defined?(JRUBY_VERSION)
5
12
 
6
13
  def self.jruby?
@@ -13,10 +20,12 @@ module Puma
13
20
  IS_WINDOWS
14
21
  end
15
22
 
23
+ # @version 5.0.0
16
24
  def self.mri?
17
25
  RUBY_ENGINE == 'ruby' || RUBY_ENGINE.nil?
18
26
  end
19
27
 
28
+ # @version 5.0.0
20
29
  def self.forkable?
21
30
  ::Process.respond_to?(:fork)
22
31
  end
@@ -14,22 +14,23 @@ module Puma
14
14
  # end
15
15
  # config.load
16
16
  #
17
- # puts config.options[:binds]
18
- # "tcp://127.0.0.1:3001"
17
+ # puts config.options[:binds] # => "tcp://127.0.0.1:3001"
19
18
  #
20
19
  # Used to load file:
21
20
  #
22
21
  # $ cat puma_config.rb
23
- # port 3002
22
+ # port 3002
23
+ #
24
+ # Resulting configuration:
24
25
  #
25
26
  # config = Configuration.new(config_file: "puma_config.rb")
26
27
  # config.load
27
28
  #
28
- # puts config.options[:binds]
29
- # # => "tcp://127.0.0.1:3002"
29
+ # puts config.options[:binds] # => "tcp://127.0.0.1:3002"
30
30
  #
31
31
  # You can also find many examples being used by the test suite in
32
32
  # +test/config+.
33
+ #
33
34
  class DSL
34
35
  include ConfigDefault
35
36
 
@@ -98,6 +99,9 @@ module Puma
98
99
  # [body]
99
100
  # ]
100
101
  # end
102
+ #
103
+ # @see Puma::Configuration#app
104
+ #
101
105
  def app(obj=nil, &block)
102
106
  obj ||= block
103
107
 
@@ -160,12 +164,12 @@ module Puma
160
164
  #
161
165
  # You can use query parameters within the url to specify options:
162
166
  #
163
- # - Set the socket backlog depth with +backlog+, default is 1024.
164
- # - Set up an SSL certificate with +key+ & +cert+.
165
- # - Set whether to optimize for low latency instead of throughput with
166
- # +low_latency+, default is to optimize for low latency. This is done
167
- # via +Socket::TCP_NODELAY+.
168
- # - Set socket permissions with +umask+.
167
+ # * Set the socket backlog depth with +backlog+, default is 1024.
168
+ # * Set up an SSL certificate with +key+ & +cert+.
169
+ # * Set whether to optimize for low latency instead of throughput with
170
+ # +low_latency+, default is to optimize for low latency. This is done
171
+ # via +Socket::TCP_NODELAY+.
172
+ # * Set socket permissions with +umask+.
169
173
  #
170
174
  # @example Backlog depth
171
175
  # bind 'unix:///var/run/puma.sock?backlog=512'
@@ -175,6 +179,9 @@ module Puma
175
179
  # bind 'tcp://0.0.0.0:9292?low_latency=false'
176
180
  # @example Socket permissions
177
181
  # bind 'unix:///var/run/puma.sock?umask=0111'
182
+ # @see Puma::Runner#load_and_bind
183
+ # @see Puma::Cluster#run
184
+ #
178
185
  def bind(url)
179
186
  @options[:binds] ||= []
180
187
  @options[:binds] << url
@@ -193,13 +200,14 @@ module Puma
193
200
  bind "tcp://#{host}:#{port}"
194
201
  end
195
202
 
196
- # Define how long persistent connections can be idle before Puma closes
197
- # them.
203
+ # Define how long persistent connections can be idle before Puma closes them.
204
+ # @see Puma::Server.new
198
205
  def persistent_timeout(seconds)
199
206
  @options[:persistent_timeout] = Integer(seconds)
200
207
  end
201
208
 
202
209
  # Define how long the tcp socket stays open, if no data has been received.
210
+ # @see Puma::Server.new
203
211
  def first_data_timeout(seconds)
204
212
  @options[:first_data_timeout] = Integer(seconds)
205
213
  end
@@ -210,10 +218,11 @@ module Puma
210
218
  @options[:clean_thread_locals] = which
211
219
  end
212
220
 
213
- # When shutting down, drain the accept socket of pending
214
- # connections and process them. This loops over the accept
215
- # socket until there are no more read events and then stops
216
- # looking and waits for the requests to finish.
221
+ # When shutting down, drain the accept socket of pending connections and
222
+ # process them. This loops over the accept socket until there are no more
223
+ # read events and then stops looking and waits for the requests to finish.
224
+ # @see Puma::Server#graceful_shutdown
225
+ #
217
226
  def drain_on_shutdown(which=true)
218
227
  @options[:drain_on_shutdown] = which
219
228
  end
@@ -236,6 +245,7 @@ module Puma
236
245
  #
237
246
  # Puma always waits a few seconds after killing a thread for it to try
238
247
  # to finish up it's work, even in :immediately mode.
248
+ # @see Puma::Server#graceful_shutdown
239
249
  def force_shutdown_after(val=:forever)
240
250
  i = case val
241
251
  when :forever
@@ -315,7 +325,7 @@ module Puma
315
325
  @options[:early_hints] = answer
316
326
  end
317
327
 
318
- # Redirect STDOUT and STDERR to files specified. The +append+ parameter
328
+ # Redirect +STDOUT+ and +STDERR+ to files specified. The +append+ parameter
319
329
  # specifies whether the output is appended, the default is +false+.
320
330
  #
321
331
  # @example
@@ -356,8 +366,8 @@ module Puma
356
366
  @options[:max_threads] = max
357
367
  end
358
368
 
359
- # Instead of "bind 'ssl://127.0.0.1:9292?key=key_path&cert=cert_path'" you
360
- # can also use the "ssl_bind" option.
369
+ # Instead of `bind 'ssl://127.0.0.1:9292?key=key_path&cert=cert_path'` you
370
+ # can also use the this method.
361
371
  #
362
372
  # @example
363
373
  # ssl_bind '127.0.0.1', '9292', {
@@ -403,6 +413,8 @@ module Puma
403
413
  #
404
414
  # @example
405
415
  # state_permission 0600
416
+ # @version 5.0.0
417
+ #
406
418
  def state_permission(permission)
407
419
  @options[:state_permission] = permission
408
420
  end
@@ -413,6 +425,7 @@ module Puma
413
425
  # The default is 0.
414
426
  #
415
427
  # @note Cluster mode only.
428
+ # @see Puma::Cluster
416
429
  def workers(count)
417
430
  @options[:workers] = count.to_i
418
431
  end
@@ -516,7 +529,8 @@ module Puma
516
529
  # on_refork do
517
530
  # 3.times {GC.start}
518
531
  # end
519
-
532
+ # @version 5.0.0
533
+ #
520
534
  def on_refork(&block)
521
535
  @options[:before_refork] ||= []
522
536
  @options[:before_refork] << block
@@ -582,7 +596,7 @@ module Puma
582
596
  # new Bundler context and thus can float around as the release
583
597
  # dictates.
584
598
  #
585
- # See also: extra_runtime_dependencies
599
+ # @see extra_runtime_dependencies
586
600
  #
587
601
  # @note This is incompatible with +preload_app!+.
588
602
  # @note This is only supported for RubyGems 2.2+
@@ -599,6 +613,9 @@ module Puma
599
613
  #
600
614
  # @example
601
615
  # raise_exception_on_sigterm false
616
+ # @see Puma::Launcher#setup_signals
617
+ # @see Puma::Cluster#setup_signals
618
+ #
602
619
  def raise_exception_on_sigterm(answer=true)
603
620
  @options[:raise_exception_on_sigterm] = answer
604
621
  end
@@ -614,6 +631,8 @@ module Puma
614
631
  # extra_runtime_dependencies ['gem_name_1', 'gem_name_2']
615
632
  # @example
616
633
  # extra_runtime_dependencies ['puma_worker_killer', 'puma-heroku']
634
+ # @see Puma::Launcher#extra_runtime_deps_directories
635
+ #
617
636
  def extra_runtime_dependencies(answer = [])
618
637
  @options[:extra_runtime_dependencies] = Array(answer)
619
638
  end
@@ -641,6 +660,8 @@ module Puma
641
660
  # @note Cluster mode only.
642
661
  # @example
643
662
  # worker_timeout 60
663
+ # @see Puma::Cluster::Worker#ping_timeout
664
+ #
644
665
  def worker_timeout(timeout)
645
666
  timeout = Integer(timeout)
646
667
  min = Const::WORKER_CHECK_INTERVAL
@@ -657,15 +678,20 @@ module Puma
657
678
  # If unspecified, this defaults to the value of worker_timeout.
658
679
  #
659
680
  # @note Cluster mode only.
660
- # @example:
681
+ #
682
+ # @example
661
683
  # worker_boot_timeout 60
684
+ # @see Puma::Cluster::Worker#ping_timeout
685
+ #
662
686
  def worker_boot_timeout(timeout)
663
687
  @options[:worker_boot_timeout] = Integer(timeout)
664
688
  end
665
689
 
666
- # Set the timeout for worker shutdown
690
+ # Set the timeout for worker shutdown.
667
691
  #
668
692
  # @note Cluster mode only.
693
+ # @see Puma::Cluster::Worker#term
694
+ #
669
695
  def worker_shutdown_timeout(timeout)
670
696
  @options[:worker_shutdown_timeout] = Integer(timeout)
671
697
  end
@@ -683,6 +709,7 @@ module Puma
683
709
  # slow clients will occupy a handler thread while the request
684
710
  # is being sent. A reverse proxy, such as nginx, can handle
685
711
  # slow clients and queue requests before they reach Puma.
712
+ # @see Puma::Server
686
713
  def queue_requests(answer=true)
687
714
  @options[:queue_requests] = answer
688
715
  end
@@ -690,6 +717,7 @@ module Puma
690
717
  # When a shutdown is requested, the backtraces of all the
691
718
  # threads will be written to $stdout. This can help figure
692
719
  # out why shutdown is hanging.
720
+ #
693
721
  def shutdown_debug(val=true)
694
722
  @options[:shutdown_debug] = val
695
723
  end
@@ -700,6 +728,10 @@ module Puma
700
728
  # requests to pick up new requests first.
701
729
  #
702
730
  # Only works on MRI. For all other interpreters, this setting does nothing.
731
+ # @see Puma::Server#handle_servers
732
+ # @see Puma::ThreadPool#wait_for_less_busy_worker
733
+ # @version 5.0.0
734
+ #
703
735
  def wait_for_less_busy_worker(val=0.005)
704
736
  @options[:wait_for_less_busy_worker] = val.to_f
705
737
  end
@@ -711,18 +743,18 @@ module Puma
711
743
  #
712
744
  # There are 4 possible values:
713
745
  #
714
- # * :socket (the default) - read the peername from the socket using the
715
- # syscall. This is the normal behavior.
716
- # * :localhost - set the remote address to "127.0.0.1"
717
- # * header: http_header - set the remote address to the value of the
718
- # provided http header. For instance:
719
- # `set_remote_address header: "X-Real-IP"`.
720
- # Only the first word (as separated by spaces or comma)
721
- # is used, allowing headers such as X-Forwarded-For
722
- # to be used as well.
723
- # * Any string - this allows you to hardcode remote address to any value
724
- # you wish. Because Puma never uses this field anyway, it's
725
- # format is entirely in your hands.
746
+ # 1. **:socket** (the default) - read the peername from the socket using the
747
+ # syscall. This is the normal behavior.
748
+ # 2. **:localhost** - set the remote address to "127.0.0.1"
749
+ # 3. **header: <http_header>**- set the remote address to the value of the
750
+ # provided http header. For instance:
751
+ # `set_remote_address header: "X-Real-IP"`.
752
+ # Only the first word (as separated by spaces or comma) is used, allowing
753
+ # headers such as X-Forwarded-For to be used as well.
754
+ # 4. **\<Any string\>** - this allows you to hardcode remote address to any value
755
+ # you wish. Because Puma never uses this field anyway, it's format is
756
+ # entirely in your hands.
757
+ #
726
758
  def set_remote_address(val=:socket)
727
759
  case val
728
760
  when :socket
@@ -756,6 +788,8 @@ module Puma
756
788
  # (default 1000), or pass 0 to disable auto refork.
757
789
  #
758
790
  # @note Cluster mode only.
791
+ # @version 5.0.0
792
+ #
759
793
  def fork_worker(after_requests=1000)
760
794
  @options[:fork_worker] = Integer(after_requests)
761
795
  end
@@ -769,6 +803,10 @@ module Puma
769
803
  # also increase time to boot and fork. See your logs for details on how much
770
804
  # time this adds to your boot process. For most apps, it will be less than one
771
805
  # second.
806
+ #
807
+ # @see Puma::Cluster#nakayoshi_gc
808
+ # @version 5.0.0
809
+ #
772
810
  def nakayoshi_fork(enabled=true)
773
811
  @options[:nakayoshi_fork] = enabled
774
812
  end
@@ -4,6 +4,7 @@ require 'puma/const'
4
4
 
5
5
  module Puma
6
6
  # The implementation of a detailed error logging.
7
+ # @version 5.0.0
7
8
  #
8
9
  class ErrorLogger
9
10
  include Const
@@ -91,6 +91,7 @@ module Puma
91
91
  # An HTTP connection error has occurred.
92
92
  # +error+ a connection exception, +req+ the request,
93
93
  # and +text+ additional info
94
+ # @version 5.0.0
94
95
  #
95
96
  def connection_error(error, req, text="HTTP connection error")
96
97
  @error_logger.info(error: error, req: req, text: text)
@@ -124,6 +125,7 @@ module Puma
124
125
  # Log occurred error debug dump.
125
126
  # +error+ an exception object, +req+ the request,
126
127
  # and +text+ additional info
128
+ # @version 5.0.0
127
129
  #
128
130
  def debug_error(error, req=nil, text="")
129
131
  @error_logger.debug(error: error, req: req, text: text)
@@ -188,6 +188,7 @@ module Puma
188
188
  end
189
189
 
190
190
  # Return all tcp ports the launcher may be using, TCP or SSL
191
+ # @version 5.0.0
191
192
  def connected_ports
192
193
  @binder.connected_ports
193
194
  end
@@ -206,6 +207,7 @@ module Puma
206
207
  @binder.close_listeners
207
208
  end
208
209
 
210
+ # @version 5.0.0
209
211
  def thread_status
210
212
  Thread.list.each do |thread|
211
213
  name = "Thread: TID-#{thread.object_id.to_s(36)}"
@@ -478,6 +480,7 @@ module Puma
478
480
  "You must have RubyGems #{min_version}+ to use this feature."
479
481
  end
480
482
 
483
+ # @version 5.0.0
481
484
  def with_unbundled_env
482
485
  bundler_ver = Gem::Version.new(Bundler::VERSION)
483
486
  if bundler_ver < Gem::Version.new('2.1.0')
@@ -10,9 +10,9 @@ require 'puma/puma_http11'
10
10
 
11
11
  module Puma
12
12
  module MiniSSL
13
-
14
- # define constant at runtime, as it's easy to determine at built time,
13
+ # Define constant at runtime, as it's easy to determine at built time,
15
14
  # but Puma could (it shouldn't) be loaded with an older OpenSSL version
15
+ # @version 5.0.0
16
16
  HAS_TLS1_3 = !IS_JRUBY &&
17
17
  (OPENSSL_VERSION[/ \d+\.\d+\.\d+/].split('.').map(&:to_i) <=> [1,1,1]) != -1 &&
18
18
  (OPENSSL_LIBRARY_VERSION[/ \d+\.\d+\.\d+/].split('.').map(&:to_i) <=> [1,1,1]) !=-1
@@ -32,19 +32,21 @@ module Puma
32
32
  @socket.closed?
33
33
  end
34
34
 
35
- # returns a two element array
36
- # first is protocol version (SSL_get_version)
35
+ # Returns a two element array,
36
+ # first is protocol version (SSL_get_version),
37
37
  # second is 'handshake' state (SSL_state_string)
38
38
  #
39
- # used for dropping tcp connections to ssl
40
- # see OpenSSL ssl/ssl_stat.c SSL_state_string for info
39
+ # Used for dropping tcp connections to ssl.
40
+ # See OpenSSL ssl/ssl_stat.c SSL_state_string for info
41
+ # @version 5.0.0
41
42
  #
42
43
  def ssl_version_state
43
44
  IS_JRUBY ? [nil, nil] : @engine.ssl_vers_st
44
45
  end
45
46
 
46
- # used to check the handshake status, in particular when a TCP connection
47
+ # Used to check the handshake status, in particular when a TCP connection
47
48
  # is made with TLSv1.3 as an available protocol
49
+ # @version 5.0.0
48
50
  def bad_tlsv1_3?
49
51
  HAS_TLS1_3 && @engine.ssl_vers_st == ['TLSv1.3', 'SSLERR']
50
52
  end
@@ -136,14 +138,18 @@ module Puma
136
138
  alias_method :<<, :write
137
139
 
138
140
  # This is a temporary fix to deal with websockets code using
139
- # write_nonblock. The problem with implementing it properly
141
+ # write_nonblock.
142
+
143
+ # The problem with implementing it properly
140
144
  # is that it means we'd have to have the ability to rewind
141
145
  # an engine because after we write+extract, the socket
142
146
  # write_nonblock call might raise an exception and later
143
147
  # code would pass the same data in, but the engine would think
144
- # it had already written the data in. So for the time being
145
- # (and since write blocking is quite rare), go ahead and actually
146
- # block in write_nonblock.
148
+ # it had already written the data in.
149
+ #
150
+ # So for the time being (and since write blocking is quite rare),
151
+ # go ahead and actually block in write_nonblock.
152
+ #
147
153
  def write_nonblock(data, *_)
148
154
  write data
149
155
  end
@@ -203,8 +209,6 @@ module Puma
203
209
  class SSLError < StandardError
204
210
  # Define this for jruby even though it isn't used.
205
211
  end
206
-
207
- def self.check; end
208
212
  end
209
213
 
210
214
  class Context
@@ -261,13 +265,13 @@ module Puma
261
265
 
262
266
  # disables TLSv1
263
267
  def no_tlsv1=(tlsv1)
264
- raise ArgumentError, "Invalid value of no_tlsv1" unless ['true', 'false', true, false].include?(tlsv1)
268
+ raise ArgumentError, "Invalid value of no_tlsv1=" unless ['true', 'false', true, false].include?(tlsv1)
265
269
  @no_tlsv1 = tlsv1
266
270
  end
267
271
 
268
272
  # disables TLSv1 and TLSv1.1. Overrides `#no_tlsv1=`
269
273
  def no_tlsv1_1=(tlsv1_1)
270
- raise ArgumentError, "Invalid value of no_tlsv1" unless ['true', 'false', true, false].include?(tlsv1_1)
274
+ raise ArgumentError, "Invalid value of no_tlsv1_1=" unless ['true', 'false', true, false].include?(tlsv1_1)
271
275
  @no_tlsv1_1 = tlsv1_1
272
276
  end
273
277
 
@@ -303,6 +307,7 @@ module Puma
303
307
  Socket.new io, engine
304
308
  end
305
309
 
310
+ # @version 5.0.0
306
311
  def addr
307
312
  @socket.addr
308
313
  end
@@ -2,9 +2,6 @@ module Puma
2
2
  module MiniSSL
3
3
  class ContextBuilder
4
4
  def initialize(params, events)
5
- require 'puma/minissl'
6
- MiniSSL.check
7
-
8
5
  @params = params
9
6
  @events = events
10
7
  end
Binary file
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'puma/util'
4
- require 'puma/minissl'
4
+ require 'puma/minissl' if ::Puma::HAS_SSL
5
5
 
6
6
  require 'nio'
7
7
 
@@ -2,7 +2,6 @@
2
2
 
3
3
  require 'puma/server'
4
4
  require 'puma/const'
5
- require 'puma/minissl/context_builder'
6
5
 
7
6
  module Puma
8
7
  # Generic class that is used by `Puma::Cluster` and `Puma::Single` to
@@ -30,6 +29,7 @@ module Puma
30
29
  @events.log str
31
30
  end
32
31
 
32
+ # @version 5.0.0
33
33
  def stop_control
34
34
  @control.stop(true) if @control
35
35
  end
@@ -64,6 +64,7 @@ module Puma
64
64
  @control = control
65
65
  end
66
66
 
67
+ # @version 5.0.0
67
68
  def close_control_listeners
68
69
  @control.binder.close_listeners if @control
69
70
  end
@@ -9,12 +9,9 @@ require 'puma/null_io'
9
9
  require 'puma/reactor'
10
10
  require 'puma/client'
11
11
  require 'puma/binder'
12
- require 'puma/accept_nonblock'
13
12
  require 'puma/util'
14
13
  require 'puma/io_buffer'
15
14
 
16
- require 'puma/puma_http11'
17
-
18
15
  require 'socket'
19
16
  require 'forwardable'
20
17
 
@@ -37,7 +34,7 @@ module Puma
37
34
 
38
35
  attr_reader :thread
39
36
  attr_reader :events
40
- attr_reader :requests_count
37
+ attr_reader :requests_count # @version 5.0.0
41
38
  attr_accessor :app
42
39
 
43
40
  attr_accessor :min_threads
@@ -100,11 +97,11 @@ module Puma
100
97
 
101
98
  class << self
102
99
  # :nodoc:
100
+ # @version 5.0.0
103
101
  def tcp_cork_supported?
104
102
  RbConfig::CONFIG['host_os'] =~ /linux/ &&
105
103
  Socket.const_defined?(:IPPROTO_TCP) &&
106
104
  Socket.const_defined?(:TCP_CORK) &&
107
- Socket.const_defined?(:SOL_TCP) &&
108
105
  Socket.const_defined?(:TCP_INFO)
109
106
  end
110
107
  private :tcp_cork_supported?
@@ -140,7 +137,7 @@ module Puma
140
137
  return false unless @precheck_closing
141
138
 
142
139
  begin
143
- tcp_info = socket.getsockopt(Socket::SOL_TCP, Socket::TCP_INFO)
140
+ tcp_info = socket.getsockopt(Socket::IPPROTO_TCP, Socket::TCP_INFO)
144
141
  rescue IOError, SystemCallError
145
142
  Thread.current.purge_interrupt_queue if Thread.current.respond_to? :purge_interrupt_queue
146
143
  @precheck_closing = false
@@ -998,9 +995,11 @@ module Puma
998
995
  private :possible_header_injection?
999
996
 
1000
997
  # List of methods invoked by #stats.
998
+ # @version 5.0.0
1001
999
  STAT_METHODS = [:backlog, :running, :pool_capacity, :max_threads, :requests_count].freeze
1002
1000
 
1003
1001
  # Returns a hash of stats about the running server for reporting purposes.
1002
+ # @version 5.0.0
1004
1003
  def stats
1005
1004
  STAT_METHODS.map {|name| [name, send(name) || 0]}.to_h
1006
1005
  end
@@ -66,7 +66,7 @@ module Puma
66
66
 
67
67
  attr_reader :spawned, :trim_requested, :waiting
68
68
  attr_accessor :clean_thread_locals
69
- attr_accessor :out_of_band_hook
69
+ attr_accessor :out_of_band_hook # @version 5.0.0
70
70
 
71
71
  def self.clean_thread_locals
72
72
  Thread.current.keys.each do |key| # rubocop: disable Performance/HashEachMethods
@@ -84,6 +84,7 @@ module Puma
84
84
  waiting + (@max - spawned)
85
85
  end
86
86
 
87
+ # @version 5.0.0
87
88
  def busy_threads
88
89
  with_mutex { @spawned - @waiting + @todo.size }
89
90
  end
@@ -151,6 +152,7 @@ module Puma
151
152
 
152
153
  private :spawn_thread
153
154
 
155
+ # @version 5.0.0
154
156
  def trigger_out_of_band_hook
155
157
  return false unless out_of_band_hook && out_of_band_hook.any?
156
158
 
@@ -166,6 +168,7 @@ module Puma
166
168
 
167
169
  private :trigger_out_of_band_hook
168
170
 
171
+ # @version 5.0.0
169
172
  def with_mutex(&block)
170
173
  @mutex.owned? ?
171
174
  yield :
@@ -231,6 +234,7 @@ module Puma
231
234
  end
232
235
  end
233
236
 
237
+ # @version 5.0.0
234
238
  def wait_for_less_busy_worker(delay_s)
235
239
  # Ruby MRI does GVL, this can result
236
240
  # in processing contention when multiple threads
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.0.0.beta2
4
+ version: 5.0.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: 2020-09-05 00:00:00.000000000 Z
11
+ date: 2020-09-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  requirement: !ruby/object:Gem::Requirement
@@ -69,6 +69,7 @@ files:
69
69
  - ext/puma_http11/http11_parser.rl
70
70
  - ext/puma_http11/http11_parser_common.rl
71
71
  - ext/puma_http11/mini_ssl.c
72
+ - ext/puma_http11/no_ssl/PumaHttp11Service.java
72
73
  - ext/puma_http11/org/jruby/puma/Http11.java
73
74
  - ext/puma_http11/org/jruby/puma/Http11Parser.java
74
75
  - ext/puma_http11/org/jruby/puma/MiniSSL.java
@@ -129,9 +130,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
129
130
  version: '2.2'
130
131
  required_rubygems_version: !ruby/object:Gem::Requirement
131
132
  requirements:
132
- - - ">"
133
+ - - ">="
133
134
  - !ruby/object:Gem::Version
134
- version: 1.3.1
135
+ version: '0'
135
136
  requirements: []
136
137
  rubygems_version: 3.0.6
137
138
  signing_key: