passenger 4.0.36 → 4.0.37
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/NEWS +51 -0
- data/README.md +3 -1
- data/build/integration_tests.rb +5 -1
- data/build/test_basics.rb +2 -2
- data/dev/run_travis.sh +3 -0
- data/doc/Users guide Nginx.txt +3 -3
- data/ext/common/ApplicationPool2/Group.h +2 -1
- data/ext/common/ApplicationPool2/Implementation.cpp +30 -1
- data/ext/common/ApplicationPool2/Pool.h +26 -3
- data/ext/common/ApplicationPool2/Process.h +39 -10
- data/ext/common/Constants.h +1 -1
- data/ext/common/MultiLibeio.cpp +4 -0
- data/ext/common/ServerInstanceDir.h +1 -1
- data/ext/common/Utils.cpp +29 -0
- data/ext/common/Utils.h +7 -1
- data/ext/common/Utils/BufferedIO.h +13 -0
- data/ext/common/agents/HelperAgent/Main.cpp +6 -2
- data/ext/common/agents/HelperAgent/RequestHandler.h +32 -1
- data/helper-scripts/meteor-loader.rb +126 -10
- data/helper-scripts/node-loader.js +5 -3
- data/helper-scripts/wsgi-loader.py +23 -11
- data/lib/phusion_passenger.rb +1 -1
- data/lib/phusion_passenger/config/detach_process_command.rb +96 -0
- data/lib/phusion_passenger/config/main.rb +1 -0
- data/lib/phusion_passenger/request_handler.rb +11 -4
- data/node_lib/phusion_passenger/httplib_emulation.js +20 -14
- data/test/cxx/RequestHandlerTest.cpp +80 -0
- data/test/integration_tests/apache2_tests.rb +57 -0
- data/test/integration_tests/nginx_tests.rb +62 -0
- data/test/node/httplib_emulation_spec.js +137 -5
- data/test/node/spec_helper.js +13 -0
- data/test/stub/node/app.js +125 -0
- data/test/stub/node/public/.gitignore +0 -0
- data/test/stub/node/tmp/.gitignore +0 -0
- data/test/stub/rack/config.ru +19 -0
- data/test/stub/wsgi/passenger_wsgi.py +37 -1
- metadata +6 -2
- metadata.gz.asc +7 -7
data/lib/phusion_passenger.rb
CHANGED
@@ -30,7 +30,7 @@ module PhusionPassenger
|
|
30
30
|
|
31
31
|
PACKAGE_NAME = 'passenger'
|
32
32
|
# Run 'rake ext/common/Constants.h' after changing this number.
|
33
|
-
VERSION_STRING = '4.0.
|
33
|
+
VERSION_STRING = '4.0.37'
|
34
34
|
|
35
35
|
PREFERRED_NGINX_VERSION = '1.4.4'
|
36
36
|
NGINX_SHA256_CHECKSUM = '7c989a58e5408c9593da0bebcd0e4ffc3d892d1316ba5042ddb0be5b0b4102b9'
|
@@ -0,0 +1,96 @@
|
|
1
|
+
# Phusion Passenger - https://www.phusionpassenger.com/
|
2
|
+
# Copyright (c) 2014 Phusion
|
3
|
+
#
|
4
|
+
# "Phusion Passenger" is a trademark of Hongli Lai & Ninh Bui.
|
5
|
+
#
|
6
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
7
|
+
# of this software and associated documentation files (the "Software"), to deal
|
8
|
+
# in the Software without restriction, including without limitation the rights
|
9
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
10
|
+
# copies of the Software, and to permit persons to whom the Software is
|
11
|
+
# furnished to do so, subject to the following conditions:
|
12
|
+
#
|
13
|
+
# The above copyright notice and this permission notice shall be included in
|
14
|
+
# all copies or substantial portions of the Software.
|
15
|
+
#
|
16
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
17
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
18
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
19
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
20
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
21
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
22
|
+
# THE SOFTWARE.
|
23
|
+
|
24
|
+
require 'optparse'
|
25
|
+
PhusionPassenger.require_passenger_lib 'constants'
|
26
|
+
PhusionPassenger.require_passenger_lib 'admin_tools/server_instance'
|
27
|
+
PhusionPassenger.require_passenger_lib 'config/command'
|
28
|
+
PhusionPassenger.require_passenger_lib 'config/utils'
|
29
|
+
|
30
|
+
module PhusionPassenger
|
31
|
+
module Config
|
32
|
+
|
33
|
+
class DetachProcessCommand < Command
|
34
|
+
include PhusionPassenger::Config::Utils
|
35
|
+
|
36
|
+
def self.description
|
37
|
+
return "Detach an application process from the process pool"
|
38
|
+
end
|
39
|
+
|
40
|
+
def run
|
41
|
+
parse_options
|
42
|
+
select_passenger_instance
|
43
|
+
@admin_client = connect_to_passenger_admin_socket(:role => :passenger_status)
|
44
|
+
perform_detach
|
45
|
+
end
|
46
|
+
|
47
|
+
private
|
48
|
+
def self.create_option_parser(options)
|
49
|
+
OptionParser.new do |opts|
|
50
|
+
nl = "\n" + ' ' * 37
|
51
|
+
opts.banner = "Usage: passenger-config detach-process [OPTIONS] <PID>\n"
|
52
|
+
opts.separator ""
|
53
|
+
opts.separator " Remove an application process from the #{PROGRAM_NAME} process pool."
|
54
|
+
opts.separator " Has a similar effect to killing the application process directly with"
|
55
|
+
opts.separator " `kill <PID>`, but killing directly may cause the HTTP client to see an"
|
56
|
+
opts.separator " error, while using this command guarantees that clients see no errors."
|
57
|
+
opts.separator ""
|
58
|
+
|
59
|
+
opts.separator "Options:"
|
60
|
+
opts.on("--instance INSTANCE_PID", Integer, "The #{PROGRAM_NAME} instance to select") do |value|
|
61
|
+
options[:instance] = value
|
62
|
+
end
|
63
|
+
opts.on("-h", "--help", "Show this help") do
|
64
|
+
options[:help] = true
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def help
|
70
|
+
puts @parser
|
71
|
+
end
|
72
|
+
|
73
|
+
def parse_options
|
74
|
+
super
|
75
|
+
if @argv.empty?
|
76
|
+
abort "Please pass a PID. " +
|
77
|
+
"See --help for more information."
|
78
|
+
elsif @argv.size == 1
|
79
|
+
@pid = @argv[0].to_i
|
80
|
+
elsif @argv.size > 1
|
81
|
+
help
|
82
|
+
abort
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
def perform_detach
|
87
|
+
if @admin_client.pool_detach_process(@pid)
|
88
|
+
puts "Process #{@pid} detached."
|
89
|
+
else
|
90
|
+
abort "Could not detach process #{@pid}."
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
end # module Config
|
96
|
+
end # module PhusionPassenger
|
@@ -28,6 +28,7 @@ module PhusionPassenger
|
|
28
28
|
# Core of the `passenger-config` command. Dispatches a subcommand to a specific class.
|
29
29
|
module Config
|
30
30
|
KNOWN_COMMANDS = [
|
31
|
+
["detach-process", "DetachProcessCommand"],
|
31
32
|
["restart-app", "RestartAppCommand"],
|
32
33
|
["validate-install", "ValidateInstallCommand"],
|
33
34
|
["about", "AboutCommand"]
|
@@ -95,6 +95,11 @@ class RequestHandler
|
|
95
95
|
"analytics_logger",
|
96
96
|
"pool_account_username"
|
97
97
|
)
|
98
|
+
|
99
|
+
@force_http_session = ENV["_PASSENGER_FORCE_HTTP_SESSION"] == "true"
|
100
|
+
if @force_http_session
|
101
|
+
@connect_password = nil
|
102
|
+
end
|
98
103
|
@thread_handler = options["thread_handler"] || ThreadHandler
|
99
104
|
@concurrency = 1
|
100
105
|
if options["pool_account_password_base64"]
|
@@ -114,7 +119,7 @@ class RequestHandler
|
|
114
119
|
@server_sockets[:main] = {
|
115
120
|
:address => @main_socket_address,
|
116
121
|
:socket => @main_socket,
|
117
|
-
:protocol => :session,
|
122
|
+
:protocol => @force_http_session ? :http_session : :session,
|
118
123
|
:concurrency => @concurrency
|
119
124
|
}
|
120
125
|
|
@@ -125,7 +130,7 @@ class RequestHandler
|
|
125
130
|
:protocol => :http,
|
126
131
|
:concurrency => 1
|
127
132
|
}
|
128
|
-
|
133
|
+
|
129
134
|
@owner_pipe = owner_pipe
|
130
135
|
@options = options
|
131
136
|
@previous_signal_handlers = {}
|
@@ -308,7 +313,7 @@ private
|
|
308
313
|
# is still bugged as of version 1.7.0. They can
|
309
314
|
# cause unexplicable freezes when used in combination
|
310
315
|
# with threading.
|
311
|
-
return ruby_engine != "jruby"
|
316
|
+
return !@force_http_session && ruby_engine != "jruby"
|
312
317
|
end
|
313
318
|
|
314
319
|
def create_unix_socket_on_filesystem
|
@@ -400,7 +405,9 @@ private
|
|
400
405
|
main_socket_options = common_options.merge(
|
401
406
|
:server_socket => @main_socket,
|
402
407
|
:socket_name => "main socket",
|
403
|
-
:protocol => :session
|
408
|
+
:protocol => @server_sockets[:main][:protocol] == :session ?
|
409
|
+
:session :
|
410
|
+
:http
|
404
411
|
)
|
405
412
|
http_socket_options = common_options.merge(
|
406
413
|
:server_socket => @http_socket,
|
@@ -1,6 +1,6 @@
|
|
1
1
|
/*
|
2
2
|
* Phusion Passenger - https://www.phusionpassenger.com/
|
3
|
-
* Copyright (c) 2013 Phusion
|
3
|
+
* Copyright (c) 2013-2014 Phusion
|
4
4
|
*
|
5
5
|
* "Phusion Passenger" is a trademark of Hongli Lai & Ninh Bui.
|
6
6
|
*
|
@@ -68,11 +68,15 @@ function inferHttpVersion(protocolDescription) {
|
|
68
68
|
}
|
69
69
|
}
|
70
70
|
|
71
|
-
function mayHaveRequestBody(headers) {
|
72
|
-
return headers['REQUEST_METHOD'] != 'GET' || headers['HTTP_UPGRADE'];
|
73
|
-
}
|
74
|
-
|
75
71
|
function createIncomingMessage(headers, socket, bodyBegin) {
|
72
|
+
/* Node's HTTP parser simulates an 'end' event if it determines that
|
73
|
+
* the request should not have a request body. Currently (Node 0.10.18),
|
74
|
+
* it thinks GET requests without an Upgrade header should not have a
|
75
|
+
* request body, even though technically such GET requests are allowed
|
76
|
+
* to have a request body. For compatibility reasons we implement the
|
77
|
+
* same behavior as Node's HTTP parser.
|
78
|
+
*/
|
79
|
+
|
76
80
|
var message = new http.IncomingMessage(socket);
|
77
81
|
setHttpHeaders(message.headers, headers);
|
78
82
|
message.cgiHeaders = headers;
|
@@ -81,7 +85,14 @@ function createIncomingMessage(headers, socket, bodyBegin) {
|
|
81
85
|
message.url = headers['REQUEST_URI'];
|
82
86
|
message.connection.remoteAddress = headers['REMOTE_ADDR'];
|
83
87
|
message.connection.remotePort = parseInt(headers['REMOTE_PORT']);
|
84
|
-
message.
|
88
|
+
message.upgrade = !!headers['HTTP_UPGRADE'];
|
89
|
+
|
90
|
+
if (message.upgrade) {
|
91
|
+
// Emit end event as described above.
|
92
|
+
message.push(null);
|
93
|
+
return message;
|
94
|
+
}
|
95
|
+
|
85
96
|
message._emitEndEvent = IncomingMessage_emitEndEvent;
|
86
97
|
resetIncomingMessageOverridedMethods(message);
|
87
98
|
|
@@ -95,14 +106,7 @@ function createIncomingMessage(headers, socket, bodyBegin) {
|
|
95
106
|
message.emit('timeout');
|
96
107
|
});
|
97
108
|
|
98
|
-
|
99
|
-
* the request should not have a request body. Currently (Node 0.10.18),
|
100
|
-
* it thinks GET requests without an Upgrade header should not have a
|
101
|
-
* request body, even though technically such GET requests are allowed
|
102
|
-
* to have a request body. For compatibility reasons we implement the
|
103
|
-
* same behavior as Node's HTTP parser.
|
104
|
-
*/
|
105
|
-
if (message._mayHaveRequestBody) {
|
109
|
+
if (headers['REQUEST_METHOD'] != 'GET') {
|
106
110
|
if (bodyBegin.length > 0) {
|
107
111
|
message.push(bodyBegin);
|
108
112
|
}
|
@@ -112,6 +116,7 @@ function createIncomingMessage(headers, socket, bodyBegin) {
|
|
112
116
|
}
|
113
117
|
}
|
114
118
|
} else {
|
119
|
+
// Emit end event as described above.
|
115
120
|
message.push(null);
|
116
121
|
}
|
117
122
|
|
@@ -139,6 +144,7 @@ function IncomingMessage_on(event, listener) {
|
|
139
144
|
}
|
140
145
|
this._orig_on.call(this, event, listener);
|
141
146
|
resetIncomingMessageOverridedMethods(this);
|
147
|
+
return this;
|
142
148
|
}
|
143
149
|
|
144
150
|
function IncomingMessage_emitEndEvent() {
|
@@ -6,6 +6,7 @@
|
|
6
6
|
#include <Utils/json.h>
|
7
7
|
#include <Utils/IOUtils.h>
|
8
8
|
#include <Utils/Timer.h>
|
9
|
+
#include <Utils/BufferedIO.h>
|
9
10
|
|
10
11
|
#include <boost/shared_array.hpp>
|
11
12
|
#include <string>
|
@@ -51,6 +52,7 @@ namespace tut {
|
|
51
52
|
setPrintAppOutputAsDebuggingMessages(true);
|
52
53
|
|
53
54
|
agentOptions.passengerRoot = resourceLocator->getRoot();
|
55
|
+
agentOptions.defaultRubyCommand = DEFAULT_RUBY;
|
54
56
|
agentOptions.defaultUser = testConfig["default_user"].asString();
|
55
57
|
agentOptions.defaultGroup = testConfig["default_group"].asString();
|
56
58
|
root = resourceLocator->getRoot();
|
@@ -972,6 +974,84 @@ namespace tut {
|
|
972
974
|
ensure(containsSubstring(response, "Counter: 2\n"));
|
973
975
|
}
|
974
976
|
|
977
|
+
TEST_METHOD(53) {
|
978
|
+
set_test_name("It supports switching protocols when communicating over application session sockets");
|
979
|
+
|
980
|
+
init();
|
981
|
+
connect();
|
982
|
+
sendHeaders(defaultHeaders,
|
983
|
+
"PASSENGER_APP_ROOT", wsgiAppPath.c_str(),
|
984
|
+
"PATH_INFO", "/switch_protocol",
|
985
|
+
"HTTP_UPGRADE", "raw",
|
986
|
+
"HTTP_CONNECTION", "Upgrade",
|
987
|
+
NULL
|
988
|
+
);
|
989
|
+
|
990
|
+
BufferedIO io(connection);
|
991
|
+
string header;
|
992
|
+
bool done = false;
|
993
|
+
|
994
|
+
ensure_equals(io.readLine(), "HTTP/1.1 101 Switching Protocols\r\n");
|
995
|
+
|
996
|
+
do {
|
997
|
+
string line = io.readLine();
|
998
|
+
done = line.empty() || line == "\r\n";
|
999
|
+
if (!done) {
|
1000
|
+
header.append(line);
|
1001
|
+
}
|
1002
|
+
} while (!done);
|
1003
|
+
|
1004
|
+
ensure("(1)", containsSubstring(header, "Upgrade: raw\r\n"));
|
1005
|
+
ensure("(2)", containsSubstring(header, "Connection: Upgrade\r\n"));
|
1006
|
+
|
1007
|
+
writeExact(connection, "hello\n");
|
1008
|
+
ensure_equals(io.readLine(), "Echo: hello\n");
|
1009
|
+
}
|
1010
|
+
|
1011
|
+
TEST_METHOD(54) {
|
1012
|
+
set_test_name("It supports switching protocols when communication over application http_session sockets");
|
1013
|
+
|
1014
|
+
init();
|
1015
|
+
connect();
|
1016
|
+
sendHeaders(defaultHeaders,
|
1017
|
+
"_PASSENGER_FORCE_HTTP_SESSION", "true",
|
1018
|
+
"PASSENGER_APP_ROOT", rackAppPath.c_str(),
|
1019
|
+
"PASSENGER_APP_TYPE", "rack",
|
1020
|
+
"REQUEST_URI", "/switch_protocol",
|
1021
|
+
"PATH_INFO", "/switch_protocol",
|
1022
|
+
"HTTP_UPGRADE", "raw",
|
1023
|
+
"HTTP_CONNECTION", "Upgrade",
|
1024
|
+
NULL
|
1025
|
+
);
|
1026
|
+
|
1027
|
+
BufferedIO io(connection);
|
1028
|
+
string header;
|
1029
|
+
bool done = false;
|
1030
|
+
vector<ProcessPtr> processes;
|
1031
|
+
|
1032
|
+
ensure_equals(io.readLine(), "HTTP/1.1 101 Switching Protocols\r\n");
|
1033
|
+
processes = pool->getProcesses();
|
1034
|
+
{
|
1035
|
+
LockGuard l(pool->syncher);
|
1036
|
+
ProcessPtr process = processes[0];
|
1037
|
+
ensure_equals(process->sessionSockets.top()->protocol, "http_session");
|
1038
|
+
}
|
1039
|
+
|
1040
|
+
do {
|
1041
|
+
string line = io.readLine();
|
1042
|
+
done = line.empty() || line == "\r\n";
|
1043
|
+
if (!done) {
|
1044
|
+
header.append(line);
|
1045
|
+
}
|
1046
|
+
} while (!done);
|
1047
|
+
|
1048
|
+
ensure("(1)", containsSubstring(header, "Upgrade: raw\r\n"));
|
1049
|
+
ensure("(2)", containsSubstring(header, "Connection: Upgrade\r\n"));
|
1050
|
+
|
1051
|
+
writeExact(connection, "hello\n");
|
1052
|
+
ensure_equals(io.readLine(), "Echo: hello\n");
|
1053
|
+
}
|
1054
|
+
|
975
1055
|
// Test small response buffering.
|
976
1056
|
// Test large response buffering.
|
977
1057
|
}
|
@@ -158,6 +158,63 @@ describe "Apache 2 module" do
|
|
158
158
|
end
|
159
159
|
end
|
160
160
|
|
161
|
+
describe "a Node.js app running on the root URI" do
|
162
|
+
before :all do
|
163
|
+
create_apache2_controller
|
164
|
+
@server = "http://1.passenger.test:#{@apache2.port}"
|
165
|
+
@stub = NodejsStub.new('node')
|
166
|
+
@apache2 << "RailsMaxPoolSize 1"
|
167
|
+
@apache2.set_vhost("1.passenger.test", "#{@stub.full_app_root}/public")
|
168
|
+
@apache2.start
|
169
|
+
end
|
170
|
+
|
171
|
+
after :all do
|
172
|
+
@stub.destroy
|
173
|
+
@apache2.stop if @apache2
|
174
|
+
end
|
175
|
+
|
176
|
+
before :each do
|
177
|
+
@stub.reset
|
178
|
+
end
|
179
|
+
|
180
|
+
it_should_behave_like "an example web app"
|
181
|
+
end
|
182
|
+
|
183
|
+
describe "a Node.js app running in a sub-URI" do
|
184
|
+
before :all do
|
185
|
+
create_apache2_controller
|
186
|
+
@server = "http://1.passenger.test:#{@apache2.port}/subapp"
|
187
|
+
@stub = NodejsStub.new('node')
|
188
|
+
@apache2 << "RailsMaxPoolSize 1"
|
189
|
+
@apache2.set_vhost("1.passenger.test", File.expand_path("stub")) do |vhost|
|
190
|
+
vhost << %Q{
|
191
|
+
Alias /subapp #{@stub.full_app_root}/public
|
192
|
+
<Location /subapp>
|
193
|
+
PassengerBaseURI /subapp
|
194
|
+
PassengerAppRoot #{@stub.full_app_root}
|
195
|
+
</Location>
|
196
|
+
}
|
197
|
+
end
|
198
|
+
@apache2.start
|
199
|
+
end
|
200
|
+
|
201
|
+
after :all do
|
202
|
+
@stub.destroy
|
203
|
+
@apache2.stop if @apache2
|
204
|
+
end
|
205
|
+
|
206
|
+
before :each do
|
207
|
+
@stub.reset
|
208
|
+
end
|
209
|
+
|
210
|
+
it_should_behave_like "an example web app"
|
211
|
+
|
212
|
+
it "does not interfere with the root website" do
|
213
|
+
@server = "http://1.passenger.test:#{@apache2.port}"
|
214
|
+
get('/').should == "This is the stub directory."
|
215
|
+
end
|
216
|
+
end
|
217
|
+
|
161
218
|
describe "compatibility with other modules" do
|
162
219
|
before :all do
|
163
220
|
create_apache2_controller
|
@@ -163,6 +163,68 @@ describe "Phusion Passenger for Nginx" do
|
|
163
163
|
end
|
164
164
|
end
|
165
165
|
|
166
|
+
describe "a Node.js app running on the root URI" do
|
167
|
+
before :all do
|
168
|
+
create_nginx_controller
|
169
|
+
@server = "http://1.passenger.test:#{@nginx.port}"
|
170
|
+
@stub = NodejsStub.new('node')
|
171
|
+
@nginx.add_server do |server|
|
172
|
+
server[:server_name] = "1.passenger.test"
|
173
|
+
server[:root] = "#{@stub.full_app_root}/public"
|
174
|
+
end
|
175
|
+
@nginx.start
|
176
|
+
end
|
177
|
+
|
178
|
+
after :all do
|
179
|
+
@stub.destroy
|
180
|
+
@nginx.stop if @nginx
|
181
|
+
end
|
182
|
+
|
183
|
+
before :each do
|
184
|
+
@stub.reset
|
185
|
+
end
|
186
|
+
|
187
|
+
it_should_behave_like "an example web app"
|
188
|
+
end
|
189
|
+
|
190
|
+
describe "a Node.js app running in a sub-URI" do
|
191
|
+
before :all do
|
192
|
+
create_nginx_controller
|
193
|
+
@server = "http://1.passenger.test:#{@nginx.port}/subapp"
|
194
|
+
@stub = NodejsStub.new('node')
|
195
|
+
@nginx.add_server do |server|
|
196
|
+
server[:server_name] = "1.passenger.test"
|
197
|
+
server[:root] = "#{PhusionPassenger.source_root}/test/stub"
|
198
|
+
server << %Q{
|
199
|
+
location ~ ^/subapp(/.*|$) {
|
200
|
+
alias #{@stub.full_app_root}/public$1;
|
201
|
+
passenger_base_uri /subapp;
|
202
|
+
passenger_document_root #{@stub.full_app_root}/public;
|
203
|
+
passenger_app_root #{@stub.full_app_root};
|
204
|
+
passenger_enabled on;
|
205
|
+
}
|
206
|
+
}
|
207
|
+
end
|
208
|
+
@nginx.start
|
209
|
+
end
|
210
|
+
|
211
|
+
after :all do
|
212
|
+
@stub.destroy
|
213
|
+
@nginx.stop if @nginx
|
214
|
+
end
|
215
|
+
|
216
|
+
before :each do
|
217
|
+
@stub.reset
|
218
|
+
end
|
219
|
+
|
220
|
+
it_should_behave_like "an example web app"
|
221
|
+
|
222
|
+
it "does not interfere with the root website" do
|
223
|
+
@server = "http://1.passenger.test:#{@nginx.port}"
|
224
|
+
get('/').should == "This is the stub directory."
|
225
|
+
end
|
226
|
+
end
|
227
|
+
|
166
228
|
describe "various features" do
|
167
229
|
before :all do
|
168
230
|
create_nginx_controller
|