passenger 4.0.38 → 4.0.39
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of passenger might be problematic. Click here for more details.
- checksums.yaml +8 -8
- checksums.yaml.gz.asc +7 -7
- data.tar.gz.asc +7 -7
- data/CHANGELOG +24 -0
- data/bin/passenger +5 -0
- data/bin/passenger-install-apache2-module +1 -1
- data/bin/passenger-install-nginx-module +1 -1
- data/build/apache2.rb +2 -6
- data/build/cxx_tests.rb +5 -0
- data/build/packaging.rb +1 -0
- data/dev/list_tests.rb +36 -0
- data/doc/Users guide Standalone.txt +20 -5
- data/doc/users_guide_snippets/analysis_and_system_maintenance.txt +6 -13
- data/ext/common/Constants.h +1 -1
- data/ext/common/MessageClient.h +7 -7
- data/ext/common/Utils.cpp +6 -2
- data/ext/common/Utils/MessageIO.h +6 -11
- data/ext/common/agents/HelperAgent/RequestHandler.cpp +6 -3
- data/ext/common/agents/HelperAgent/RequestHandler.h +146 -24
- data/ext/ruby/extconf.rb +12 -0
- data/ext/ruby/passenger_native_support.c +18 -13
- data/helper-scripts/wsgi-loader.py +25 -2
- data/lib/phusion_passenger.rb +1 -1
- data/lib/phusion_passenger/config/about_command.rb +3 -0
- data/lib/phusion_passenger/rack/thread_handler_extension.rb +1 -4
- data/lib/phusion_passenger/request_handler/thread_handler.rb +0 -21
- data/lib/phusion_passenger/standalone/command.rb +10 -3
- data/lib/phusion_passenger/standalone/start_command.rb +4 -0
- data/lib/phusion_passenger/utils/tee_input.rb +82 -14
- data/lib/phusion_passenger/utils/terminal_choice_menu.rb +17 -2
- data/lib/phusion_passenger/utils/unseekable_socket.rb +0 -30
- data/resources/templates/error_layout.html.template +1 -1
- data/resources/templates/standalone/config.erb +18 -5
- data/test/cxx/RequestHandlerTest.cpp +410 -194
- data/test/integration_tests/native_packaging_spec.rb +5 -1
- data/test/ruby/request_handler_spec.rb +4 -71
- data/test/ruby/utils/tee_input_spec.rb +235 -0
- metadata +5 -3
- metadata.gz.asc +7 -7
@@ -113,7 +113,11 @@ describe "A natively packaged Phusion Passenger" do
|
|
113
113
|
if $?.exitstatus == 0
|
114
114
|
return output
|
115
115
|
else
|
116
|
-
|
116
|
+
filename = `mktemp /tmp/output.XXXXXX`.strip
|
117
|
+
File.open(filename, "w") do |f|
|
118
|
+
f.write(output)
|
119
|
+
end
|
120
|
+
abort "Command #{command} exited with status #{$?.exitstatus}. Output written to #{filename}"
|
117
121
|
end
|
118
122
|
end
|
119
123
|
|
@@ -328,7 +328,7 @@ describe RequestHandler do
|
|
328
328
|
hijack_callback_called.should == true
|
329
329
|
end
|
330
330
|
|
331
|
-
specify "
|
331
|
+
specify "requests with Content-Length are assumed to have a request body" do
|
332
332
|
@options["thread_handler"] = Class.new(RequestHandler::ThreadHandler) do
|
333
333
|
include Rack::ThreadHandlerExtension
|
334
334
|
end
|
@@ -362,7 +362,7 @@ describe RequestHandler do
|
|
362
362
|
lambda_called.should be_true
|
363
363
|
end
|
364
364
|
|
365
|
-
specify "
|
365
|
+
specify "requests with Transfer-Encoding chunked are assumed to have a request body" do
|
366
366
|
@options["thread_handler"] = Class.new(RequestHandler::ThreadHandler) do
|
367
367
|
include Rack::ThreadHandlerExtension
|
368
368
|
end
|
@@ -402,7 +402,7 @@ describe RequestHandler do
|
|
402
402
|
lambda_called.should be_true
|
403
403
|
end
|
404
404
|
|
405
|
-
specify "
|
405
|
+
specify "requests with neither Content-Length nor Transfer-Encoding are assumed to have no request body" do
|
406
406
|
@options["thread_handler"] = Class.new(RequestHandler::ThreadHandler) do
|
407
407
|
include Rack::ThreadHandlerExtension
|
408
408
|
end
|
@@ -416,72 +416,6 @@ describe RequestHandler do
|
|
416
416
|
[200, {}, ["ok"]]
|
417
417
|
end
|
418
418
|
|
419
|
-
@request_handler = RequestHandler.new(@owner_pipe[1], @options)
|
420
|
-
@request_handler.start_main_loop_thread
|
421
|
-
client = connect
|
422
|
-
begin
|
423
|
-
send_binary_request(client,
|
424
|
-
"REQUEST_METHOD" => "GET",
|
425
|
-
"PATH_INFO" => "/")
|
426
|
-
client.close_write
|
427
|
-
client.read.should ==
|
428
|
-
"Status: 200\r\n" +
|
429
|
-
"\r\n" +
|
430
|
-
"ok"
|
431
|
-
ensure
|
432
|
-
client.close
|
433
|
-
end
|
434
|
-
|
435
|
-
lambda_called.should be_true
|
436
|
-
end
|
437
|
-
|
438
|
-
specify "GET requests with Content-Length 0 are assumed to have no request body" do
|
439
|
-
@options["thread_handler"] = Class.new(RequestHandler::ThreadHandler) do
|
440
|
-
include Rack::ThreadHandlerExtension
|
441
|
-
end
|
442
|
-
|
443
|
-
lambda_called = false
|
444
|
-
|
445
|
-
@options["app"] = lambda do |env|
|
446
|
-
lambda_called = true
|
447
|
-
env['rack.input'].read(1).should be_nil
|
448
|
-
env['rack.input'].gets.should be_nil
|
449
|
-
[200, {}, ["ok"]]
|
450
|
-
end
|
451
|
-
|
452
|
-
@request_handler = RequestHandler.new(@owner_pipe[1], @options)
|
453
|
-
@request_handler.start_main_loop_thread
|
454
|
-
client = connect
|
455
|
-
begin
|
456
|
-
send_binary_request(client,
|
457
|
-
"REQUEST_METHOD" => "GET",
|
458
|
-
"PATH_INFO" => "/",
|
459
|
-
"CONTENT_LENGTH" => "0")
|
460
|
-
client.close_write
|
461
|
-
client.read.should ==
|
462
|
-
"Status: 200\r\n" +
|
463
|
-
"\r\n" +
|
464
|
-
"ok"
|
465
|
-
ensure
|
466
|
-
client.close
|
467
|
-
end
|
468
|
-
|
469
|
-
lambda_called.should be_true
|
470
|
-
end
|
471
|
-
|
472
|
-
specify "non-GET requests are assumed to have a request body, even those without Content-Length and Transfer-Encoding" do
|
473
|
-
@options["thread_handler"] = Class.new(RequestHandler::ThreadHandler) do
|
474
|
-
include Rack::ThreadHandlerExtension
|
475
|
-
end
|
476
|
-
|
477
|
-
lambda_called = false
|
478
|
-
|
479
|
-
@options["app"] = lambda do |env|
|
480
|
-
lambda_called = true
|
481
|
-
env['rack.input'].read(3).should == "abc"
|
482
|
-
[200, {}, ["ok"]]
|
483
|
-
end
|
484
|
-
|
485
419
|
@request_handler = RequestHandler.new(@owner_pipe[1], @options)
|
486
420
|
@request_handler.start_main_loop_thread
|
487
421
|
client = connect
|
@@ -489,7 +423,6 @@ describe RequestHandler do
|
|
489
423
|
send_binary_request(client,
|
490
424
|
"REQUEST_METHOD" => "POST",
|
491
425
|
"PATH_INFO" => "/")
|
492
|
-
client.write("abc")
|
493
426
|
client.close_write
|
494
427
|
client.read.should ==
|
495
428
|
"Status: 200\r\n" +
|
@@ -502,7 +435,7 @@ describe RequestHandler do
|
|
502
435
|
lambda_called.should be_true
|
503
436
|
end
|
504
437
|
|
505
|
-
describe "on
|
438
|
+
describe "on requests that are not supposed to have a body" do
|
506
439
|
before :each do
|
507
440
|
@options["thread_handler"] = Class.new(RequestHandler::ThreadHandler) do
|
508
441
|
include Rack::ThreadHandlerExtension
|
@@ -0,0 +1,235 @@
|
|
1
|
+
# encoding: binary
|
2
|
+
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
|
3
|
+
PhusionPassenger.require_passenger_lib 'utils/tee_input'
|
4
|
+
require 'stringio'
|
5
|
+
|
6
|
+
module PhusionPassenger
|
7
|
+
|
8
|
+
shared_examples "TeeInput#gets" do
|
9
|
+
context "if Content-Length is given" do
|
10
|
+
before :each do
|
11
|
+
init_input("hello\nworld\nlast line!", "CONTENT_LENGTH" => 21)
|
12
|
+
end
|
13
|
+
|
14
|
+
it "reads a line, including newline character" do
|
15
|
+
@input.gets.should == "hello\n"
|
16
|
+
@input.gets.should == "world\n"
|
17
|
+
end
|
18
|
+
|
19
|
+
it "reads until EOF if no newline is encountered before EOF" do
|
20
|
+
@input.gets
|
21
|
+
@input.gets
|
22
|
+
@input.gets.should == "last line"
|
23
|
+
end
|
24
|
+
|
25
|
+
it "returns nil if EOF is reached" do
|
26
|
+
@input.gets
|
27
|
+
@input.gets
|
28
|
+
@input.gets
|
29
|
+
@input.gets.should be_nil
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
context "if Transfer-Encoding is chunked" do
|
34
|
+
before :each do
|
35
|
+
init_input("hello\nworld\nlast line", "HTTP_TRANSFER_ENCODING" => "chunked")
|
36
|
+
end
|
37
|
+
|
38
|
+
it "reads a line, including newline character" do
|
39
|
+
@input.gets.should == "hello\n"
|
40
|
+
@input.gets.should == "world\n"
|
41
|
+
end
|
42
|
+
|
43
|
+
it "reads until EOF if no newline is encountered before EOF" do
|
44
|
+
@input.gets
|
45
|
+
@input.gets
|
46
|
+
@input.gets.should == "last line"
|
47
|
+
end
|
48
|
+
|
49
|
+
it "returns nil if EOF is reached" do
|
50
|
+
@input.gets
|
51
|
+
@input.gets
|
52
|
+
@input.gets
|
53
|
+
@input.gets.should be_nil
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
context "if neither Content-Length nor Transfer-Encoding chunked are given" do
|
58
|
+
before :each do
|
59
|
+
init_input("hello\nworld\nlast line")
|
60
|
+
end
|
61
|
+
|
62
|
+
it "returns nil" do
|
63
|
+
@input.gets.should be_nil
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
shared_examples "TeeInput#read" do
|
69
|
+
describe "with no arguments" do
|
70
|
+
context "if Content-Length is given" do
|
71
|
+
before :each do
|
72
|
+
init_input("hello!", "CONTENT_LENGTH" => 5)
|
73
|
+
end
|
74
|
+
|
75
|
+
it "slurps up to Content-Length bytes from the socket" do
|
76
|
+
@input.read.should == "hello"
|
77
|
+
end
|
78
|
+
|
79
|
+
it "returns the empty string if EOF is reached" do
|
80
|
+
@input.read
|
81
|
+
@input.read.should == ""
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
context "if Transfer-Encoding is chunked" do
|
86
|
+
before :each do
|
87
|
+
init_input("hello!", "HTTP_TRANSFER_ENCODING" => "chunked")
|
88
|
+
end
|
89
|
+
|
90
|
+
it "slurps the entire socket" do
|
91
|
+
@input.read.should == "hello!"
|
92
|
+
end
|
93
|
+
|
94
|
+
it "returns the empty string if EOF is reached" do
|
95
|
+
@input.read
|
96
|
+
@input.read.should == ""
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
context "if neither Content-Length nor Transfer-Encoding chunked are given" do
|
101
|
+
before :each do
|
102
|
+
init_input("hello!")
|
103
|
+
end
|
104
|
+
|
105
|
+
it "returns the empty string" do
|
106
|
+
@input.read.should == ""
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
describe "with a length argument" do
|
112
|
+
it "raises ArgumentError if len < 0" do
|
113
|
+
init_input("")
|
114
|
+
lambda { @input.read(-1) }.should raise_error(ArgumentError)
|
115
|
+
end
|
116
|
+
|
117
|
+
it "returns the empty string if len == 0" do
|
118
|
+
init_input("hello", "HTTP_TRANSFER_ENCODING" => "chunked")
|
119
|
+
@input.read(0).should == ""
|
120
|
+
end
|
121
|
+
|
122
|
+
context "if Content-Length is given" do
|
123
|
+
before :each do
|
124
|
+
init_input("hello!", "CONTENT_LENGTH" => 5)
|
125
|
+
end
|
126
|
+
|
127
|
+
it "reads exactly len bytes if available" do
|
128
|
+
@input.read(2).should == "he"
|
129
|
+
@input.read(2).should == "ll"
|
130
|
+
end
|
131
|
+
|
132
|
+
it "reads at most Content-Length bytes if Content-Length < len are available" do
|
133
|
+
@input.read(2).should == "he"
|
134
|
+
@input.read(4).should == "llo"
|
135
|
+
end
|
136
|
+
|
137
|
+
it "returns nil if Content-Length is reached" do
|
138
|
+
@input.read(5).should == "hello"
|
139
|
+
@input.read(1).should be_nil
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
context "if Transfer-Encoding is chunked" do
|
144
|
+
before :each do
|
145
|
+
init_input("hello", "HTTP_TRANSFER_ENCODING" => "chunked")
|
146
|
+
end
|
147
|
+
|
148
|
+
it "reads exactly len bytes if available" do
|
149
|
+
@input.read(2).should == "he"
|
150
|
+
@input.read(2).should == "ll"
|
151
|
+
end
|
152
|
+
|
153
|
+
it "reads until EOF if less than len bytes are available" do
|
154
|
+
@input.read(2).should == "he"
|
155
|
+
@input.read(4).should == "llo"
|
156
|
+
end
|
157
|
+
|
158
|
+
it "returns nil if EOF is reached" do
|
159
|
+
@input.read(5).should == "hello"
|
160
|
+
@input.read(1).should be_nil
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
context "if neither Content-Length nor Transfer-Encoding chunked are given" do
|
165
|
+
it "returns nil" do
|
166
|
+
init_input("hello")
|
167
|
+
@input.read(2).should be_nil
|
168
|
+
end
|
169
|
+
end
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
shared_examples "TeeInput#size" do
|
174
|
+
context "if Content-Length is given" do
|
175
|
+
it "returns the value in Content-Length" do
|
176
|
+
init_input("hello world", "CONTENT_LENGTH" => 10)
|
177
|
+
@input.size.should == 10
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
context "if Transfer-Encoding is chunked" do
|
182
|
+
it "returns the number of bytes that can be read from the socket until EOF" do
|
183
|
+
init_input("hello world", "HTTP_TRANSFER_ENCODING" => "chunked")
|
184
|
+
@input.size.should == 11
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
188
|
+
context "if neither Content-Length nor Transfer-Encoding chunked are given" do
|
189
|
+
it "returns 0" do
|
190
|
+
init_input("hello world")
|
191
|
+
@input.size.should == 0
|
192
|
+
end
|
193
|
+
end
|
194
|
+
end
|
195
|
+
|
196
|
+
describe Utils::TeeInput do
|
197
|
+
before :each do
|
198
|
+
@sock, @sock2 = UNIXSocket.pair
|
199
|
+
end
|
200
|
+
|
201
|
+
after :each do
|
202
|
+
[@sock, @sock2].each do |sock|
|
203
|
+
sock.close if sock && !sock.closed?
|
204
|
+
end
|
205
|
+
@input.close if @input
|
206
|
+
end
|
207
|
+
|
208
|
+
context "when unbuffered" do
|
209
|
+
def init_input(data, env = {})
|
210
|
+
@input = Utils::TeeInput.new(@sock2, env)
|
211
|
+
@sock.write(data)
|
212
|
+
@sock.close
|
213
|
+
end
|
214
|
+
|
215
|
+
describe("#gets") { include_examples "TeeInput#gets" }
|
216
|
+
describe("#read") { include_examples "TeeInput#read" }
|
217
|
+
describe("#size") { include_examples "TeeInput#size" }
|
218
|
+
end
|
219
|
+
|
220
|
+
context "when buffered" do
|
221
|
+
def init_input(data, env = {})
|
222
|
+
@input = Utils::TeeInput.new(@sock2, env)
|
223
|
+
@sock.write(data)
|
224
|
+
@sock.close
|
225
|
+
@input.read
|
226
|
+
@input.rewind
|
227
|
+
end
|
228
|
+
|
229
|
+
describe("#gets") { include_examples "TeeInput#gets" }
|
230
|
+
describe("#read") { include_examples "TeeInput#read" }
|
231
|
+
describe("#size") { include_examples "TeeInput#size" }
|
232
|
+
end
|
233
|
+
end
|
234
|
+
|
235
|
+
end # module PhusionPassenger
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: passenger
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 4.0.
|
4
|
+
version: 4.0.39
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Phusion - http://www.phusion.nl/
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-03-
|
11
|
+
date: 2014-03-18 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|
@@ -124,6 +124,7 @@ files:
|
|
124
124
|
- dev/copy_boost_headers.rb
|
125
125
|
- dev/find_owner_pipe_leaks.rb
|
126
126
|
- dev/install_scripts_bootstrap_code.rb
|
127
|
+
- dev/list_tests.rb
|
127
128
|
- dev/render_error_pages.rb
|
128
129
|
- dev/run_travis.sh
|
129
130
|
- dev/runner
|
@@ -2576,6 +2577,7 @@ files:
|
|
2576
2577
|
- test/ruby/standalone/runtime_locator_spec.rb
|
2577
2578
|
- test/ruby/utils/file_system_watcher_spec.rb
|
2578
2579
|
- test/ruby/utils/hosts_file_parser.rb
|
2580
|
+
- test/ruby/utils/tee_input_spec.rb
|
2579
2581
|
- test/ruby/utils/unseekable_socket_spec.rb
|
2580
2582
|
- test/ruby/utils_spec.rb
|
2581
2583
|
- test/stub/.DS_Store
|
@@ -2938,7 +2940,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
2938
2940
|
version: '0'
|
2939
2941
|
requirements: []
|
2940
2942
|
rubyforge_project: passenger
|
2941
|
-
rubygems_version: 2.2.
|
2943
|
+
rubygems_version: 2.2.2
|
2942
2944
|
signing_key:
|
2943
2945
|
specification_version: 4
|
2944
2946
|
summary: A fast and robust web server and application server for Ruby, Python and
|
metadata.gz.asc
CHANGED
@@ -2,11 +2,11 @@
|
|
2
2
|
Version: GnuPG/MacGPG2 v2.0.17 (Darwin)
|
3
3
|
Comment: GPGTools - http://gpgtools.org
|
4
4
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
=
|
5
|
+
iQEcBAABAgAGBQJTKAuvAAoJECrHRaUKISqMJV0H/jJ3TdSzvcOED6fM21+rWEUZ
|
6
|
+
GwCLToeTuTnXM8kazH/A/+k+Gc1taW3TqdD6Ovu6iJftsrAt+nnfWY23Eo2+X47R
|
7
|
+
mwYRWSx1e9nJ+oeiTR/hzo+0swQ+HUR31Fu5sN0dqhptddyEfr6lvvpWY0C71tf9
|
8
|
+
o9WL3UP6uZqFJs3fSMW5F+mbC+mqjhJLC1dCzoAq+l18TW6zrkkpFdmhKqQ+z/Q0
|
9
|
+
E2u6TyDmIXfyU9proT8Qi/yjV/jhMhFpw19ENAWB1SzFZ/06ZcOy86YqSj4BYScA
|
10
|
+
uli9v4gcArgNtDZLE3IogSIQrRQVST7XKhdP0bpZlx5nzkOeWPU+8HS3dK2ZH14=
|
11
|
+
=oBMO
|
12
12
|
-----END PGP SIGNATURE-----
|