puma 5.0.0-java → 5.1.0-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.
Potentially problematic release.
This version of puma might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/History.md +1190 -574
- data/README.md +28 -20
- data/bin/puma-wild +3 -9
- data/docs/compile_options.md +19 -0
- data/docs/deployment.md +5 -6
- data/docs/fork_worker.md +2 -0
- data/docs/jungle/README.md +0 -4
- data/docs/jungle/rc.d/puma +2 -2
- data/docs/nginx.md +1 -1
- data/docs/restart.md +46 -23
- data/docs/systemd.md +25 -3
- data/ext/puma_http11/ext_help.h +1 -1
- data/ext/puma_http11/extconf.rb +4 -5
- data/ext/puma_http11/http11_parser.c +64 -64
- data/ext/puma_http11/mini_ssl.c +39 -37
- data/ext/puma_http11/puma_http11.c +25 -12
- data/lib/puma.rb +7 -4
- data/lib/puma/app/status.rb +44 -46
- data/lib/puma/binder.rb +48 -1
- data/lib/puma/cli.rb +4 -0
- data/lib/puma/client.rb +31 -80
- data/lib/puma/cluster.rb +39 -202
- data/lib/puma/cluster/worker.rb +176 -0
- data/lib/puma/cluster/worker_handle.rb +86 -0
- data/lib/puma/configuration.rb +20 -8
- data/lib/puma/const.rb +11 -3
- data/lib/puma/control_cli.rb +71 -70
- data/lib/puma/dsl.rb +67 -19
- data/lib/puma/error_logger.rb +2 -2
- data/lib/puma/events.rb +21 -3
- data/lib/puma/json.rb +96 -0
- data/lib/puma/launcher.rb +61 -12
- data/lib/puma/minissl.rb +8 -0
- data/lib/puma/puma_http11.jar +0 -0
- data/lib/puma/queue_close.rb +26 -0
- data/lib/puma/reactor.rb +79 -373
- data/lib/puma/request.rb +451 -0
- data/lib/puma/runner.rb +15 -21
- data/lib/puma/server.rb +193 -508
- data/lib/puma/single.rb +3 -2
- data/lib/puma/state_file.rb +5 -3
- data/lib/puma/systemd.rb +46 -0
- data/lib/puma/thread_pool.rb +22 -2
- data/lib/puma/util.rb +12 -0
- metadata +9 -6
- data/docs/jungle/upstart/README.md +0 -61
- data/docs/jungle/upstart/puma-manager.conf +0 -31
- data/docs/jungle/upstart/puma.conf +0 -69
- data/lib/puma/accept_nonblock.rb +0 -29
data/ext/puma_http11/mini_ssl.c
CHANGED
@@ -2,12 +2,7 @@
|
|
2
2
|
|
3
3
|
#include <ruby.h>
|
4
4
|
#include <ruby/version.h>
|
5
|
-
|
6
|
-
#if RUBY_API_VERSION_MAJOR == 1
|
7
|
-
#include <rubyio.h>
|
8
|
-
#else
|
9
5
|
#include <ruby/io.h>
|
10
|
-
#endif
|
11
6
|
|
12
7
|
#ifdef HAVE_OPENSSL_BIO_H
|
13
8
|
|
@@ -33,7 +28,8 @@ typedef struct {
|
|
33
28
|
int bytes;
|
34
29
|
} ms_cert_buf;
|
35
30
|
|
36
|
-
void engine_free(
|
31
|
+
void engine_free(void *ptr) {
|
32
|
+
ms_conn *conn = ptr;
|
37
33
|
ms_cert_buf* cert_buf = (ms_cert_buf*)SSL_get_app_data(conn->ssl);
|
38
34
|
if(cert_buf) {
|
39
35
|
OPENSSL_free(cert_buf->buf);
|
@@ -45,10 +41,16 @@ void engine_free(ms_conn* conn) {
|
|
45
41
|
free(conn);
|
46
42
|
}
|
47
43
|
|
44
|
+
const rb_data_type_t engine_data_type = {
|
45
|
+
"MiniSSL/ENGINE",
|
46
|
+
{ 0, engine_free, 0 },
|
47
|
+
0, 0, RUBY_TYPED_FREE_IMMEDIATELY,
|
48
|
+
};
|
49
|
+
|
48
50
|
ms_conn* engine_alloc(VALUE klass, VALUE* obj) {
|
49
51
|
ms_conn* conn;
|
50
52
|
|
51
|
-
*obj =
|
53
|
+
*obj = TypedData_Make_Struct(klass, ms_conn, &engine_data_type, conn);
|
52
54
|
|
53
55
|
conn->read = BIO_new(BIO_s_mem());
|
54
56
|
BIO_set_nbio(conn->read, 1);
|
@@ -198,7 +200,7 @@ VALUE engine_init_server(VALUE self, VALUE mini_ssl_ctx) {
|
|
198
200
|
else {
|
199
201
|
min = TLS1_VERSION;
|
200
202
|
}
|
201
|
-
|
203
|
+
|
202
204
|
SSL_CTX_set_min_proto_version(ctx, min);
|
203
205
|
|
204
206
|
SSL_CTX_set_options(ctx, ssl_options);
|
@@ -281,7 +283,7 @@ VALUE engine_inject(VALUE self, VALUE str) {
|
|
281
283
|
ms_conn* conn;
|
282
284
|
long used;
|
283
285
|
|
284
|
-
|
286
|
+
TypedData_Get_Struct(self, ms_conn, &engine_data_type, conn);
|
285
287
|
|
286
288
|
StringValue(str);
|
287
289
|
|
@@ -334,7 +336,7 @@ VALUE engine_read(VALUE self) {
|
|
334
336
|
char buf[512];
|
335
337
|
int bytes, error;
|
336
338
|
|
337
|
-
|
339
|
+
TypedData_Get_Struct(self, ms_conn, &engine_data_type, conn);
|
338
340
|
|
339
341
|
ERR_clear_error();
|
340
342
|
|
@@ -361,7 +363,7 @@ VALUE engine_write(VALUE self, VALUE str) {
|
|
361
363
|
ms_conn* conn;
|
362
364
|
int bytes;
|
363
365
|
|
364
|
-
|
366
|
+
TypedData_Get_Struct(self, ms_conn, &engine_data_type, conn);
|
365
367
|
|
366
368
|
StringValue(str);
|
367
369
|
|
@@ -385,7 +387,7 @@ VALUE engine_extract(VALUE self) {
|
|
385
387
|
size_t pending;
|
386
388
|
char buf[512];
|
387
389
|
|
388
|
-
|
390
|
+
TypedData_Get_Struct(self, ms_conn, &engine_data_type, conn);
|
389
391
|
|
390
392
|
pending = BIO_pending(conn->write);
|
391
393
|
if(pending > 0) {
|
@@ -404,7 +406,7 @@ VALUE engine_shutdown(VALUE self) {
|
|
404
406
|
ms_conn* conn;
|
405
407
|
int ok;
|
406
408
|
|
407
|
-
|
409
|
+
TypedData_Get_Struct(self, ms_conn, &engine_data_type, conn);
|
408
410
|
|
409
411
|
ERR_clear_error();
|
410
412
|
|
@@ -419,7 +421,7 @@ VALUE engine_shutdown(VALUE self) {
|
|
419
421
|
VALUE engine_init(VALUE self) {
|
420
422
|
ms_conn* conn;
|
421
423
|
|
422
|
-
|
424
|
+
TypedData_Get_Struct(self, ms_conn, &engine_data_type, conn);
|
423
425
|
|
424
426
|
return SSL_in_init(conn->ssl) ? Qtrue : Qfalse;
|
425
427
|
}
|
@@ -432,7 +434,7 @@ VALUE engine_peercert(VALUE self) {
|
|
432
434
|
ms_cert_buf* cert_buf = NULL;
|
433
435
|
VALUE rb_cert_buf;
|
434
436
|
|
435
|
-
|
437
|
+
TypedData_Get_Struct(self, ms_conn, &engine_data_type, conn);
|
436
438
|
|
437
439
|
cert = SSL_get_peer_certificate(conn->ssl);
|
438
440
|
if(!cert) {
|
@@ -469,7 +471,7 @@ VALUE engine_peercert(VALUE self) {
|
|
469
471
|
static VALUE
|
470
472
|
engine_ssl_vers_st(VALUE self) {
|
471
473
|
ms_conn* conn;
|
472
|
-
|
474
|
+
TypedData_Get_Struct(self, ms_conn, &engine_data_type, conn);
|
473
475
|
return rb_ary_new3(2, rb_str_new2(SSL_get_version(conn->ssl)), rb_str_new2(SSL_state_string(conn->ssl)));
|
474
476
|
}
|
475
477
|
|
@@ -504,27 +506,27 @@ void Init_mini_ssl(VALUE puma) {
|
|
504
506
|
#else
|
505
507
|
rb_define_const(mod, "OPENSSL_LIBRARY_VERSION", rb_str_new2(SSLeay_version(SSLEAY_VERSION)));
|
506
508
|
#endif
|
507
|
-
|
508
|
-
#if defined(OPENSSL_NO_SSL3) || defined(OPENSSL_NO_SSL3_METHOD)
|
509
|
-
/* True if SSL3 is not available */
|
510
|
-
rb_define_const(mod, "OPENSSL_NO_SSL3", Qtrue);
|
511
|
-
#else
|
512
|
-
rb_define_const(mod, "OPENSSL_NO_SSL3", Qfalse);
|
513
|
-
#endif
|
514
|
-
|
515
|
-
#if defined(OPENSSL_NO_TLS1) || defined(OPENSSL_NO_TLS1_METHOD)
|
516
|
-
/* True if TLS1 is not available */
|
517
|
-
rb_define_const(mod, "OPENSSL_NO_TLS1", Qtrue);
|
518
|
-
#else
|
519
|
-
rb_define_const(mod, "OPENSSL_NO_TLS1", Qfalse);
|
520
|
-
#endif
|
521
|
-
|
522
|
-
#if defined(OPENSSL_NO_TLS1_1) || defined(OPENSSL_NO_TLS1_1_METHOD)
|
523
|
-
/* True if TLS1_1 is not available */
|
524
|
-
rb_define_const(mod, "OPENSSL_NO_TLS1_1", Qtrue);
|
525
|
-
#else
|
526
|
-
rb_define_const(mod, "OPENSSL_NO_TLS1_1", Qfalse);
|
527
|
-
#endif
|
509
|
+
|
510
|
+
#if defined(OPENSSL_NO_SSL3) || defined(OPENSSL_NO_SSL3_METHOD)
|
511
|
+
/* True if SSL3 is not available */
|
512
|
+
rb_define_const(mod, "OPENSSL_NO_SSL3", Qtrue);
|
513
|
+
#else
|
514
|
+
rb_define_const(mod, "OPENSSL_NO_SSL3", Qfalse);
|
515
|
+
#endif
|
516
|
+
|
517
|
+
#if defined(OPENSSL_NO_TLS1) || defined(OPENSSL_NO_TLS1_METHOD)
|
518
|
+
/* True if TLS1 is not available */
|
519
|
+
rb_define_const(mod, "OPENSSL_NO_TLS1", Qtrue);
|
520
|
+
#else
|
521
|
+
rb_define_const(mod, "OPENSSL_NO_TLS1", Qfalse);
|
522
|
+
#endif
|
523
|
+
|
524
|
+
#if defined(OPENSSL_NO_TLS1_1) || defined(OPENSSL_NO_TLS1_1_METHOD)
|
525
|
+
/* True if TLS1_1 is not available */
|
526
|
+
rb_define_const(mod, "OPENSSL_NO_TLS1_1", Qtrue);
|
527
|
+
#else
|
528
|
+
rb_define_const(mod, "OPENSSL_NO_TLS1_1", Qfalse);
|
529
|
+
#endif
|
528
530
|
|
529
531
|
rb_define_singleton_method(mod, "check", noop, 0);
|
530
532
|
|
@@ -40,7 +40,9 @@ static VALUE global_http_version;
|
|
40
40
|
static VALUE global_request_path;
|
41
41
|
|
42
42
|
/** Defines common length and error messages for input length validation. */
|
43
|
-
#define
|
43
|
+
#define QUOTE(s) #s
|
44
|
+
#define EXPLAND_MAX_LENGHT_VALUE(s) QUOTE(s)
|
45
|
+
#define DEF_MAX_LENGTH(N,length) const size_t MAX_##N##_LENGTH = length; const char *MAX_##N##_LENGTH_ERR = "HTTP element " # N " is longer than the " EXPLAND_MAX_LENGHT_VALUE(length) " allowed length (was %d)"
|
44
46
|
|
45
47
|
/** Validates the max length of given input and throws an HttpParserError exception if over. */
|
46
48
|
#define VALIDATE_MAX_LENGTH(len, N) if(len > MAX_##N##_LENGTH) { rb_raise(eHttpParserError, MAX_##N##_LENGTH_ERR, len); }
|
@@ -50,12 +52,16 @@ static VALUE global_request_path;
|
|
50
52
|
|
51
53
|
|
52
54
|
/* Defines the maximum allowed lengths for various input elements.*/
|
55
|
+
#ifndef PUMA_QUERY_STRING_MAX_LENGTH
|
56
|
+
#define PUMA_QUERY_STRING_MAX_LENGTH (1024 * 10)
|
57
|
+
#endif
|
58
|
+
|
53
59
|
DEF_MAX_LENGTH(FIELD_NAME, 256);
|
54
60
|
DEF_MAX_LENGTH(FIELD_VALUE, 80 * 1024);
|
55
61
|
DEF_MAX_LENGTH(REQUEST_URI, 1024 * 12);
|
56
62
|
DEF_MAX_LENGTH(FRAGMENT, 1024); /* Don't know if this length is specified somewhere or not */
|
57
63
|
DEF_MAX_LENGTH(REQUEST_PATH, 8192);
|
58
|
-
DEF_MAX_LENGTH(QUERY_STRING,
|
64
|
+
DEF_MAX_LENGTH(QUERY_STRING, PUMA_QUERY_STRING_MAX_LENGTH);
|
59
65
|
DEF_MAX_LENGTH(HEADER, (1024 * (80 + 32)));
|
60
66
|
|
61
67
|
struct common_field {
|
@@ -253,11 +259,18 @@ void HttpParser_free(void *data) {
|
|
253
259
|
}
|
254
260
|
}
|
255
261
|
|
256
|
-
void HttpParser_mark(
|
262
|
+
void HttpParser_mark(void *ptr) {
|
263
|
+
puma_parser *hp = ptr;
|
257
264
|
if(hp->request) rb_gc_mark(hp->request);
|
258
265
|
if(hp->body) rb_gc_mark(hp->body);
|
259
266
|
}
|
260
267
|
|
268
|
+
const rb_data_type_t HttpParser_data_type = {
|
269
|
+
"HttpParser",
|
270
|
+
{ HttpParser_mark, HttpParser_free, 0 },
|
271
|
+
0, 0, RUBY_TYPED_FREE_IMMEDIATELY,
|
272
|
+
};
|
273
|
+
|
261
274
|
VALUE HttpParser_alloc(VALUE klass)
|
262
275
|
{
|
263
276
|
puma_parser *hp = ALLOC_N(puma_parser, 1);
|
@@ -274,7 +287,7 @@ VALUE HttpParser_alloc(VALUE klass)
|
|
274
287
|
|
275
288
|
puma_parser_init(hp);
|
276
289
|
|
277
|
-
return
|
290
|
+
return TypedData_Wrap_Struct(klass, &HttpParser_data_type, hp);
|
278
291
|
}
|
279
292
|
|
280
293
|
/**
|
@@ -286,7 +299,7 @@ VALUE HttpParser_alloc(VALUE klass)
|
|
286
299
|
VALUE HttpParser_init(VALUE self)
|
287
300
|
{
|
288
301
|
puma_parser *http = NULL;
|
289
|
-
DATA_GET(self, puma_parser, http);
|
302
|
+
DATA_GET(self, puma_parser, &HttpParser_data_type, http);
|
290
303
|
puma_parser_init(http);
|
291
304
|
|
292
305
|
return self;
|
@@ -303,7 +316,7 @@ VALUE HttpParser_init(VALUE self)
|
|
303
316
|
VALUE HttpParser_reset(VALUE self)
|
304
317
|
{
|
305
318
|
puma_parser *http = NULL;
|
306
|
-
DATA_GET(self, puma_parser, http);
|
319
|
+
DATA_GET(self, puma_parser, &HttpParser_data_type, http);
|
307
320
|
puma_parser_init(http);
|
308
321
|
|
309
322
|
return Qnil;
|
@@ -320,7 +333,7 @@ VALUE HttpParser_reset(VALUE self)
|
|
320
333
|
VALUE HttpParser_finish(VALUE self)
|
321
334
|
{
|
322
335
|
puma_parser *http = NULL;
|
323
|
-
DATA_GET(self, puma_parser, http);
|
336
|
+
DATA_GET(self, puma_parser, &HttpParser_data_type, http);
|
324
337
|
puma_parser_finish(http);
|
325
338
|
|
326
339
|
return puma_parser_is_finished(http) ? Qtrue : Qfalse;
|
@@ -351,7 +364,7 @@ VALUE HttpParser_execute(VALUE self, VALUE req_hash, VALUE data, VALUE start)
|
|
351
364
|
char *dptr = NULL;
|
352
365
|
long dlen = 0;
|
353
366
|
|
354
|
-
DATA_GET(self, puma_parser, http);
|
367
|
+
DATA_GET(self, puma_parser, &HttpParser_data_type, http);
|
355
368
|
|
356
369
|
from = FIX2INT(start);
|
357
370
|
dptr = rb_extract_chars(data, &dlen);
|
@@ -385,7 +398,7 @@ VALUE HttpParser_execute(VALUE self, VALUE req_hash, VALUE data, VALUE start)
|
|
385
398
|
VALUE HttpParser_has_error(VALUE self)
|
386
399
|
{
|
387
400
|
puma_parser *http = NULL;
|
388
|
-
DATA_GET(self, puma_parser, http);
|
401
|
+
DATA_GET(self, puma_parser, &HttpParser_data_type, http);
|
389
402
|
|
390
403
|
return puma_parser_has_error(http) ? Qtrue : Qfalse;
|
391
404
|
}
|
@@ -400,7 +413,7 @@ VALUE HttpParser_has_error(VALUE self)
|
|
400
413
|
VALUE HttpParser_is_finished(VALUE self)
|
401
414
|
{
|
402
415
|
puma_parser *http = NULL;
|
403
|
-
DATA_GET(self, puma_parser, http);
|
416
|
+
DATA_GET(self, puma_parser, &HttpParser_data_type, http);
|
404
417
|
|
405
418
|
return puma_parser_is_finished(http) ? Qtrue : Qfalse;
|
406
419
|
}
|
@@ -416,7 +429,7 @@ VALUE HttpParser_is_finished(VALUE self)
|
|
416
429
|
VALUE HttpParser_nread(VALUE self)
|
417
430
|
{
|
418
431
|
puma_parser *http = NULL;
|
419
|
-
DATA_GET(self, puma_parser, http);
|
432
|
+
DATA_GET(self, puma_parser, &HttpParser_data_type, http);
|
420
433
|
|
421
434
|
return INT2FIX(http->nread);
|
422
435
|
}
|
@@ -429,7 +442,7 @@ VALUE HttpParser_nread(VALUE self)
|
|
429
442
|
*/
|
430
443
|
VALUE HttpParser_body(VALUE self) {
|
431
444
|
puma_parser *http = NULL;
|
432
|
-
DATA_GET(self, puma_parser, http);
|
445
|
+
DATA_GET(self, puma_parser, &HttpParser_data_type, http);
|
433
446
|
|
434
447
|
return http->body;
|
435
448
|
}
|
data/lib/puma.rb
CHANGED
@@ -10,23 +10,26 @@ require 'stringio'
|
|
10
10
|
|
11
11
|
require 'thread'
|
12
12
|
|
13
|
-
|
14
|
-
|
13
|
+
require 'puma/puma_http11'
|
14
|
+
require 'puma/detect'
|
15
|
+
require 'puma/json'
|
15
16
|
|
16
17
|
module Puma
|
17
18
|
autoload :Const, 'puma/const'
|
18
19
|
autoload :Server, 'puma/server'
|
19
20
|
autoload :Launcher, 'puma/launcher'
|
20
21
|
|
22
|
+
# @!attribute [rw] stats_object=
|
21
23
|
def self.stats_object=(val)
|
22
24
|
@get_stats = val
|
23
25
|
end
|
24
26
|
|
27
|
+
# @!attribute [rw] stats_object
|
25
28
|
def self.stats
|
26
|
-
|
27
|
-
@get_stats.stats.to_json
|
29
|
+
Puma::JSON.generate @get_stats.stats
|
28
30
|
end
|
29
31
|
|
32
|
+
# @!attribute [r] stats_hash
|
30
33
|
# @version 5.0.0
|
31
34
|
def self.stats_hash
|
32
35
|
@get_stats.stats
|
data/lib/puma/app/status.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
require 'puma/json'
|
2
3
|
|
3
4
|
module Puma
|
4
5
|
module App
|
@@ -7,71 +8,68 @@ module Puma
|
|
7
8
|
class Status
|
8
9
|
OK_STATUS = '{ "status": "ok" }'.freeze
|
9
10
|
|
10
|
-
|
11
|
-
|
11
|
+
# @param launcher [::Puma::Launcher]
|
12
|
+
# @param token [String, nil] the token used for authentication
|
13
|
+
#
|
14
|
+
def initialize(launcher, token = nil)
|
15
|
+
@launcher = launcher
|
12
16
|
@auth_token = token
|
13
17
|
end
|
14
18
|
|
19
|
+
# most commands call methods in `::Puma::Launcher` based on command in
|
20
|
+
# `env['PATH_INFO']`
|
15
21
|
def call(env)
|
16
22
|
unless authenticate(env)
|
17
23
|
return rack_response(403, 'Invalid auth token', 'text/plain')
|
18
24
|
end
|
19
25
|
|
20
|
-
|
21
|
-
|
22
|
-
|
26
|
+
# resp_type is processed by following case statement, return
|
27
|
+
# is a number (status) or a string used as the body of a 200 response
|
28
|
+
resp_type =
|
29
|
+
case env['PATH_INFO'][/\/([^\/]+)$/, 1]
|
30
|
+
when 'stop'
|
31
|
+
@launcher.stop ; 200
|
23
32
|
|
24
|
-
|
25
|
-
|
26
|
-
@cli.stop
|
27
|
-
rack_response(200, OK_STATUS)
|
33
|
+
when 'halt'
|
34
|
+
@launcher.halt ; 200
|
28
35
|
|
29
|
-
|
30
|
-
|
31
|
-
rack_response(200, OK_STATUS)
|
36
|
+
when 'restart'
|
37
|
+
@launcher.restart ; 200
|
32
38
|
|
33
|
-
|
34
|
-
|
35
|
-
rack_response(200, OK_STATUS)
|
39
|
+
when 'phased-restart'
|
40
|
+
@launcher.phased_restart ? 200 : 404
|
36
41
|
|
37
|
-
|
38
|
-
|
39
|
-
rack_response(404, '{ "error": "phased restart not available" }')
|
40
|
-
else
|
41
|
-
rack_response(200, OK_STATUS)
|
42
|
-
end
|
42
|
+
when 'reload-worker-directory'
|
43
|
+
@launcher.send(:reload_worker_directory) ? 200 : 404
|
43
44
|
|
44
|
-
|
45
|
-
|
46
|
-
rack_response(404, '{ "error": "reload_worker_directory not available" }')
|
47
|
-
else
|
48
|
-
rack_response(200, OK_STATUS)
|
49
|
-
end
|
45
|
+
when 'gc'
|
46
|
+
GC.start ; 200
|
50
47
|
|
51
|
-
|
52
|
-
|
53
|
-
rack_response(200, OK_STATUS)
|
48
|
+
when 'gc-stats'
|
49
|
+
Puma::JSON.generate GC.stat
|
54
50
|
|
55
|
-
|
56
|
-
|
51
|
+
when 'stats'
|
52
|
+
Puma::JSON.generate @launcher.stats
|
57
53
|
|
58
|
-
|
59
|
-
|
54
|
+
when 'thread-backtraces'
|
55
|
+
backtraces = []
|
56
|
+
@launcher.thread_status do |name, backtrace|
|
57
|
+
backtraces << { name: name, backtrace: backtrace }
|
58
|
+
end
|
59
|
+
Puma::JSON.generate backtraces
|
60
60
|
|
61
|
-
|
62
|
-
|
63
|
-
@cli.thread_status do |name, backtrace|
|
64
|
-
backtraces << { name: name, backtrace: backtrace }
|
61
|
+
else
|
62
|
+
return rack_response(404, "Unsupported action", 'text/plain')
|
65
63
|
end
|
66
64
|
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
rack_response
|
72
|
-
|
73
|
-
|
74
|
-
rack_response 404, "
|
65
|
+
case resp_type
|
66
|
+
when String
|
67
|
+
rack_response 200, resp_type
|
68
|
+
when 200
|
69
|
+
rack_response 200, OK_STATUS
|
70
|
+
when 404
|
71
|
+
str = env['PATH_INFO'][/\/(\S+)/, 1].tr '-', '_'
|
72
|
+
rack_response 404, "{ \"error\": \"#{str} not available\" }"
|
75
73
|
end
|
76
74
|
end
|
77
75
|
|
data/lib/puma/binder.rb
CHANGED
@@ -12,7 +12,15 @@ module Puma
|
|
12
12
|
if HAS_SSL
|
13
13
|
require 'puma/minissl'
|
14
14
|
require 'puma/minissl/context_builder'
|
15
|
-
|
15
|
+
|
16
|
+
# Odd bug in 'pure Ruby' nio4r verion 2.5.2, which installs with Ruby 2.3.
|
17
|
+
# NIO doesn't create any OpenSSL objects, but it rescues an OpenSSL error.
|
18
|
+
# The bug was that it did not require openssl.
|
19
|
+
# @todo remove when Ruby 2.3 support is dropped
|
20
|
+
#
|
21
|
+
if windows? && RbConfig::CONFIG['ruby_version'] == '2.3.0'
|
22
|
+
require 'openssl'
|
23
|
+
end
|
16
24
|
end
|
17
25
|
|
18
26
|
class Binder
|
@@ -66,6 +74,7 @@ module Puma
|
|
66
74
|
@ios.each { |i| i.close }
|
67
75
|
end
|
68
76
|
|
77
|
+
# @!attribute [r] connected_ports
|
69
78
|
# @version 5.0.0
|
70
79
|
def connected_ports
|
71
80
|
ios.map { |io| io.addr[1] }.uniq
|
@@ -102,6 +111,43 @@ module Puma
|
|
102
111
|
["LISTEN_FDS", "LISTEN_PID"] # Signal to remove these keys from ENV
|
103
112
|
end
|
104
113
|
|
114
|
+
# Synthesize binds from systemd socket activation
|
115
|
+
#
|
116
|
+
# When systemd socket activation is enabled, it can be tedious to keep the
|
117
|
+
# binds in sync. This method can synthesize any binds based on the received
|
118
|
+
# activated sockets. Any existing matching binds will be respected.
|
119
|
+
#
|
120
|
+
# When only_matching is true in, all binds that do not match an activated
|
121
|
+
# socket is removed in place.
|
122
|
+
#
|
123
|
+
# It's a noop if no activated sockets were received.
|
124
|
+
def synthesize_binds_from_activated_fs(binds, only_matching)
|
125
|
+
return binds unless activated_sockets.any?
|
126
|
+
|
127
|
+
activated_binds = []
|
128
|
+
|
129
|
+
activated_sockets.keys.each do |proto, addr, port|
|
130
|
+
if port
|
131
|
+
tcp_url = "#{proto}://#{addr}:#{port}"
|
132
|
+
ssl_url = "ssl://#{addr}:#{port}"
|
133
|
+
ssl_url_prefix = "#{ssl_url}?"
|
134
|
+
|
135
|
+
existing = binds.find { |bind| bind == tcp_url || bind == ssl_url || bind.start_with?(ssl_url_prefix) }
|
136
|
+
|
137
|
+
activated_binds << (existing || tcp_url)
|
138
|
+
else
|
139
|
+
# TODO: can there be a SSL bind without a port?
|
140
|
+
activated_binds << "#{proto}://#{addr}"
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
if only_matching
|
145
|
+
activated_binds
|
146
|
+
else
|
147
|
+
binds | activated_binds
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
105
151
|
def parse(binds, logger, log_msg = 'Listening')
|
106
152
|
binds.each do |str|
|
107
153
|
uri = URI.parse str
|
@@ -391,6 +437,7 @@ module Puma
|
|
391
437
|
|
392
438
|
private
|
393
439
|
|
440
|
+
# @!attribute [r] loopback_addresses
|
394
441
|
def loopback_addresses
|
395
442
|
Socket.ip_address_list.select do |addrinfo|
|
396
443
|
addrinfo.ipv6_loopback? || addrinfo.ipv4_loopback?
|