passenger 5.3.7 → 6.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG +14 -0
- data/build/agent.rb +4 -2
- data/build/support/cxx_dependency_map.rb +134 -0
- data/resources/templates/standalone/server.erb +1 -0
- data/src/agent/AgentMain.cpp +4 -0
- data/src/agent/Core/ApplicationPool/Group/StateInspection.cpp +1 -1
- data/src/agent/Core/ApplicationPool/Options.h +7 -7
- data/src/agent/Core/ApplicationPool/Process.h +3 -0
- data/src/agent/Core/Config.h +9 -2
- data/src/agent/Core/Controller/Config.h +27 -6
- data/src/agent/Core/Controller/InitRequest.cpp +12 -7
- data/src/agent/Core/Controller/InitializationAndShutdown.cpp +2 -0
- data/src/agent/Core/CoreMain.cpp +62 -33
- data/src/agent/Core/OptionParser.h +6 -0
- data/src/agent/Core/SpawningKit/Spawner.h +20 -5
- data/src/agent/Core/SpawningKit/UserSwitchingRules.h +13 -6
- data/src/agent/Core/TelemetryCollector.h +1 -0
- data/src/agent/FileReadHelper/FileReadHelperMain.cpp +198 -0
- data/src/agent/Watchdog/Config.h +1 -0
- data/src/apache2_module/ConfigGeneral/AutoGeneratedDefinitions.cpp +5 -0
- data/src/apache2_module/ConfigGeneral/AutoGeneratedSetterFuncs.cpp +15 -0
- data/src/apache2_module/DirConfig/AutoGeneratedCreateFunction.cpp +5 -0
- data/src/apache2_module/DirConfig/AutoGeneratedManifestGeneration.cpp +13 -0
- data/src/apache2_module/DirConfig/AutoGeneratedMergeFunction.cpp +7 -0
- data/src/apache2_module/DirConfig/AutoGeneratedStruct.h +13 -0
- data/src/apache2_module/DirectoryMapper.h +14 -3
- data/src/apache2_module/Hooks.cpp +15 -4
- data/src/cxx_supportlib/AppLocalConfigFileUtils.h +148 -0
- data/src/cxx_supportlib/AppTypeDetector/CBindings.cpp +12 -1
- data/src/cxx_supportlib/AppTypeDetector/CBindings.h +2 -0
- data/src/cxx_supportlib/AppTypeDetector/Detector.h +38 -4
- data/src/cxx_supportlib/Constants.h +1 -1
- data/src/nginx_module/ConfigGeneral/AutoGeneratedDefinitions.c +16 -0
- data/src/nginx_module/ConfigGeneral/AutoGeneratedManifestDefaultsInitialization.c +6 -0
- data/src/nginx_module/ConfigGeneral/AutoGeneratedSetterFuncs.c +12 -0
- data/src/nginx_module/Configuration.c +20 -0
- data/src/nginx_module/ContentHandler.c +301 -23
- data/src/nginx_module/ContentHandler.h +5 -0
- data/src/nginx_module/LocationConfig/AutoGeneratedCreateFunction.c +10 -0
- data/src/nginx_module/LocationConfig/AutoGeneratedManifestGeneration.c +27 -0
- data/src/nginx_module/LocationConfig/AutoGeneratedMergeFunction.c +3 -0
- data/src/nginx_module/LocationConfig/AutoGeneratedStruct.h +7 -0
- data/src/nginx_module/ngx_http_passenger_module.h +6 -1
- data/src/ruby_supportlib/phusion_passenger.rb +6 -5
- data/src/ruby_supportlib/phusion_passenger/apache2/config_options.rb +6 -0
- data/src/ruby_supportlib/phusion_passenger/nginx/config_options.rb +14 -0
- data/src/ruby_supportlib/phusion_passenger/standalone/app_finder.rb +1 -0
- data/src/ruby_supportlib/phusion_passenger/standalone/config_options_list.rb +11 -1
- data/src/ruby_supportlib/phusion_passenger/standalone/start_command/builtin_engine.rb +1 -0
- metadata +4 -2
@@ -0,0 +1,198 @@
|
|
1
|
+
/*
|
2
|
+
* Phusion Passenger - https://www.phusionpassenger.com/
|
3
|
+
* Copyright (c) 2018 Phusion Holding B.V.
|
4
|
+
*
|
5
|
+
* "Passenger", "Phusion Passenger" and "Union Station" are registered
|
6
|
+
* trademarks of Phusion Holding B.V.
|
7
|
+
*
|
8
|
+
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
9
|
+
* of this software and associated documentation files (the "Software"), to deal
|
10
|
+
* in the Software without restriction, including without limitation the rights
|
11
|
+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
12
|
+
* copies of the Software, and to permit persons to whom the Software is
|
13
|
+
* furnished to do so, subject to the following conditions:
|
14
|
+
*
|
15
|
+
* The above copyright notice and this permission notice shall be included in
|
16
|
+
* all copies or substantial portions of the Software.
|
17
|
+
*
|
18
|
+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
19
|
+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
20
|
+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
21
|
+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
22
|
+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
23
|
+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
24
|
+
* THE SOFTWARE.
|
25
|
+
*/
|
26
|
+
|
27
|
+
// A helper app that reads from an arbitrary file.
|
28
|
+
// Its main reason for existance is to allow root processes (such as the Core)
|
29
|
+
// to read from arbitrary files in a way that's safe from symlink and other
|
30
|
+
// kinds of attacks. See the documentation for safeReadFile()
|
31
|
+
// to learn more about the different types of attacks.
|
32
|
+
//
|
33
|
+
// file-read-helper is used when the caller cannot use safeReadFile(),
|
34
|
+
// e.g. when the following two conditions hold at the same time:
|
35
|
+
//
|
36
|
+
// 1. The caller does not have control over the safety of the parent
|
37
|
+
// directories leading to the file.
|
38
|
+
// 2. The caller cannot choose not to disclose the contents of the file.
|
39
|
+
//
|
40
|
+
// file-read-helper MUST be used in combination with exec-helper in order
|
41
|
+
// to lower its privilege, otherwise no protection is provided.
|
42
|
+
|
43
|
+
#include <cstdio>
|
44
|
+
#include <cstdlib>
|
45
|
+
#include <cstddef>
|
46
|
+
#include <cerrno>
|
47
|
+
#include <cstring>
|
48
|
+
#include <string>
|
49
|
+
#include <algorithm>
|
50
|
+
#include <limits>
|
51
|
+
|
52
|
+
#include <fcntl.h>
|
53
|
+
#include <unistd.h>
|
54
|
+
|
55
|
+
#include <Constants.h>
|
56
|
+
#include <ProcessManagement/Utils.h>
|
57
|
+
#include <IOTools/IOUtils.h>
|
58
|
+
#include <Utils/OptionParsing.h>
|
59
|
+
|
60
|
+
namespace Passenger {
|
61
|
+
namespace FileReadHelper {
|
62
|
+
|
63
|
+
using namespace std;
|
64
|
+
|
65
|
+
|
66
|
+
struct Options {
|
67
|
+
size_t limit;
|
68
|
+
int programArgStart;
|
69
|
+
|
70
|
+
Options()
|
71
|
+
: limit(std::numeric_limits<size_t>::max()),
|
72
|
+
programArgStart(2)
|
73
|
+
{ }
|
74
|
+
};
|
75
|
+
|
76
|
+
static void
|
77
|
+
usage() {
|
78
|
+
// ....|---------------Keep output within standard terminal width (80 chars)------------|
|
79
|
+
printf("Usage: " AGENT_EXE " file-read-helper [OPTIONS...] <PATH>\n");
|
80
|
+
printf("Reads the given file with O_NONBLOCK.\n");
|
81
|
+
printf("\n");
|
82
|
+
printf("Options:\n");
|
83
|
+
printf(" --limit <SIZE> Limit the number of bytes read (default: unlimited).\n");
|
84
|
+
printf(" --help Show this help message.\n");
|
85
|
+
}
|
86
|
+
|
87
|
+
static bool
|
88
|
+
parseOption(int argc, const char *argv[], int &i, Options &options) {
|
89
|
+
OptionParser p(usage);
|
90
|
+
|
91
|
+
if (p.isValueFlag(argc, i, argv[i], '\0', "--limit")) {
|
92
|
+
options.limit = atoi(argv[i + 1]);
|
93
|
+
i += 2;
|
94
|
+
} else {
|
95
|
+
return false;
|
96
|
+
}
|
97
|
+
return true;
|
98
|
+
}
|
99
|
+
|
100
|
+
static bool
|
101
|
+
parseOptions(int argc, const char *argv[], Options &options) {
|
102
|
+
OptionParser p(usage);
|
103
|
+
int i = 2;
|
104
|
+
|
105
|
+
while (i < argc) {
|
106
|
+
if (parseOption(argc, argv, i, options)) {
|
107
|
+
continue;
|
108
|
+
} else if (p.isFlag(argv[i], 'h', "--help")) {
|
109
|
+
usage();
|
110
|
+
exit(0);
|
111
|
+
} else if (*argv[i] == '-') {
|
112
|
+
fprintf(stderr, "ERROR: unrecognized argument %s. Please type "
|
113
|
+
"'%s file-read-helper --help' for usage.\n", argv[i], argv[0]);
|
114
|
+
exit(1);
|
115
|
+
} else {
|
116
|
+
options.programArgStart = i;
|
117
|
+
return true;
|
118
|
+
}
|
119
|
+
}
|
120
|
+
|
121
|
+
return true;
|
122
|
+
}
|
123
|
+
|
124
|
+
int
|
125
|
+
fileReadHelperMain(int argc, char *argv[]) {
|
126
|
+
if (argc < 3) {
|
127
|
+
usage();
|
128
|
+
exit(1);
|
129
|
+
}
|
130
|
+
|
131
|
+
Options options;
|
132
|
+
if (!parseOptions(argc, (const char **) argv, options)) {
|
133
|
+
fprintf(stderr, "Error parsing arguments.\n");
|
134
|
+
usage();
|
135
|
+
exit(1);
|
136
|
+
}
|
137
|
+
|
138
|
+
if (argc != options.programArgStart + 1) {
|
139
|
+
fprintf(stderr, "ERROR: no file path given. Please type "
|
140
|
+
"'%s file-read-helper --help' for usage.\n", argv[0]);
|
141
|
+
exit(1);
|
142
|
+
}
|
143
|
+
|
144
|
+
if (geteuid() == 0) {
|
145
|
+
fprintf(stderr, "ERROR: file-read-helper cannot be run with root"
|
146
|
+
" privileges. Please use in combination with exec-helper.\n");
|
147
|
+
exit(1);
|
148
|
+
}
|
149
|
+
|
150
|
+
resetSignalHandlersAndMask();
|
151
|
+
disableMallocDebugging();
|
152
|
+
|
153
|
+
const char *path = argv[options.programArgStart];
|
154
|
+
int fd;
|
155
|
+
do {
|
156
|
+
fd = open(path, O_RDONLY | O_NONBLOCK);
|
157
|
+
} while (fd == -1 && errno == EINTR);
|
158
|
+
if (fd == -1) {
|
159
|
+
int e = errno;
|
160
|
+
fprintf(stderr, "Error opening %s for reading: %s (errno=%d)\n",
|
161
|
+
path, strerror(e), e);
|
162
|
+
exit(1);
|
163
|
+
}
|
164
|
+
|
165
|
+
size_t totalRead = 0;
|
166
|
+
char buf[1024 * 16];
|
167
|
+
|
168
|
+
while (totalRead < options.limit) {
|
169
|
+
ssize_t ret;
|
170
|
+
do {
|
171
|
+
ret = read(fd, buf,
|
172
|
+
std::min<size_t>(sizeof(buf), options.limit - totalRead));
|
173
|
+
} while (ret == -1 && errno == EINTR);
|
174
|
+
if (ret == -1) {
|
175
|
+
int e = errno;
|
176
|
+
fprintf(stderr, "Error reading from %s: %s (errno=%d)\n",
|
177
|
+
path, strerror(e), e);
|
178
|
+
exit(1);
|
179
|
+
} else if (ret == 0) {
|
180
|
+
break;
|
181
|
+
} else {
|
182
|
+
totalRead += ret;
|
183
|
+
writeExact(1, StaticString(buf, ret));
|
184
|
+
}
|
185
|
+
}
|
186
|
+
|
187
|
+
return 0;
|
188
|
+
}
|
189
|
+
|
190
|
+
|
191
|
+
} // namespace FileReadHelper
|
192
|
+
} // namespace Passenger
|
193
|
+
|
194
|
+
|
195
|
+
int
|
196
|
+
fileReadHelperMain(int argc, char *argv[]) {
|
197
|
+
return Passenger::FileReadHelper::fileReadHelperMain(argc, argv);
|
198
|
+
}
|
data/src/agent/Watchdog/Config.h
CHANGED
@@ -150,6 +150,7 @@ using namespace std;
|
|
150
150
|
* setsid boolean - default(false)
|
151
151
|
* show_version_in_header boolean - default(true)
|
152
152
|
* single_app_mode_app_root string - default,read_only
|
153
|
+
* single_app_mode_app_start_command string - read_only
|
153
154
|
* single_app_mode_app_type string - read_only
|
154
155
|
* single_app_mode_startup_file string - read_only
|
155
156
|
* standalone_engine string - default
|
@@ -107,6 +107,11 @@ extern "C" const command_rec passenger_commands[] = {
|
|
107
107
|
NULL,
|
108
108
|
RSRC_CONF | ACCESS_CONF,
|
109
109
|
"The application's root directory."),
|
110
|
+
AP_INIT_TAKE1("PassengerAppStartCommand",
|
111
|
+
(Take1Func) cmd_passenger_app_start_command,
|
112
|
+
NULL,
|
113
|
+
RSRC_CONF | ACCESS_CONF,
|
114
|
+
"Command string for starting the application."),
|
110
115
|
AP_INIT_TAKE1("PassengerAppType",
|
111
116
|
(Take1Func) cmd_passenger_app_type,
|
112
117
|
NULL,
|
@@ -203,6 +203,21 @@ cmd_passenger_app_root(cmd_parms *cmd, void *pcfg, const char *arg) {
|
|
203
203
|
return NULL;
|
204
204
|
}
|
205
205
|
|
206
|
+
static const char *
|
207
|
+
cmd_passenger_app_start_command(cmd_parms *cmd, void *pcfg, const char *arg) {
|
208
|
+
const char *err = ap_check_cmd_context(cmd, NOT_IN_FILES);
|
209
|
+
if (err != NULL) {
|
210
|
+
return err;
|
211
|
+
}
|
212
|
+
|
213
|
+
DirConfig *config = (DirConfig *) pcfg;
|
214
|
+
config->mAppStartCommandSourceFile = cmd->directive->filename;
|
215
|
+
config->mAppStartCommandSourceLine = cmd->directive->line_num;
|
216
|
+
config->mAppStartCommandExplicitlySet = true;
|
217
|
+
config->mAppStartCommand = arg;
|
218
|
+
return NULL;
|
219
|
+
}
|
220
|
+
|
206
221
|
static const char *
|
207
222
|
cmd_passenger_app_type(cmd_parms *cmd, void *pcfg, const char *arg) {
|
208
223
|
const char *err = ap_check_cmd_context(cmd, NOT_IN_FILES);
|
@@ -64,6 +64,9 @@ createDirConfig_autoGenerated(DirConfig *config) {
|
|
64
64
|
/*
|
65
65
|
* config->mAppRoot: default initialized
|
66
66
|
*/
|
67
|
+
/*
|
68
|
+
* config->mAppStartCommand: default initialized
|
69
|
+
*/
|
67
70
|
/*
|
68
71
|
* config->mAppType: default initialized
|
69
72
|
*/
|
@@ -124,6 +127,7 @@ createDirConfig_autoGenerated(DirConfig *config) {
|
|
124
127
|
config->mAppGroupNameSourceLine = 0;
|
125
128
|
config->mAppLogFileSourceLine = 0;
|
126
129
|
config->mAppRootSourceLine = 0;
|
130
|
+
config->mAppStartCommandSourceLine = 0;
|
127
131
|
config->mAppTypeSourceLine = 0;
|
128
132
|
config->mBaseURIsSourceLine = 0;
|
129
133
|
config->mBufferResponseSourceLine = 0;
|
@@ -158,6 +162,7 @@ createDirConfig_autoGenerated(DirConfig *config) {
|
|
158
162
|
config->mAppGroupNameExplicitlySet = false;
|
159
163
|
config->mAppLogFileExplicitlySet = false;
|
160
164
|
config->mAppRootExplicitlySet = false;
|
165
|
+
config->mAppStartCommandExplicitlySet = false;
|
161
166
|
config->mAppTypeExplicitlySet = false;
|
162
167
|
config->mBaseURIsExplicitlySet = false;
|
163
168
|
config->mBufferResponseExplicitlySet = false;
|
@@ -116,6 +116,19 @@ ConfigManifestGenerator::autoGenerated_generateConfigManifestForDirConfig(server
|
|
116
116
|
pdconf->mAppRoot.data(),
|
117
117
|
pdconf->mAppRoot.data() + pdconf->mAppRoot.size());
|
118
118
|
}
|
119
|
+
if (pdconf->mAppStartCommandExplicitlySet) {
|
120
|
+
findOrCreateAppAndLocOptionsContainers(serverRec, csconf, cdconf,
|
121
|
+
pdconf, context, &appOptionsContainer, &locOptionsContainer);
|
122
|
+
Json::Value &optionContainer = findOrCreateOptionContainer(*appOptionsContainer,
|
123
|
+
"PassengerAppStartCommand",
|
124
|
+
sizeof("PassengerAppStartCommand") - 1);
|
125
|
+
Json::Value &hierarchyMember = addOptionContainerHierarchyMember(optionContainer,
|
126
|
+
pdconf->mAppStartCommandSourceFile,
|
127
|
+
pdconf->mAppStartCommandSourceLine);
|
128
|
+
hierarchyMember["value"] = Json::Value(
|
129
|
+
pdconf->mAppStartCommand.data(),
|
130
|
+
pdconf->mAppStartCommand.data() + pdconf->mAppStartCommand.size());
|
131
|
+
}
|
119
132
|
if (pdconf->mAppTypeExplicitlySet) {
|
120
133
|
findOrCreateAppAndLocOptionsContainers(serverRec, csconf, cdconf,
|
121
134
|
pdconf, context, &appOptionsContainer, &locOptionsContainer);
|
@@ -68,6 +68,10 @@ mergeDirConfig_autoGenerated(DirConfig *config, DirConfig *base, DirConfig *add)
|
|
68
68
|
(!add->mAppRoot.empty())
|
69
69
|
? add->mAppRoot
|
70
70
|
: base->mAppRoot;
|
71
|
+
config->mAppStartCommand =
|
72
|
+
(!add->mAppStartCommand.empty())
|
73
|
+
? add->mAppStartCommand
|
74
|
+
: base->mAppStartCommand;
|
71
75
|
config->mAppType =
|
72
76
|
(!add->mAppType.empty())
|
73
77
|
? add->mAppType
|
@@ -186,6 +190,7 @@ mergeDirConfig_autoGenerated(DirConfig *config, DirConfig *base, DirConfig *add)
|
|
186
190
|
config->mAppGroupNameSourceFile = add->mAppGroupNameSourceFile;
|
187
191
|
config->mAppLogFileSourceFile = add->mAppLogFileSourceFile;
|
188
192
|
config->mAppRootSourceFile = add->mAppRootSourceFile;
|
193
|
+
config->mAppStartCommandSourceFile = add->mAppStartCommandSourceFile;
|
189
194
|
config->mAppTypeSourceFile = add->mAppTypeSourceFile;
|
190
195
|
config->mBaseURIsSourceFile = add->mBaseURIsSourceFile;
|
191
196
|
config->mBufferResponseSourceFile = add->mBufferResponseSourceFile;
|
@@ -220,6 +225,7 @@ mergeDirConfig_autoGenerated(DirConfig *config, DirConfig *base, DirConfig *add)
|
|
220
225
|
config->mAppGroupNameSourceLine = add->mAppGroupNameSourceLine;
|
221
226
|
config->mAppLogFileSourceLine = add->mAppLogFileSourceLine;
|
222
227
|
config->mAppRootSourceLine = add->mAppRootSourceLine;
|
228
|
+
config->mAppStartCommandSourceLine = add->mAppStartCommandSourceLine;
|
223
229
|
config->mAppTypeSourceLine = add->mAppTypeSourceLine;
|
224
230
|
config->mBaseURIsSourceLine = add->mBaseURIsSourceLine;
|
225
231
|
config->mBufferResponseSourceLine = add->mBufferResponseSourceLine;
|
@@ -254,6 +260,7 @@ mergeDirConfig_autoGenerated(DirConfig *config, DirConfig *base, DirConfig *add)
|
|
254
260
|
config->mAppGroupNameExplicitlySet = add->mAppGroupNameExplicitlySet;
|
255
261
|
config->mAppLogFileExplicitlySet = add->mAppLogFileExplicitlySet;
|
256
262
|
config->mAppRootExplicitlySet = add->mAppRootExplicitlySet;
|
263
|
+
config->mAppStartCommandExplicitlySet = add->mAppStartCommandExplicitlySet;
|
257
264
|
config->mAppTypeExplicitlySet = add->mAppTypeExplicitlySet;
|
258
265
|
config->mBaseURIsExplicitlySet = add->mBaseURIsExplicitlySet;
|
259
266
|
config->mBufferResponseExplicitlySet = add->mBufferResponseExplicitlySet;
|
@@ -156,6 +156,11 @@ struct AutoGeneratedDirConfig {
|
|
156
156
|
*/
|
157
157
|
StaticString mAppRoot;
|
158
158
|
|
159
|
+
/*
|
160
|
+
* Command string for starting the application.
|
161
|
+
*/
|
162
|
+
StaticString mAppStartCommand;
|
163
|
+
|
159
164
|
/*
|
160
165
|
* Force specific application type.
|
161
166
|
*/
|
@@ -242,6 +247,7 @@ struct AutoGeneratedDirConfig {
|
|
242
247
|
StaticString mAppGroupNameSourceFile;
|
243
248
|
StaticString mAppLogFileSourceFile;
|
244
249
|
StaticString mAppRootSourceFile;
|
250
|
+
StaticString mAppStartCommandSourceFile;
|
245
251
|
StaticString mAppTypeSourceFile;
|
246
252
|
StaticString mGroupSourceFile;
|
247
253
|
StaticString mMeteorAppSettingsSourceFile;
|
@@ -276,6 +282,7 @@ struct AutoGeneratedDirConfig {
|
|
276
282
|
unsigned int mAppGroupNameSourceLine;
|
277
283
|
unsigned int mAppLogFileSourceLine;
|
278
284
|
unsigned int mAppRootSourceLine;
|
285
|
+
unsigned int mAppStartCommandSourceLine;
|
279
286
|
unsigned int mAppTypeSourceLine;
|
280
287
|
unsigned int mGroupSourceLine;
|
281
288
|
unsigned int mMeteorAppSettingsSourceLine;
|
@@ -310,6 +317,7 @@ struct AutoGeneratedDirConfig {
|
|
310
317
|
bool mAppGroupNameExplicitlySet: 1;
|
311
318
|
bool mAppLogFileExplicitlySet: 1;
|
312
319
|
bool mAppRootExplicitlySet: 1;
|
320
|
+
bool mAppStartCommandExplicitlySet: 1;
|
313
321
|
bool mAppTypeExplicitlySet: 1;
|
314
322
|
bool mGroupExplicitlySet: 1;
|
315
323
|
bool mMeteorAppSettingsExplicitlySet: 1;
|
@@ -489,6 +497,11 @@ struct AutoGeneratedDirConfig {
|
|
489
497
|
return mAppRoot;
|
490
498
|
}
|
491
499
|
|
500
|
+
StaticString
|
501
|
+
getAppStartCommand() const {
|
502
|
+
return mAppStartCommand;
|
503
|
+
}
|
504
|
+
|
492
505
|
StaticString
|
493
506
|
getAppType() const {
|
494
507
|
return mAppType;
|
@@ -77,6 +77,7 @@ private:
|
|
77
77
|
request_rec *r;
|
78
78
|
CachedFileStat *cstat;
|
79
79
|
boost::mutex *cstatMutex;
|
80
|
+
boost::mutex *configMutex;
|
80
81
|
const char *baseURI;
|
81
82
|
string publicDir;
|
82
83
|
string appRoot;
|
@@ -148,10 +149,16 @@ private:
|
|
148
149
|
|
149
150
|
UPDATE_TRACE_POINT();
|
150
151
|
AppTypeDetector::Detector detector(registry, cstat,
|
151
|
-
cstatMutex, throttleRate);
|
152
|
+
cstatMutex, throttleRate, configMutex);
|
152
153
|
AppTypeDetector::Detector::Result detectorResult;
|
153
154
|
string appRoot;
|
154
|
-
|
155
|
+
// If `AppStartCommand` is set, then it means the config specified that it is
|
156
|
+
// either a generic app or a Kuria app.
|
157
|
+
if (!config->getAppStartCommand().empty()) {
|
158
|
+
appRoot = config->getAppRoot();
|
159
|
+
} else if (config->getAppType().empty()) {
|
160
|
+
// If neither `AppStartCommand` nor `AppType` are set, then
|
161
|
+
// autodetect what kind of app this is.
|
155
162
|
if (config->getAppRoot().empty()) {
|
156
163
|
detectorResult = detector.checkDocumentRoot(publicDir,
|
157
164
|
baseURI != NULL,
|
@@ -161,6 +168,9 @@ private:
|
|
161
168
|
detectorResult = detector.checkAppRoot(appRoot);
|
162
169
|
}
|
163
170
|
} else if (!config->getAppRoot().empty()) {
|
171
|
+
// If `AppStartCommand` is not set but `AppType` is (as well as
|
172
|
+
// the required `AppRoot`), then verify whether the given
|
173
|
+
// `AppType` value is supported and resolve aliases.
|
164
174
|
appRoot = config->getAppRoot().toString();
|
165
175
|
detectorResult.wrapperRegistryEntry = ®istry.lookup(
|
166
176
|
config->getAppType());
|
@@ -186,13 +196,14 @@ public:
|
|
186
196
|
DirectoryMapper(request_rec *r, DirConfig *config,
|
187
197
|
const WrapperRegistry::Registry &_registry,
|
188
198
|
CachedFileStat *cstat, boost::mutex *cstatMutex,
|
189
|
-
unsigned int throttleRate)
|
199
|
+
unsigned int throttleRate, boost::mutex *configMutex)
|
190
200
|
: registry(_registry)
|
191
201
|
{
|
192
202
|
this->r = r;
|
193
203
|
this->config = config;
|
194
204
|
this->cstat = cstat;
|
195
205
|
this->cstatMutex = cstatMutex;
|
206
|
+
this->configMutex = configMutex;
|
196
207
|
this->throttleRate = throttleRate;
|
197
208
|
baseURI = NULL;
|
198
209
|
autoDetectionDone = false;
|
@@ -237,6 +237,7 @@ private:
|
|
237
237
|
CachedFileStat cstat;
|
238
238
|
WatchdogLauncher watchdogLauncher;
|
239
239
|
boost::mutex cstatMutex;
|
240
|
+
boost::mutex configMutex;
|
240
241
|
|
241
242
|
static Json::Value strsetToJson(const set<string> &input) {
|
242
243
|
Json::Value result(Json::arrayValue);
|
@@ -446,9 +447,11 @@ private:
|
|
446
447
|
TRACE_POINT();
|
447
448
|
|
448
449
|
DirectoryMapper mapper(r, config, wrapperRegistry, &cstat,
|
449
|
-
|
450
|
+
&cstatMutex, serverConfig.statThrottleRate, &configMutex);
|
450
451
|
try {
|
451
|
-
if (
|
452
|
+
if (config->getAppStartCommand().empty()
|
453
|
+
&& mapper.getDetectorResult().isNull())
|
454
|
+
{
|
452
455
|
// (B) is not true.
|
453
456
|
disableRequestNote(r);
|
454
457
|
return false;
|
@@ -988,8 +991,16 @@ private:
|
|
988
991
|
// Phusion Passenger options.
|
989
992
|
addHeader(result, P_STATIC_STRING("!~PASSENGER_APP_ROOT"),
|
990
993
|
mapper.getAppRoot());
|
991
|
-
|
992
|
-
|
994
|
+
if (!config->getAppStartCommand().empty()) {
|
995
|
+
addHeader(result, P_STATIC_STRING("!~PASSENGER_APP_START_COMMAND"),
|
996
|
+
config->getAppStartCommand());
|
997
|
+
} else if (mapper.getDetectorResult().wrapperRegistryEntry != NULL) {
|
998
|
+
addHeader(result, P_STATIC_STRING("!~PASSENGER_APP_TYPE"),
|
999
|
+
mapper.getDetectorResult().wrapperRegistryEntry->language);
|
1000
|
+
} else {
|
1001
|
+
addHeader(result, P_STATIC_STRING("!~PASSENGER_APP_START_COMMAND"),
|
1002
|
+
mapper.getDetectorResult().appStartCommand);
|
1003
|
+
}
|
993
1004
|
constructRequestHeaders_autoGenerated(r, config, result);
|
994
1005
|
|
995
1006
|
/*********************/
|