puma 4.3.5 → 4.3.9
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of puma might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/History.md +21 -4
- data/ext/puma_http11/extconf.rb +1 -1
- data/ext/puma_http11/http11_parser.c +19 -12
- data/ext/puma_http11/http11_parser_common.rl +1 -1
- data/ext/puma_http11/org/jruby/puma/Http11Parser.java +34 -34
- data/ext/puma_http11/puma_http11.c +1 -0
- data/lib/puma/app/status.rb +4 -2
- data/lib/puma/client.rb +21 -9
- data/lib/puma/const.rb +1 -1
- data/lib/puma/server.rb +14 -9
- metadata +6 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9b3570ed48d3096b14fb6fa46a835dc625900593359d6f8cdab1a8e0e5b40c94
|
4
|
+
data.tar.gz: 462479b52c688979f1cf957fa13c5c9d8e86f2390ee191641e6ed0f7c1a7011b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4708cdd8122a6467559f623b16d6628809895d920a8ebae9cb14aedee0423aff6b199f6c917b1b8f7d18013f0520aa035a15b68cdde27c502534fe84348f2918
|
7
|
+
data.tar.gz: fce13221ceef9fc7b2539138de5058dc7d9e031a846ea6ff0a41978d961c282a960071d7d9d644d159d7fa1ac197d40b1cba0c31143da128c356e8ec5ccf6d49
|
data/History.md
CHANGED
@@ -1,11 +1,28 @@
|
|
1
|
-
##
|
1
|
+
## 4.3.9 / 2021-10-12
|
2
2
|
|
3
|
-
*
|
4
|
-
*
|
3
|
+
* Security
|
4
|
+
* Do not allow LF as a line ending in a header (CVE-2021-41136)
|
5
|
+
|
6
|
+
## 4.3.8 / 2021-05-11
|
7
|
+
|
8
|
+
* Security
|
9
|
+
* Close keepalive connections after the maximum number of fast inlined requests (#2625)
|
10
|
+
|
11
|
+
## 4.3.7 / 2020-11-30
|
5
12
|
|
6
13
|
* Bugfixes
|
7
|
-
*
|
14
|
+
* Backport set CONTENT_LENGTH for chunked requests (Originally: #2287, backport: #2496)
|
15
|
+
|
16
|
+
## 4.3.6 / 2020-09-05
|
17
|
+
|
18
|
+
* Bugfixes
|
19
|
+
* Explicitly include ctype.h to fix compilation warning and build error on macOS with Xcode 12 (#2304)
|
20
|
+
* Don't require json at boot (#2269)
|
21
|
+
* Set `CONTENT_LENGTH` for chunked requests (#2287)
|
22
|
+
|
23
|
+
## 4.3.4/4.3.5 and 3.12.5/3.12.6 / 2020-05-22
|
8
24
|
|
25
|
+
Each patchlevel release contains a separate security fix. We recommend simply upgrading to 4.3.5/3.12.6.
|
9
26
|
|
10
27
|
## 4.3.3 and 3.12.4 / 2020-02-28
|
11
28
|
* Bugfixes
|
data/ext/puma_http11/extconf.rb
CHANGED
@@ -428,10 +428,13 @@ st18:
|
|
428
428
|
case 18:
|
429
429
|
#line 428 "ext/puma_http11/http11_parser.c"
|
430
430
|
switch( (*p) ) {
|
431
|
+
case 9: goto tr25;
|
431
432
|
case 13: goto tr26;
|
432
433
|
case 32: goto tr27;
|
433
434
|
}
|
434
|
-
|
435
|
+
if ( 33 <= (*p) && (*p) <= 126 )
|
436
|
+
goto tr25;
|
437
|
+
goto st0;
|
435
438
|
tr25:
|
436
439
|
#line 44 "ext/puma_http11/http11_parser.rl"
|
437
440
|
{ MARK(mark, p); }
|
@@ -440,10 +443,14 @@ st19:
|
|
440
443
|
if ( ++p == pe )
|
441
444
|
goto _test_eof19;
|
442
445
|
case 19:
|
443
|
-
#line
|
444
|
-
|
445
|
-
goto
|
446
|
-
|
446
|
+
#line 445 "ext/puma_http11/http11_parser.c"
|
447
|
+
switch( (*p) ) {
|
448
|
+
case 9: goto st19;
|
449
|
+
case 13: goto tr29;
|
450
|
+
}
|
451
|
+
if ( 32 <= (*p) && (*p) <= 126 )
|
452
|
+
goto st19;
|
453
|
+
goto st0;
|
447
454
|
tr9:
|
448
455
|
#line 51 "ext/puma_http11/http11_parser.rl"
|
449
456
|
{
|
@@ -486,7 +493,7 @@ st20:
|
|
486
493
|
if ( ++p == pe )
|
487
494
|
goto _test_eof20;
|
488
495
|
case 20:
|
489
|
-
#line
|
496
|
+
#line 495 "ext/puma_http11/http11_parser.c"
|
490
497
|
switch( (*p) ) {
|
491
498
|
case 32: goto tr31;
|
492
499
|
case 60: goto st0;
|
@@ -507,7 +514,7 @@ st21:
|
|
507
514
|
if ( ++p == pe )
|
508
515
|
goto _test_eof21;
|
509
516
|
case 21:
|
510
|
-
#line
|
517
|
+
#line 516 "ext/puma_http11/http11_parser.c"
|
511
518
|
switch( (*p) ) {
|
512
519
|
case 32: goto tr33;
|
513
520
|
case 60: goto st0;
|
@@ -528,7 +535,7 @@ st22:
|
|
528
535
|
if ( ++p == pe )
|
529
536
|
goto _test_eof22;
|
530
537
|
case 22:
|
531
|
-
#line
|
538
|
+
#line 537 "ext/puma_http11/http11_parser.c"
|
532
539
|
switch( (*p) ) {
|
533
540
|
case 43: goto st22;
|
534
541
|
case 58: goto st23;
|
@@ -553,7 +560,7 @@ st23:
|
|
553
560
|
if ( ++p == pe )
|
554
561
|
goto _test_eof23;
|
555
562
|
case 23:
|
556
|
-
#line
|
563
|
+
#line 562 "ext/puma_http11/http11_parser.c"
|
557
564
|
switch( (*p) ) {
|
558
565
|
case 32: goto tr8;
|
559
566
|
case 34: goto st0;
|
@@ -573,7 +580,7 @@ st24:
|
|
573
580
|
if ( ++p == pe )
|
574
581
|
goto _test_eof24;
|
575
582
|
case 24:
|
576
|
-
#line
|
583
|
+
#line 582 "ext/puma_http11/http11_parser.c"
|
577
584
|
switch( (*p) ) {
|
578
585
|
case 32: goto tr37;
|
579
586
|
case 34: goto st0;
|
@@ -596,7 +603,7 @@ st25:
|
|
596
603
|
if ( ++p == pe )
|
597
604
|
goto _test_eof25;
|
598
605
|
case 25:
|
599
|
-
#line
|
606
|
+
#line 605 "ext/puma_http11/http11_parser.c"
|
600
607
|
switch( (*p) ) {
|
601
608
|
case 32: goto tr41;
|
602
609
|
case 34: goto st0;
|
@@ -616,7 +623,7 @@ st26:
|
|
616
623
|
if ( ++p == pe )
|
617
624
|
goto _test_eof26;
|
618
625
|
case 26:
|
619
|
-
#line
|
626
|
+
#line 625 "ext/puma_http11/http11_parser.c"
|
620
627
|
switch( (*p) ) {
|
621
628
|
case 32: goto tr44;
|
622
629
|
case 34: goto st0;
|
@@ -43,7 +43,7 @@
|
|
43
43
|
|
44
44
|
field_name = ( token -- ":" )+ >start_field $snake_upcase_field %write_field;
|
45
45
|
|
46
|
-
field_value =
|
46
|
+
field_value = ( print | "\t" )* >start_value %write_value;
|
47
47
|
|
48
48
|
message_header = field_name ":" " "* field_value :> CRLF;
|
49
49
|
|
@@ -34,9 +34,9 @@ private static short[] init__puma_parser_key_offsets_0()
|
|
34
34
|
{
|
35
35
|
return new short [] {
|
36
36
|
0, 0, 8, 17, 27, 29, 30, 31, 32, 33, 34, 36,
|
37
|
-
39, 41, 44, 45, 61, 62, 78,
|
38
|
-
|
39
|
-
|
37
|
+
39, 41, 44, 45, 61, 62, 78, 83, 87, 95, 103, 113,
|
38
|
+
121, 130, 138, 146, 155, 164, 173, 182, 191, 200, 209, 218,
|
39
|
+
227, 236, 245, 254, 263, 272, 281, 290, 299, 308, 309
|
40
40
|
};
|
41
41
|
}
|
42
42
|
|
@@ -52,14 +52,13 @@ private static char[] init__puma_parser_trans_keys_0()
|
|
52
52
|
46, 48, 57, 48, 57, 13, 48, 57, 10, 13, 33, 124,
|
53
53
|
126, 35, 39, 42, 43, 45, 46, 48, 57, 65, 90, 94,
|
54
54
|
122, 10, 33, 58, 124, 126, 35, 39, 42, 43, 45, 46,
|
55
|
-
48, 57, 65, 90, 94, 122, 13, 32,
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
65, 90, 32, 36, 95, 45, 46, 48, 57, 65, 90, 32,
|
55
|
+
48, 57, 65, 90, 94, 122, 9, 13, 32, 33, 126, 9,
|
56
|
+
13, 32, 126, 32, 60, 62, 127, 0, 31, 34, 35, 32,
|
57
|
+
60, 62, 127, 0, 31, 34, 35, 43, 58, 45, 46, 48,
|
58
|
+
57, 65, 90, 97, 122, 32, 34, 35, 60, 62, 127, 0,
|
59
|
+
31, 32, 34, 35, 60, 62, 63, 127, 0, 31, 32, 34,
|
60
|
+
35, 60, 62, 127, 0, 31, 32, 34, 35, 60, 62, 127,
|
61
|
+
0, 31, 32, 36, 95, 45, 46, 48, 57, 65, 90, 32,
|
63
62
|
36, 95, 45, 46, 48, 57, 65, 90, 32, 36, 95, 45,
|
64
63
|
46, 48, 57, 65, 90, 32, 36, 95, 45, 46, 48, 57,
|
65
64
|
65, 90, 32, 36, 95, 45, 46, 48, 57, 65, 90, 32,
|
@@ -71,7 +70,8 @@ private static char[] init__puma_parser_trans_keys_0()
|
|
71
70
|
65, 90, 32, 36, 95, 45, 46, 48, 57, 65, 90, 32,
|
72
71
|
36, 95, 45, 46, 48, 57, 65, 90, 32, 36, 95, 45,
|
73
72
|
46, 48, 57, 65, 90, 32, 36, 95, 45, 46, 48, 57,
|
74
|
-
65, 90, 32,
|
73
|
+
65, 90, 32, 36, 95, 45, 46, 48, 57, 65, 90, 32,
|
74
|
+
36, 95, 45, 46, 48, 57, 65, 90, 32, 0
|
75
75
|
};
|
76
76
|
}
|
77
77
|
|
@@ -82,7 +82,7 @@ private static byte[] init__puma_parser_single_lengths_0()
|
|
82
82
|
{
|
83
83
|
return new byte [] {
|
84
84
|
0, 2, 3, 4, 2, 1, 1, 1, 1, 1, 0, 1,
|
85
|
-
0, 1, 1, 4, 1, 4,
|
85
|
+
0, 1, 1, 4, 1, 4, 3, 2, 4, 4, 2, 6,
|
86
86
|
7, 6, 6, 3, 3, 3, 3, 3, 3, 3, 3, 3,
|
87
87
|
3, 3, 3, 3, 3, 3, 3, 3, 3, 1, 0
|
88
88
|
};
|
@@ -95,7 +95,7 @@ private static byte[] init__puma_parser_range_lengths_0()
|
|
95
95
|
{
|
96
96
|
return new byte [] {
|
97
97
|
0, 3, 3, 3, 0, 0, 0, 0, 0, 0, 1, 1,
|
98
|
-
1, 1, 0, 6, 0, 6,
|
98
|
+
1, 1, 0, 6, 0, 6, 1, 1, 2, 2, 4, 1,
|
99
99
|
1, 1, 1, 3, 3, 3, 3, 3, 3, 3, 3, 3,
|
100
100
|
3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0
|
101
101
|
};
|
@@ -108,9 +108,9 @@ private static short[] init__puma_parser_index_offsets_0()
|
|
108
108
|
{
|
109
109
|
return new short [] {
|
110
110
|
0, 0, 6, 13, 21, 24, 26, 28, 30, 32, 34, 36,
|
111
|
-
39, 41, 44, 46, 57, 59, 70,
|
112
|
-
|
113
|
-
|
111
|
+
39, 41, 44, 46, 57, 59, 70, 75, 79, 86, 93, 100,
|
112
|
+
108, 117, 125, 133, 140, 147, 154, 161, 168, 175, 182, 189,
|
113
|
+
196, 203, 210, 217, 224, 231, 238, 245, 252, 259, 261
|
114
114
|
};
|
115
115
|
}
|
116
116
|
|
@@ -125,23 +125,23 @@ private static byte[] init__puma_parser_indicies_0()
|
|
125
125
|
10, 1, 11, 1, 12, 1, 13, 1, 14, 1, 15, 1,
|
126
126
|
16, 15, 1, 17, 1, 18, 17, 1, 19, 1, 20, 21,
|
127
127
|
21, 21, 21, 21, 21, 21, 21, 21, 1, 22, 1, 23,
|
128
|
-
24, 23, 23, 23, 23, 23, 23, 23, 23, 1,
|
129
|
-
|
130
|
-
1, 1, 1, 1, 33, 34, 35, 34,
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
46, 46, 46, 1, 2, 47, 47, 47,
|
135
|
-
48, 48, 48, 48, 48, 1, 2, 49,
|
136
|
-
|
137
|
-
|
138
|
-
53, 53, 53, 53, 1, 2, 54, 54,
|
139
|
-
|
140
|
-
56, 1, 2, 57, 57, 57, 57, 57,
|
141
|
-
|
142
|
-
60, 60, 60, 60, 60, 1, 2, 61,
|
143
|
-
|
144
|
-
|
128
|
+
24, 23, 23, 23, 23, 23, 23, 23, 23, 1, 25, 26,
|
129
|
+
27, 25, 1, 28, 29, 28, 1, 30, 1, 1, 1, 1,
|
130
|
+
1, 31, 32, 1, 1, 1, 1, 1, 33, 34, 35, 34,
|
131
|
+
34, 34, 34, 1, 8, 1, 9, 1, 1, 1, 1, 35,
|
132
|
+
36, 1, 38, 1, 1, 39, 1, 1, 37, 40, 1, 42,
|
133
|
+
1, 1, 1, 1, 41, 43, 1, 45, 1, 1, 1, 1,
|
134
|
+
44, 2, 46, 46, 46, 46, 46, 1, 2, 47, 47, 47,
|
135
|
+
47, 47, 1, 2, 48, 48, 48, 48, 48, 1, 2, 49,
|
136
|
+
49, 49, 49, 49, 1, 2, 50, 50, 50, 50, 50, 1,
|
137
|
+
2, 51, 51, 51, 51, 51, 1, 2, 52, 52, 52, 52,
|
138
|
+
52, 1, 2, 53, 53, 53, 53, 53, 1, 2, 54, 54,
|
139
|
+
54, 54, 54, 1, 2, 55, 55, 55, 55, 55, 1, 2,
|
140
|
+
56, 56, 56, 56, 56, 1, 2, 57, 57, 57, 57, 57,
|
141
|
+
1, 2, 58, 58, 58, 58, 58, 1, 2, 59, 59, 59,
|
142
|
+
59, 59, 1, 2, 60, 60, 60, 60, 60, 1, 2, 61,
|
143
|
+
61, 61, 61, 61, 1, 2, 62, 62, 62, 62, 62, 1,
|
144
|
+
2, 63, 63, 63, 63, 63, 1, 2, 1, 1, 0
|
145
145
|
};
|
146
146
|
}
|
147
147
|
|
data/lib/puma/app/status.rb
CHANGED
@@ -1,7 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'json'
|
4
|
-
|
5
3
|
module Puma
|
6
4
|
module App
|
7
5
|
# Check out {#call}'s source code to see what actions this web application
|
@@ -19,6 +17,10 @@ module Puma
|
|
19
17
|
return rack_response(403, 'Invalid auth token', 'text/plain')
|
20
18
|
end
|
21
19
|
|
20
|
+
if env['PATH_INFO'] =~ /\/(gc-stats|stats|thread-backtraces)$/
|
21
|
+
require 'json'
|
22
|
+
end
|
23
|
+
|
22
24
|
case env['PATH_INFO']
|
23
25
|
when /\/stop$/
|
24
26
|
@cli.stop
|
data/lib/puma/client.rb
CHANGED
@@ -153,7 +153,7 @@ module Puma
|
|
153
153
|
|
154
154
|
begin
|
155
155
|
data = @io.read_nonblock(CHUNK_SIZE)
|
156
|
-
rescue
|
156
|
+
rescue IO::WaitReadable
|
157
157
|
return false
|
158
158
|
rescue SystemCallError, IOError, EOFError
|
159
159
|
raise ConnectionError, "Connection error detected during read"
|
@@ -351,7 +351,7 @@ module Puma
|
|
351
351
|
|
352
352
|
begin
|
353
353
|
chunk = @io.read_nonblock(want)
|
354
|
-
rescue
|
354
|
+
rescue IO::WaitReadable
|
355
355
|
return false
|
356
356
|
rescue SystemCallError, IOError
|
357
357
|
raise ConnectionError, "Connection error detected during read"
|
@@ -397,7 +397,10 @@ module Puma
|
|
397
397
|
raise EOFError
|
398
398
|
end
|
399
399
|
|
400
|
-
|
400
|
+
if decode_chunk(chunk)
|
401
|
+
@env[CONTENT_LENGTH] = @chunked_content_length
|
402
|
+
return true
|
403
|
+
end
|
401
404
|
end
|
402
405
|
end
|
403
406
|
|
@@ -410,19 +413,28 @@ module Puma
|
|
410
413
|
@body.binmode
|
411
414
|
@tempfile = @body
|
412
415
|
|
413
|
-
|
416
|
+
@chunked_content_length = 0
|
417
|
+
|
418
|
+
if decode_chunk(body)
|
419
|
+
@env[CONTENT_LENGTH] = @chunked_content_length
|
420
|
+
return true
|
421
|
+
end
|
422
|
+
end
|
423
|
+
|
424
|
+
def write_chunk(str)
|
425
|
+
@chunked_content_length += @body.write(str)
|
414
426
|
end
|
415
427
|
|
416
428
|
def decode_chunk(chunk)
|
417
429
|
if @partial_part_left > 0
|
418
430
|
if @partial_part_left <= chunk.size
|
419
431
|
if @partial_part_left > 2
|
420
|
-
|
432
|
+
write_chunk(chunk[0..(@partial_part_left-3)]) # skip the \r\n
|
421
433
|
end
|
422
434
|
chunk = chunk[@partial_part_left..-1]
|
423
435
|
@partial_part_left = 0
|
424
436
|
else
|
425
|
-
|
437
|
+
write_chunk(chunk) if @partial_part_left > 2 # don't include the last \r\n
|
426
438
|
@partial_part_left -= chunk.size
|
427
439
|
return false
|
428
440
|
end
|
@@ -469,12 +481,12 @@ module Puma
|
|
469
481
|
|
470
482
|
case
|
471
483
|
when got == len
|
472
|
-
|
484
|
+
write_chunk(part[0..-3]) # to skip the ending \r\n
|
473
485
|
when got <= len - 2
|
474
|
-
|
486
|
+
write_chunk(part)
|
475
487
|
@partial_part_left = len - part.size
|
476
488
|
when got == len - 1 # edge where we get just \r but not \n
|
477
|
-
|
489
|
+
write_chunk(part[0..-2])
|
478
490
|
@partial_part_left = len - part.size
|
479
491
|
end
|
480
492
|
else
|
data/lib/puma/const.rb
CHANGED
@@ -100,7 +100,7 @@ module Puma
|
|
100
100
|
# too taxing on performance.
|
101
101
|
module Const
|
102
102
|
|
103
|
-
PUMA_VERSION = VERSION = "4.3.
|
103
|
+
PUMA_VERSION = VERSION = "4.3.9".freeze
|
104
104
|
CODE_NAME = "Mysterious Traveller".freeze
|
105
105
|
PUMA_SERVER_STRING = ['puma', PUMA_VERSION, CODE_NAME].join(' ').freeze
|
106
106
|
|
data/lib/puma/server.rb
CHANGED
@@ -483,15 +483,20 @@ module Puma
|
|
483
483
|
|
484
484
|
requests += 1
|
485
485
|
|
486
|
-
|
486
|
+
# Closing keepalive sockets after they've made a reasonable
|
487
|
+
# number of requests allows Puma to service many connections
|
488
|
+
# fairly, even when the number of concurrent connections exceeds
|
489
|
+
# the size of the threadpool. It also allows cluster mode Pumas
|
490
|
+
# to keep load evenly distributed across workers, because clients
|
491
|
+
# are randomly assigned a new worker when opening a new connection.
|
492
|
+
#
|
493
|
+
# Previously, Puma would kick connections in this conditional back
|
494
|
+
# to the reactor. However, because this causes the todo set to increase
|
495
|
+
# in size, the wait_until_full mutex would never unlock, leaving
|
496
|
+
# any additional connections unserviced.
|
497
|
+
break if requests >= MAX_FAST_INLINE
|
487
498
|
|
488
|
-
|
489
|
-
# This will mean that reset will only try to use the data it already
|
490
|
-
# has buffered and won't try to read more data. What this means is that
|
491
|
-
# every client, independent of their request speed, gets treated like a slow
|
492
|
-
# one once every MAX_FAST_INLINE requests.
|
493
|
-
check_for_more_data = false
|
494
|
-
end
|
499
|
+
check_for_more_data = @status == :run
|
495
500
|
|
496
501
|
unless client.reset(check_for_more_data)
|
497
502
|
close_socket = false
|
@@ -694,7 +699,7 @@ module Puma
|
|
694
699
|
to_add = {}
|
695
700
|
end
|
696
701
|
|
697
|
-
to_add[k.
|
702
|
+
to_add[k.tr(",", "_")] = v
|
698
703
|
end
|
699
704
|
end
|
700
705
|
|
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: 4.3.
|
4
|
+
version: 4.3.9
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Evan Phoenix
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-10-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: nio4r
|
@@ -121,7 +121,7 @@ licenses:
|
|
121
121
|
metadata:
|
122
122
|
msys2_mingw_dependencies: openssl
|
123
123
|
changelog_uri: https://github.com/puma/puma/blob/master/History.md
|
124
|
-
post_install_message:
|
124
|
+
post_install_message:
|
125
125
|
rdoc_options: []
|
126
126
|
require_paths:
|
127
127
|
- lib
|
@@ -136,8 +136,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
136
136
|
- !ruby/object:Gem::Version
|
137
137
|
version: '0'
|
138
138
|
requirements: []
|
139
|
-
rubygems_version: 3.
|
140
|
-
signing_key:
|
139
|
+
rubygems_version: 3.2.3
|
140
|
+
signing_key:
|
141
141
|
specification_version: 4
|
142
142
|
summary: Puma is a simple, fast, threaded, and highly concurrent HTTP 1.1 server for
|
143
143
|
Ruby/Rack applications
|