puma 6.1.1-java → 6.2.1-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 +4 -4
- data/History.md +32 -0
- data/README.md +14 -3
- data/lib/puma/cli.rb +1 -1
- data/lib/puma/commonlogger.rb +21 -14
- data/lib/puma/configuration.rb +1 -0
- data/lib/puma/const.rb +2 -2
- data/lib/puma/dsl.rb +44 -1
- data/lib/puma/error_logger.rb +2 -1
- data/lib/puma/launcher.rb +2 -0
- data/lib/puma/log_writer.rb +9 -3
- data/lib/puma/request.rb +52 -42
- data/lib/rack/handler/puma.rb +5 -3
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6659952663ca1247a27a1d731a96489881d0db6bcdeb15d17bd92d90ece41064
|
4
|
+
data.tar.gz: 311b9aad92753880cd75092f32e0638493d0a4f29a835ad448af76f2bca2a656
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 69e663cc10eb939cf94cf0adce7c5fe65b24974ac285cf198f98dfc348fce68cc46cdf821f0f2ed3d9924d8bdadcf583242c04d3f6d1f0adae3cb802a1e52702
|
7
|
+
data.tar.gz: e0d54567b32b35b8fc53a0f9829b664b1003e24af534bf8c1d8dc01bb2dc018c789a4f0b7975fbfa72687c19827f42b75024b4f5fa2884db7d4775b1ce40698f
|
data/History.md
CHANGED
@@ -1,3 +1,23 @@
|
|
1
|
+
## 6.2.1 / 2023-03-31
|
2
|
+
|
3
|
+
* Bugfixes
|
4
|
+
* Fix java 8 compatibility ([#3109], [#3108])
|
5
|
+
* Always write io_buffer when in "enum bodies" branch. ([#3113], [#3112])
|
6
|
+
* Fix warn_if_in_single_mode incorrect message ([#3111])
|
7
|
+
|
8
|
+
## 6.2.0 / 2023-03-29
|
9
|
+
|
10
|
+
* Features
|
11
|
+
* Ability to supply a custom logger ([#2770], [#2511])
|
12
|
+
* Warn when clustered-only hooks are defined in single mode ([#3089])
|
13
|
+
* Adds the on_booted event ([#2709])
|
14
|
+
|
15
|
+
* Bugfixes
|
16
|
+
* Loggers - internal_write - catch Errno::EINVAL ([#3091])
|
17
|
+
* commonlogger.rb - fix HIJACK time format, use constants, not strings ([#3074])
|
18
|
+
* Fixed some edge cases regarding request hijacking ([#3072])
|
19
|
+
|
20
|
+
|
1
21
|
## 6.1.1 / 2023-02-28
|
2
22
|
|
3
23
|
* Bugfixes
|
@@ -1954,6 +1974,18 @@ be added back in a future date when a java Puma::MiniSSL is added.
|
|
1954
1974
|
* Bugfixes
|
1955
1975
|
* Your bugfix goes here <Most recent on the top, like GitHub> (#Github Number)
|
1956
1976
|
|
1977
|
+
[#3109]:https://github.com/puma/puma/pull/3109 "PR by @ahorek, merged 2023-03-31"
|
1978
|
+
[#3108]:https://github.com/puma/puma/issues/3108 "Issue by @treviateo, closed 2023-03-31"
|
1979
|
+
[#3113]:https://github.com/puma/puma/pull/3113 "PR by @collinsauve, merged 2023-03-31"
|
1980
|
+
[#3112]:https://github.com/puma/puma/issues/3112 "Issue by @dmke, closed 2023-03-31"
|
1981
|
+
[#3111]:https://github.com/puma/puma/pull/3111 "PR by @adzap, merged 2023-03-30"
|
1982
|
+
[#2770]:https://github.com/puma/puma/pull/2770 "PR by @vzajkov, merged 2023-03-29"
|
1983
|
+
[#2511]:https://github.com/puma/puma/issues/2511 "Issue by @jchristie55332, closed 2021-12-12"
|
1984
|
+
[#3089]:https://github.com/puma/puma/pull/3089 "PR by @Vuta, merged 2023-03-06"
|
1985
|
+
[#2709]:https://github.com/puma/puma/pull/2709 "PR by @rodzyn, merged 2023-02-20"
|
1986
|
+
[#3091]:https://github.com/puma/puma/pull/3091 "PR by @MSP-Greg, merged 2023-03-28"
|
1987
|
+
[#3074]:https://github.com/puma/puma/pull/3074 "PR by @MSP-Greg, merged 2023-03-14"
|
1988
|
+
[#3072]:https://github.com/puma/puma/pull/3072 "PR by @MSP-Greg, merged 2023-02-17"
|
1957
1989
|
[#3079]:https://github.com/puma/puma/pull/3079 "PR by @mohamedhafez, merged 2023-02-24"
|
1958
1990
|
[#3080]:https://github.com/puma/puma/pull/3080 "PR by @MSP-Greg, merged 2023-02-16"
|
1959
1991
|
[#3058]:https://github.com/puma/puma/pull/3058 "PR by @dentarg, merged 2023-01-29"
|
data/README.md
CHANGED
@@ -157,6 +157,15 @@ before_fork do
|
|
157
157
|
end
|
158
158
|
```
|
159
159
|
|
160
|
+
You can also specify a block to be run after puma is booted using `on_booted`:
|
161
|
+
|
162
|
+
```ruby
|
163
|
+
# config/puma.rb
|
164
|
+
on_booted do
|
165
|
+
# configuration here
|
166
|
+
end
|
167
|
+
```
|
168
|
+
|
160
169
|
### Error handling
|
161
170
|
|
162
171
|
If puma encounters an error outside of the context of your application, it will respond with a 500 and a simple
|
@@ -345,11 +354,13 @@ end
|
|
345
354
|
|
346
355
|
## Deployment
|
347
356
|
|
348
|
-
Puma has support for Capistrano with an [external gem](https://github.com/seuros/capistrano-puma).
|
357
|
+
* Puma has support for Capistrano with an [external gem](https://github.com/seuros/capistrano-puma).
|
358
|
+
|
359
|
+
* Additionally, Puma has support for built-in daemonization via the [puma-daemon](https://github.com/kigster/puma-daemon) ruby gem. The gem restores the `daemonize` option that was removed from Puma starting version 5, but only for MRI Ruby.
|
360
|
+
|
349
361
|
|
350
362
|
It is common to use process monitors with Puma. Modern process monitors like systemd or rc.d
|
351
|
-
provide continuous monitoring and restarts for increased
|
352
|
-
reliability in production environments:
|
363
|
+
provide continuous monitoring and restarts for increased reliability in production environments:
|
353
364
|
|
354
365
|
* [rc.d](docs/jungle/rc.d/README.md)
|
355
366
|
* [systemd](docs/systemd.md)
|
data/lib/puma/cli.rb
CHANGED
@@ -93,7 +93,7 @@ module Puma
|
|
93
93
|
#
|
94
94
|
|
95
95
|
def setup_options
|
96
|
-
@conf = Configuration.new do |user_config, file_config|
|
96
|
+
@conf = Configuration.new({}, {events: @events}) do |user_config, file_config|
|
97
97
|
@parser = OptionParser.new do |o|
|
98
98
|
o.on "-b", "--bind URI", "URI to bind to (tcp://, unix://, ssl://)" do |arg|
|
99
99
|
user_config.bind arg
|
data/lib/puma/commonlogger.rb
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|
module Puma
|
4
4
|
# Rack::CommonLogger forwards every request to the given +app+, and
|
5
5
|
# logs a line in the
|
6
|
-
# {Apache common log format}[https://httpd.apache.org/docs/
|
6
|
+
# {Apache common log format}[https://httpd.apache.org/docs/2.4/logs.html#common]
|
7
7
|
# to the +logger+.
|
8
8
|
#
|
9
9
|
# If +logger+ is nil, CommonLogger will fall back +rack.errors+, which is
|
@@ -16,7 +16,7 @@ module Puma
|
|
16
16
|
# (which is called without arguments in order to make the error appear for
|
17
17
|
# sure)
|
18
18
|
class CommonLogger
|
19
|
-
# Common Log Format: https://httpd.apache.org/docs/
|
19
|
+
# Common Log Format: https://httpd.apache.org/docs/2.4/logs.html#common
|
20
20
|
#
|
21
21
|
# lilith.local - - [07/Aug/2006 23:58:02 -0400] "GET / HTTP/1.1" 500 -
|
22
22
|
#
|
@@ -25,10 +25,17 @@ module Puma
|
|
25
25
|
|
26
26
|
HIJACK_FORMAT = %{%s - %s [%s] "%s %s%s %s" HIJACKED -1 %0.4f\n}
|
27
27
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
28
|
+
LOG_TIME_FORMAT = '%d/%b/%Y:%H:%M:%S %z'
|
29
|
+
|
30
|
+
CONTENT_LENGTH = 'Content-Length' # should be lower case from app,
|
31
|
+
# Util::HeaderHash allows mixed
|
32
|
+
HTTP_VERSION = Const::HTTP_VERSION
|
33
|
+
HTTP_X_FORWARDED_FOR = Const::HTTP_X_FORWARDED_FOR
|
34
|
+
PATH_INFO = Const::PATH_INFO
|
35
|
+
QUERY_STRING = Const::QUERY_STRING
|
36
|
+
REMOTE_ADDR = Const::REMOTE_ADDR
|
37
|
+
REMOTE_USER = 'REMOTE_USER'
|
38
|
+
REQUEST_METHOD = Const::REQUEST_METHOD
|
32
39
|
|
33
40
|
def initialize(app, logger=nil)
|
34
41
|
@app = app
|
@@ -57,13 +64,13 @@ module Puma
|
|
57
64
|
now = Time.now
|
58
65
|
|
59
66
|
msg = HIJACK_FORMAT % [
|
60
|
-
env[
|
61
|
-
env[
|
62
|
-
now.strftime(
|
67
|
+
env[HTTP_X_FORWARDED_FOR] || env[REMOTE_ADDR] || "-",
|
68
|
+
env[REMOTE_USER] || "-",
|
69
|
+
now.strftime(LOG_TIME_FORMAT),
|
63
70
|
env[REQUEST_METHOD],
|
64
71
|
env[PATH_INFO],
|
65
72
|
env[QUERY_STRING].empty? ? "" : "?#{env[QUERY_STRING]}",
|
66
|
-
env[
|
73
|
+
env[HTTP_VERSION],
|
67
74
|
now - began_at ]
|
68
75
|
|
69
76
|
write(msg)
|
@@ -74,13 +81,13 @@ module Puma
|
|
74
81
|
length = extract_content_length(header)
|
75
82
|
|
76
83
|
msg = FORMAT % [
|
77
|
-
env[
|
78
|
-
env[
|
79
|
-
now.strftime(
|
84
|
+
env[HTTP_X_FORWARDED_FOR] || env[REMOTE_ADDR] || "-",
|
85
|
+
env[REMOTE_USER] || "-",
|
86
|
+
now.strftime(LOG_TIME_FORMAT),
|
80
87
|
env[REQUEST_METHOD],
|
81
88
|
env[PATH_INFO],
|
82
89
|
env[QUERY_STRING].empty? ? "" : "?#{env[QUERY_STRING]}",
|
83
|
-
env[
|
90
|
+
env[HTTP_VERSION],
|
84
91
|
status.to_s[0..3],
|
85
92
|
length,
|
86
93
|
now - began_at ]
|
data/lib/puma/configuration.rb
CHANGED
data/lib/puma/const.rb
CHANGED
@@ -99,8 +99,8 @@ module Puma
|
|
99
99
|
# too taxing on performance.
|
100
100
|
module Const
|
101
101
|
|
102
|
-
PUMA_VERSION = VERSION = "6.
|
103
|
-
CODE_NAME = "
|
102
|
+
PUMA_VERSION = VERSION = "6.2.1"
|
103
|
+
CODE_NAME = "Speaking of Now"
|
104
104
|
|
105
105
|
PUMA_SERVER_STRING = ["puma", PUMA_VERSION, CODE_NAME].join(" ").freeze
|
106
106
|
|
data/lib/puma/dsl.rb
CHANGED
@@ -419,6 +419,11 @@ module Puma
|
|
419
419
|
@options[:log_requests] = which
|
420
420
|
end
|
421
421
|
|
422
|
+
# Pass in a custom logging class instance
|
423
|
+
def custom_logger(custom_logger)
|
424
|
+
@options[:custom_logger] = custom_logger
|
425
|
+
end
|
426
|
+
|
422
427
|
# Show debugging info
|
423
428
|
#
|
424
429
|
def debug
|
@@ -585,6 +590,11 @@ module Puma
|
|
585
590
|
@options[:silence_single_worker_warning] = true
|
586
591
|
end
|
587
592
|
|
593
|
+
# Disable warning message when running single mode with callback hook defined.
|
594
|
+
def silence_fork_callback_warning
|
595
|
+
@options[:silence_fork_callback_warning] = true
|
596
|
+
end
|
597
|
+
|
588
598
|
# Code to run immediately before master process
|
589
599
|
# forks workers (once on boot). These hooks can block if necessary
|
590
600
|
# to wait for background operations unknown to Puma to finish before
|
@@ -600,6 +610,8 @@ module Puma
|
|
600
610
|
# puts "Starting workers..."
|
601
611
|
# end
|
602
612
|
def before_fork(&block)
|
613
|
+
warn_if_in_single_mode('before_fork')
|
614
|
+
|
603
615
|
@options[:before_fork] ||= []
|
604
616
|
@options[:before_fork] << block
|
605
617
|
end
|
@@ -615,6 +627,8 @@ module Puma
|
|
615
627
|
# puts 'Before worker boot...'
|
616
628
|
# end
|
617
629
|
def on_worker_boot(key = nil, &block)
|
630
|
+
warn_if_in_single_mode('on_worker_boot')
|
631
|
+
|
618
632
|
process_hook :before_worker_boot, key, block, 'on_worker_boot'
|
619
633
|
end
|
620
634
|
|
@@ -631,6 +645,8 @@ module Puma
|
|
631
645
|
# puts 'On worker shutdown...'
|
632
646
|
# end
|
633
647
|
def on_worker_shutdown(key = nil, &block)
|
648
|
+
warn_if_in_single_mode('on_worker_shutdown')
|
649
|
+
|
634
650
|
process_hook :before_worker_shutdown, key, block, 'on_worker_shutdown'
|
635
651
|
end
|
636
652
|
|
@@ -645,6 +661,8 @@ module Puma
|
|
645
661
|
# puts 'Before worker fork...'
|
646
662
|
# end
|
647
663
|
def on_worker_fork(&block)
|
664
|
+
warn_if_in_single_mode('on_worker_fork')
|
665
|
+
|
648
666
|
process_hook :before_worker_fork, nil, block, 'on_worker_fork'
|
649
667
|
end
|
650
668
|
|
@@ -659,11 +677,23 @@ module Puma
|
|
659
677
|
# puts 'After worker fork...'
|
660
678
|
# end
|
661
679
|
def after_worker_fork(&block)
|
680
|
+
warn_if_in_single_mode('after_worker_fork')
|
681
|
+
|
662
682
|
process_hook :after_worker_fork, nil, block, 'after_worker_fork'
|
663
683
|
end
|
664
684
|
|
665
685
|
alias_method :after_worker_boot, :after_worker_fork
|
666
686
|
|
687
|
+
# Code to run after puma is booted (works for both: single and clustered)
|
688
|
+
#
|
689
|
+
# @example
|
690
|
+
# on_booted do
|
691
|
+
# puts 'After booting...'
|
692
|
+
# end
|
693
|
+
def on_booted(&block)
|
694
|
+
@config.options[:events].on_booted(&block)
|
695
|
+
end
|
696
|
+
|
667
697
|
# When `fork_worker` is enabled, code to run in Worker 0
|
668
698
|
# before all other workers are re-forked from this process,
|
669
699
|
# after the server has temporarily stopped serving requests
|
@@ -1063,7 +1093,20 @@ module Puma
|
|
1063
1093
|
elsif key.nil?
|
1064
1094
|
@options[options_key] << block
|
1065
1095
|
else
|
1066
|
-
raise "'#{
|
1096
|
+
raise "'#{meth}' key must be String or Symbol"
|
1097
|
+
end
|
1098
|
+
end
|
1099
|
+
|
1100
|
+
def warn_if_in_single_mode(hook_name)
|
1101
|
+
return if @options[:silence_fork_callback_warning]
|
1102
|
+
|
1103
|
+
if (@options[:workers] || 0) == 0
|
1104
|
+
log_string =
|
1105
|
+
"Warning: You specified code to run in a `#{hook_name}` block, " \
|
1106
|
+
"but Puma is not configured to run in cluster mode (worker count > 0 ), " \
|
1107
|
+
"so your `#{hook_name}` block did not run"
|
1108
|
+
|
1109
|
+
LogWriter.stdio.log(log_string)
|
1067
1110
|
end
|
1068
1111
|
end
|
1069
1112
|
end
|
data/lib/puma/error_logger.rb
CHANGED
@@ -102,7 +102,8 @@ module Puma
|
|
102
102
|
@ioerr.is_a?(IO) and @ioerr.wait_writable(1)
|
103
103
|
@ioerr.write "#{w_str}\n"
|
104
104
|
@ioerr.flush unless @ioerr.sync
|
105
|
-
rescue Errno::EPIPE, Errno::EBADF, IOError
|
105
|
+
rescue Errno::EPIPE, Errno::EBADF, IOError, Errno::EINVAL
|
106
|
+
# 'Invalid argument' (Errno::EINVAL) may be raised by flush
|
106
107
|
end
|
107
108
|
end
|
108
109
|
rescue ThreadError
|
data/lib/puma/launcher.rb
CHANGED
@@ -79,6 +79,8 @@ module Puma
|
|
79
79
|
@log_writer.formatter = LogWriter::PidFormatter.new if clustered?
|
80
80
|
@log_writer.formatter = options[:log_formatter] if @options[:log_formatter]
|
81
81
|
|
82
|
+
@log_writer.custom_logger = options[:custom_logger] if @options[:custom_logger]
|
83
|
+
|
82
84
|
generate_restart_data
|
83
85
|
|
84
86
|
if clustered? && !Puma.forkable?
|
data/lib/puma/log_writer.rb
CHANGED
@@ -28,11 +28,12 @@ module Puma
|
|
28
28
|
attr_reader :stdout,
|
29
29
|
:stderr
|
30
30
|
|
31
|
-
attr_accessor :formatter
|
31
|
+
attr_accessor :formatter, :custom_logger
|
32
32
|
|
33
33
|
# Create a LogWriter that prints to +stdout+ and +stderr+.
|
34
34
|
def initialize(stdout, stderr)
|
35
35
|
@formatter = DefaultFormatter.new
|
36
|
+
@custom_logger = nil
|
36
37
|
@stdout = stdout
|
37
38
|
@stderr = stderr
|
38
39
|
|
@@ -59,7 +60,11 @@ module Puma
|
|
59
60
|
|
60
61
|
# Write +str+ to +@stdout+
|
61
62
|
def log(str)
|
62
|
-
|
63
|
+
if @custom_logger&.respond_to?(:write)
|
64
|
+
@custom_logger.write(format(str))
|
65
|
+
else
|
66
|
+
internal_write "#{@formatter.call str}\n"
|
67
|
+
end
|
63
68
|
end
|
64
69
|
|
65
70
|
def write(str)
|
@@ -73,7 +78,8 @@ module Puma
|
|
73
78
|
@stdout.is_a?(IO) and @stdout.wait_writable(1)
|
74
79
|
@stdout.write w_str
|
75
80
|
@stdout.flush unless @stdout.sync
|
76
|
-
rescue Errno::EPIPE, Errno::EBADF, IOError
|
81
|
+
rescue Errno::EPIPE, Errno::EBADF, IOError, Errno::EINVAL
|
82
|
+
# 'Invalid argument' (Errno::EINVAL) may be raised by flush
|
77
83
|
end
|
78
84
|
end
|
79
85
|
rescue ThreadError
|
data/lib/puma/request.rb
CHANGED
@@ -106,6 +106,7 @@ module Puma
|
|
106
106
|
# is called
|
107
107
|
res_body = app_body
|
108
108
|
|
109
|
+
# full hijack, app called env['rack.hijack']
|
109
110
|
return :async if client.hijacked
|
110
111
|
|
111
112
|
status = status.to_i
|
@@ -169,54 +170,55 @@ module Puma
|
|
169
170
|
resp_info = str_headers(env, status, headers, res_body, io_buffer, force_keep_alive)
|
170
171
|
|
171
172
|
close_body = false
|
173
|
+
response_hijack = nil
|
174
|
+
content_length = resp_info[:content_length]
|
175
|
+
keep_alive = resp_info[:keep_alive]
|
172
176
|
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
if
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
177
|
+
if res_body.respond_to?(:each) && !resp_info[:response_hijack]
|
178
|
+
# below converts app_body into body, dependent on app_body's characteristics, and
|
179
|
+
# content_length will be set if it can be determined
|
180
|
+
if !content_length && !resp_info[:transfer_encoding] && status != 204
|
181
|
+
if res_body.respond_to?(:to_ary) && (array_body = res_body.to_ary) &&
|
182
|
+
array_body.is_a?(Array)
|
183
|
+
body = array_body.compact
|
184
|
+
content_length = body.sum(&:bytesize)
|
185
|
+
elsif res_body.is_a?(File) && res_body.respond_to?(:size)
|
186
|
+
body = res_body
|
187
|
+
content_length = body.size
|
188
|
+
elsif res_body.respond_to?(:to_path) && File.readable?(fn = res_body.to_path)
|
189
|
+
body = File.open fn, 'rb'
|
190
|
+
content_length = body.size
|
191
|
+
close_body = true
|
192
|
+
else
|
193
|
+
body = res_body
|
194
|
+
end
|
195
|
+
elsif !res_body.is_a?(::File) && res_body.respond_to?(:to_path) &&
|
183
196
|
File.readable?(fn = res_body.to_path)
|
184
197
|
body = File.open fn, 'rb'
|
185
|
-
|
198
|
+
content_length = body.size
|
186
199
|
close_body = true
|
200
|
+
elsif !res_body.is_a?(::File) && res_body.respond_to?(:filename) &&
|
201
|
+
res_body.respond_to?(:bytesize) && File.readable?(fn = res_body.filename)
|
202
|
+
# Sprockets::Asset
|
203
|
+
content_length = res_body.bytesize unless content_length
|
204
|
+
if (body_str = res_body.to_hash[:source])
|
205
|
+
body = [body_str]
|
206
|
+
else # avoid each and use a File object
|
207
|
+
body = File.open fn, 'rb'
|
208
|
+
close_body = true
|
209
|
+
end
|
187
210
|
else
|
188
211
|
body = res_body
|
189
212
|
end
|
190
|
-
elsif !res_body.is_a?(::File) && res_body.respond_to?(:to_path) && res_body.respond_to?(:each) &&
|
191
|
-
File.readable?(fn = res_body.to_path)
|
192
|
-
body = File.open fn, 'rb'
|
193
|
-
resp_info[:content_length] = body.size
|
194
|
-
close_body = true
|
195
|
-
elsif !res_body.is_a?(::File) && res_body.respond_to?(:filename) && res_body.respond_to?(:each) &&
|
196
|
-
res_body.respond_to?(:bytesize) && File.readable?(fn = res_body.filename)
|
197
|
-
# Sprockets::Asset
|
198
|
-
resp_info[:content_length] = res_body.bytesize unless resp_info[:content_length]
|
199
|
-
if res_body.to_hash[:source] # use each to return @source
|
200
|
-
body = res_body
|
201
|
-
else # avoid each and use a File object
|
202
|
-
body = File.open fn, 'rb'
|
203
|
-
close_body = true
|
204
|
-
end
|
205
213
|
else
|
206
|
-
|
214
|
+
# partial hijack, from Rack spec:
|
215
|
+
# Servers must ignore the body part of the response tuple when the
|
216
|
+
# rack.hijack response header is present.
|
217
|
+
response_hijack = resp_info[:response_hijack] || res_body
|
207
218
|
end
|
208
219
|
|
209
220
|
line_ending = LINE_END
|
210
221
|
|
211
|
-
content_length = resp_info[:content_length]
|
212
|
-
keep_alive = resp_info[:keep_alive]
|
213
|
-
|
214
|
-
if res_body && !res_body.respond_to?(:each)
|
215
|
-
response_hijack = res_body
|
216
|
-
else
|
217
|
-
response_hijack = resp_info[:response_hijack]
|
218
|
-
end
|
219
|
-
|
220
222
|
cork_socket socket
|
221
223
|
|
222
224
|
if resp_info[:no_body]
|
@@ -244,6 +246,8 @@ module Puma
|
|
244
246
|
|
245
247
|
io_buffer << line_ending
|
246
248
|
|
249
|
+
# partial hijack, we write headers, then hand the socket to the app via
|
250
|
+
# response_hijack.call
|
247
251
|
if response_hijack
|
248
252
|
fast_write_str socket, io_buffer.read_and_reset
|
249
253
|
uncork_socket socket
|
@@ -358,16 +362,22 @@ module Puma
|
|
358
362
|
fast_write_str(socket, io_buffer.read_and_reset) unless io_buffer.length.zero?
|
359
363
|
else
|
360
364
|
# for enum bodies
|
361
|
-
fast_write_str socket, io_buffer.read_and_reset
|
362
365
|
if chunked
|
366
|
+
empty_body = true
|
363
367
|
body.each do |part|
|
364
|
-
next if (byte_size = part.bytesize).zero?
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
+
next if part.nil? || (byte_size = part.bytesize).zero?
|
369
|
+
empty_body = false
|
370
|
+
io_buffer.append byte_size.to_s(16), LINE_END, part, LINE_END
|
371
|
+
fast_write_str socket, io_buffer.read_and_reset
|
372
|
+
end
|
373
|
+
if empty_body
|
374
|
+
io_buffer << CLOSE_CHUNKED
|
375
|
+
fast_write_str socket, io_buffer.read_and_reset
|
376
|
+
else
|
377
|
+
fast_write_str socket, CLOSE_CHUNKED
|
368
378
|
end
|
369
|
-
fast_write_str socket, CLOSE_CHUNKED
|
370
379
|
else
|
380
|
+
fast_write_str socket, io_buffer.read_and_reset
|
371
381
|
body.each do |part|
|
372
382
|
next if part.bytesize.zero?
|
373
383
|
fast_write_str socket, part
|
data/lib/rack/handler/puma.rb
CHANGED
@@ -27,7 +27,9 @@ module Puma
|
|
27
27
|
end
|
28
28
|
end
|
29
29
|
|
30
|
-
|
30
|
+
@events = options[:events] || ::Puma::Events.new
|
31
|
+
|
32
|
+
conf = ::Puma::Configuration.new(options, default_options.merge({events: @events})) do |user_config, file_config, default_config|
|
31
33
|
if options.delete(:Verbose)
|
32
34
|
require 'rack/common_logger'
|
33
35
|
app = Rack::CommonLogger.new(app, STDOUT)
|
@@ -59,11 +61,11 @@ module Puma
|
|
59
61
|
end
|
60
62
|
|
61
63
|
def run(app, **options)
|
62
|
-
conf
|
64
|
+
conf = self.config(app, options)
|
63
65
|
|
64
66
|
log_writer = options.delete(:Silent) ? ::Puma::LogWriter.strings : ::Puma::LogWriter.stdio
|
65
67
|
|
66
|
-
launcher = ::Puma::Launcher.new(conf, :log_writer => log_writer)
|
68
|
+
launcher = ::Puma::Launcher.new(conf, :log_writer => log_writer, events: @events)
|
67
69
|
|
68
70
|
yield launcher if block_given?
|
69
71
|
begin
|