passenger 2.2.4 → 2.2.5
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/NEWS +137 -0
- data/Rakefile +101 -19
- data/bin/passenger-install-nginx-module +10 -3
- data/bin/passenger-make-enterprisey +1 -1
- data/doc/Users guide Apache.html +227 -92
- data/doc/Users guide Apache.txt +169 -75
- data/doc/Users guide Nginx.html +1 -1
- data/doc/cxxapi/Bucket_8h-source.html +1 -1
- data/doc/cxxapi/Configuration_8h-source.html +373 -338
- data/doc/cxxapi/DirectoryMapper_8h-source.html +1 -1
- data/doc/cxxapi/Hooks_8h-source.html +1 -1
- data/doc/cxxapi/annotated.html +1 -1
- data/doc/cxxapi/classHooks-members.html +1 -1
- data/doc/cxxapi/classHooks.html +2 -2
- data/doc/cxxapi/classPassenger_1_1DirectoryMapper-members.html +1 -1
- data/doc/cxxapi/classPassenger_1_1DirectoryMapper.html +1 -1
- data/doc/cxxapi/classes.html +1 -1
- data/doc/cxxapi/definitions_8h-source.html +1 -1
- data/doc/cxxapi/files.html +1 -1
- data/doc/cxxapi/functions.html +1 -1
- data/doc/cxxapi/functions_func.html +1 -1
- data/doc/cxxapi/graph_legend.html +1 -1
- data/doc/cxxapi/group__Configuration.html +1 -1
- data/doc/cxxapi/group__Core.html +1 -1
- data/doc/cxxapi/group__Hooks.html +1 -1
- data/doc/cxxapi/group__Support.html +1 -1
- data/doc/cxxapi/main.html +1 -1
- data/doc/cxxapi/modules.html +1 -1
- data/doc/rdoc/classes/ConditionVariable.html +59 -59
- data/doc/rdoc/classes/Exception.html +11 -11
- data/doc/rdoc/classes/GC.html +4 -4
- data/doc/rdoc/classes/IO.html +14 -14
- data/doc/rdoc/classes/PhusionPassenger.html +1 -1
- data/doc/rdoc/classes/PhusionPassenger/AbstractInstaller.html +8 -8
- data/doc/rdoc/classes/PhusionPassenger/AbstractRequestHandler.html +136 -136
- data/doc/rdoc/classes/PhusionPassenger/AbstractServer.html +254 -254
- data/doc/rdoc/classes/PhusionPassenger/AbstractServerCollection.html +61 -61
- data/doc/rdoc/classes/PhusionPassenger/AppInitError.html +4 -4
- data/doc/rdoc/classes/PhusionPassenger/Application.html +14 -14
- data/doc/rdoc/classes/PhusionPassenger/ConsoleTextTemplate.html +12 -12
- data/doc/rdoc/classes/PhusionPassenger/FrameworkInitError.html +4 -4
- data/doc/rdoc/classes/PhusionPassenger/HTMLTemplate.html +12 -12
- data/doc/rdoc/classes/PhusionPassenger/InitializationError.html +5 -5
- data/doc/rdoc/classes/PhusionPassenger/MessageChannel.html +139 -139
- data/doc/rdoc/classes/PhusionPassenger/Rack/RequestHandler.html +61 -56
- data/doc/rdoc/classes/PhusionPassenger/Railz/ApplicationSpawner.html +3 -3
- data/doc/rdoc/classes/PhusionPassenger/Railz/FrameworkSpawner.html +7 -7
- data/doc/rdoc/classes/PhusionPassenger/Railz/RequestHandler.html +15 -15
- data/doc/rdoc/classes/PhusionPassenger/SpawnManager.html +119 -119
- data/doc/rdoc/classes/PhusionPassenger/UnknownError.html +4 -4
- data/doc/rdoc/classes/PhusionPassenger/Utils.html +310 -312
- data/doc/rdoc/classes/PhusionPassenger/Utils/PseudoIO.html +169 -0
- data/doc/rdoc/classes/PhusionPassenger/VersionNotFound.html +4 -4
- data/doc/rdoc/classes/PlatformInfo.html +165 -164
- data/doc/rdoc/classes/Signal.html +23 -23
- data/doc/rdoc/created.rid +1 -1
- data/doc/rdoc/files/ext/phusion_passenger/native_support_c.html +1 -1
- data/doc/rdoc/files/lib/phusion_passenger/abstract_request_handler_rb.html +26 -28
- data/doc/rdoc/files/lib/phusion_passenger/abstract_server_rb.html +26 -28
- data/doc/rdoc/files/lib/phusion_passenger/admin_tools/control_process_rb.html +1 -1
- data/doc/rdoc/files/lib/phusion_passenger/constants_rb.html +1 -1
- data/doc/rdoc/files/lib/phusion_passenger/message_channel_rb.html +26 -28
- data/doc/rdoc/files/lib/phusion_passenger/platform_info_rb.html +1 -1
- data/doc/rdoc/files/lib/phusion_passenger/rack/application_spawner_rb.html +1 -1
- data/doc/rdoc/files/lib/phusion_passenger/rack/request_handler_rb.html +26 -28
- data/doc/rdoc/files/lib/phusion_passenger/railz/application_spawner_rb.html +1 -2
- data/doc/rdoc/files/lib/phusion_passenger/railz/framework_spawner_rb.html +1 -1
- data/doc/rdoc/files/lib/phusion_passenger/railz/request_handler_rb.html +26 -28
- data/doc/rdoc/files/lib/phusion_passenger/spawn_manager_rb.html +26 -28
- data/doc/rdoc/files/lib/phusion_passenger/utils_rb.html +34 -36
- data/doc/rdoc/fr_class_index.html +1 -0
- data/doc/rdoc/fr_method_index.html +72 -68
- data/ext/apache2/Configuration.cpp +69 -15
- data/ext/apache2/Configuration.h +37 -2
- data/ext/apache2/Hooks.cpp +167 -59
- data/ext/common/ApplicationPoolServerExecutable.cpp +1 -1
- data/ext/common/MessageChannel.h +4 -4
- data/ext/common/StandardApplicationPool.h +1 -1
- data/ext/common/Timer.h +2 -0
- data/ext/common/Version.h +1 -1
- data/ext/nginx/Configuration.c +3 -3
- data/ext/nginx/ContentHandler.c +16 -4
- data/ext/nginx/HelperServer.cpp +1 -1
- data/ext/oxt/system_calls.cpp +6 -1
- data/ext/oxt/thread.hpp +17 -2
- data/ext/phusion_passenger/native_support.c +4 -4
- data/lib/phusion_passenger/abstract_request_handler.rb +3 -3
- data/lib/phusion_passenger/abstract_server.rb +1 -0
- data/lib/phusion_passenger/constants.rb +1 -1
- data/lib/phusion_passenger/message_channel.rb +1 -0
- data/lib/phusion_passenger/platform_info.rb +3 -2
- data/lib/phusion_passenger/rack/request_handler.rb +11 -7
- data/lib/phusion_passenger/railz/application_spawner.rb +7 -4
- data/lib/phusion_passenger/railz/request_handler.rb +1 -0
- data/lib/phusion_passenger/spawn_manager.rb +1 -0
- data/lib/phusion_passenger/utils.rb +38 -20
- data/test/integration_tests/apache2_tests.rb +162 -100
- data/test/integration_tests/mycook_spec.rb +63 -62
- data/test/integration_tests/nginx_tests.rb +12 -5
- data/test/ruby/utils_spec.rb +98 -14
- data/test/stub/apache2/httpd.conf.erb +2 -1
- data/test/stub/rails_apps/mycook/app/controllers/welcome_controller.rb +8 -0
- data/test/support/apache2_controller.rb +5 -1
- data/test/support/test_helper.rb +42 -13
- metadata +7 -137
data/ext/apache2/Configuration.h
CHANGED
@@ -28,6 +28,7 @@
|
|
28
28
|
#ifdef __cplusplus
|
29
29
|
#include "Utils.h"
|
30
30
|
#include "MessageChannel.h"
|
31
|
+
#include "Logging.h"
|
31
32
|
#endif
|
32
33
|
|
33
34
|
/* The APR headers must come after the Passenger headers. See Hooks.cpp
|
@@ -134,11 +135,25 @@
|
|
134
135
|
* in the directory configuration. */
|
135
136
|
bool memoryLimitSpecified;
|
136
137
|
|
138
|
+
/** Whether symlinks in the document root path should be resolved.
|
139
|
+
* The implication of this is documented in the users guide, section
|
140
|
+
* "How Phusion Passenger detects whether a virtual host is a web application".
|
141
|
+
*/
|
142
|
+
Threeway resolveSymlinksInDocRoot;
|
143
|
+
|
144
|
+
/** Whether high performance mode should be turned on. */
|
137
145
|
Threeway highPerformance;
|
138
146
|
|
139
147
|
/** Whether global queuing should be used. */
|
140
148
|
Threeway useGlobalQueue;
|
141
149
|
|
150
|
+
/**
|
151
|
+
* Whether encoded slashes in URLs should be supported. This however conflicts
|
152
|
+
* with mod_rewrite support because of a bug/limitation in Apache, so it's one
|
153
|
+
* or the other.
|
154
|
+
*/
|
155
|
+
Threeway allowEncodedSlashes;
|
156
|
+
|
142
157
|
/**
|
143
158
|
* Throttle the number of stat() calls on files like
|
144
159
|
* restart.txt to the once per given number of seconds.
|
@@ -170,7 +185,11 @@
|
|
170
185
|
|
171
186
|
string getAppRoot(const char *documentRoot) const {
|
172
187
|
if (appRoot == NULL) {
|
173
|
-
|
188
|
+
if (resolveSymlinksInDocRoot == DirConfig::ENABLED) {
|
189
|
+
return extractDirName(resolveSymlink(documentRoot));
|
190
|
+
} else {
|
191
|
+
return extractDirName(documentRoot);
|
192
|
+
}
|
174
193
|
} else {
|
175
194
|
return appRoot;
|
176
195
|
}
|
@@ -178,7 +197,11 @@
|
|
178
197
|
|
179
198
|
string getAppRoot(const string &documentRoot) const {
|
180
199
|
if (appRoot == NULL) {
|
181
|
-
|
200
|
+
if (resolveSymlinksInDocRoot == DirConfig::ENABLED) {
|
201
|
+
return extractDirName(resolveSymlink(documentRoot));
|
202
|
+
} else {
|
203
|
+
return extractDirName(documentRoot);
|
204
|
+
}
|
182
205
|
} else {
|
183
206
|
return appRoot;
|
184
207
|
}
|
@@ -237,6 +260,10 @@
|
|
237
260
|
return useGlobalQueue == ENABLED;
|
238
261
|
}
|
239
262
|
|
263
|
+
bool allowsEncodedSlashes() const {
|
264
|
+
return allowEncodedSlashes == ENABLED;
|
265
|
+
}
|
266
|
+
|
240
267
|
unsigned long getStatThrottleRate() const {
|
241
268
|
if (statThrottleRateSpecified) {
|
242
269
|
return statThrottleRate;
|
@@ -321,6 +348,14 @@
|
|
321
348
|
*/
|
322
349
|
const char *tempDir;
|
323
350
|
|
351
|
+
const char *getRuby() const {
|
352
|
+
if (ruby != NULL) {
|
353
|
+
return ruby;
|
354
|
+
} else {
|
355
|
+
return "ruby";
|
356
|
+
}
|
357
|
+
}
|
358
|
+
|
324
359
|
const char *getDefaultUser() const {
|
325
360
|
if (defaultUser != NULL) {
|
326
361
|
return defaultUser;
|
data/ext/apache2/Hooks.cpp
CHANGED
@@ -68,14 +68,24 @@ using namespace Passenger;
|
|
68
68
|
extern "C" module AP_MODULE_DECLARE_DATA passenger_module;
|
69
69
|
|
70
70
|
|
71
|
-
|
71
|
+
/*
|
72
|
+
* This is the main source file which interfaces directly with Apache by
|
73
|
+
* installing hooks. The code here can look a bit convoluted, but it'll make
|
74
|
+
* more sense if you read:
|
75
|
+
* http://httpd.apache.org/docs/2.2/developer/request.html
|
76
|
+
*
|
77
|
+
* Scroll all the way down to passenger_register_hooks to get an idea of
|
78
|
+
* what we're hooking into and what we do in those hooks.
|
79
|
+
*/
|
80
|
+
|
72
81
|
|
73
82
|
/**
|
74
83
|
* If the HTTP client sends POST data larger than this value (in bytes),
|
75
|
-
* then the POST data will be fully
|
84
|
+
* then the POST data will be fully buffered into a temporary file, before
|
76
85
|
* allocating a Ruby web application session.
|
86
|
+
* File uploads smaller than this are buffered into memory instead.
|
77
87
|
*/
|
78
|
-
#define
|
88
|
+
#define LARGE_UPLOAD_THRESHOLD 1024 * 8
|
79
89
|
|
80
90
|
|
81
91
|
/**
|
@@ -120,13 +130,14 @@ private:
|
|
120
130
|
ReportFileSystemError(const FileSystemException &ex): e(ex) { }
|
121
131
|
|
122
132
|
int report(request_rec *r) {
|
133
|
+
r->status = 500;
|
123
134
|
ap_set_content_type(r, "text/html; charset=UTF-8");
|
124
135
|
ap_rputs("<h1>Passenger error #2</h1>\n", r);
|
125
136
|
ap_rputs("An error occurred while trying to access '", r);
|
126
137
|
ap_rputs(ap_escape_html(r->pool, e.filename().c_str()), r);
|
127
138
|
ap_rputs("': ", r);
|
128
139
|
ap_rputs(ap_escape_html(r->pool, e.what()), r);
|
129
|
-
if (e.code() == EPERM) {
|
140
|
+
if (e.code() == EACCES || e.code() == EPERM) {
|
130
141
|
ap_rputs("<p>", r);
|
131
142
|
ap_rputs("Apache doesn't have read permissions to that file. ", r);
|
132
143
|
ap_rputs("Please fix the relevant file permissions.", r);
|
@@ -310,12 +321,27 @@ private:
|
|
310
321
|
* Later, in the handler hook, we inform the user about this
|
311
322
|
* problem so that he can either disable Phusion Passenger's
|
312
323
|
* autodetection routines, or fix the permissions.
|
324
|
+
*
|
325
|
+
* If it's not a permission problem then we'll disable
|
326
|
+
* Phusion Passenger for the rest of the request.
|
313
327
|
*/
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
328
|
+
if (e.code() == EACCES || e.code() == EPERM) {
|
329
|
+
// TODO: filesystem error is not always reported. need
|
330
|
+
// to figure out why. test case:
|
331
|
+
// - mkdir /foo
|
332
|
+
// - mkdir /foo/public
|
333
|
+
// - mkdir /foo/config
|
334
|
+
// - chmod 000 /foo/config
|
335
|
+
// - add vhost 'foo' with document root /foo/public
|
336
|
+
// - curl http://foo/
|
337
|
+
apr_pool_userdata_set(new ReportFileSystemError(e),
|
338
|
+
"Phusion Passenger: error report",
|
339
|
+
ReportFileSystemError::cleanup,
|
340
|
+
r->pool);
|
341
|
+
return true;
|
342
|
+
} else {
|
343
|
+
return false;
|
344
|
+
}
|
319
345
|
}
|
320
346
|
|
321
347
|
/* Save some information for the hook methods that are called later.
|
@@ -449,7 +475,8 @@ private:
|
|
449
475
|
this_thread::disable_syscall_interruption dsi;
|
450
476
|
Application::SessionPtr session;
|
451
477
|
bool expectingUploadData;
|
452
|
-
|
478
|
+
string uploadDataMemory;
|
479
|
+
shared_ptr<BufferedUpload> uploadDataFile;
|
453
480
|
const char *contentLength;
|
454
481
|
|
455
482
|
expectingUploadData = ap_should_client_block(r);
|
@@ -458,14 +485,18 @@ private:
|
|
458
485
|
/* If the HTTP upload data is larger than a threshold, or if the HTTP
|
459
486
|
* client sent HTTP upload data using the "chunked" transfer encoding
|
460
487
|
* (which implies Content-Length == NULL), then buffer the upload
|
461
|
-
* data into a tempfile.
|
488
|
+
* data into a tempfile. Otherwise, buffer it into memory.
|
489
|
+
*
|
490
|
+
* We never forward the data directly to the backend process because
|
491
|
+
* the HTTP client might block indefinitely until it's done uploading.
|
492
|
+
* This would quickly exhaust the application pool.
|
462
493
|
*/
|
463
|
-
if (expectingUploadData
|
464
|
-
|
465
|
-
|
466
|
-
|
467
|
-
|
468
|
-
|
494
|
+
if (expectingUploadData) {
|
495
|
+
if (contentLength == NULL || atol(contentLength) > LARGE_UPLOAD_THRESHOLD) {
|
496
|
+
uploadDataFile = receiveRequestBody(r, contentLength);
|
497
|
+
} else {
|
498
|
+
receiveRequestBody(r, contentLength, uploadDataMemory);
|
499
|
+
}
|
469
500
|
}
|
470
501
|
|
471
502
|
if (expectingUploadData && contentLength == NULL) {
|
@@ -474,8 +505,13 @@ private:
|
|
474
505
|
* data. Rails requires this header for its HTTP upload data
|
475
506
|
* multipart parsing process.
|
476
507
|
*/
|
477
|
-
|
478
|
-
|
508
|
+
if (uploadDataFile != NULL) {
|
509
|
+
apr_table_set(r->headers_in, "Content-Length",
|
510
|
+
toString(ftell(uploadDataFile->handle)).c_str());
|
511
|
+
} else {
|
512
|
+
apr_table_set(r->headers_in, "Content-Length",
|
513
|
+
toString(uploadDataMemory.size()).c_str());
|
514
|
+
}
|
479
515
|
}
|
480
516
|
|
481
517
|
|
@@ -527,15 +563,13 @@ private:
|
|
527
563
|
}
|
528
564
|
|
529
565
|
UPDATE_TRACE_POINT();
|
530
|
-
|
531
|
-
session->setWriterTimeout(r->server->timeout / 1000);
|
532
|
-
sendHeaders(r, session, mapper.getBaseURI());
|
566
|
+
sendHeaders(r, config, session, mapper.getBaseURI());
|
533
567
|
if (expectingUploadData) {
|
534
|
-
if (
|
535
|
-
sendRequestBody(r, session,
|
536
|
-
|
568
|
+
if (uploadDataFile != NULL) {
|
569
|
+
sendRequestBody(r, session, uploadDataFile);
|
570
|
+
uploadDataFile.reset();
|
537
571
|
} else {
|
538
|
-
sendRequestBody(r, session);
|
572
|
+
sendRequestBody(r, session, uploadDataMemory);
|
539
573
|
}
|
540
574
|
}
|
541
575
|
try {
|
@@ -610,11 +644,14 @@ private:
|
|
610
644
|
ap_pass_brigade(r->output_filters, bb);
|
611
645
|
|
612
646
|
if (r->connection->aborted) {
|
613
|
-
P_WARN("
|
614
|
-
"
|
615
|
-
"
|
647
|
+
P_WARN("Either the vistor clicked on the 'Stop' button in the "
|
648
|
+
"web browser, or the visitor's connection has stalled "
|
649
|
+
"and couldn't receive the data that Apache is sending "
|
650
|
+
"to it. As a result, you will probably see a 'Broken Pipe' "
|
616
651
|
"error in this log file. Please ignore it, "
|
617
|
-
"this is normal."
|
652
|
+
"this is normal. You might also want to increase Apache's "
|
653
|
+
"TimeOut configuration option if you experience this "
|
654
|
+
"problem often.");
|
618
655
|
} else if (!bucketState->completed) {
|
619
656
|
P_WARN("Apache stopped forwarding the backend's response, "
|
620
657
|
"even though the HTTP client did not close the "
|
@@ -747,13 +784,14 @@ private:
|
|
747
784
|
}
|
748
785
|
}
|
749
786
|
|
750
|
-
apr_status_t sendHeaders(request_rec *r, Application::SessionPtr &session, const char *baseURI) {
|
787
|
+
apr_status_t sendHeaders(request_rec *r, DirConfig *config, Application::SessionPtr &session, const char *baseURI) {
|
751
788
|
apr_table_t *headers;
|
752
789
|
headers = apr_table_make(r->pool, 40);
|
753
790
|
if (headers == NULL) {
|
754
791
|
return APR_ENOMEM;
|
755
792
|
}
|
756
793
|
|
794
|
+
|
757
795
|
// Set standard CGI variables.
|
758
796
|
addHeader(headers, "SERVER_SOFTWARE", ap_get_server_version());
|
759
797
|
addHeader(headers, "SERVER_PROTOCOL", r->protocol);
|
@@ -765,17 +803,39 @@ private:
|
|
765
803
|
addHeader(headers, "REMOTE_PORT", apr_psprintf(r->pool, "%d", r->connection->remote_addr->port));
|
766
804
|
addHeader(headers, "REMOTE_USER", r->user);
|
767
805
|
addHeader(headers, "REQUEST_METHOD", r->method);
|
768
|
-
addHeader(headers, "REQUEST_URI", r->unparsed_uri);
|
769
806
|
addHeader(headers, "QUERY_STRING", r->args ? r->args : "");
|
807
|
+
addHeader(headers, "HTTPS", lookupEnv(r, "HTTPS"));
|
808
|
+
addHeader(headers, "CONTENT_TYPE", lookupHeader(r, "Content-type"));
|
809
|
+
addHeader(headers, "DOCUMENT_ROOT", ap_document_root(r));
|
810
|
+
|
811
|
+
if (config->allowsEncodedSlashes()) {
|
812
|
+
/*
|
813
|
+
* Apache decodes encoded slashes in r->uri, so we must use r->unparsed_uri
|
814
|
+
* if we are to support encoded slashes. However mod_rewrite doesn't change
|
815
|
+
* r->unparsed_uri, so the user must make a choice between mod_rewrite
|
816
|
+
* support or encoded slashes support. Sucks. :-(
|
817
|
+
*
|
818
|
+
* http://code.google.com/p/phusion-passenger/issues/detail?id=113
|
819
|
+
* http://code.google.com/p/phusion-passenger/issues/detail?id=230
|
820
|
+
*/
|
821
|
+
addHeader(headers, "REQUEST_URI", r->unparsed_uri);
|
822
|
+
} else {
|
823
|
+
const char *request_uri;
|
824
|
+
if (r->args != NULL) {
|
825
|
+
request_uri = apr_pstrcat(r->pool, r->uri, "?", r->args, NULL);
|
826
|
+
} else {
|
827
|
+
request_uri = r->uri;
|
828
|
+
}
|
829
|
+
addHeader(headers, "REQUEST_URI", request_uri);
|
830
|
+
}
|
831
|
+
|
770
832
|
if (strcmp(baseURI, "/") == 0) {
|
771
833
|
addHeader(headers, "SCRIPT_NAME", "");
|
834
|
+
addHeader(headers, "PATH_INFO", r->uri);
|
772
835
|
} else {
|
773
836
|
addHeader(headers, "SCRIPT_NAME", baseURI);
|
837
|
+
addHeader(headers, "PATH_INFO", r->uri + strlen(baseURI));
|
774
838
|
}
|
775
|
-
addHeader(headers, "HTTPS", lookupEnv(r, "HTTPS"));
|
776
|
-
addHeader(headers, "CONTENT_TYPE", lookupHeader(r, "Content-type"));
|
777
|
-
addHeader(headers, "DOCUMENT_ROOT", ap_document_root(r));
|
778
|
-
addHeader(headers, "PATH_INFO", r->parsed_uri.path);
|
779
839
|
|
780
840
|
// Set HTTP headers.
|
781
841
|
const apr_array_header_t *hdrs_arr;
|
@@ -790,6 +850,16 @@ private:
|
|
790
850
|
}
|
791
851
|
}
|
792
852
|
|
853
|
+
// Add other environment variables.
|
854
|
+
const apr_array_header_t *env_arr;
|
855
|
+
apr_table_entry_t *env;
|
856
|
+
|
857
|
+
env_arr = apr_table_elts(r->subprocess_env);
|
858
|
+
env = (apr_table_entry_t*) env_arr->elts;
|
859
|
+
for (i = 0; i < env_arr->nelts; ++i) {
|
860
|
+
addHeader(headers, env[i].key, env[i].val);
|
861
|
+
}
|
862
|
+
|
793
863
|
// Now send the headers.
|
794
864
|
string buffer;
|
795
865
|
|
@@ -1035,11 +1105,58 @@ private:
|
|
1035
1105
|
}
|
1036
1106
|
|
1037
1107
|
if (contentLength != NULL && ftell(tempFile->handle) != atol(contentLength)) {
|
1038
|
-
|
1108
|
+
string message = "It looks like the browser did not finish the file upload: "
|
1109
|
+
"it said it will upload ";
|
1110
|
+
message.append(contentLength);
|
1111
|
+
message.append(" bytes, but it closed the connection after sending ");
|
1112
|
+
message.append(toString(ftell(tempFile->handle)));
|
1113
|
+
message.append(" bytes. The user probably clicked Stop in the browser "
|
1114
|
+
"or his Internet connection stalled.");
|
1115
|
+
throw IOException(message);
|
1039
1116
|
}
|
1040
1117
|
return tempFile;
|
1041
1118
|
}
|
1042
1119
|
|
1120
|
+
/**
|
1121
|
+
* Receive the HTTP upload data and buffer it into a string.
|
1122
|
+
*
|
1123
|
+
* @param r The request.
|
1124
|
+
* @param contentLength The value of the HTTP Content-Length header. This is used
|
1125
|
+
* to check whether the HTTP client has sent complete upload
|
1126
|
+
* data. NULL indicates that there is no Content-Length header,
|
1127
|
+
* i.e. that the HTTP client used chunked transfer encoding.
|
1128
|
+
* @param string The string to buffer into.
|
1129
|
+
* @throws RuntimeException
|
1130
|
+
* @throws IOException
|
1131
|
+
*/
|
1132
|
+
void receiveRequestBody(request_rec *r, const char *contentLength, string &buffer) {
|
1133
|
+
TRACE_POINT();
|
1134
|
+
unsigned long l_contentLength = 0;
|
1135
|
+
char buf[1024 * 32];
|
1136
|
+
apr_off_t len;
|
1137
|
+
|
1138
|
+
buffer.clear();
|
1139
|
+
if (contentLength != NULL) {
|
1140
|
+
l_contentLength = atol(contentLength);
|
1141
|
+
buffer.reserve(l_contentLength);
|
1142
|
+
}
|
1143
|
+
|
1144
|
+
while ((len = readRequestBodyFromApache(r, buf, sizeof(buf))) > 0) {
|
1145
|
+
buffer.append(buf, len);
|
1146
|
+
}
|
1147
|
+
|
1148
|
+
if (contentLength != NULL && buffer.size() != l_contentLength) {
|
1149
|
+
string message = "It looks like the browser did not finish the file upload: "
|
1150
|
+
"it said it will upload ";
|
1151
|
+
message.append(contentLength);
|
1152
|
+
message.append(" bytes, but it closed the connection after sending ");
|
1153
|
+
message.append(toString(buffer.size()));
|
1154
|
+
message.append(" bytes. The user probably clicked Stop in the browser "
|
1155
|
+
"or his Internet connection stalled.");
|
1156
|
+
throw IOException(message);
|
1157
|
+
}
|
1158
|
+
}
|
1159
|
+
|
1043
1160
|
void sendRequestBody(request_rec *r, Application::SessionPtr &session, shared_ptr<BufferedUpload> &uploadData) {
|
1044
1161
|
TRACE_POINT();
|
1045
1162
|
rewind(uploadData->handle);
|
@@ -1053,13 +1170,8 @@ private:
|
|
1053
1170
|
}
|
1054
1171
|
}
|
1055
1172
|
|
1056
|
-
void sendRequestBody(request_rec *r, Application::SessionPtr &session) {
|
1057
|
-
|
1058
|
-
apr_off_t len;
|
1059
|
-
|
1060
|
-
while ((len = readRequestBodyFromApache(r, buf, sizeof(buf))) > 0) {
|
1061
|
-
session->sendBodyBlock(buf, len);
|
1062
|
-
}
|
1173
|
+
void sendRequestBody(request_rec *r, Application::SessionPtr &session, const string &buffer) {
|
1174
|
+
session->sendBodyBlock(buffer.c_str(), buffer.size());
|
1063
1175
|
}
|
1064
1176
|
|
1065
1177
|
public:
|
@@ -1075,22 +1187,13 @@ public:
|
|
1075
1187
|
P_DEBUG("Initializing Phusion Passenger...");
|
1076
1188
|
ap_add_version_component(pconf, "Phusion_Passenger/" PASSENGER_VERSION);
|
1077
1189
|
|
1078
|
-
const char *
|
1190
|
+
const char *user;
|
1079
1191
|
string applicationPoolServerExe, spawnServer;
|
1080
1192
|
|
1081
|
-
/*
|
1082
|
-
* As described in the comment in init_module, upon (re)starting
|
1083
|
-
* Apache, the Hooks constructor is called twice. We unset
|
1084
|
-
* PASSENGER_INSTANCE_TEMP_DIR before calling createPassengerTempDir()
|
1085
|
-
* because we want the temp directory's name to contain the PID
|
1086
|
-
* of the process in which the Hooks constructor was called for
|
1087
|
-
* the second time.
|
1088
|
-
*/
|
1089
1193
|
createPassengerTempDir(config->getTempDir(), config->userSwitching,
|
1090
1194
|
config->getDefaultUser(), unixd_config.user_id,
|
1091
1195
|
unixd_config.group_id);
|
1092
1196
|
|
1093
|
-
ruby = (config->ruby != NULL) ? config->ruby : DEFAULT_RUBY_COMMAND;
|
1094
1197
|
if (config->userSwitching) {
|
1095
1198
|
user = "";
|
1096
1199
|
} else {
|
@@ -1124,7 +1227,7 @@ public:
|
|
1124
1227
|
applicationPoolServer = ptr(
|
1125
1228
|
new ApplicationPoolServer(
|
1126
1229
|
applicationPoolServerExe, spawnServer, "",
|
1127
|
-
|
1230
|
+
config->getRuby(), user)
|
1128
1231
|
);
|
1129
1232
|
|
1130
1233
|
ApplicationPoolPtr pool(applicationPoolServer->connect());
|
@@ -1162,7 +1265,7 @@ public:
|
|
1162
1265
|
* A is top-most directory that exists. B is the first filename piece that
|
1163
1266
|
* normally follows A. For example, suppose that a website's DocumentRoot
|
1164
1267
|
* is /website, on server http://test.com/. Suppose that there's also a
|
1165
|
-
* directory /website/images.
|
1268
|
+
* directory /website/images. No other files or directories exist in /website.
|
1166
1269
|
*
|
1167
1270
|
* If we access: then r->filename will be:
|
1168
1271
|
* http://test.com/foo/bar /website/foo
|
@@ -1187,14 +1290,19 @@ public:
|
|
1187
1290
|
*/
|
1188
1291
|
return OK;
|
1189
1292
|
} else {
|
1190
|
-
|
1191
|
-
|
1192
|
-
|
1293
|
+
/* core.c's map_to_storage hook will transform the filename, as
|
1294
|
+
* described by saveOriginalFilename(). Here we restore the
|
1295
|
+
* original filename.
|
1296
|
+
*/
|
1193
1297
|
const char *filename = apr_table_get(r->notes, "Phusion Passenger: original filename");
|
1194
1298
|
if (filename == NULL) {
|
1195
1299
|
return DECLINED;
|
1196
1300
|
} else {
|
1197
1301
|
prepareRequest(r, config, filename);
|
1302
|
+
/* Always return declined in order to let other modules'
|
1303
|
+
* hooks run, regardless of what prepareRequest()'s
|
1304
|
+
* result is.
|
1305
|
+
*/
|
1198
1306
|
return DECLINED;
|
1199
1307
|
}
|
1200
1308
|
}
|