puma 5.3.0-java → 5.5.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: 7497bbe935eaedda6aabf9c47876bcdd0727dcfbe17835c9a7d025925fbe9fce
4
- data.tar.gz: 13769e38a5e5845279f97ad77117d31da0403e9cd1a52d21417f41e40cecddb7
3
+ metadata.gz: 661cbffdacb6abddfeca2df52a317f8e3944290f9738e6500d718b6e99cd80d5
4
+ data.tar.gz: afd4a42aafc203919afac39161e564411cafbf08a4817171d0c8aa940922ce35
5
5
  SHA512:
6
- metadata.gz: b4901602b62972f60c4d56034bb7c0f64b6b562d423e5ab2a3d1002fc7edc8854f969919bd46f3b46b68efb15a08f02abb209d19988ac9b494897d2dd254aaa7
7
- data.tar.gz: a2f58db0f3eff88455f03e47b9c0016682d89327796531bbff39f04a93b0a8ff3a3a3f7d3662af640cd2c60d198d3baa0cd961fccb451c45222e66d8b60ca3cf
6
+ metadata.gz: 6f4f11d8ae7fc1c2f9b982dee9818bade60af588583d03ef56cb60965f87616008f961dc1ae179560ea2d263df65f4bb162465d47f029398bcecea79774e41a4
7
+ data.tar.gz: 0da863e974c4c9e2d91ff954c6c86621c1fc3ba0aa7a82c5d518e56edda289fabd110b1afb44937b327820ac84dd333d66a9b826c8152aab66ab124066a22f13
data/History.md CHANGED
@@ -1,3 +1,46 @@
1
+ ## 5.5.0 / 2021-09-19
2
+
3
+ * Features
4
+ * Automatic SSL certificate provisioning for localhost, via localhost gem ([#2610], [#2257])
5
+ * add support for the PROXY protocol (v1 only) ([#2654], [#2651])
6
+ * Add a semantic CLI option for no config file ([#2689])
7
+
8
+ * Bugfixes
9
+ * More elaborate exception handling - lets some dead pumas die. ([#2700], [#2699])
10
+ * allow multiple after_worker_fork hooks ([#2690])
11
+ * Preserve BUNDLE_APP_CONFIG on worker fork ([#2688], [#2687])
12
+
13
+ * Performance
14
+ * Fix performance of server-side SSL connection close. ([#2675])
15
+
16
+ ## 5.4.0 / 2021-07-28
17
+
18
+ * Features
19
+ * Better/expanded names for threadpool threads ([#2657])
20
+ * Allow pkg_config for OpenSSL ([#2648], [#1412])
21
+ * Add `rack_url_scheme` to Puma::DSL, allows setting of `rack.url_scheme` header ([#2586], [#2569])
22
+
23
+ * Bugfixes
24
+ * `Binder#parse` - allow for symlinked unix path, add create_activated_fds debug ENV ([#2643], [#2638])
25
+ * Fix deprecation warning: minissl.c - Use Random.bytes if available ([#2642])
26
+ * Client certificates: set session id context while creating SSLContext ([#2633])
27
+ * Fix deadlock issue in thread pool ([#2656])
28
+
29
+ * Refactor
30
+ * Replace `IO.select` with `IO#wait_*` when checking a single IO ([#2666])
31
+
32
+ ## 5.3.2 / 2021-05-21
33
+
34
+ * Bugfixes
35
+ * Gracefully handle Rack not accepting CLI options ([#2630], [#2626])
36
+ * Fix sigterm misbehavior ([#2629])
37
+ * Improvements to keepalive-connection shedding ([#2628])
38
+
39
+ ## 5.3.1 / 2021-05-11
40
+
41
+ * Security
42
+ * Close keepalive connections after the maximum number of fast inlined requests (CVE-2021-29509) ([#2625])
43
+
1
44
  ## 5.3.0 / 2021-05-07
2
45
 
3
46
  * Features
@@ -208,6 +251,11 @@
208
251
  * Support parallel tests in verbose progress reporting ([#2223])
209
252
  * Refactor error handling in server accept loop ([#2239])
210
253
 
254
+ ## 4.3.8 / 2021-05-11
255
+
256
+ * Security
257
+ * Close keepalive connections after the maximum number of fast inlined requests (CVE-2021-29509) ([#2625])
258
+
211
259
  ## 4.3.7 / 2020-11-30
212
260
 
213
261
  * Bugfixes
@@ -1736,6 +1784,33 @@ be added back in a future date when a java Puma::MiniSSL is added.
1736
1784
  * Bugfixes
1737
1785
  * Your bugfix goes here <Most recent on the top, like GitHub> (#Github Number)
1738
1786
 
1787
+ [#2610]:https://github.com/puma/puma/pull/2610 "PR by @ye-lin-aung, merged 2021-08-18"
1788
+ [#2257]:https://github.com/puma/puma/issues/2257 "Issue by @nateberkopec, closed 2021-08-18"
1789
+ [#2654]:https://github.com/puma/puma/pull/2654 "PR by @Roguelazer, merged 2021-09-07"
1790
+ [#2651]:https://github.com/puma/puma/issues/2651 "Issue by @Roguelazer, closed 2021-09-07"
1791
+ [#2689]:https://github.com/puma/puma/pull/2689 "PR by @jacobherrington, merged 2021-09-05"
1792
+ [#2700]:https://github.com/puma/puma/pull/2700 "PR by @ioquatix, merged 2021-09-16"
1793
+ [#2699]:https://github.com/puma/puma/issues/2699 "Issue by @ioquatix, closed 2021-09-16"
1794
+ [#2690]:https://github.com/puma/puma/pull/2690 "PR by @doits, merged 2021-09-06"
1795
+ [#2688]:https://github.com/puma/puma/pull/2688 "PR by @jdelStrother, merged 2021-09-03"
1796
+ [#2687]:https://github.com/puma/puma/issues/2687 "Issue by @jdelStrother, closed 2021-09-03"
1797
+ [#2675]:https://github.com/puma/puma/pull/2675 "PR by @devwout, merged 2021-09-08"
1798
+ [#2657]:https://github.com/puma/puma/pull/2657 "PR by @olivierbellone, merged 2021-07-13"
1799
+ [#2648]:https://github.com/puma/puma/pull/2648 "PR by @MSP-Greg, merged 2021-06-27"
1800
+ [#1412]:https://github.com/puma/puma/issues/1412 "Issue by @x-yuri, closed 2021-06-27"
1801
+ [#2586]:https://github.com/puma/puma/pull/2586 "PR by @MSP-Greg, merged 2021-05-26"
1802
+ [#2569]:https://github.com/puma/puma/issues/2569 "Issue by @tarragon, closed 2021-05-26"
1803
+ [#2643]:https://github.com/puma/puma/pull/2643 "PR by @MSP-Greg, merged 2021-06-27"
1804
+ [#2638]:https://github.com/puma/puma/issues/2638 "Issue by @gingerlime, closed 2021-06-27"
1805
+ [#2642]:https://github.com/puma/puma/pull/2642 "PR by @MSP-Greg, merged 2021-06-16"
1806
+ [#2633]:https://github.com/puma/puma/pull/2633 "PR by @onlined, merged 2021-06-04"
1807
+ [#2656]:https://github.com/puma/puma/pull/2656 "PR by @olivierbellone, merged 2021-07-07"
1808
+ [#2666]:https://github.com/puma/puma/pull/2666 "PR by @MSP-Greg, merged 2021-07-25"
1809
+ [#2630]:https://github.com/puma/puma/pull/2630 "PR by @seangoedecke, merged 2021-05-20"
1810
+ [#2626]:https://github.com/puma/puma/issues/2626 "Issue by @rorymckinley, closed 2021-05-20"
1811
+ [#2629]:https://github.com/puma/puma/pull/2629 "PR by @ye-lin-aung, merged 2021-05-20"
1812
+ [#2628]:https://github.com/puma/puma/pull/2628 "PR by @wjordan, merged 2021-05-20"
1813
+ [#2625]:https://github.com/puma/puma/issues/2625 "Issue by @jarthod, closed 2021-05-11"
1739
1814
  [#2564]:https://github.com/puma/puma/pull/2564 "PR by @MSP-Greg, merged 2021-04-24"
1740
1815
  [#2526]:https://github.com/puma/puma/issues/2526 "Issue by @nerdrew, closed 2021-04-24"
1741
1816
  [#2559]:https://github.com/puma/puma/pull/2559 "PR by @ylecuyer, merged 2021-03-11"
@@ -1750,11 +1825,11 @@ be added back in a future date when a java Puma::MiniSSL is added.
1750
1825
  [#2605]:https://github.com/puma/puma/pull/2605 "PR by @pascalbetz, merged 2021-04-26"
1751
1826
  [#2584]:https://github.com/puma/puma/issues/2584 "Issue by @kaorihinata, closed 2021-04-26"
1752
1827
  [#2607]:https://github.com/puma/puma/pull/2607 "PR by @calvinxiao, merged 2021-04-23"
1753
- [#2552]:https://github.com/puma/puma/issues/2552 "Issue by @feliperaul, opened 2021-02-09"
1828
+ [#2552]:https://github.com/puma/puma/issues/2552 "Issue by @feliperaul, closed 2021-05-24"
1754
1829
  [#2606]:https://github.com/puma/puma/pull/2606 "PR by @wjordan, merged 2021-04-20"
1755
1830
  [#2574]:https://github.com/puma/puma/issues/2574 "Issue by @darkhelmet, closed 2021-04-20"
1756
- [#2567]:https://github.com/puma/puma/pull/2567 "PR by @kddeisz, merged 2021-04-19"
1757
- [#2566]:https://github.com/puma/puma/issues/2566 "Issue by @kddeisz, closed 2021-04-19"
1831
+ [#2567]:https://github.com/puma/puma/pull/2567 "PR by @kddnewton, merged 2021-04-19"
1832
+ [#2566]:https://github.com/puma/puma/issues/2566 "Issue by @kddnewton, closed 2021-04-19"
1758
1833
  [#2596]:https://github.com/puma/puma/pull/2596 "PR by @MSP-Greg, merged 2021-04-18"
1759
1834
  [#2588]:https://github.com/puma/puma/pull/2588 "PR by @dentarg, merged 2021-04-02"
1760
1835
  [#2556]:https://github.com/puma/puma/issues/2556 "Issue by @gamecreature, closed 2021-04-02"
data/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
  <img src="https://puma.io/images/logos/puma-logo-large.png">
3
3
  </p>
4
4
 
5
- # Puma: A Ruby Web Server Built For Concurrency
5
+ # Puma: A Ruby Web Server Built For Parallelism
6
6
 
7
7
  [![Actions MRI](https://github.com/puma/puma/workflows/MRI/badge.svg?branch=master)](https://github.com/puma/puma/actions?query=workflow%3AMRI)
8
8
  [![Actions non MRI](https://github.com/puma/puma/workflows/non_MRI/badge.svg?branch=master)](https://github.com/puma/puma/actions?query=workflow%3Anon_MRI)
@@ -10,11 +10,11 @@
10
10
  [![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
11
  [![StackOverflow](https://img.shields.io/badge/stackoverflow-Puma-blue.svg)]( https://stackoverflow.com/questions/tagged/puma )
12
12
 
13
- Puma is a **simple, fast, multi-threaded, and highly concurrent HTTP 1.1 server for Ruby/Rack applications**.
13
+ Puma is a **simple, fast, multi-threaded, and highly parallel HTTP 1.1 server for Ruby/Rack applications**.
14
14
 
15
- ## Built For Speed &amp; Concurrency
15
+ ## Built For Speed &amp; Parallelism
16
16
 
17
- Puma processes requests using a C-optimized Ragel extension (inherited from Mongrel) that provides fast, accurate HTTP 1.1 protocol parsing in a portable way. Puma then serves the request using a thread pool. Each request is served in a separate thread, so truly concurrent Ruby implementations (JRuby, Rubinius) will use all available CPU cores.
17
+ Puma processes requests using a C-optimized Ragel extension (inherited from Mongrel) that provides fast, accurate HTTP 1.1 protocol parsing in a portable way. Puma then serves the request using a thread pool. Each request is served in a separate thread, so truly parallel Ruby implementations (JRuby, Rubinius) will use all available CPU cores.
18
18
 
19
19
  Originally designed as a server for [Rubinius](https://github.com/rubinius/rubinius), Puma also works well with Ruby (MRI) and JRuby.
20
20
 
@@ -187,6 +187,21 @@ Need a bit of security? Use SSL sockets:
187
187
  ```
188
188
  $ puma -b 'ssl://127.0.0.1:9292?key=path_to_key&cert=path_to_cert'
189
189
  ```
190
+ #### Self-signed SSL certificates (via _localhost_ gem, for development use):
191
+
192
+ Puma supports [localhost](https://github.com/socketry/localhost) gem for self-signed certificates. This is particularly useful if you want to use Puma with SSL locally, and self-signed certificates will work for your use-case. Currently, `localhost-authority` can be used only in MRI. To use [localhost](https://github.com/socketry/localhost), you have to `require "localhost/authority"`:
193
+
194
+ ```ruby
195
+ # config.ru
196
+ require './app'
197
+ require 'localhost/authority'
198
+ run Sinatra::Application
199
+
200
+ ...
201
+
202
+ $ puma -b 'ssl://localhost:9292' config.ru
203
+ ```
204
+
190
205
 
191
206
  #### Controlling SSL Cipher Suites
192
207
 
@@ -257,9 +272,13 @@ $ puma -C /path/to/config
257
272
 
258
273
  If no configuration file is specified, Puma will look for a configuration file at `config/puma.rb`. If an environment is specified, either via the `-e` and `--environment` flags, or through the `RACK_ENV` or the `RAILS_ENV` environment variables, Puma first looks for configuration at `config/puma/<environment_name>.rb`, and then falls back to `config/puma.rb`.
259
274
 
260
- If you want to prevent Puma from looking for a configuration file in those locations, provide a dash as the argument to the `-C` (or `--config`) flag:
275
+ If you want to prevent Puma from looking for a configuration file in those locations, include the `--no-config` flag:
261
276
 
262
277
  ```
278
+ $ puma --no-config
279
+
280
+ # or
281
+
263
282
  $ puma -C "-"
264
283
  ```
265
284
 
data/docs/deployment.md CHANGED
@@ -97,20 +97,5 @@ and use `runit` or hell, even `monit`.
97
97
  ## Restarting
98
98
 
99
99
  You probably will want to deploy some new code at some point, and you'd like
100
- puma to start running that new code. Minimizing the amount of time the server
101
- is unavailable would be nice as well. Here's how to do it:
102
-
103
- 1. Don't use `preload!`. This dirties the master process and means it will have
104
- to shutdown all the workers and re-exec itself to get your new code. It is not compatible with phased-restart and `prune_bundler` as well.
105
-
106
- 1. Use `prune_bundler`. This makes it so that the cluster master will detach itself
107
- from a Bundler context on start. This allows the cluster workers to load your app
108
- and start a brand new Bundler context within the worker only. This means your
109
- master remains pristine and can live on between new releases of your code.
110
-
111
- 1. Use phased-restart (`SIGUSR1` or `pumactl phased-restart`). This tells the master
112
- to kill off one worker at a time and restart them in your new code. This minimizes
113
- downtime and staggers the restart nicely. **WARNING** This means that both your
114
- old code and your new code will be running concurrently. Most deployment solutions
115
- already cause that, but it's worth warning you about it again. Be careful with your
116
- migrations, etc!
100
+ puma to start running that new code. There are a few options for restarting
101
+ puma, described separately in our [restart documentation](restart.md).
data/docs/systemd.md CHANGED
@@ -248,3 +248,4 @@ cap $stage puma:stop --dry-run
248
248
 
249
249
  [Restart]: https://www.freedesktop.org/software/systemd/man/systemd.service.html#Restart=
250
250
  [#1367]: https://github.com/puma/puma/issues/1367
251
+ [#1499]: https://github.com/puma/puma/issues/1499
@@ -11,9 +11,18 @@ end
11
11
  unless ENV["DISABLE_SSL"]
12
12
  dir_config("openssl")
13
13
 
14
- if %w'crypto libeay32'.find {|crypto| have_library(crypto, 'BIO_read')} and
14
+ found_ssl = if pkg_config 'openssl'
15
+ puts 'using OpenSSL pkgconfig (openssl.pc)'
16
+ true
17
+ elsif %w'crypto libeay32'.find {|crypto| have_library(crypto, 'BIO_read')} &&
15
18
  %w'ssl ssleay32'.find {|ssl| have_library(ssl, 'SSL_CTX_new')}
19
+ true
20
+ else
21
+ puts '** Puma will be compiled without SSL support'
22
+ false
23
+ end
16
24
 
25
+ if found_ssl
17
26
  have_header "openssl/bio.h"
18
27
 
19
28
  # below is yes for 1.0.2 & later
@@ -25,6 +34,14 @@ unless ENV["DISABLE_SSL"]
25
34
 
26
35
  have_func "X509_STORE_up_ref"
27
36
  have_func("SSL_CTX_set_ecdh_auto(NULL, 0)", "openssl/ssl.h")
37
+
38
+ # Random.bytes available in Ruby 2.5 and later, Random::DEFAULT deprecated in 3.0
39
+ if Random.respond_to?(:bytes)
40
+ $defs.push("-DHAVE_RANDOM_BYTES")
41
+ puts "checking for Random.bytes... yes"
42
+ else
43
+ puts "checking for Random.bytes... no"
44
+ end
28
45
  end
29
46
  end
30
47
 
@@ -208,7 +208,7 @@ sslctx_initialize(VALUE self, VALUE mini_ssl_ctx) {
208
208
  #endif
209
209
  int ssl_options;
210
210
  VALUE key, cert, ca, verify_mode, ssl_cipher_filter, no_tlsv1, no_tlsv1_1,
211
- verification_flags;
211
+ verification_flags, session_id_bytes;
212
212
  DH *dh;
213
213
 
214
214
  #if OPENSSL_VERSION_NUMBER < 0x10002000L
@@ -309,6 +309,21 @@ sslctx_initialize(VALUE self, VALUE mini_ssl_ctx) {
309
309
  } else {
310
310
  SSL_CTX_set_verify(ctx, NUM2INT(verify_mode), engine_verify_callback);
311
311
  }
312
+
313
+ // Random.bytes available in Ruby 2.5 and later, Random::DEFAULT deprecated in 3.0
314
+ session_id_bytes = rb_funcall(
315
+ #ifdef HAVE_RANDOM_BYTES
316
+ rb_cRandom,
317
+ #else
318
+ rb_const_get(rb_cRandom, rb_intern_const("DEFAULT")),
319
+ #endif
320
+ rb_intern_const("bytes"),
321
+ 1, ULL2NUM(SSL_MAX_SSL_SESSION_ID_LENGTH));
322
+
323
+ SSL_CTX_set_session_id_context(ctx,
324
+ (unsigned char *) RSTRING_PTR(session_id_bytes),
325
+ SSL_MAX_SSL_SESSION_ID_LENGTH);
326
+
312
327
  // printf("\ninitialize end security_level %d\n", SSL_CTX_get_security_level(ctx));
313
328
  rb_obj_freeze(self);
314
329
  return self;
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
- require 'puma/json'
2
+ require 'puma/json_serialization'
3
3
 
4
4
  module Puma
5
5
  module App
@@ -46,17 +46,17 @@ module Puma
46
46
  GC.start ; 200
47
47
 
48
48
  when 'gc-stats'
49
- Puma::JSON.generate GC.stat
49
+ Puma::JSONSerialization.generate GC.stat
50
50
 
51
51
  when 'stats'
52
- Puma::JSON.generate @launcher.stats
52
+ Puma::JSONSerialization.generate @launcher.stats
53
53
 
54
54
  when 'thread-backtraces'
55
55
  backtraces = []
56
56
  @launcher.thread_status do |name, backtrace|
57
57
  backtraces << { name: name, backtrace: backtrace }
58
58
  end
59
- Puma::JSON.generate backtraces
59
+ Puma::JSONSerialization.generate backtraces
60
60
 
61
61
  else
62
62
  return rack_response(404, "Unsupported action", 'text/plain')
data/lib/puma/binder.rb CHANGED
@@ -41,6 +41,7 @@ module Puma
41
41
  "rack.multithread".freeze => conf.options[:max_threads] > 1,
42
42
  "rack.multiprocess".freeze => conf.options[:workers] >= 1,
43
43
  "rack.run_once".freeze => false,
44
+ RACK_URL_SCHEME => conf.options[:rack_url_scheme],
44
45
  "SCRIPT_NAME".freeze => ENV['SCRIPT_NAME'] || "",
45
46
 
46
47
  # I'd like to set a default CONTENT_TYPE here but some things
@@ -56,6 +57,7 @@ module Puma
56
57
 
57
58
  @envs = {}
58
59
  @ios = []
60
+ localhost_authority
59
61
  end
60
62
 
61
63
  attr_reader :ios
@@ -95,6 +97,7 @@ module Puma
95
97
  # @version 5.0.0
96
98
  #
97
99
  def create_activated_fds(env_hash)
100
+ @events.debug "ENV['LISTEN_FDS'] #{ENV['LISTEN_FDS'].inspect} env_hash['LISTEN_PID'] #{env_hash['LISTEN_PID'].inspect}"
98
101
  return [] unless env_hash['LISTEN_FDS'] && env_hash['LISTEN_PID'].to_i == $$
99
102
  env_hash['LISTEN_FDS'].to_i.times do |index|
100
103
  sock = TCPServer.for_fd(socket_activation_fd(index))
@@ -163,7 +166,7 @@ module Puma
163
166
  ios_len = @ios.length
164
167
  params = Util.parse_query uri.query
165
168
 
166
- opt = params.key?('low_latency')
169
+ opt = params.key?('low_latency') && params['low_latency'] != 'false'
167
170
  bak = params.fetch('backlog', 1024).to_i
168
171
 
169
172
  io = add_tcp_listener uri.host, uri.port, opt, bak
@@ -188,7 +191,8 @@ module Puma
188
191
  @unix_paths << path unless abstract
189
192
  io = inherit_unix_listener path, fd
190
193
  logger.log "* Inherited #{str}"
191
- elsif sock = @activated_sockets.delete([ :unix, path ])
194
+ elsif sock = @activated_sockets.delete([ :unix, path ]) ||
195
+ @activated_sockets.delete([ :unix, File.realdirpath(path) ])
192
196
  @unix_paths << path unless abstract || File.exist?(path)
193
197
  io = inherit_unix_listener path, sock
194
198
  logger.log "* Activated #{str}"
@@ -224,7 +228,13 @@ module Puma
224
228
  raise "Puma compiled without SSL support" unless HAS_SSL
225
229
 
226
230
  params = Util.parse_query uri.query
227
- ctx = MiniSSL::ContextBuilder.new(params, @events).context
231
+
232
+ # If key and certs are not defined and localhost gem is required.
233
+ # localhost gem will be used for self signed
234
+ # Load localhost authority if not loaded.
235
+ ctx = localhost_authority && localhost_authority_context if params.empty?
236
+
237
+ ctx ||= MiniSSL::ContextBuilder.new(params, @events).context
228
238
 
229
239
  if fd = @inherited_fds.delete(str)
230
240
  logger.log "* Inherited #{str}"
@@ -282,6 +292,22 @@ module Puma
282
292
  end
283
293
  end
284
294
 
295
+ def localhost_authority
296
+ @localhost_authority ||= Localhost::Authority.fetch if defined?(Localhost::Authority) && !Puma::IS_JRUBY
297
+ end
298
+
299
+ def localhost_authority_context
300
+ return unless localhost_authority
301
+
302
+ key_path, crt_path = if [:key_path, :certificate_path].all? { |m| localhost_authority.respond_to?(m) }
303
+ [localhost_authority.key_path, localhost_authority.certificate_path]
304
+ else
305
+ local_certificates_path = File.expand_path("~/.localhost")
306
+ [File.join(local_certificates_path, "localhost.key"), File.join(local_certificates_path, "localhost.crt")]
307
+ end
308
+ MiniSSL::ContextBuilder.new({ "key" => key_path, "cert" => crt_path }, @events).context
309
+ end
310
+
285
311
  # Tell the server to listen on host +host+, port +port+.
286
312
  # If +optimize_for_latency+ is true (the default) then clients connecting
287
313
  # will be optimized for latency over throughput.
@@ -299,6 +325,7 @@ module Puma
299
325
 
300
326
  host = host[1..-2] if host and host[0..0] == '['
301
327
  tcp_server = TCPServer.new(host, port)
328
+
302
329
  if optimize_for_latency
303
330
  tcp_server.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1)
304
331
  end
@@ -320,6 +347,8 @@ module Puma
320
347
  optimize_for_latency=true, backlog=1024)
321
348
 
322
349
  raise "Puma compiled without SSL support" unless HAS_SSL
350
+ # Puma will try to use local authority context if context is supplied nil
351
+ ctx ||= localhost_authority_context
323
352
 
324
353
  if host == "localhost"
325
354
  loopback_addresses.each do |addr|
@@ -347,6 +376,8 @@ module Puma
347
376
 
348
377
  def inherit_ssl_listener(fd, ctx)
349
378
  raise "Puma compiled without SSL support" unless HAS_SSL
379
+ # Puma will try to use local authority context if context is supplied nil
380
+ ctx ||= localhost_authority_context
350
381
 
351
382
  s = fd.kind_of?(::TCPServer) ? fd : ::TCPServer.for_fd(fd)
352
383
 
data/lib/puma/cli.rb CHANGED
@@ -112,6 +112,11 @@ module Puma
112
112
  file_config.load arg
113
113
  end
114
114
 
115
+ # Identical to supplying --config "-", but more semantic
116
+ o.on "--no-config", "Prevent Puma from searching for a config file" do |arg|
117
+ file_config.load "-"
118
+ end
119
+
115
120
  o.on "--control-url URL", "The bind url to use for the control server. Use 'auto' to use temp unix server" do |arg|
116
121
  configure_control_url(arg)
117
122
  end
data/lib/puma/client.rb CHANGED
@@ -56,6 +56,7 @@ module Puma
56
56
  @parser = HttpParser.new
57
57
  @parsed_bytes = 0
58
58
  @read_header = true
59
+ @read_proxy = false
59
60
  @ready = false
60
61
 
61
62
  @body = nil
@@ -69,7 +70,9 @@ module Puma
69
70
  @hijacked = false
70
71
 
71
72
  @peerip = nil
73
+ @listener = nil
72
74
  @remote_addr_header = nil
75
+ @expect_proxy_proto = false
73
76
 
74
77
  @body_remain = 0
75
78
 
@@ -81,7 +84,7 @@ module Puma
81
84
 
82
85
  attr_writer :peerip
83
86
 
84
- attr_accessor :remote_addr_header
87
+ attr_accessor :remote_addr_header, :listener
85
88
 
86
89
  def_delegators :@io, :closed?
87
90
 
@@ -105,7 +108,7 @@ module Puma
105
108
 
106
109
  # @!attribute [r] in_data_phase
107
110
  def in_data_phase
108
- !@read_header
111
+ !(@read_header || @read_proxy)
109
112
  end
110
113
 
111
114
  def set_timeout(val)
@@ -120,6 +123,7 @@ module Puma
120
123
  def reset(fast_check=true)
121
124
  @parser.reset
122
125
  @read_header = true
126
+ @read_proxy = !!@expect_proxy_proto
123
127
  @env = @proto_env.dup
124
128
  @body = nil
125
129
  @tempfile = nil
@@ -130,6 +134,8 @@ module Puma
130
134
  @in_last_chunk = false
131
135
 
132
136
  if @buffer
137
+ return false unless try_to_parse_proxy_protocol
138
+
133
139
  @parsed_bytes = @parser.execute(@env, @buffer, @parsed_bytes)
134
140
 
135
141
  if @parser.finished?
@@ -142,8 +148,7 @@ module Puma
142
148
  return false
143
149
  else
144
150
  begin
145
- if fast_check &&
146
- IO.select([@to_io], nil, nil, FAST_TRACK_KA_TIMEOUT)
151
+ if fast_check && @to_io.wait_readable(FAST_TRACK_KA_TIMEOUT)
147
152
  return try_to_finish
148
153
  end
149
154
  rescue IOError
@@ -161,8 +166,32 @@ module Puma
161
166
  end
162
167
  end
163
168
 
169
+ # If necessary, read the PROXY protocol from the buffer. Returns
170
+ # false if more data is needed.
171
+ def try_to_parse_proxy_protocol
172
+ if @read_proxy
173
+ if @expect_proxy_proto == :v1
174
+ if @buffer.include? "\r\n"
175
+ if md = PROXY_PROTOCOL_V1_REGEX.match(@buffer)
176
+ if md[1]
177
+ @peerip = md[1].split(" ")[0]
178
+ end
179
+ @buffer = md.post_match
180
+ end
181
+ # if the buffer has a \r\n but doesn't have a PROXY protocol
182
+ # request, this is just HTTP from a non-PROXY client; move on
183
+ @read_proxy = false
184
+ return @buffer.size > 0
185
+ else
186
+ return false
187
+ end
188
+ end
189
+ end
190
+ true
191
+ end
192
+
164
193
  def try_to_finish
165
- return read_body unless @read_header
194
+ return read_body if in_data_phase
166
195
 
167
196
  begin
168
197
  data = @io.read_nonblock(CHUNK_SIZE)
@@ -187,6 +216,8 @@ module Puma
187
216
  @buffer = data
188
217
  end
189
218
 
219
+ return false unless try_to_parse_proxy_protocol
220
+
190
221
  @parsed_bytes = @parser.execute(@env, @buffer, @parsed_bytes)
191
222
 
192
223
  if @parser.finished?
@@ -201,13 +232,13 @@ module Puma
201
232
 
202
233
  def eagerly_finish
203
234
  return true if @ready
204
- return false unless IO.select([@to_io], nil, nil, 0)
235
+ return false unless @to_io.wait_readable(0)
205
236
  try_to_finish
206
237
  end
207
238
 
208
239
  def finish(timeout)
209
240
  return if @ready
210
- IO.select([@to_io], nil, nil, timeout) || timeout! until try_to_finish
241
+ @to_io.wait_readable(timeout) || timeout! until try_to_finish
211
242
  end
212
243
 
213
244
  def timeout!
@@ -243,6 +274,17 @@ module Puma
243
274
  @parsed_bytes == 0
244
275
  end
245
276
 
277
+ def expect_proxy_proto=(val)
278
+ if val
279
+ if @read_header
280
+ @read_proxy = true
281
+ end
282
+ else
283
+ @read_proxy = false
284
+ end
285
+ @expect_proxy_proto = val
286
+ end
287
+
246
288
  private
247
289
 
248
290
  def setup_body
@@ -308,7 +350,7 @@ module Puma
308
350
 
309
351
  @body_remain = remain
310
352
 
311
- return false
353
+ false
312
354
  end
313
355
 
314
356
  def read_body
@@ -33,9 +33,9 @@ module Puma
33
33
  Signal.trap "SIGINT", "IGNORE"
34
34
  Signal.trap "SIGCHLD", "DEFAULT"
35
35
 
36
- Thread.new do
36
+ Thread.new do
37
37
  Puma.set_thread_name "worker check pipe"
38
- IO.select [@check_pipe]
38
+ @check_pipe.wait_readable
39
39
  log "! Detected parent died, dying"
40
40
  exit! 1
41
41
  end
@@ -54,7 +54,14 @@ module Puma
54
54
  # things in shape before booting the app.
55
55
  @launcher.config.run_hooks :before_worker_boot, index, @launcher.events
56
56
 
57
+ begin
57
58
  server = @server ||= start_server
59
+ rescue Exception => e
60
+ log "! Unable to start worker"
61
+ log e.backtrace[0]
62
+ exit 1
63
+ end
64
+
58
65
  restart_server = Queue.new << true << false
59
66
 
60
67
  fork_worker = @options[:fork_worker] && index == 0
data/lib/puma/cluster.rb CHANGED
@@ -426,9 +426,7 @@ module Puma
426
426
 
427
427
  check_workers
428
428
 
429
- res = IO.select([read], nil, nil, [0, @next_check - Time.now].max)
430
-
431
- if res
429
+ if read.wait_readable([0, @next_check - Time.now].max)
432
430
  req = read.read_nonblock(1)
433
431
 
434
432
  @next_check = Time.now if req == "!"
@@ -343,6 +343,8 @@ module Puma
343
343
  raise "Missing rackup file '#{rackup}'" unless File.exist?(rackup)
344
344
 
345
345
  rack_app, rack_options = rack_builder.parse_file(rackup)
346
+ rack_options = rack_options || {}
347
+
346
348
  @options.file_options.merge!(rack_options)
347
349
 
348
350
  config_ru_binds = []
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.3.0".freeze
104
- CODE_NAME = "Sweetnighter".freeze
103
+ PUMA_VERSION = VERSION = "5.5.0".freeze
104
+ CODE_NAME = "Zawgyi".freeze
105
105
 
106
106
  PUMA_SERVER_STRING = ['puma', PUMA_VERSION, CODE_NAME].join(' ').freeze
107
107
 
@@ -247,5 +247,7 @@ module Puma
247
247
 
248
248
  # Banned keys of response header
249
249
  BANNED_HEADER_KEY = /\A(rack\.|status\z)/.freeze
250
+
251
+ PROXY_PROTOCOL_V1_REGEX = /^PROXY (?:TCP4|TCP6|UNKNOWN) ([^\r]+)\r\n/.freeze
250
252
  end
251
253
  end
data/lib/puma/dsl.rb CHANGED
@@ -201,7 +201,7 @@ module Puma
201
201
  # * Set the socket backlog depth with +backlog+, default is 1024.
202
202
  # * Set up an SSL certificate with +key+ & +cert+.
203
203
  # * Set whether to optimize for low latency instead of throughput with
204
- # +low_latency+, default is to optimize for low latency. This is done
204
+ # +low_latency+, default is to not optimize for low latency. This is done
205
205
  # via +Socket::TCP_NODELAY+.
206
206
  # * Set socket permissions with +umask+.
207
207
  #
@@ -381,6 +381,13 @@ module Puma
381
381
  @options[:rackup] ||= path.to_s
382
382
  end
383
383
 
384
+ # Allows setting `env['rack.url_scheme']`.
385
+ # Only necessary if X-Forwarded-Proto is not being set by your proxy
386
+ # Normal values are 'http' or 'https'.
387
+ def rack_url_scheme(scheme=nil)
388
+ @options[:rack_url_scheme] = scheme
389
+ end
390
+
384
391
  def early_hints(answer=true)
385
392
  @options[:early_hints] = answer
386
393
  end
@@ -578,7 +585,7 @@ module Puma
578
585
  # end
579
586
  def after_worker_fork(&block)
580
587
  @options[:after_worker_fork] ||= []
581
- @options[:after_worker_fork] = block
588
+ @options[:after_worker_fork] << block
582
589
  end
583
590
 
584
591
  alias_method :after_worker_boot, :after_worker_fork
@@ -811,7 +818,7 @@ module Puma
811
818
  # a kernel syscall is required which for very fast rack handlers
812
819
  # slows down the handling significantly.
813
820
  #
814
- # There are 4 possible values:
821
+ # There are 5 possible values:
815
822
  #
816
823
  # 1. **:socket** (the default) - read the peername from the socket using the
817
824
  # syscall. This is the normal behavior.
@@ -821,7 +828,10 @@ module Puma
821
828
  # `set_remote_address header: "X-Real-IP"`.
822
829
  # Only the first word (as separated by spaces or comma) is used, allowing
823
830
  # headers such as X-Forwarded-For to be used as well.
824
- # 4. **\<Any string\>** - this allows you to hardcode remote address to any value
831
+ # 4. **proxy_protocol: :v1**- set the remote address to the value read from the
832
+ # HAproxy PROXY protocol, version 1. If the request does not have the PROXY
833
+ # protocol attached to it, will fall back to :socket
834
+ # 5. **\<Any string\>** - this allows you to hardcode remote address to any value
825
835
  # you wish. Because Puma never uses this field anyway, it's format is
826
836
  # entirely in your hands.
827
837
  #
@@ -839,6 +849,13 @@ module Puma
839
849
  if hdr = val[:header]
840
850
  @options[:remote_address] = :header
841
851
  @options[:remote_address_header] = "HTTP_" + hdr.upcase.tr("-", "_")
852
+ elsif protocol_version = val[:proxy_protocol]
853
+ @options[:remote_address] = :proxy_protocol
854
+ protocol_version = protocol_version.downcase.to_sym
855
+ unless [:v1].include?(protocol_version)
856
+ raise "Invalid value for proxy_protocol - #{protocol_version.inspect}"
857
+ end
858
+ @options[:remote_address_proxy_protocol] = protocol_version
842
859
  else
843
860
  raise "Invalid value for set_remote_address - #{val.inspect}"
844
861
  end
@@ -17,7 +17,7 @@ module Puma
17
17
  # be particularly full-featured or fast. It just has to handle the few places
18
18
  # where Puma relies on JSON serialization internally.
19
19
 
20
- module JSON
20
+ module JSONSerialization
21
21
  QUOTE = /"/
22
22
  BACKSLASH = /\\/
23
23
  CONTROL_CHAR_TO_ESCAPE = /[\x00-\x1F]/ # As required by ECMA-404
data/lib/puma/launcher.rb CHANGED
@@ -319,10 +319,12 @@ module Puma
319
319
  log '* Pruning Bundler environment'
320
320
  home = ENV['GEM_HOME']
321
321
  bundle_gemfile = Bundler.original_env['BUNDLE_GEMFILE']
322
+ bundle_app_config = Bundler.original_env['BUNDLE_APP_CONFIG']
322
323
  with_unbundled_env do
323
324
  ENV['GEM_HOME'] = home
324
325
  ENV['BUNDLE_GEMFILE'] = bundle_gemfile
325
326
  ENV['PUMA_BUNDLER_PRUNED'] = '1'
327
+ ENV["BUNDLE_APP_CONFIG"] = bundle_app_config
326
328
  args = [Gem.ruby, puma_wild_location, '-I', dirs.join(':')] + @original_argv
327
329
  # Ruby 2.0+ defaults to true which breaks socket activation
328
330
  args += [{:close_others => false}]
data/lib/puma/minissl.rb CHANGED
@@ -161,28 +161,13 @@ module Puma
161
161
  @socket.flush
162
162
  end
163
163
 
164
- def read_and_drop(timeout = 1)
165
- return :timeout unless IO.select([@socket], nil, nil, timeout)
166
- case @socket.read_nonblock(1024, exception: false)
167
- when nil
168
- :eof
169
- when :wait_readable
170
- :eagain
171
- else
172
- :drop
173
- end
174
- end
175
-
176
- def should_drop_bytes?
177
- @engine.init? || !@engine.shutdown
178
- end
179
-
180
164
  def close
181
165
  begin
182
- # Read any drop any partially initialized sockets and any received bytes during shutdown.
183
- # Don't let this socket hold this loop forever.
184
- # If it can't send more packets within 1s, then give up.
185
- return if [:timeout, :eof].include?(read_and_drop(1)) while should_drop_bytes?
166
+ unless @engine.shutdown
167
+ while alert_data = @engine.extract
168
+ @socket.write alert_data
169
+ end
170
+ end
186
171
  rescue IOError, SystemCallError
187
172
  Thread.current.purge_interrupt_queue if Thread.current.respond_to? :purge_interrupt_queue
188
173
  # nothing
data/lib/puma/plugin.rb CHANGED
@@ -91,7 +91,7 @@ module Puma
91
91
  path = ary.first[CALLER_FILE]
92
92
 
93
93
  m = %r!puma/plugin/([^/]*)\.rb$!.match(path)
94
- return m[1]
94
+ m[1]
95
95
  end
96
96
 
97
97
  def self.create(&blk)
Binary file
@@ -165,7 +165,7 @@ module Puma::Rack
165
165
  require config
166
166
  app = Object.const_get(::File.basename(config, '.rb').capitalize)
167
167
  end
168
- return app, options
168
+ [app, options]
169
169
  end
170
170
 
171
171
  def self.new_from_string(builder_script, file="(rackup)")
data/lib/puma/request.rb CHANGED
@@ -26,9 +26,10 @@ module Puma
26
26
  # Finally, it'll return +true+ on keep-alive connections.
27
27
  # @param client [Puma::Client]
28
28
  # @param lines [Puma::IOBuffer]
29
+ # @param requests [Integer]
29
30
  # @return [Boolean,:async]
30
31
  #
31
- def handle_request(client, lines)
32
+ def handle_request(client, lines, requests)
32
33
  env = client.env
33
34
  io = client.io # io may be a MiniSSL::Socket
34
35
 
@@ -50,7 +51,7 @@ module Puma
50
51
  head = env[REQUEST_METHOD] == HEAD
51
52
 
52
53
  env[RACK_INPUT] = body
53
- env[RACK_URL_SCHEME] = default_server_port(env) == PORT_443 ? HTTPS : HTTP
54
+ env[RACK_URL_SCHEME] ||= default_server_port(env) == PORT_443 ? HTTPS : HTTP
54
55
 
55
56
  if @early_hints
56
57
  env[EARLY_HINTS] = lambda { |headers|
@@ -110,7 +111,7 @@ module Puma
110
111
 
111
112
  cork_socket io
112
113
 
113
- str_headers(env, status, headers, res_info, lines)
114
+ str_headers(env, status, headers, res_info, lines, requests, client)
114
115
 
115
116
  line_ending = LINE_END
116
117
 
@@ -175,7 +176,7 @@ module Puma
175
176
  after_reply.each { |o| o.call }
176
177
  end
177
178
 
178
- return res_info[:keep_alive]
179
+ res_info[:keep_alive]
179
180
  end
180
181
 
181
182
  # @param env [Hash] see Puma::Client#env, from request
@@ -200,7 +201,7 @@ module Puma
200
201
  begin
201
202
  n = io.syswrite str
202
203
  rescue Errno::EAGAIN, Errno::EWOULDBLOCK
203
- if !IO.select(nil, [io], nil, WRITE_TIMEOUT)
204
+ unless io.wait_writable WRITE_TIMEOUT
204
205
  raise ConnectionError, "Socket timeout writing data"
205
206
  end
206
207
 
@@ -367,9 +368,11 @@ module Puma
367
368
  # @param headers [Hash] the headers returned by the Rack application
368
369
  # @param res_info [Hash] used to pass info between this method and #handle_request
369
370
  # @param lines [Puma::IOBuffer] modified inn place
371
+ # @param requests [Integer] number of inline requests handled
372
+ # @param client [Puma::Client]
370
373
  # @version 5.0.3
371
374
  #
372
- def str_headers(env, status, headers, res_info, lines)
375
+ def str_headers(env, status, headers, res_info, lines, requests, client)
373
376
  line_ending = LINE_END
374
377
  colon = COLON
375
378
 
@@ -410,6 +413,14 @@ module Puma
410
413
  # if running without request queueing
411
414
  res_info[:keep_alive] &&= @queue_requests
412
415
 
416
+ # Close the connection after a reasonable number of inline requests
417
+ # if the server is at capacity and the listener has a new connection ready.
418
+ # This allows Puma to service connections fairly when the number
419
+ # of concurrent connections exceeds the size of the threadpool.
420
+ res_info[:keep_alive] &&= requests < @max_fast_inline ||
421
+ @thread_pool.busy_threads < @max_threads ||
422
+ !client.listener.to_io.wait_readable(0)
423
+
413
424
  res_info[:response_hijack] = nil
414
425
 
415
426
  headers.each do |k, vs|
data/lib/puma/server.rb CHANGED
@@ -14,6 +14,7 @@ require 'puma/io_buffer'
14
14
  require 'puma/request'
15
15
 
16
16
  require 'socket'
17
+ require 'io/wait'
17
18
  require 'forwardable'
18
19
 
19
20
  module Puma
@@ -227,6 +228,7 @@ module Puma
227
228
  @status = :run
228
229
 
229
230
  @thread_pool = ThreadPool.new(
231
+ thread_name,
230
232
  @min_threads,
231
233
  @max_threads,
232
234
  ::Puma::IOBuffer,
@@ -321,6 +323,8 @@ module Puma
321
323
  remote_addr_value = @options[:remote_address_value]
322
324
  when :header
323
325
  remote_addr_header = @options[:remote_address_header]
326
+ when :proxy_protocol
327
+ remote_addr_proxy_protocol = @options[:remote_address_proxy_protocol]
324
328
  end
325
329
 
326
330
  while @status == :run || (drain && shutting_down?)
@@ -341,15 +345,21 @@ module Puma
341
345
  end
342
346
  drain += 1 if shutting_down?
343
347
  client = Client.new io, @binder.env(sock)
348
+ client.listener = sock
344
349
  if remote_addr_value
345
350
  client.peerip = remote_addr_value
346
351
  elsif remote_addr_header
347
352
  client.remote_addr_header = remote_addr_header
353
+ elsif remote_addr_proxy_protocol
354
+ client.expect_proxy_proto = remote_addr_proxy_protocol
348
355
  end
349
356
  pool << client
350
357
  end
351
358
  end
352
- rescue Object => e
359
+ rescue IOError, Errno::EBADF
360
+ # In the case that any of the sockets are unexpectedly close.
361
+ raise
362
+ rescue StandardError => e
353
363
  @events.unknown_error e, nil, "Listen loop"
354
364
  end
355
365
  end
@@ -395,7 +405,7 @@ module Puma
395
405
  return true
396
406
  end
397
407
 
398
- return false
408
+ false
399
409
  end
400
410
 
401
411
  # Given a connection on +client+, handle the incoming requests,
@@ -434,7 +444,7 @@ module Puma
434
444
 
435
445
  while true
436
446
  @requests_count += 1
437
- case handle_request(client, buffer)
447
+ case handle_request(client, buffer, requests + 1)
438
448
  when false
439
449
  break
440
450
  when :async
@@ -447,18 +457,17 @@ module Puma
447
457
 
448
458
  requests += 1
449
459
 
450
- check_for_more_data = @status == :run
460
+ # As an optimization, try to read the next request from the
461
+ # socket for a short time before returning to the reactor.
462
+ fast_check = @status == :run
451
463
 
452
- if requests >= @max_fast_inline
453
- # This will mean that reset will only try to use the data it already
454
- # has buffered and won't try to read more data. What this means is that
455
- # every client, independent of their request speed, gets treated like a slow
456
- # one once every max_fast_inline requests.
457
- check_for_more_data = false
458
- end
464
+ # Always pass the client back to the reactor after a reasonable
465
+ # number of inline requests if there are other requests pending.
466
+ fast_check = false if requests >= @max_fast_inline &&
467
+ @thread_pool.backlog > 0
459
468
 
460
469
  next_request_ready = with_force_shutdown(client) do
461
- client.reset(check_for_more_data)
470
+ client.reset(fast_check)
462
471
  end
463
472
 
464
473
  unless next_request_ready
@@ -29,7 +29,7 @@ module Puma
29
29
  # The block passed is the work that will be performed in each
30
30
  # thread.
31
31
  #
32
- def initialize(min, max, *extra, &block)
32
+ def initialize(name, min, max, *extra, &block)
33
33
  @not_empty = ConditionVariable.new
34
34
  @not_full = ConditionVariable.new
35
35
  @mutex = Mutex.new
@@ -39,6 +39,7 @@ module Puma
39
39
  @spawned = 0
40
40
  @waiting = 0
41
41
 
42
+ @name = name
42
43
  @min = Integer(min)
43
44
  @max = Integer(max)
44
45
  @block = block
@@ -101,7 +102,7 @@ module Puma
101
102
  @spawned += 1
102
103
 
103
104
  th = Thread.new(@spawned) do |spawned|
104
- Puma.set_thread_name 'threadpool %03i' % spawned
105
+ Puma.set_thread_name '%s threadpool %03i' % [@name, spawned]
105
106
  todo = @todo
106
107
  block = @block
107
108
  mutex = @mutex
@@ -119,6 +120,7 @@ module Puma
119
120
  @trim_requested -= 1
120
121
  @spawned -= 1
121
122
  @workers.delete th
123
+ not_full.signal
122
124
  Thread.exit
123
125
  end
124
126
 
@@ -318,12 +320,12 @@ module Puma
318
320
  end
319
321
 
320
322
  def auto_trim!(timeout=30)
321
- @auto_trim = Automaton.new(self, timeout, "threadpool trimmer", :trim)
323
+ @auto_trim = Automaton.new(self, timeout, "#{@name} threadpool trimmer", :trim)
322
324
  @auto_trim.start!
323
325
  end
324
326
 
325
327
  def auto_reap!(timeout=5)
326
- @reaper = Automaton.new(self, timeout, "threadpool reaper", :reap)
328
+ @reaper = Automaton.new(self, timeout, "#{@name} threadpool reaper", :reap)
327
329
  @reaper.start!
328
330
  end
329
331
 
data/lib/puma/util.rb CHANGED
@@ -61,7 +61,7 @@ module Puma
61
61
  end
62
62
  end
63
63
 
64
- return params
64
+ params
65
65
  end
66
66
 
67
67
  # A case-insensitive Hash that preserves the original case of a
data/lib/puma.rb CHANGED
@@ -12,7 +12,7 @@ require 'thread'
12
12
 
13
13
  require 'puma/puma_http11'
14
14
  require 'puma/detect'
15
- require 'puma/json'
15
+ require 'puma/json_serialization'
16
16
 
17
17
  module Puma
18
18
  autoload :Const, 'puma/const'
@@ -60,7 +60,7 @@ module Puma
60
60
 
61
61
  # @!attribute [rw] stats_object
62
62
  def self.stats
63
- Puma::JSON.generate @get_stats.stats
63
+ Puma::JSONSerialization.generate @get_stats.stats
64
64
  end
65
65
 
66
66
  # @!attribute [r] stats_hash
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.3.0
4
+ version: 5.5.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: 2021-05-07 00:00:00.000000000 Z
11
+ date: 2021-09-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  requirement: !ruby/object:Gem::Requirement
@@ -24,9 +24,9 @@ dependencies:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
26
  version: '2.0'
27
- description: Puma is a simple, fast, threaded, and highly concurrent HTTP 1.1 server
27
+ description: Puma is a simple, fast, threaded, and highly parallel HTTP 1.1 server
28
28
  for Ruby/Rack applications. Puma is intended for use in both development and production
29
- environments. It's great for highly concurrent Ruby implementations such as Rubinius
29
+ environments. It's great for highly parallel Ruby implementations such as Rubinius
30
30
  and JRuby as well as as providing process worker support to support CRuby well.
31
31
  email:
32
32
  - evan@phx.io
@@ -93,7 +93,7 @@ files:
93
93
  - lib/puma/events.rb
94
94
  - lib/puma/io_buffer.rb
95
95
  - lib/puma/jruby_restart.rb
96
- - lib/puma/json.rb
96
+ - lib/puma/json_serialization.rb
97
97
  - lib/puma/launcher.rb
98
98
  - lib/puma/minissl.rb
99
99
  - lib/puma/minissl/context_builder.rb
@@ -143,6 +143,6 @@ requirements: []
143
143
  rubygems_version: 3.1.6
144
144
  signing_key:
145
145
  specification_version: 4
146
- summary: Puma is a simple, fast, threaded, and highly concurrent HTTP 1.1 server for
146
+ summary: Puma is a simple, fast, threaded, and highly parallel HTTP 1.1 server for
147
147
  Ruby/Rack applications
148
148
  test_files: []