passenger 4.0.3 → 4.0.4
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.
- data.tar.gz.asc +7 -7
- data/NEWS +30 -0
- data/build/agents.rb +3 -0
- data/build/apache2.rb +2 -3
- data/build/basics.rb +20 -0
- data/build/common_library.rb +15 -0
- data/build/cxx_tests.rb +4 -1
- data/build/packaging.rb +22 -32
- data/doc/Packaging.html +792 -0
- data/doc/Users guide Nginx.html +2 -2
- data/doc/Users guide Nginx.txt +2 -2
- data/ext/apache2/Configuration.cpp +34 -62
- data/ext/apache2/Configuration.hpp +1 -14
- data/ext/apache2/DirectoryMapper.h +134 -104
- data/ext/apache2/Hooks.cpp +33 -19
- data/ext/common/AgentsStarter.cpp +22 -22
- data/ext/common/AgentsStarter.h +25 -25
- data/ext/common/ApplicationPool2/AppTypes.cpp +6 -6
- data/ext/common/ApplicationPool2/AppTypes.h +61 -9
- data/ext/common/ApplicationPool2/Implementation.cpp +14 -2
- data/ext/common/Constants.h +54 -23
- data/ext/common/Constants.h.erb +42 -0
- data/ext/common/ServerInstanceDir.h +6 -11
- data/ext/common/Utils/CachedFileStat.cpp +10 -9
- data/ext/common/Utils/CachedFileStat.h +8 -8
- data/ext/common/Utils/LargeFiles.cpp +12 -4
- data/ext/common/agents/HelperAgent/RequestHandler.h +1 -0
- data/ext/common/agents/Watchdog/Main.cpp +2 -2
- data/ext/nginx/Configuration.c +1 -1
- data/ext/nginx/Configuration.h +0 -1
- data/ext/nginx/ContentHandler.c +15 -15
- data/ext/nginx/ngx_http_passenger_module.c +48 -48
- data/ext/nginx/ngx_http_passenger_module.h +7 -9
- data/helper-scripts/wsgi-loader.py +2 -2
- data/lib/phusion_passenger.rb +1 -3
- data/lib/phusion_passenger/admin_tools/server_instance.rb +5 -11
- data/lib/phusion_passenger/constants.rb +42 -0
- data/lib/phusion_passenger/packaging.rb +8 -6
- data/lib/phusion_passenger/platform_info.rb +11 -6
- data/lib/phusion_passenger/standalone/command.rb +4 -2
- data/lib/phusion_passenger/standalone/runtime_installer.rb +1 -1
- data/resources/templates/standalone/config.erb +14 -2
- data/test/ruby/admin_tools_spec.rb +14 -16
- metadata +4 -3
- metadata.gz.asc +7 -7
- data/lib/phusion_passenger/wsgi/request_handler.py +0 -199
data/ext/apache2/Hooks.cpp
CHANGED
@@ -149,6 +149,24 @@ private:
|
|
149
149
|
return OK;
|
150
150
|
}
|
151
151
|
};
|
152
|
+
|
153
|
+
class ReportDocumentRootDeterminationError: public ErrorReport {
|
154
|
+
private:
|
155
|
+
DocumentRootDeterminationError e;
|
156
|
+
|
157
|
+
public:
|
158
|
+
ReportDocumentRootDeterminationError(const DocumentRootDeterminationError &ex): e(ex) { }
|
159
|
+
|
160
|
+
int report(request_rec *r) {
|
161
|
+
r->status = 500;
|
162
|
+
ap_set_content_type(r, "text/html; charset=UTF-8");
|
163
|
+
ap_rputs("<h1>Passenger error #1</h1>\n", r);
|
164
|
+
ap_rputs("Cannot determine the document root for the current request.", r);
|
165
|
+
P_ERROR("Cannot determine the document root for the current request.\n" <<
|
166
|
+
" Backtrace:\n" << e.backtrace());
|
167
|
+
return OK;
|
168
|
+
}
|
169
|
+
};
|
152
170
|
|
153
171
|
struct RequestNote {
|
154
172
|
DirectoryMapper mapper;
|
@@ -313,13 +331,6 @@ private:
|
|
313
331
|
return m_hasModXsendfile == YES;
|
314
332
|
}
|
315
333
|
|
316
|
-
int reportDocumentRootDeterminationError(request_rec *r) {
|
317
|
-
ap_set_content_type(r, "text/html; charset=UTF-8");
|
318
|
-
ap_rputs("<h1>Passenger error #1</h1>\n", r);
|
319
|
-
ap_rputs("Cannot determine the document root for the current request.", r);
|
320
|
-
return OK;
|
321
|
-
}
|
322
|
-
|
323
334
|
int reportBusyException(request_rec *r) {
|
324
335
|
ap_custom_response(r, HTTP_SERVICE_UNAVAILABLE,
|
325
336
|
"This website is too busy right now. Please try again later.");
|
@@ -352,11 +363,17 @@ private:
|
|
352
363
|
|
353
364
|
DirectoryMapper mapper(r, config, &cstat, config->getStatThrottleRate());
|
354
365
|
try {
|
355
|
-
if (mapper.
|
366
|
+
if (mapper.getApplicationType() == PAT_NONE) {
|
356
367
|
// (B) is not true.
|
357
368
|
disableRequestNote(r);
|
358
369
|
return false;
|
359
370
|
}
|
371
|
+
} catch (const DocumentRootDeterminationError &e) {
|
372
|
+
auto_ptr<RequestNote> note(new RequestNote(mapper, config));
|
373
|
+
note->errorReport = new ReportDocumentRootDeterminationError(e);
|
374
|
+
apr_pool_userdata_set(note.release(), "Phusion Passenger",
|
375
|
+
RequestNote::cleanup, r->pool);
|
376
|
+
return true;
|
360
377
|
} catch (const FileSystemException &e) {
|
361
378
|
/* DirectoryMapper tried to examine the filesystem in order
|
362
379
|
* to autodetect the application type (e.g. by checking whether
|
@@ -482,14 +499,11 @@ private:
|
|
482
499
|
TRACE_POINT();
|
483
500
|
DirConfig *config = note->config;
|
484
501
|
DirectoryMapper &mapper = note->mapper;
|
485
|
-
string publicDirectory, appRoot;
|
486
502
|
|
487
503
|
try {
|
488
|
-
|
489
|
-
|
490
|
-
|
491
|
-
}
|
492
|
-
appRoot = config->getAppRoot(publicDirectory.c_str());
|
504
|
+
mapper.getPublicDirectory();
|
505
|
+
} catch (const DocumentRootDeterminationError &e) {
|
506
|
+
return ReportDocumentRootDeterminationError(e).report(r);
|
493
507
|
} catch (const FileSystemException &e) {
|
494
508
|
/* The application root cannot be determined. This could
|
495
509
|
* happen if, for example, the user specified 'RailsBaseURI /foo'
|
@@ -570,7 +584,7 @@ private:
|
|
570
584
|
requestData.reserve(3);
|
571
585
|
headerData.reserve(1024 * 2);
|
572
586
|
requestData.push_back(StaticString());
|
573
|
-
size = constructHeaders(r, config, requestData, mapper,
|
587
|
+
size = constructHeaders(r, config, requestData, mapper, headerData);
|
574
588
|
requestData.push_back(",");
|
575
589
|
|
576
590
|
ret = snprintf(sizeString, sizeof(sizeString) - 1, "%u:", size);
|
@@ -857,7 +871,7 @@ private:
|
|
857
871
|
}
|
858
872
|
|
859
873
|
unsigned int constructHeaders(request_rec *r, DirConfig *config,
|
860
|
-
vector<StaticString> &requestData, DirectoryMapper &mapper,
|
874
|
+
vector<StaticString> &requestData, DirectoryMapper &mapper,
|
861
875
|
string &output)
|
862
876
|
{
|
863
877
|
const char *baseURI = mapper.getBaseURI();
|
@@ -920,7 +934,7 @@ private:
|
|
920
934
|
addHeader(output, "REQUEST_URI", request_uri);
|
921
935
|
}
|
922
936
|
|
923
|
-
if (
|
937
|
+
if (baseURI == NULL) {
|
924
938
|
addHeader(output, "SCRIPT_NAME", "");
|
925
939
|
addHeader(output, "PATH_INFO", escapedUri);
|
926
940
|
} else {
|
@@ -953,8 +967,8 @@ private:
|
|
953
967
|
|
954
968
|
// Phusion Passenger options.
|
955
969
|
addHeader(output, "PASSENGER_STATUS_LINE", "false");
|
956
|
-
addHeader(output, "PASSENGER_APP_ROOT",
|
957
|
-
addHeader(output, "PASSENGER_APP_GROUP_NAME", config->getAppGroupName(
|
970
|
+
addHeader(output, "PASSENGER_APP_ROOT", mapper.getAppRoot());
|
971
|
+
addHeader(output, "PASSENGER_APP_GROUP_NAME", config->getAppGroupName(mapper.getAppRoot()));
|
958
972
|
addHeader(output, "PASSENGER_RUBY", config->ruby ? config->ruby : serverConfig.defaultRuby);
|
959
973
|
addHeader(output, "PASSENGER_PYTHON", config->python);
|
960
974
|
addHeader(output, "PASSENGER_ENV", config->getEnvironment());
|
@@ -33,13 +33,13 @@ using namespace boost;
|
|
33
33
|
using namespace oxt;
|
34
34
|
|
35
35
|
|
36
|
-
|
37
|
-
|
38
|
-
return (
|
36
|
+
PP_VariantMap *
|
37
|
+
pp_variant_map_new() {
|
38
|
+
return (PP_VariantMap *) new Passenger::VariantMap();
|
39
39
|
}
|
40
40
|
|
41
41
|
void
|
42
|
-
|
42
|
+
pp_variant_map_set(PP_VariantMap *m,
|
43
43
|
const char *name,
|
44
44
|
const char *value,
|
45
45
|
unsigned int value_len)
|
@@ -49,7 +49,7 @@ psg_variant_map_set(PSG_VariantMap *m,
|
|
49
49
|
}
|
50
50
|
|
51
51
|
void
|
52
|
-
|
52
|
+
pp_variant_map_set2(PP_VariantMap *m,
|
53
53
|
const char *name,
|
54
54
|
unsigned int name_len,
|
55
55
|
const char *value,
|
@@ -60,7 +60,7 @@ psg_variant_map_set2(PSG_VariantMap *m,
|
|
60
60
|
}
|
61
61
|
|
62
62
|
void
|
63
|
-
|
63
|
+
pp_variant_map_set_int(PP_VariantMap *m,
|
64
64
|
const char *name,
|
65
65
|
int value)
|
66
66
|
{
|
@@ -69,7 +69,7 @@ psg_variant_map_set_int(PSG_VariantMap *m,
|
|
69
69
|
}
|
70
70
|
|
71
71
|
void
|
72
|
-
|
72
|
+
pp_variant_map_set_bool(PP_VariantMap *m,
|
73
73
|
const char *name,
|
74
74
|
int value)
|
75
75
|
{
|
@@ -78,7 +78,7 @@ psg_variant_map_set_bool(PSG_VariantMap *m,
|
|
78
78
|
}
|
79
79
|
|
80
80
|
void
|
81
|
-
|
81
|
+
pp_variant_map_set_strset(PP_VariantMap *m,
|
82
82
|
const char *name,
|
83
83
|
const char **strs,
|
84
84
|
unsigned int count)
|
@@ -93,21 +93,21 @@ psg_variant_map_set_strset(PSG_VariantMap *m,
|
|
93
93
|
}
|
94
94
|
|
95
95
|
void
|
96
|
-
|
96
|
+
pp_variant_map_free(PP_VariantMap *m) {
|
97
97
|
delete (Passenger::VariantMap *) m;
|
98
98
|
}
|
99
99
|
|
100
100
|
|
101
|
-
|
102
|
-
|
103
|
-
return (
|
101
|
+
PP_AgentsStarter *
|
102
|
+
pp_agents_starter_new(PP_AgentsStarterType type, char **error_message) {
|
103
|
+
return (PP_AgentsStarter *) new Passenger::AgentsStarter(type);
|
104
104
|
}
|
105
105
|
|
106
106
|
int
|
107
|
-
|
107
|
+
pp_agents_starter_start(PP_AgentsStarter *as,
|
108
108
|
const char *passengerRoot,
|
109
|
-
|
110
|
-
const
|
109
|
+
PP_VariantMap *extraParams,
|
110
|
+
const PP_AfterForkCallback afterFork,
|
111
111
|
void *callbackArgument,
|
112
112
|
char **errorMessage)
|
113
113
|
{
|
@@ -135,7 +135,7 @@ psg_agents_starter_start(PSG_AgentsStarter *as,
|
|
135
135
|
}
|
136
136
|
|
137
137
|
const char *
|
138
|
-
|
138
|
+
pp_agents_starter_get_request_socket_filename(PP_AgentsStarter *as, unsigned int *size) {
|
139
139
|
Passenger::AgentsStarter *agentsStarter = (Passenger::AgentsStarter *) as;
|
140
140
|
if (size != NULL) {
|
141
141
|
*size = agentsStarter->getRequestSocketFilename().size();
|
@@ -144,7 +144,7 @@ psg_agents_starter_get_request_socket_filename(PSG_AgentsStarter *as, unsigned i
|
|
144
144
|
}
|
145
145
|
|
146
146
|
const char *
|
147
|
-
|
147
|
+
pp_agents_starter_get_request_socket_password(PP_AgentsStarter *as, unsigned int *size) {
|
148
148
|
Passenger::AgentsStarter *agentsStarter = (Passenger::AgentsStarter *) as;
|
149
149
|
if (size != NULL) {
|
150
150
|
*size = agentsStarter->getRequestSocketPassword().size();
|
@@ -153,31 +153,31 @@ psg_agents_starter_get_request_socket_password(PSG_AgentsStarter *as, unsigned i
|
|
153
153
|
}
|
154
154
|
|
155
155
|
const char *
|
156
|
-
|
156
|
+
pp_agents_starter_get_server_instance_dir(PP_AgentsStarter *as) {
|
157
157
|
Passenger::AgentsStarter *agentsStarter = (Passenger::AgentsStarter *) as;
|
158
158
|
return agentsStarter->getServerInstanceDir()->getPath().c_str();
|
159
159
|
}
|
160
160
|
|
161
161
|
const char *
|
162
|
-
|
162
|
+
pp_agents_starter_get_generation_dir(PP_AgentsStarter *as) {
|
163
163
|
Passenger::AgentsStarter *agentsStarter = (Passenger::AgentsStarter *) as;
|
164
164
|
return agentsStarter->getGeneration()->getPath().c_str();
|
165
165
|
}
|
166
166
|
|
167
167
|
pid_t
|
168
|
-
|
168
|
+
pp_agents_starter_get_pid(PP_AgentsStarter *as) {
|
169
169
|
Passenger::AgentsStarter *agentsStarter = (Passenger::AgentsStarter *) as;
|
170
170
|
return agentsStarter->getPid();
|
171
171
|
}
|
172
172
|
|
173
173
|
void
|
174
|
-
|
174
|
+
pp_agents_starter_detach(PP_AgentsStarter *as) {
|
175
175
|
Passenger::AgentsStarter *agentsStarter = (Passenger::AgentsStarter *) as;
|
176
176
|
agentsStarter->detach();
|
177
177
|
}
|
178
178
|
|
179
179
|
void
|
180
|
-
|
180
|
+
pp_agents_starter_free(PP_AgentsStarter *as) {
|
181
181
|
Passenger::AgentsStarter *agentsStarter = (Passenger::AgentsStarter *) as;
|
182
182
|
delete agentsStarter;
|
183
183
|
}
|
data/ext/common/AgentsStarter.h
CHANGED
@@ -36,49 +36,49 @@
|
|
36
36
|
typedef enum {
|
37
37
|
AS_APACHE,
|
38
38
|
AS_NGINX
|
39
|
-
}
|
39
|
+
} PP_AgentsStarterType;
|
40
40
|
|
41
|
-
typedef void
|
42
|
-
typedef void
|
43
|
-
typedef void (*
|
41
|
+
typedef void PP_AgentsStarter;
|
42
|
+
typedef void PP_VariantMap;
|
43
|
+
typedef void (*PP_AfterForkCallback)(void *);
|
44
44
|
|
45
|
-
|
46
|
-
void
|
45
|
+
PP_VariantMap *pp_variant_map_new();
|
46
|
+
void pp_variant_map_set(PP_VariantMap *m,
|
47
47
|
const char *name,
|
48
48
|
const char *value,
|
49
49
|
unsigned int value_len);
|
50
|
-
void
|
50
|
+
void pp_variant_map_set2(PP_VariantMap *m,
|
51
51
|
const char *name,
|
52
52
|
unsigned int name_len,
|
53
53
|
const char *value,
|
54
54
|
unsigned int value_len);
|
55
|
-
void
|
55
|
+
void pp_variant_map_set_int(PP_VariantMap *m,
|
56
56
|
const char *name,
|
57
57
|
int value);
|
58
|
-
void
|
58
|
+
void pp_variant_map_set_bool(PP_VariantMap *m,
|
59
59
|
const char *name,
|
60
60
|
int value);
|
61
|
-
void
|
61
|
+
void pp_variant_map_set_strset(PP_VariantMap *m,
|
62
62
|
const char *name,
|
63
63
|
const char **strs,
|
64
64
|
unsigned int count);
|
65
|
-
void
|
65
|
+
void pp_variant_map_free(PP_VariantMap *m);
|
66
66
|
|
67
|
-
|
67
|
+
PP_AgentsStarter *pp_agents_starter_new(PP_AgentsStarterType type,
|
68
68
|
char **error_message);
|
69
|
-
int
|
69
|
+
int pp_agents_starter_start(PP_AgentsStarter *as,
|
70
70
|
const char *passengerRoot,
|
71
|
-
|
72
|
-
const
|
71
|
+
PP_VariantMap *params,
|
72
|
+
const PP_AfterForkCallback afterFork,
|
73
73
|
void *callbackArgument,
|
74
74
|
char **errorMessage);
|
75
|
-
const char *
|
76
|
-
const char *
|
77
|
-
const char *
|
78
|
-
const char *
|
79
|
-
pid_t
|
80
|
-
void
|
81
|
-
void
|
75
|
+
const char *pp_agents_starter_get_request_socket_filename(PP_AgentsStarter *as, unsigned int *size);
|
76
|
+
const char *pp_agents_starter_get_request_socket_password(PP_AgentsStarter *as, unsigned int *size);
|
77
|
+
const char *pp_agents_starter_get_server_instance_dir(PP_AgentsStarter *as);
|
78
|
+
const char *pp_agents_starter_get_generation_dir(PP_AgentsStarter *as);
|
79
|
+
pid_t pp_agents_starter_get_pid(PP_AgentsStarter *as);
|
80
|
+
void pp_agents_starter_detach(PP_AgentsStarter *as);
|
81
|
+
void pp_agents_starter_free(PP_AgentsStarter *as);
|
82
82
|
|
83
83
|
#ifdef __cplusplus
|
84
84
|
} /* extern "C" */
|
@@ -121,7 +121,7 @@ using namespace oxt;
|
|
121
121
|
*/
|
122
122
|
class AgentsStarter {
|
123
123
|
private:
|
124
|
-
|
124
|
+
PP_AgentsStarterType type;
|
125
125
|
|
126
126
|
/** The watchdog's PID. Equals 0 if the watchdog hasn't been started yet
|
127
127
|
* or if detach() is called. */
|
@@ -288,7 +288,7 @@ public:
|
|
288
288
|
*
|
289
289
|
* @param type Whether one wants to start the Apache or the Nginx helper agent.
|
290
290
|
*/
|
291
|
-
AgentsStarter(
|
291
|
+
AgentsStarter(PP_AgentsStarterType type) {
|
292
292
|
this->type = type;
|
293
293
|
pid = 0;
|
294
294
|
}
|
@@ -329,7 +329,7 @@ public:
|
|
329
329
|
/**
|
330
330
|
* Returns the type as was passed to the constructor.
|
331
331
|
*/
|
332
|
-
|
332
|
+
PP_AgentsStarterType getType() const {
|
333
333
|
return type;
|
334
334
|
}
|
335
335
|
|
@@ -42,18 +42,18 @@ const AppTypeDefinition appTypeDefinitions[] = {
|
|
42
42
|
using namespace Passenger;
|
43
43
|
using namespace Passenger::ApplicationPool2;
|
44
44
|
|
45
|
-
|
46
|
-
|
45
|
+
PP_AppTypeDetector *
|
46
|
+
pp_app_type_detector_new() {
|
47
47
|
return new AppTypeDetector();
|
48
48
|
}
|
49
49
|
|
50
50
|
void
|
51
|
-
|
51
|
+
pp_app_type_detector_free(PP_AppTypeDetector *detector) {
|
52
52
|
delete (AppTypeDetector *) detector;
|
53
53
|
}
|
54
54
|
|
55
55
|
PassengerAppType
|
56
|
-
|
56
|
+
pp_app_type_detector_check_document_root(PP_AppTypeDetector *_detector,
|
57
57
|
const char *documentRoot, unsigned int len, int resolveFirstSymlink)
|
58
58
|
{
|
59
59
|
AppTypeDetector *detector = (AppTypeDetector *) _detector;
|
@@ -61,7 +61,7 @@ passenger_app_type_detector_check_document_root(PassengerAppTypeDetector *_detec
|
|
61
61
|
}
|
62
62
|
|
63
63
|
PassengerAppType
|
64
|
-
|
64
|
+
pp_app_type_detector_check_app_root(PP_AppTypeDetector *_detector,
|
65
65
|
const char *appRoot, unsigned int len)
|
66
66
|
{
|
67
67
|
AppTypeDetector *detector = (AppTypeDetector *) _detector;
|
@@ -69,6 +69,6 @@ passenger_app_type_detector_check_app_root(PassengerAppTypeDetector *_detector,
|
|
69
69
|
}
|
70
70
|
|
71
71
|
const char *
|
72
|
-
|
72
|
+
pp_get_app_type_name(PassengerAppType type) {
|
73
73
|
return getAppTypeName(type);
|
74
74
|
}
|
@@ -25,6 +25,15 @@
|
|
25
25
|
#ifndef _PASSENGER_APPLICATION_POOL2_APP_TYPES_H_
|
26
26
|
#define _PASSENGER_APPLICATION_POOL2_APP_TYPES_H_
|
27
27
|
|
28
|
+
/**
|
29
|
+
* Application type registry
|
30
|
+
*
|
31
|
+
* All supported application types (e.g. Rack, classic Rails, WSGI, etc)
|
32
|
+
* are registered here. The AppTypeDetector is responsible for checking
|
33
|
+
* what kind of application lives under the given directory.
|
34
|
+
*/
|
35
|
+
|
36
|
+
|
28
37
|
#ifdef __cplusplus
|
29
38
|
extern "C" {
|
30
39
|
#endif /* __cplusplus */
|
@@ -36,16 +45,16 @@ typedef enum {
|
|
36
45
|
PAT_NONE
|
37
46
|
} PassengerAppType;
|
38
47
|
|
39
|
-
typedef void
|
48
|
+
typedef void PP_AppTypeDetector;
|
40
49
|
|
41
|
-
|
42
|
-
void
|
43
|
-
PassengerAppType
|
50
|
+
PP_AppTypeDetector *pp_app_type_detector_new();
|
51
|
+
void pp_app_type_detector_free(PP_AppTypeDetector *detector);
|
52
|
+
PassengerAppType pp_app_type_detector_check_document_root(PP_AppTypeDetector *detector,
|
44
53
|
const char *documentRoot, unsigned int len, int resolveFirstSymlink);
|
45
|
-
PassengerAppType
|
54
|
+
PassengerAppType pp_app_type_detector_check_app_root(PP_AppTypeDetector *detector,
|
46
55
|
const char *appRoot, unsigned int len);
|
47
56
|
|
48
|
-
const char *
|
57
|
+
const char *pp_get_app_type_name(PassengerAppType type);
|
49
58
|
|
50
59
|
#ifdef __cplusplus
|
51
60
|
}
|
@@ -56,6 +65,7 @@ const char *passenger_get_app_type_name(PassengerAppType type);
|
|
56
65
|
#include <oxt/macros.hpp>
|
57
66
|
#include <oxt/backtrace.hpp>
|
58
67
|
#include <cstdlib>
|
68
|
+
#include <string>
|
59
69
|
#include <Logging.h>
|
60
70
|
#include <StaticString.h>
|
61
71
|
#include <Utils.h>
|
@@ -65,6 +75,8 @@ const char *passenger_get_app_type_name(PassengerAppType type);
|
|
65
75
|
namespace Passenger {
|
66
76
|
namespace ApplicationPool2 {
|
67
77
|
|
78
|
+
using namespace std;
|
79
|
+
|
68
80
|
|
69
81
|
struct AppTypeDefinition {
|
70
82
|
const PassengerAppType type;
|
@@ -114,18 +126,58 @@ public:
|
|
114
126
|
}
|
115
127
|
}
|
116
128
|
|
117
|
-
|
129
|
+
/**
|
130
|
+
* Given a web server document root (that is, some subdirectory under the
|
131
|
+
* application root, e.g. "/webapps/foobar/public"), returns the type of
|
132
|
+
* application that lives there. Returns PAT_NONE if it wasn't able to detect
|
133
|
+
* a supported application type.
|
134
|
+
*
|
135
|
+
* If `resolveFirstSymlink` is given, and `documentRoot` is a symlink, then
|
136
|
+
* this function will check the parent directory
|
137
|
+
* of the directory that the symlink points to (i.e. `resolve(documentRoot) + "/.."`),
|
138
|
+
* instead of checking the directory that the symlink is located in (i.e.
|
139
|
+
* `dirname(documentRoot)`).
|
140
|
+
*
|
141
|
+
* If `appRoot` is non-NULL, then the inferred application root will be stored here.
|
142
|
+
*
|
143
|
+
* @throws FileSystemException Unable to check because of a filesystem error.
|
144
|
+
* @throws TimeRetrievalException
|
145
|
+
* @throws boost::thread_interrupted
|
146
|
+
*/
|
147
|
+
PassengerAppType checkDocumentRoot(const StaticString &documentRoot,
|
148
|
+
bool resolveFirstSymlink = false,
|
149
|
+
string *appRoot = NULL)
|
150
|
+
{
|
118
151
|
if (!resolveFirstSymlink) {
|
119
|
-
|
152
|
+
if (appRoot != NULL) {
|
153
|
+
*appRoot = extractDirNameStatic(documentRoot);
|
154
|
+
return checkAppRoot(*appRoot);
|
155
|
+
} else {
|
156
|
+
return checkAppRoot(extractDirNameStatic(documentRoot));
|
157
|
+
}
|
120
158
|
} else {
|
121
159
|
char ntDocRoot[documentRoot.size() + 1];
|
122
160
|
memcpy(ntDocRoot, documentRoot.data(), documentRoot.size());
|
123
161
|
ntDocRoot[documentRoot.size()] = '\0';
|
124
162
|
string resolvedDocumentRoot = resolveSymlink(ntDocRoot);
|
125
|
-
|
163
|
+
if (appRoot != NULL) {
|
164
|
+
*appRoot = extractDirNameStatic(resolvedDocumentRoot);
|
165
|
+
return checkAppRoot(*appRoot);
|
166
|
+
} else {
|
167
|
+
return checkAppRoot(extractDirNameStatic(resolvedDocumentRoot));
|
168
|
+
}
|
126
169
|
}
|
127
170
|
}
|
128
171
|
|
172
|
+
/**
|
173
|
+
* Returns the type of application that lives under the application
|
174
|
+
* directory `appRoot`. Returns PAT_NONE if it wasn't able to detect
|
175
|
+
* a supported application type.
|
176
|
+
*
|
177
|
+
* @throws FileSystemException Unable to check because of a filesystem error.
|
178
|
+
* @throws TimeRetrievalException
|
179
|
+
* @throws boost::thread_interrupted
|
180
|
+
*/
|
129
181
|
PassengerAppType checkAppRoot(const StaticString &appRoot) {
|
130
182
|
char buf[appRoot.size() + 32];
|
131
183
|
const char *end = buf + appRoot.size() + 32;
|