passenger 2.2.2 → 2.2.3
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/DEVELOPERS.TXT +13 -3
- data/Rakefile +42 -33
- data/bin/passenger-install-apache2-module +1 -2
- data/bin/passenger-install-nginx-module +7 -19
- data/bin/passenger-status +64 -15
- data/bin/passenger-stress-test +2 -2
- data/doc/ApplicationPool algorithm.txt +26 -22
- data/doc/Users guide Apache.html +374 -149
- data/doc/Users guide Apache.txt +318 -51
- data/doc/Users guide Nginx.html +13 -13
- data/doc/Users guide Nginx.txt +7 -2
- data/doc/cxxapi/Bucket_8h-source.html +62 -25
- data/doc/cxxapi/Configuration_8h-source.html +343 -326
- data/doc/cxxapi/DirectoryMapper_8h-source.html +12 -12
- 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 +1 -1
- data/doc/cxxapi/classPassenger_1_1DirectoryMapper-members.html +2 -2
- data/doc/cxxapi/classPassenger_1_1DirectoryMapper.html +9 -9
- 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 +2 -2
- data/doc/cxxapi/functions_func.html +2 -2
- 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 +194 -0
- data/doc/rdoc/classes/Exception.html +120 -0
- data/doc/rdoc/classes/GC.html +113 -0
- data/doc/rdoc/classes/IO.html +169 -0
- data/doc/rdoc/classes/PhusionPassenger.html +238 -0
- data/doc/rdoc/classes/PhusionPassenger/AbstractInstaller.html +153 -0
- data/doc/rdoc/classes/PhusionPassenger/AbstractRequestHandler.html +517 -0
- data/doc/rdoc/classes/PhusionPassenger/AbstractServer.html +719 -0
- data/doc/rdoc/classes/PhusionPassenger/AbstractServer/ServerAlreadyStarted.html +97 -0
- data/doc/rdoc/classes/PhusionPassenger/AbstractServer/ServerError.html +96 -0
- data/doc/rdoc/classes/PhusionPassenger/AbstractServer/ServerNotStarted.html +97 -0
- data/doc/rdoc/classes/PhusionPassenger/AbstractServer/UnknownMessage.html +96 -0
- data/doc/rdoc/classes/PhusionPassenger/AbstractServerCollection.html +598 -0
- data/doc/rdoc/classes/PhusionPassenger/AdminTools.html +140 -0
- data/doc/rdoc/classes/PhusionPassenger/AdminTools/ControlProcess.html +317 -0
- data/doc/rdoc/classes/PhusionPassenger/AdminTools/ControlProcess/Instance.html +138 -0
- data/doc/rdoc/classes/PhusionPassenger/AppInitError.html +154 -0
- data/doc/rdoc/classes/PhusionPassenger/Application.html +283 -0
- data/doc/rdoc/classes/PhusionPassenger/ConsoleTextTemplate.html +172 -0
- data/doc/rdoc/classes/PhusionPassenger/FrameworkInitError.html +145 -0
- data/doc/rdoc/classes/PhusionPassenger/HTMLTemplate.html +175 -0
- data/doc/rdoc/classes/PhusionPassenger/InitializationError.html +141 -0
- data/doc/rdoc/classes/PhusionPassenger/InvalidPath.html +92 -0
- data/doc/rdoc/classes/PhusionPassenger/MessageChannel.html +489 -0
- data/doc/rdoc/classes/PhusionPassenger/NativeSupport.html +350 -0
- data/doc/rdoc/classes/PhusionPassenger/Rack.html +91 -0
- data/doc/rdoc/classes/PhusionPassenger/Rack/ApplicationSpawner.html +188 -0
- data/doc/rdoc/classes/PhusionPassenger/Rack/RequestHandler.html +194 -0
- data/doc/rdoc/classes/PhusionPassenger/Railz.html +95 -0
- data/doc/rdoc/classes/PhusionPassenger/Railz/ApplicationSpawner.html +442 -0
- data/doc/rdoc/classes/PhusionPassenger/Railz/ApplicationSpawner/Error.html +98 -0
- data/doc/rdoc/classes/PhusionPassenger/Railz/CGIFixed.html +200 -0
- data/doc/rdoc/classes/PhusionPassenger/Railz/FrameworkSpawner.html +436 -0
- data/doc/rdoc/classes/PhusionPassenger/Railz/FrameworkSpawner/Error.html +98 -0
- data/doc/rdoc/classes/PhusionPassenger/Railz/RequestHandler.html +155 -0
- data/doc/rdoc/classes/PhusionPassenger/SpawnManager.html +402 -0
- data/doc/rdoc/classes/PhusionPassenger/UnknownError.html +125 -0
- data/doc/rdoc/classes/PhusionPassenger/Utils.html +805 -0
- data/doc/rdoc/classes/PhusionPassenger/VersionNotFound.html +140 -0
- data/doc/rdoc/classes/PhusionPassenger/WSGI.html +89 -0
- data/doc/rdoc/classes/PhusionPassenger/WSGI/ApplicationSpawner.html +188 -0
- data/doc/rdoc/classes/PlatformInfo.html +831 -0
- data/doc/rdoc/classes/RakeExtensions.html +197 -0
- data/doc/rdoc/classes/Signal.html +131 -0
- data/doc/rdoc/created.rid +1 -0
- data/doc/rdoc/files/DEVELOPERS_TXT.html +255 -0
- data/doc/rdoc/files/README.html +157 -0
- data/doc/rdoc/files/ext/phusion_passenger/native_support_c.html +92 -0
- data/doc/rdoc/files/lib/phusion_passenger/abstract_installer_rb.html +129 -0
- data/doc/rdoc/files/lib/phusion_passenger/abstract_request_handler_rb.html +131 -0
- data/doc/rdoc/files/lib/phusion_passenger/abstract_server_collection_rb.html +126 -0
- data/doc/rdoc/files/lib/phusion_passenger/abstract_server_rb.html +130 -0
- data/doc/rdoc/files/lib/phusion_passenger/admin_tools/control_process_rb.html +130 -0
- data/doc/rdoc/files/lib/phusion_passenger/admin_tools_rb.html +122 -0
- data/doc/rdoc/files/lib/phusion_passenger/application_rb.html +127 -0
- data/doc/rdoc/files/lib/phusion_passenger/console_text_template_rb.html +126 -0
- data/doc/rdoc/files/lib/phusion_passenger/constants_rb.html +122 -0
- data/doc/rdoc/files/lib/phusion_passenger/dependencies_rb.html +134 -0
- data/doc/rdoc/files/lib/phusion_passenger/events_rb.html +122 -0
- data/doc/rdoc/files/lib/phusion_passenger/exceptions_rb.html +122 -0
- data/doc/rdoc/files/lib/phusion_passenger/html_template_rb.html +126 -0
- data/doc/rdoc/files/lib/phusion_passenger/message_channel_rb.html +122 -0
- data/doc/rdoc/files/lib/phusion_passenger/packaging_rb.html +122 -0
- data/doc/rdoc/files/lib/phusion_passenger/platform_info_rb.html +127 -0
- data/doc/rdoc/files/lib/phusion_passenger/rack/application_spawner_rb.html +133 -0
- data/doc/rdoc/files/lib/phusion_passenger/rack/request_handler_rb.html +127 -0
- data/doc/rdoc/files/lib/phusion_passenger/railz/application_spawner_rb.html +143 -0
- data/doc/rdoc/files/lib/phusion_passenger/railz/cgi_fixed_rb.html +126 -0
- data/doc/rdoc/files/lib/phusion_passenger/railz/framework_spawner_rb.html +145 -0
- data/doc/rdoc/files/lib/phusion_passenger/railz/request_handler_rb.html +127 -0
- data/doc/rdoc/files/lib/phusion_passenger/simple_benchmarking_rb.html +122 -0
- data/doc/rdoc/files/lib/phusion_passenger/spawn_manager_rb.html +161 -0
- data/doc/rdoc/files/lib/phusion_passenger/utils_rb.html +175 -0
- data/doc/rdoc/files/lib/phusion_passenger/wsgi/application_spawner_rb.html +129 -0
- data/doc/rdoc/files/misc/rake/extensions_rb.html +130 -0
- data/doc/rdoc/fr_class_index.html +90 -0
- data/doc/rdoc/fr_file_index.html +76 -0
- data/doc/rdoc/fr_method_index.html +200 -0
- data/doc/rdoc/index.html +26 -0
- data/doc/rdoc/rdoc-style.css +187 -0
- data/doc/users_guide_snippets/rackup_specifications.txt +2 -8
- data/ext/apache2/Bucket.cpp +71 -38
- data/ext/apache2/Bucket.h +53 -16
- data/ext/apache2/Configuration.cpp +15 -0
- data/ext/apache2/Configuration.h +19 -2
- data/ext/apache2/DirectoryMapper.h +10 -10
- data/ext/apache2/Hooks.cpp +334 -74
- data/ext/boost/mpl/apply.hpp +5 -1
- data/ext/boost/mpl/apply_wrap.hpp +5 -2
- data/ext/boost/mpl/aux_/full_lambda.hpp +5 -1
- data/ext/boost/mpl/bind.hpp +5 -1
- data/ext/common/Application.h +11 -31
- data/ext/common/ApplicationPool.h +2 -1
- data/ext/common/ApplicationPoolServer.h +61 -20
- data/ext/common/ApplicationPoolServerExecutable.cpp +132 -4
- data/ext/common/ApplicationPoolStatusReporter.h +189 -65
- data/ext/common/Base64.cpp +143 -0
- data/ext/common/Base64.h +57 -0
- data/ext/common/CachedFileStat.cpp +25 -82
- data/ext/common/CachedFileStat.h +11 -125
- data/ext/common/CachedFileStat.hpp +243 -0
- data/ext/common/Exceptions.h +13 -0
- data/ext/common/FileChangeChecker.h +209 -0
- data/ext/common/Logging.h +3 -2
- data/ext/common/MessageChannel.h +10 -10
- data/ext/common/PoolOptions.h +72 -5
- data/ext/common/SpawnManager.h +11 -8
- data/ext/common/StandardApplicationPool.h +38 -39
- data/ext/common/StaticString.h +1 -0
- data/ext/common/StringListCreator.h +83 -0
- data/ext/common/SystemTime.h +3 -2
- data/ext/common/Timer.h +88 -0
- data/ext/common/Utils.cpp +161 -42
- data/ext/common/Utils.h +62 -31
- data/ext/common/Version.h +1 -1
- data/ext/nginx/Configuration.c +0 -4
- data/ext/nginx/ContentHandler.c +8 -6
- data/ext/nginx/HelperServer.cpp +45 -55
- data/ext/nginx/HttpStatusExtractor.h +4 -0
- data/ext/nginx/StaticContentHandler.c +25 -5
- data/ext/nginx/config +3 -0
- data/ext/nginx/ngx_http_passenger_module.c +72 -17
- data/ext/nginx/ngx_http_passenger_module.h +2 -2
- data/lib/phusion_passenger/abstract_request_handler.rb +15 -7
- data/lib/phusion_passenger/abstract_server.rb +16 -2
- data/lib/phusion_passenger/admin_tools/control_process.rb +36 -25
- data/lib/phusion_passenger/constants.rb +1 -1
- data/lib/phusion_passenger/dependencies.rb +10 -0
- data/lib/phusion_passenger/platform_info.rb +1 -1
- data/lib/phusion_passenger/rack/application_spawner.rb +21 -2
- data/lib/phusion_passenger/rack/request_handler.rb +10 -0
- data/lib/phusion_passenger/railz/application_spawner.rb +38 -2
- data/lib/phusion_passenger/railz/framework_spawner.rb +26 -28
- data/lib/phusion_passenger/railz/request_handler.rb +5 -1
- data/lib/phusion_passenger/spawn_manager.rb +6 -2
- data/lib/phusion_passenger/utils.rb +79 -27
- data/misc/rake/cplusplus.rb +5 -5
- data/test/ApplicationPoolServerTest.cpp +42 -0
- data/test/ApplicationPoolTest.cpp +255 -267
- data/test/Base64Test.cpp +48 -0
- data/test/CachedFileStatTest.cpp +243 -103
- data/test/FileChangeCheckerTest.cpp +331 -0
- data/test/PoolOptionsTest.cpp +80 -0
- data/test/UtilsTest.cpp +5 -17
- data/test/integration_tests/apache2_tests.rb +15 -4
- data/test/integration_tests/mycook_spec.rb +3 -4
- data/test/oxt/syscall_interruption_test.cpp +2 -14
- data/test/ruby/abstract_server_collection_spec.rb +1 -1
- data/test/ruby/abstract_server_spec.rb +35 -1
- data/test/ruby/rack/application_spawner_spec.rb +23 -6
- data/test/ruby/rails/application_spawner_spec.rb +6 -6
- data/test/ruby/rails/framework_spawner_spec.rb +6 -5
- data/test/ruby/rails/minimal_spawner_spec.rb +19 -0
- data/test/ruby/rails/spawner_error_handling_spec.rb +62 -7
- data/test/ruby/spawn_manager_spec.rb +10 -7
- data/test/ruby/spawn_server_spec.rb +1 -1
- data/test/ruby/utils_spec.rb +193 -20
- data/test/ruby/wsgi/application_spawner_spec.rb +3 -1
- data/test/stub/apache2/httpd.conf.erb +3 -0
- data/test/stub/rack/config.ru +1 -1
- data/test/stub/rails_apps/mycook/app/controllers/welcome_controller.rb +8 -0
- data/test/support/Support.cpp +84 -0
- data/test/support/Support.h +66 -8
- data/test/support/config.rb +14 -2
- data/test/support/test_helper.rb +5 -0
- data/vendor/rack-1.0.0-git/lib/rack/auth/openid.rb +123 -116
- data/vendor/rack-1.0.0-git/lib/rack/cascade.rb +17 -12
- data/vendor/rack-1.0.0-git/lib/rack/commonlogger.rb +34 -43
- data/vendor/rack-1.0.0-git/lib/rack/handler/cgi.rb +1 -1
- data/vendor/rack-1.0.0-git/lib/rack/handler/fastcgi.rb +1 -1
- data/vendor/rack-1.0.0-git/lib/rack/handler/lsws.rb +1 -1
- data/vendor/rack-1.0.0-git/lib/rack/handler/mongrel.rb +1 -1
- data/vendor/rack-1.0.0-git/lib/rack/handler/scgi.rb +1 -1
- data/vendor/rack-1.0.0-git/lib/rack/handler/webrick.rb +1 -1
- data/vendor/rack-1.0.0-git/lib/rack/mock.rb +4 -17
- data/vendor/rack-1.0.0-git/lib/rack/request.rb +3 -9
- data/vendor/rack-1.0.0-git/lib/rack/rewindable_input.rb +2 -0
- data/vendor/rack-1.0.0-git/lib/rack/utils.rb +38 -12
- metadata +231 -186
- data/ext/common/FileChecker.h +0 -112
- data/test/FileCheckerTest.cpp +0 -79
- data/test/stub/minimal-railsapp/README +0 -3
- data/test/stub/minimal-railsapp/config/application.rb +0 -0
- data/test/stub/minimal-railsapp/config/environment.rb +0 -3
- data/test/stub/minimal-railsapp/vendor/rails/actionmailer/lib/action_mailer.rb +0 -0
- data/test/stub/minimal-railsapp/vendor/rails/actionpack/lib/action_controller.rb +0 -10
- data/test/stub/minimal-railsapp/vendor/rails/actionpack/lib/action_pack.rb +0 -0
- data/test/stub/minimal-railsapp/vendor/rails/actionpack/lib/action_view.rb +0 -0
- data/test/stub/minimal-railsapp/vendor/rails/activerecord/lib/active_record.rb +0 -7
- data/test/stub/minimal-railsapp/vendor/rails/activeresource/lib/active_resource.rb +0 -0
- data/test/stub/minimal-railsapp/vendor/rails/activesupport/lib/active_support.rb +0 -17
- data/test/stub/minimal-railsapp/vendor/rails/activesupport/lib/active_support/whiny_nil.rb +0 -0
- data/test/stub/minimal-railsapp/vendor/rails/railties/lib/dispatcher.rb +0 -0
- data/test/stub/minimal-railsapp/vendor/rails/railties/lib/initializer.rb +0 -8
- data/test/stub/minimal-railsapp/vendor/rails/railties/lib/ruby_version_check.rb +0 -1
- data/test/stub/railsapp/app/controllers/application.rb +0 -12
- data/test/stub/railsapp/app/controllers/bar_controller.rb +0 -5
- data/test/stub/railsapp/app/controllers/bar_controller_1.txt +0 -5
- data/test/stub/railsapp/app/controllers/bar_controller_2.txt +0 -5
- data/test/stub/railsapp/app/controllers/foo_controller.rb +0 -9
- data/test/stub/railsapp/app/helpers/application_helper.rb +0 -3
- data/test/stub/railsapp/config/boot.rb +0 -108
- data/test/stub/railsapp/config/database.yml +0 -19
- data/test/stub/railsapp/config/environment.rb +0 -59
- data/test/stub/railsapp/config/environments/development.rb +0 -18
- data/test/stub/railsapp/config/environments/production.rb +0 -19
- data/test/stub/railsapp/config/initializers/inflections.rb +0 -10
- data/test/stub/railsapp/config/initializers/mime_types.rb +0 -5
- data/test/stub/railsapp/config/routes.rb +0 -35
- data/test/stub/railsapp/public/useless.txt +0 -1
- data/test/stub/railsapp2/app/controllers/application.rb +0 -12
- data/test/stub/railsapp2/app/controllers/foo_controller.rb +0 -5
- data/test/stub/railsapp2/app/helpers/application_helper.rb +0 -3
- data/test/stub/railsapp2/config/boot.rb +0 -108
- data/test/stub/railsapp2/config/database.yml +0 -19
- data/test/stub/railsapp2/config/environment.rb +0 -59
- data/test/stub/railsapp2/config/environments/development.rb +0 -18
- data/test/stub/railsapp2/config/environments/production.rb +0 -19
- data/test/stub/railsapp2/config/initializers/inflections.rb +0 -10
- data/test/stub/railsapp2/config/initializers/mime_types.rb +0 -5
- data/test/stub/railsapp2/config/routes.rb +0 -35
- data/test/stub/railsapp2/public/useless.txt +0 -1
@@ -87,6 +87,7 @@ passenger_config_create_dir(apr_pool_t *p, char *dirspec) {
|
|
87
87
|
config->statThrottleRate = 0;
|
88
88
|
config->statThrottleRateSpecified = false;
|
89
89
|
config->restartDir = NULL;
|
90
|
+
config->uploadBufferDir = NULL;
|
90
91
|
/*************************************/
|
91
92
|
return config;
|
92
93
|
}
|
@@ -127,6 +128,7 @@ passenger_config_merge_dir(apr_pool_t *p, void *basev, void *addv) {
|
|
127
128
|
config->statThrottleRate = (add->statThrottleRateSpecified) ? add->statThrottleRate : base->statThrottleRate;
|
128
129
|
config->statThrottleRateSpecified = base->statThrottleRateSpecified || add->statThrottleRateSpecified;
|
129
130
|
config->restartDir = (add->restartDir == NULL) ? base->restartDir : add->restartDir;
|
131
|
+
config->uploadBufferDir = (add->uploadBufferDir == NULL) ? base->uploadBufferDir : add->uploadBufferDir;
|
130
132
|
/*************************************/
|
131
133
|
return config;
|
132
134
|
}
|
@@ -401,6 +403,13 @@ cmd_passenger_app_root(cmd_parms *cmd, void *pcfg, const char *arg) {
|
|
401
403
|
return NULL;
|
402
404
|
}
|
403
405
|
|
406
|
+
static const char *
|
407
|
+
cmd_passenger_upload_buffer_dir(cmd_parms *cmd, void *pcfg, const char *arg) {
|
408
|
+
DirConfig *config = (DirConfig *) pcfg;
|
409
|
+
config->uploadBufferDir = arg;
|
410
|
+
return NULL;
|
411
|
+
}
|
412
|
+
|
404
413
|
|
405
414
|
/*************************************************
|
406
415
|
* Rails-specific settings
|
@@ -622,6 +631,12 @@ const command_rec passenger_commands[] = {
|
|
622
631
|
NULL,
|
623
632
|
OR_OPTIONS | ACCESS_CONF | RSRC_CONF,
|
624
633
|
"The application's root directory."),
|
634
|
+
AP_INIT_TAKE1("PassengerUploadBufferDir",
|
635
|
+
(Take1Func) cmd_passenger_upload_buffer_dir,
|
636
|
+
NULL,
|
637
|
+
OR_OPTIONS,
|
638
|
+
"The directory in which upload buffer files should be placed."),
|
639
|
+
/*****************************/
|
625
640
|
|
626
641
|
// Rails-specific settings.
|
627
642
|
AP_INIT_TAKE1("RailsBaseURI",
|
data/ext/apache2/Configuration.h
CHANGED
@@ -25,8 +25,10 @@
|
|
25
25
|
#ifndef _PASSENGER_CONFIGURATION_H_
|
26
26
|
#define _PASSENGER_CONFIGURATION_H_
|
27
27
|
|
28
|
-
#
|
29
|
-
#include "
|
28
|
+
#ifdef __cplusplus
|
29
|
+
#include "Utils.h"
|
30
|
+
#include "MessageChannel.h"
|
31
|
+
#endif
|
30
32
|
|
31
33
|
/* The APR headers must come after the Passenger headers. See Hooks.cpp
|
32
34
|
* to learn why.
|
@@ -153,6 +155,13 @@
|
|
153
155
|
*/
|
154
156
|
const char *restartDir;
|
155
157
|
|
158
|
+
/**
|
159
|
+
* The directory in which Passenger should place upload buffer
|
160
|
+
* files. NULL means that the default directory should be used.
|
161
|
+
*/
|
162
|
+
const char *uploadBufferDir;
|
163
|
+
|
164
|
+
/*************************************/
|
156
165
|
/*************************************/
|
157
166
|
|
158
167
|
bool isEnabled() const {
|
@@ -244,6 +253,14 @@
|
|
244
253
|
}
|
245
254
|
}
|
246
255
|
|
256
|
+
string getUploadBufferDir() const {
|
257
|
+
if (uploadBufferDir != NULL) {
|
258
|
+
return uploadBufferDir;
|
259
|
+
} else {
|
260
|
+
return getPassengerTempDir() + "/webserver_private";
|
261
|
+
}
|
262
|
+
}
|
263
|
+
|
247
264
|
/*************************************/
|
248
265
|
};
|
249
266
|
|
@@ -31,7 +31,7 @@
|
|
31
31
|
|
32
32
|
#include <oxt/backtrace.hpp>
|
33
33
|
|
34
|
-
#include "CachedFileStat.
|
34
|
+
#include "CachedFileStat.hpp"
|
35
35
|
#include "Configuration.h"
|
36
36
|
#include "Utils.h"
|
37
37
|
|
@@ -66,7 +66,7 @@ public:
|
|
66
66
|
private:
|
67
67
|
DirConfig *config;
|
68
68
|
request_rec *r;
|
69
|
-
|
69
|
+
CachedFileStat *cstat;
|
70
70
|
unsigned int throttleRate;
|
71
71
|
bool baseURIKnown;
|
72
72
|
const char *baseURI;
|
@@ -91,16 +91,16 @@ public:
|
|
91
91
|
/**
|
92
92
|
* Create a new DirectoryMapper object.
|
93
93
|
*
|
94
|
-
* @param
|
95
|
-
* @param throttleRate A throttling rate for
|
94
|
+
* @param cstat A CachedFileStat object used for statting files.
|
95
|
+
* @param throttleRate A throttling rate for cstat.
|
96
96
|
* @warning Do not use this object after the destruction of <tt>r</tt>,
|
97
|
-
* <tt>config</tt> or <tt>
|
97
|
+
* <tt>config</tt> or <tt>cstat</tt>.
|
98
98
|
*/
|
99
99
|
DirectoryMapper(request_rec *r, DirConfig *config,
|
100
|
-
|
100
|
+
CachedFileStat *cstat, unsigned int throttleRate) {
|
101
101
|
this->r = r;
|
102
102
|
this->config = config;
|
103
|
-
this->
|
103
|
+
this->cstat = cstat;
|
104
104
|
this->throttleRate = throttleRate;
|
105
105
|
appType = NONE;
|
106
106
|
baseURIKnown = false;
|
@@ -171,7 +171,7 @@ public:
|
|
171
171
|
|
172
172
|
UPDATE_TRACE_POINT();
|
173
173
|
if (shouldAutoDetectRails()
|
174
|
-
&& verifyRailsDir(config->getAppRoot(ap_document_root(r)),
|
174
|
+
&& verifyRailsDir(config->getAppRoot(ap_document_root(r)), cstat, throttleRate)) {
|
175
175
|
baseURIKnown = true;
|
176
176
|
baseURI = "/";
|
177
177
|
appType = RAILS;
|
@@ -180,7 +180,7 @@ public:
|
|
180
180
|
|
181
181
|
UPDATE_TRACE_POINT();
|
182
182
|
if (shouldAutoDetectRack()
|
183
|
-
&& verifyRackDir(config->getAppRoot(ap_document_root(r)),
|
183
|
+
&& verifyRackDir(config->getAppRoot(ap_document_root(r)), cstat, throttleRate)) {
|
184
184
|
baseURIKnown = true;
|
185
185
|
baseURI = "/";
|
186
186
|
appType = RACK;
|
@@ -189,7 +189,7 @@ public:
|
|
189
189
|
|
190
190
|
UPDATE_TRACE_POINT();
|
191
191
|
if (shouldAutoDetectWSGI()
|
192
|
-
&& verifyWSGIDir(config->getAppRoot(ap_document_root(r)),
|
192
|
+
&& verifyWSGIDir(config->getAppRoot(ap_document_root(r)), cstat, throttleRate)) {
|
193
193
|
baseURIKnown = true;
|
194
194
|
baseURI = "/";
|
195
195
|
appType = WSGI;
|
data/ext/apache2/Hooks.cpp
CHANGED
@@ -39,6 +39,7 @@
|
|
39
39
|
#include "ApplicationPoolServer.h"
|
40
40
|
#include "MessageChannel.h"
|
41
41
|
#include "DirectoryMapper.h"
|
42
|
+
#include "Timer.h"
|
42
43
|
#include "Version.h"
|
43
44
|
|
44
45
|
/* The Apache/APR headers *must* come after the Boost headers, otherwise
|
@@ -138,12 +139,44 @@ private:
|
|
138
139
|
}
|
139
140
|
};
|
140
141
|
|
142
|
+
/**
|
143
|
+
* A StringListCreator which returns a list of environment variable
|
144
|
+
* names and values, as found in r->subprocess_env.
|
145
|
+
*/
|
146
|
+
class EnvironmentVariablesStringListCreator: public StringListCreator {
|
147
|
+
private:
|
148
|
+
request_rec *r;
|
149
|
+
public:
|
150
|
+
EnvironmentVariablesStringListCreator(request_rec *r) {
|
151
|
+
this->r = r;
|
152
|
+
}
|
153
|
+
|
154
|
+
virtual const StringListPtr getItems() const {
|
155
|
+
const apr_array_header_t *env_arr;
|
156
|
+
apr_table_entry_t *env_entries;
|
157
|
+
StringListPtr result = ptr(new StringList());
|
158
|
+
|
159
|
+
// Some standard CGI headers.
|
160
|
+
result->push_back("SERVER_SOFTWARE");
|
161
|
+
result->push_back(ap_get_server_version());
|
162
|
+
|
163
|
+
// Subprocess environment variables.
|
164
|
+
env_arr = apr_table_elts(r->subprocess_env);
|
165
|
+
env_entries = (apr_table_entry_t *) env_arr->elts;
|
166
|
+
for (int i = 0; i < env_arr->nelts; ++i) {
|
167
|
+
result->push_back(env_entries[i].key);
|
168
|
+
result->push_back(env_entries[i].val);
|
169
|
+
}
|
170
|
+
return result;
|
171
|
+
}
|
172
|
+
};
|
173
|
+
|
141
174
|
enum Threeway { YES, NO, UNKNOWN };
|
142
175
|
|
143
176
|
ApplicationPoolServerPtr applicationPoolServer;
|
144
177
|
thread_specific_ptr<ApplicationPoolPtr> threadSpecificApplicationPool;
|
145
178
|
Threeway m_hasModRewrite, m_hasModDir, m_hasModAutoIndex;
|
146
|
-
|
179
|
+
CachedFileStat cstat;
|
147
180
|
|
148
181
|
inline DirConfig *getDirConfig(request_rec *r) {
|
149
182
|
return (DirConfig *) ap_get_module_config(r->per_dir_config, &passenger_module);
|
@@ -249,7 +282,7 @@ private:
|
|
249
282
|
* (C) r->filename already exists.
|
250
283
|
* (D) There is a page cache file for the URI.
|
251
284
|
*
|
252
|
-
* - If A is not true, or if B is not true, or if C is true, then
|
285
|
+
* - If A is not true, or if B is not true, or if C is true, then don't do anything.
|
253
286
|
* Passenger will be disabled during the rest of this request.
|
254
287
|
* - If D is true, then we first transform r->filename to the page cache file's
|
255
288
|
* filename, and then we let Apache serve it statically.
|
@@ -261,7 +294,7 @@ private:
|
|
261
294
|
*/
|
262
295
|
bool prepareRequest(request_rec *r, DirConfig *config, const char *filename, bool coreModuleWillBeRun = false) {
|
263
296
|
TRACE_POINT();
|
264
|
-
DirectoryMapper mapper(r, config,
|
297
|
+
DirectoryMapper mapper(r, config, &cstat, config->getStatThrottleRate());
|
265
298
|
try {
|
266
299
|
if (mapper.getBaseURI() == NULL) {
|
267
300
|
// (B) is not true.
|
@@ -378,6 +411,9 @@ private:
|
|
378
411
|
void *pointer;
|
379
412
|
} u;
|
380
413
|
|
414
|
+
/* Did an error occur in any of the previous hook methods during
|
415
|
+
* this request? If so, show the error and stop here.
|
416
|
+
*/
|
381
417
|
u.errorReport = 0;
|
382
418
|
apr_pool_userdata_get(&u.pointer, "Phusion Passenger: error report", r->pool);
|
383
419
|
if (u.errorReport != 0) {
|
@@ -411,8 +447,6 @@ private:
|
|
411
447
|
try {
|
412
448
|
this_thread::disable_interruption di;
|
413
449
|
this_thread::disable_syscall_interruption dsi;
|
414
|
-
apr_bucket_brigade *bb;
|
415
|
-
apr_bucket *b;
|
416
450
|
Application::SessionPtr session;
|
417
451
|
bool expectingUploadData;
|
418
452
|
shared_ptr<BufferedUpload> uploadData;
|
@@ -421,10 +455,11 @@ private:
|
|
421
455
|
expectingUploadData = ap_should_client_block(r);
|
422
456
|
contentLength = lookupHeader(r, "Content-Length");
|
423
457
|
|
424
|
-
|
425
|
-
|
426
|
-
|
427
|
-
|
458
|
+
/* If the HTTP upload data is larger than a threshold, or if the HTTP
|
459
|
+
* client sent HTTP upload data using the "chunked" transfer encoding
|
460
|
+
* (which implies Content-Length == NULL), then buffer the upload
|
461
|
+
* data into a tempfile.
|
462
|
+
*/
|
428
463
|
if (expectingUploadData && (
|
429
464
|
contentLength == NULL ||
|
430
465
|
atol(contentLength) > UPLOAD_ACCELERATION_THRESHOLD
|
@@ -434,10 +469,11 @@ private:
|
|
434
469
|
}
|
435
470
|
|
436
471
|
if (expectingUploadData && contentLength == NULL) {
|
437
|
-
|
438
|
-
|
439
|
-
|
440
|
-
|
472
|
+
/* In case of "chunked" transfer encoding, we'll set the
|
473
|
+
* Content-Length header to the length of the received upload
|
474
|
+
* data. Rails requires this header for its HTTP upload data
|
475
|
+
* multipart parsing process.
|
476
|
+
*/
|
441
477
|
apr_table_set(r->headers_in, "Content-Length",
|
442
478
|
toString(ftell(uploadData->handle)).c_str());
|
443
479
|
}
|
@@ -450,10 +486,8 @@ private:
|
|
450
486
|
try {
|
451
487
|
ServerConfig *sconfig = getServerConfig(r->server);
|
452
488
|
string publicDirectory(mapper.getPublicDirectory());
|
453
|
-
|
454
|
-
|
455
|
-
session = getApplicationPool()->get(PoolOptions(
|
456
|
-
appRoot,
|
489
|
+
PoolOptions options(
|
490
|
+
config->getAppRoot(publicDirectory.c_str()),
|
457
491
|
true,
|
458
492
|
sconfig->getDefaultUser(),
|
459
493
|
mapper.getEnvironment(),
|
@@ -465,8 +499,12 @@ private:
|
|
465
499
|
config->getMemoryLimit(),
|
466
500
|
config->usingGlobalQueue(),
|
467
501
|
config->getStatThrottleRate(),
|
468
|
-
config->getRestartDir()
|
469
|
-
|
502
|
+
config->getRestartDir(),
|
503
|
+
mapper.getBaseURI()
|
504
|
+
);
|
505
|
+
options.environmentVariables = ptr(new EnvironmentVariablesStringListCreator(r));
|
506
|
+
|
507
|
+
session = getApplicationPool()->get(options);
|
470
508
|
P_TRACE(3, "Forwarding " << r->uri << " to PID " << session->getPid());
|
471
509
|
} catch (const SpawnException &e) {
|
472
510
|
r->status = 500;
|
@@ -500,34 +538,62 @@ private:
|
|
500
538
|
sendRequestBody(r, session);
|
501
539
|
}
|
502
540
|
}
|
503
|
-
|
541
|
+
try {
|
542
|
+
session->shutdownWriter();
|
543
|
+
} catch (const SystemException &e) {
|
544
|
+
// Ignore ENOTCONN. This error occurs for some people
|
545
|
+
// for unknown reasons, but it's harmless.
|
546
|
+
if (e.code() != ENOTCONN) {
|
547
|
+
throw;
|
548
|
+
}
|
549
|
+
}
|
504
550
|
|
505
551
|
|
506
552
|
/********** Step 4: forwarding the response from the backend
|
507
553
|
process back to the HTTP client **********/
|
508
554
|
|
509
555
|
UPDATE_TRACE_POINT();
|
510
|
-
|
511
|
-
|
512
|
-
|
513
|
-
|
514
|
-
|
515
|
-
|
556
|
+
apr_bucket_brigade *bb;
|
557
|
+
apr_bucket *b;
|
558
|
+
PassengerBucketStatePtr bucketState;
|
559
|
+
pid_t backendPid;
|
560
|
+
|
561
|
+
/* Setup the bucket brigade. */
|
562
|
+
bucketState = ptr(new PassengerBucketState());
|
516
563
|
bb = apr_brigade_create(r->connection->pool, r->connection->bucket_alloc);
|
517
|
-
b = passenger_bucket_create(session,
|
564
|
+
b = passenger_bucket_create(session, bucketState, r->connection->bucket_alloc);
|
565
|
+
|
566
|
+
/* The bucket (b) still has a reference to the session, so the reset()
|
567
|
+
* call here is guaranteed not to throw any exceptions.
|
568
|
+
*/
|
569
|
+
backendPid = session->getPid();
|
518
570
|
session.reset();
|
571
|
+
|
519
572
|
APR_BRIGADE_INSERT_TAIL(bb, b);
|
520
573
|
|
521
574
|
b = apr_bucket_eos_create(r->connection->bucket_alloc);
|
522
575
|
APR_BRIGADE_INSERT_TAIL(bb, b);
|
523
576
|
|
524
|
-
|
577
|
+
/* Now read the HTTP response header, parse it and fill relevant
|
578
|
+
* information in our request_rec structure.
|
579
|
+
*/
|
580
|
+
|
581
|
+
/* I know the required size for backendData because I read
|
582
|
+
* util_script.c's source. :-(
|
583
|
+
*/
|
525
584
|
char backendData[MAX_STRING_LEN];
|
585
|
+
Timer timer;
|
526
586
|
int result = ap_scan_script_header_err_brigade(r, bb, backendData);
|
587
|
+
|
527
588
|
if (result == OK) {
|
528
589
|
// The API documentation for ap_scan_script_err_brigade() says it
|
529
590
|
// returns HTTP_OK on success, but it actually returns OK.
|
530
591
|
|
592
|
+
/* We were able to parse the HTTP response header sent by the
|
593
|
+
* backend process! Proceed with passing the bucket brigade,
|
594
|
+
* for forwarding the response body to the HTTP client.
|
595
|
+
*/
|
596
|
+
|
531
597
|
/* Manually set the Status header because
|
532
598
|
* ap_scan_script_header_err_brigade() filters it
|
533
599
|
* out. Some broken HTTP clients depend on the
|
@@ -540,17 +606,73 @@ private:
|
|
540
606
|
}
|
541
607
|
apr_table_setn(r->headers_out, "Status", r->status_line);
|
542
608
|
|
609
|
+
UPDATE_TRACE_POINT();
|
543
610
|
ap_pass_brigade(r->output_filters, bb);
|
611
|
+
|
612
|
+
if (r->connection->aborted) {
|
613
|
+
P_WARN("The HTTP client closed the connection before "
|
614
|
+
"the response could be completely sent. As a "
|
615
|
+
"result, you will probably see a 'Broken Pipe' "
|
616
|
+
"error in this log file. Please ignore it, "
|
617
|
+
"this is normal.");
|
618
|
+
} else if (!bucketState->completed) {
|
619
|
+
P_WARN("Apache stopped forwarding the backend's response, "
|
620
|
+
"even though the HTTP client did not close the "
|
621
|
+
"connection. Is this an Apache bug?");
|
622
|
+
}
|
623
|
+
|
544
624
|
return OK;
|
545
625
|
} else if (backendData[0] == '\0') {
|
546
|
-
|
547
|
-
|
626
|
+
if ((long long) timer.elapsed() >= r->server->timeout / 1000) {
|
627
|
+
// Looks like an I/O timeout.
|
628
|
+
P_ERROR("No data received from " <<
|
629
|
+
"the backend application (process " <<
|
630
|
+
backendPid << ") within " <<
|
631
|
+
(r->server->timeout / 1000) << " msec. Either " <<
|
632
|
+
"the backend application is frozen, or " <<
|
633
|
+
"your TimeOut value of " <<
|
634
|
+
(r->server->timeout / 1000000) <<
|
635
|
+
" seconds is too low. Please check " <<
|
636
|
+
"whether your application is frozen, or " <<
|
637
|
+
"increase the value of the TimeOut " <<
|
638
|
+
"configuration directive.");
|
639
|
+
} else {
|
640
|
+
P_ERROR("The backend application (process " <<
|
641
|
+
backendPid << ") did not send a valid " <<
|
642
|
+
"HTTP response; instead, it sent nothing " <<
|
643
|
+
"at all. It is possible that it has crashed; " <<
|
644
|
+
"please check whether there are crashing " <<
|
645
|
+
"bugs in this application.");
|
646
|
+
}
|
548
647
|
apr_table_setn(r->err_headers_out, "Status", "500 Internal Server Error");
|
549
648
|
return HTTP_INTERNAL_SERVER_ERROR;
|
550
649
|
} else {
|
551
|
-
|
552
|
-
|
553
|
-
|
650
|
+
if ((long long) timer.elapsed() >= r->server->timeout / 1000) {
|
651
|
+
// Looks like an I/O timeout.
|
652
|
+
P_ERROR("The backend application (process " <<
|
653
|
+
backendPid << ") hasn't sent a valid " <<
|
654
|
+
"HTTP response within " <<
|
655
|
+
(r->server->timeout / 1000) << " msec. Either " <<
|
656
|
+
"the backend application froze while " <<
|
657
|
+
"sending a response, or " <<
|
658
|
+
"your TimeOut value of " <<
|
659
|
+
(r->server->timeout / 1000000) <<
|
660
|
+
" seconds is too low. Please check " <<
|
661
|
+
"whether the application is frozen, or " <<
|
662
|
+
"increase the value of the TimeOut " <<
|
663
|
+
"configuration directive. The application " <<
|
664
|
+
"has sent this data so far: [" <<
|
665
|
+
backendData << "]");
|
666
|
+
} else {
|
667
|
+
P_ERROR("The backend application (process " <<
|
668
|
+
backendPid << ") didn't send a valid " <<
|
669
|
+
"HTTP response. It might have crashed " <<
|
670
|
+
"during the middle of sending an HTTP " <<
|
671
|
+
"response, so please check whether there " <<
|
672
|
+
"are crashing problems in your application. " <<
|
673
|
+
"This is the data that it sent: [" <<
|
674
|
+
backendData << "]");
|
675
|
+
}
|
554
676
|
apr_table_setn(r->err_headers_out, "Status", "500 Internal Server Error");
|
555
677
|
return HTTP_INTERNAL_SERVER_ERROR;
|
556
678
|
}
|
@@ -668,16 +790,6 @@ private:
|
|
668
790
|
}
|
669
791
|
}
|
670
792
|
|
671
|
-
// Add other environment variables.
|
672
|
-
const apr_array_header_t *env_arr;
|
673
|
-
apr_table_entry_t *env;
|
674
|
-
|
675
|
-
env_arr = apr_table_elts(r->subprocess_env);
|
676
|
-
env = (apr_table_entry_t*) env_arr->elts;
|
677
|
-
for (i = 0; i < env_arr->nelts; ++i) {
|
678
|
-
addHeader(headers, env[i].key, env[i].val);
|
679
|
-
}
|
680
|
-
|
681
793
|
// Now send the headers.
|
682
794
|
string buffer;
|
683
795
|
|
@@ -721,6 +833,169 @@ private:
|
|
721
833
|
return APR_SUCCESS;
|
722
834
|
}
|
723
835
|
|
836
|
+
void throwUploadBufferingException(request_rec *r, int code) {
|
837
|
+
DirConfig *config = getDirConfig(r);
|
838
|
+
string message("An error occured while "
|
839
|
+
"buffering HTTP upload data to "
|
840
|
+
"a temporary file in ");
|
841
|
+
message.append(config->getUploadBufferDir());
|
842
|
+
|
843
|
+
switch (code) {
|
844
|
+
case ENOSPC:
|
845
|
+
message.append(". Disk directory doesn't have enough disk space, "
|
846
|
+
"so please make sure that it has "
|
847
|
+
"enough disk space for buffering file uploads, "
|
848
|
+
"or set the 'PassengerUploadBufferDir' directive "
|
849
|
+
"to a directory that has enough disk space.");
|
850
|
+
throw RuntimeException(message);
|
851
|
+
break;
|
852
|
+
case EDQUOT:
|
853
|
+
message.append(". The current Apache worker process (which is "
|
854
|
+
"running as ");
|
855
|
+
message.append(getProcessUsername());
|
856
|
+
message.append(") cannot write to this directory because of "
|
857
|
+
"disk quota limits. Please make sure that the volume "
|
858
|
+
"that this directory resides on has enough disk space "
|
859
|
+
"quota for the Apache worker process, or set the "
|
860
|
+
"'PassengerUploadBufferDir' directive to a different "
|
861
|
+
"directory that has enough disk space quota.");
|
862
|
+
throw RuntimeException(message);
|
863
|
+
break;
|
864
|
+
case ENOENT:
|
865
|
+
message.append(". This directory doesn't exist, so please make "
|
866
|
+
"sure that this directory exists, or set the "
|
867
|
+
"'PassengerUploadBufferDir' directive to a "
|
868
|
+
"directory that exists and can be written to.");
|
869
|
+
throw RuntimeException(message);
|
870
|
+
break;
|
871
|
+
case EACCES:
|
872
|
+
message.append(". The current Apache worker process (which is "
|
873
|
+
"running as ");
|
874
|
+
message.append(getProcessUsername());
|
875
|
+
message.append(") doesn't have permissions to write to this "
|
876
|
+
"directory. Please change the permissions for this "
|
877
|
+
"directory (as well as all parent directories) so that "
|
878
|
+
"it is writable by the Apache worker process, or set "
|
879
|
+
"the 'PassengerUploadBufferDir' directive to a directory "
|
880
|
+
"that Apache can write to.");
|
881
|
+
throw RuntimeException(message);
|
882
|
+
break;
|
883
|
+
default:
|
884
|
+
throw SystemException(message, code);
|
885
|
+
break;
|
886
|
+
}
|
887
|
+
}
|
888
|
+
|
889
|
+
/**
|
890
|
+
* Reads the next chunk of the request body and put it into a buffer.
|
891
|
+
*
|
892
|
+
* This is like ap_get_client_block(), but can actually report errors
|
893
|
+
* in a sane way. ap_get_client_block() tells you that something went
|
894
|
+
* wrong, but not *what* went wrong.
|
895
|
+
*
|
896
|
+
* @param r The current request.
|
897
|
+
* @param buffer A buffer to put the read data into.
|
898
|
+
* @param bufsiz The size of the buffer.
|
899
|
+
* @return The number of bytes read, or 0 on EOF.
|
900
|
+
* @throws RuntimeException Something non-I/O related went wrong, e.g.
|
901
|
+
* failure to allocate memory and stuff.
|
902
|
+
* @throws IOException An I/O error occurred while trying to read the
|
903
|
+
* request body data.
|
904
|
+
*/
|
905
|
+
unsigned long readRequestBodyFromApache(request_rec *r, char *buffer, apr_size_t bufsiz) {
|
906
|
+
apr_status_t rv;
|
907
|
+
apr_bucket_brigade *bb;
|
908
|
+
|
909
|
+
if (r->remaining < 0 || (!r->read_chunked && r->remaining == 0)) {
|
910
|
+
return 0;
|
911
|
+
}
|
912
|
+
|
913
|
+
bb = apr_brigade_create(r->pool, r->connection->bucket_alloc);
|
914
|
+
if (bb == NULL) {
|
915
|
+
r->connection->keepalive = AP_CONN_CLOSE;
|
916
|
+
throw RuntimeException("An error occurred while receiving HTTP upload data: "
|
917
|
+
"unable to create a bucket brigade. Maybe the system doesn't have "
|
918
|
+
"enough free memory.");
|
919
|
+
}
|
920
|
+
|
921
|
+
rv = ap_get_brigade(r->input_filters, bb, AP_MODE_READBYTES,
|
922
|
+
APR_BLOCK_READ, bufsiz);
|
923
|
+
|
924
|
+
/* We lose the failure code here. This is why ap_get_client_block should
|
925
|
+
* not be used.
|
926
|
+
*/
|
927
|
+
if (rv != APR_SUCCESS) {
|
928
|
+
/* if we actually fail here, we want to just return and
|
929
|
+
* stop trying to read data from the client.
|
930
|
+
*/
|
931
|
+
r->connection->keepalive = AP_CONN_CLOSE;
|
932
|
+
apr_brigade_destroy(bb);
|
933
|
+
|
934
|
+
char buf[150], *errorString, message[1024];
|
935
|
+
errorString = apr_strerror(rv, buf, sizeof(buf));
|
936
|
+
if (errorString != NULL) {
|
937
|
+
snprintf(message, sizeof(message),
|
938
|
+
"An error occurred while receiving HTTP upload data: %s (%d)",
|
939
|
+
errorString, rv);
|
940
|
+
} else {
|
941
|
+
snprintf(message, sizeof(message),
|
942
|
+
"An error occurred while receiving HTTP upload data: unknown error %d",
|
943
|
+
rv);
|
944
|
+
}
|
945
|
+
message[sizeof(message) - 1] = '\0';
|
946
|
+
throw RuntimeException(message);
|
947
|
+
}
|
948
|
+
|
949
|
+
/* If this fails, it means that a filter is written incorrectly and that
|
950
|
+
* it needs to learn how to properly handle APR_BLOCK_READ requests by
|
951
|
+
* returning data when requested.
|
952
|
+
*/
|
953
|
+
if (APR_BRIGADE_EMPTY(bb)) {
|
954
|
+
throw RuntimeException("An error occurred while receiving HTTP upload data: "
|
955
|
+
"the next filter in the input filter chain has "
|
956
|
+
"a bug. Please contact the author who wrote this filter about "
|
957
|
+
"this. This problem is not caused by Phusion Passenger.");
|
958
|
+
}
|
959
|
+
|
960
|
+
/* Check to see if EOS in the brigade.
|
961
|
+
*
|
962
|
+
* If so, we have to leave a nugget for the *next* readRequestBodyFromApache()
|
963
|
+
* call to return 0.
|
964
|
+
*/
|
965
|
+
if (APR_BUCKET_IS_EOS(APR_BRIGADE_LAST(bb))) {
|
966
|
+
if (r->read_chunked) {
|
967
|
+
r->remaining = -1;
|
968
|
+
} else {
|
969
|
+
r->remaining = 0;
|
970
|
+
}
|
971
|
+
}
|
972
|
+
|
973
|
+
rv = apr_brigade_flatten(bb, buffer, &bufsiz);
|
974
|
+
if (rv != APR_SUCCESS) {
|
975
|
+
apr_brigade_destroy(bb);
|
976
|
+
|
977
|
+
char buf[150], *errorString, message[1024];
|
978
|
+
errorString = apr_strerror(rv, buf, sizeof(buf));
|
979
|
+
if (errorString != NULL) {
|
980
|
+
snprintf(message, sizeof(message),
|
981
|
+
"An error occurred while receiving HTTP upload data: %s (%d)",
|
982
|
+
errorString, rv);
|
983
|
+
} else {
|
984
|
+
snprintf(message, sizeof(message),
|
985
|
+
"An error occurred while receiving HTTP upload data: unknown error %d",
|
986
|
+
rv);
|
987
|
+
}
|
988
|
+
message[sizeof(message) - 1] = '\0';
|
989
|
+
throw IOException(message);
|
990
|
+
}
|
991
|
+
|
992
|
+
/* XXX yank me? */
|
993
|
+
r->read_length += bufsiz;
|
994
|
+
|
995
|
+
apr_brigade_destroy(bb);
|
996
|
+
return bufsiz;
|
997
|
+
}
|
998
|
+
|
724
999
|
/**
|
725
1000
|
* Receive the HTTP upload data and buffer it into a BufferedUpload temp file.
|
726
1001
|
*
|
@@ -729,44 +1004,35 @@ private:
|
|
729
1004
|
* to check whether the HTTP client has sent complete upload
|
730
1005
|
* data. NULL indicates that there is no Content-Length header,
|
731
1006
|
* i.e. that the HTTP client used chunked transfer encoding.
|
1007
|
+
* @throws RuntimeException
|
1008
|
+
* @throws SystemException
|
1009
|
+
* @throws IOException
|
732
1010
|
*/
|
733
1011
|
shared_ptr<BufferedUpload> receiveRequestBody(request_rec *r, const char *contentLength) {
|
734
1012
|
TRACE_POINT();
|
735
|
-
|
1013
|
+
DirConfig *config = getDirConfig(r);
|
1014
|
+
shared_ptr<BufferedUpload> tempFile;
|
1015
|
+
try {
|
1016
|
+
tempFile.reset(new BufferedUpload(config->getUploadBufferDir()));
|
1017
|
+
} catch (const SystemException &e) {
|
1018
|
+
throwUploadBufferingException(r, e.code());
|
1019
|
+
}
|
1020
|
+
|
736
1021
|
char buf[1024 * 32];
|
737
1022
|
apr_off_t len;
|
738
1023
|
size_t total_written = 0;
|
739
1024
|
|
740
|
-
while ((len =
|
1025
|
+
while ((len = readRequestBodyFromApache(r, buf, sizeof(buf))) > 0) {
|
741
1026
|
size_t written = 0;
|
742
1027
|
do {
|
743
1028
|
size_t ret = fwrite(buf, 1, len - written, tempFile->handle);
|
744
1029
|
if (ret <= 0 || fflush(tempFile->handle) == EOF) {
|
745
|
-
|
746
|
-
string message("An error occured while "
|
747
|
-
"buffering HTTP upload data to "
|
748
|
-
"a temporary file in ");
|
749
|
-
message.append(BufferedUpload::getDir());
|
750
|
-
if (e == ENOSPC) {
|
751
|
-
message.append(". Please make sure "
|
752
|
-
"that this directory has "
|
753
|
-
"enough disk space for "
|
754
|
-
"buffering file uploads, "
|
755
|
-
"or set the 'PassengerTempDir' "
|
756
|
-
"directive to a directory "
|
757
|
-
"that has enough disk space.");
|
758
|
-
throw RuntimeException(message);
|
759
|
-
} else {
|
760
|
-
throw SystemException(message, e);
|
761
|
-
}
|
1030
|
+
throwUploadBufferingException(r, errno);
|
762
1031
|
}
|
763
1032
|
written += ret;
|
764
1033
|
} while (written < (size_t) len);
|
765
1034
|
total_written += written;
|
766
1035
|
}
|
767
|
-
if (len == -1) {
|
768
|
-
throw IOException("An error occurred while receiving HTTP upload data.");
|
769
|
-
}
|
770
1036
|
|
771
1037
|
if (contentLength != NULL && ftell(tempFile->handle) != atol(contentLength)) {
|
772
1038
|
throw IOException("The HTTP client sent incomplete upload data.");
|
@@ -791,23 +1057,20 @@ private:
|
|
791
1057
|
char buf[1024 * 32];
|
792
1058
|
apr_off_t len;
|
793
1059
|
|
794
|
-
while ((len =
|
1060
|
+
while ((len = readRequestBodyFromApache(r, buf, sizeof(buf))) > 0) {
|
795
1061
|
session->sendBodyBlock(buf, len);
|
796
1062
|
}
|
797
|
-
if (len == -1) {
|
798
|
-
throw IOException("An error occurred while receiving HTTP upload data.");
|
799
|
-
}
|
800
1063
|
}
|
801
1064
|
|
802
1065
|
public:
|
803
|
-
Hooks(apr_pool_t *pconf, apr_pool_t *plog, apr_pool_t *ptemp, server_rec *s)
|
1066
|
+
Hooks(apr_pool_t *pconf, apr_pool_t *plog, apr_pool_t *ptemp, server_rec *s)
|
1067
|
+
: cstat(1024) {
|
804
1068
|
passenger_config_merge_all_servers(pconf, s);
|
805
1069
|
ServerConfig *config = getServerConfig(s);
|
806
1070
|
Passenger::setLogLevel(config->logLevel);
|
807
1071
|
m_hasModRewrite = UNKNOWN;
|
808
1072
|
m_hasModDir = UNKNOWN;
|
809
1073
|
m_hasModAutoIndex = UNKNOWN;
|
810
|
-
mstat = cached_multi_file_stat_new(1024);
|
811
1074
|
|
812
1075
|
P_DEBUG("Initializing Phusion Passenger...");
|
813
1076
|
ap_add_version_component(pconf, "Phusion_Passenger/" PASSENGER_VERSION);
|
@@ -823,11 +1086,9 @@ public:
|
|
823
1086
|
* of the process in which the Hooks constructor was called for
|
824
1087
|
* the second time.
|
825
1088
|
*/
|
826
|
-
unsetenv("TMPDIR");
|
827
1089
|
createPassengerTempDir(config->getTempDir(), config->userSwitching,
|
828
1090
|
config->getDefaultUser(), unixd_config.user_id,
|
829
1091
|
unixd_config.group_id);
|
830
|
-
setenv("TMPDIR", (getPassengerTempDir() + "/var").c_str(), 1);
|
831
1092
|
|
832
1093
|
ruby = (config->ruby != NULL) ? config->ruby : DEFAULT_RUBY_COMMAND;
|
833
1094
|
if (config->userSwitching) {
|
@@ -873,7 +1134,6 @@ public:
|
|
873
1134
|
}
|
874
1135
|
|
875
1136
|
~Hooks() {
|
876
|
-
cached_multi_file_stat_free(mstat);
|
877
1137
|
removeDirTree(getPassengerTempDir().c_str());
|
878
1138
|
}
|
879
1139
|
|