passenger 2.0.6 → 2.1.2
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 +10 -4
- data/LICENSE +1 -1
- data/NEWS +0 -0
- data/Rakefile +183 -117
- data/benchmark/dispatcher.rb +5 -9
- data/bin/passenger-install-apache2-module +52 -18
- data/bin/passenger-memory-stats +67 -13
- data/bin/passenger-spawn-server +8 -4
- data/bin/passenger-status +21 -46
- data/bin/passenger-stress-test +5 -5
- data/debian/postinst +1 -1
- data/doc/ApplicationPool algorithm.txt +180 -128
- data/doc/Architectural overview.html +1 -778
- data/doc/Security of user switching support.html +1 -643
- data/doc/Users guide Apache.html +3127 -0
- data/doc/Users guide Nginx.html +1458 -0
- data/doc/Users guide.html +1404 -467
- data/doc/Users guide.txt +843 -105
- data/doc/cxxapi/ApplicationPoolServer_8h-source.html +751 -641
- data/doc/cxxapi/ApplicationPool_8h-source.html +168 -171
- data/doc/cxxapi/Application_8h-source.html +494 -394
- data/doc/cxxapi/Bucket_8h-source.html +21 -15
- data/doc/cxxapi/CachedFileStat_8h-source.html +191 -0
- data/doc/cxxapi/Configuration_8h-source.html +311 -149
- data/doc/cxxapi/DirectoryMapper_8h-source.html +309 -0
- data/doc/cxxapi/DummySpawnManager_8h-source.html +3 -4
- data/doc/cxxapi/Exceptions_8h-source.html +182 -165
- data/doc/cxxapi/FileChecker_8h-source.html +130 -0
- data/doc/cxxapi/Hooks_8h-source.html +2 -3
- data/doc/cxxapi/Logging_8h-source.html +92 -89
- data/doc/cxxapi/MessageChannel_8h-source.html +585 -477
- data/doc/cxxapi/PoolOptions_8h-source.html +305 -0
- data/doc/cxxapi/SpawnManager_8h-source.html +515 -540
- data/doc/cxxapi/StandardApplicationPool_8h-source.html +779 -679
- data/doc/cxxapi/SystemTime_8h-source.html +104 -0
- data/doc/cxxapi/Utils_8h-source.html +331 -227
- data/doc/cxxapi/annotated.html +6 -7
- data/doc/cxxapi/classClient-members.html +1 -2
- data/doc/cxxapi/classClient.html +1 -2
- data/doc/cxxapi/classHooks-members.html +5 -2
- data/doc/cxxapi/classHooks.html +112 -2
- data/doc/cxxapi/classPassenger_1_1Application-members.html +2 -3
- data/doc/cxxapi/classPassenger_1_1Application.html +8 -9
- data/doc/cxxapi/classPassenger_1_1ApplicationPool-members.html +4 -4
- data/doc/cxxapi/classPassenger_1_1ApplicationPool.html +42 -81
- data/doc/cxxapi/classPassenger_1_1ApplicationPoolServer-members.html +1 -2
- data/doc/cxxapi/classPassenger_1_1ApplicationPoolServer.html +3 -4
- data/doc/cxxapi/classPassenger_1_1ApplicationPool__inherit__graph.png +0 -0
- data/doc/cxxapi/classPassenger_1_1Application_1_1Session-members.html +3 -2
- data/doc/cxxapi/classPassenger_1_1Application_1_1Session.html +74 -3
- data/doc/cxxapi/classPassenger_1_1BusyException-members.html +1 -2
- data/doc/cxxapi/classPassenger_1_1BusyException.html +2 -3
- data/doc/cxxapi/classPassenger_1_1ConfigurationException-members.html +1 -2
- data/doc/cxxapi/classPassenger_1_1ConfigurationException.html +2 -3
- data/doc/cxxapi/classPassenger_1_1DirectoryMapper-members.html +38 -0
- data/doc/cxxapi/classPassenger_1_1DirectoryMapper.html +256 -0
- data/doc/cxxapi/classPassenger_1_1DummySpawnManager-members.html +1 -2
- data/doc/cxxapi/classPassenger_1_1DummySpawnManager.html +2 -3
- data/doc/cxxapi/{classPassenger_1_1Thread-members.html → classPassenger_1_1FileChecker-members.html} +4 -5
- data/doc/cxxapi/classPassenger_1_1FileChecker.html +121 -0
- data/doc/cxxapi/classPassenger_1_1FileNotFoundException-members.html +1 -2
- data/doc/cxxapi/classPassenger_1_1FileNotFoundException.html +2 -3
- data/doc/cxxapi/classPassenger_1_1FileNotFoundException__inherit__graph.png +0 -0
- data/doc/cxxapi/classPassenger_1_1FileSystemException-members.html +2 -3
- data/doc/cxxapi/classPassenger_1_1FileSystemException.html +2 -3
- data/doc/cxxapi/classPassenger_1_1FileSystemException__inherit__graph.png +0 -0
- data/doc/cxxapi/classPassenger_1_1IOException-members.html +1 -2
- data/doc/cxxapi/classPassenger_1_1IOException.html +2 -3
- data/doc/cxxapi/classPassenger_1_1IOException__inherit__graph.png +0 -0
- data/doc/cxxapi/classPassenger_1_1MessageChannel-members.html +5 -2
- data/doc/cxxapi/classPassenger_1_1MessageChannel.html +155 -5
- data/doc/cxxapi/{classboost_1_1this__thread_1_1enable__syscall__interruption-members.html → classPassenger_1_1RuntimeException-members.html} +2 -3
- data/doc/cxxapi/{classboost_1_1this__thread_1_1enable__syscall__interruption.html → classPassenger_1_1RuntimeException.html} +10 -8
- data/doc/cxxapi/classPassenger_1_1SpawnException-members.html +1 -2
- data/doc/cxxapi/classPassenger_1_1SpawnException.html +2 -3
- data/doc/cxxapi/classPassenger_1_1SpawnManager-members.html +2 -3
- data/doc/cxxapi/classPassenger_1_1SpawnManager.html +15 -56
- data/doc/cxxapi/classPassenger_1_1StandardApplicationPool-members.html +5 -4
- data/doc/cxxapi/classPassenger_1_1StandardApplicationPool.html +20 -81
- data/doc/cxxapi/classPassenger_1_1StandardApplicationPool__inherit__graph.png +0 -0
- data/doc/cxxapi/classPassenger_1_1SystemException-members.html +2 -3
- data/doc/cxxapi/classPassenger_1_1SystemException.html +9 -10
- data/doc/cxxapi/classPassenger_1_1SystemException__inherit__graph.png +0 -0
- data/doc/cxxapi/{classboost_1_1this__thread_1_1disable__syscall__interruption-members.html → classPassenger_1_1SystemTime-members.html} +5 -3
- data/doc/cxxapi/classPassenger_1_1SystemTime.html +86 -0
- data/doc/cxxapi/classPassenger_1_1TempFile-members.html +2 -3
- data/doc/cxxapi/classPassenger_1_1TempFile.html +17 -9
- data/doc/cxxapi/definitions_8h-source.html +1 -2
- data/doc/cxxapi/files.html +6 -3
- data/doc/cxxapi/functions.html +98 -35
- data/doc/cxxapi/functions_func.html +60 -32
- data/doc/cxxapi/functions_type.html +1 -2
- data/doc/cxxapi/functions_vars.html +27 -2
- data/doc/cxxapi/graph_legend.html +1 -2
- data/doc/cxxapi/graph_legend.png +0 -0
- data/doc/cxxapi/group__Configuration.html +3 -4
- data/doc/cxxapi/group__Configuration.png +0 -0
- data/doc/cxxapi/group__Core.html +3 -4
- data/doc/cxxapi/group__Core.png +0 -0
- data/doc/cxxapi/group__Exceptions.html +4 -2
- data/doc/cxxapi/group__Hooks.html +1 -6
- data/doc/cxxapi/group__Hooks.png +0 -0
- data/doc/cxxapi/group__Support.html +259 -36
- data/doc/cxxapi/hierarchy.html +6 -7
- data/doc/cxxapi/inherit__graph__0.map +1 -1
- data/doc/cxxapi/inherit__graph__0.md5 +1 -1
- data/doc/cxxapi/inherit__graph__0.png +0 -0
- data/doc/cxxapi/inherit__graph__1.map +1 -1
- data/doc/cxxapi/inherit__graph__1.md5 +1 -1
- data/doc/cxxapi/inherit__graph__1.png +0 -0
- data/doc/cxxapi/inherit__graph__10.map +1 -1
- data/doc/cxxapi/inherit__graph__10.md5 +1 -1
- data/doc/cxxapi/inherit__graph__10.png +0 -0
- data/doc/cxxapi/inherit__graph__11.map +1 -1
- data/doc/cxxapi/inherit__graph__11.md5 +1 -1
- data/doc/cxxapi/inherit__graph__11.png +0 -0
- data/doc/cxxapi/inherit__graph__12.map +2 -1
- data/doc/cxxapi/inherit__graph__12.md5 +1 -1
- data/doc/cxxapi/inherit__graph__12.png +0 -0
- data/doc/cxxapi/inherit__graph__13.map +1 -1
- data/doc/cxxapi/inherit__graph__13.md5 +1 -1
- data/doc/cxxapi/inherit__graph__13.png +0 -0
- data/doc/cxxapi/inherit__graph__14.map +1 -2
- data/doc/cxxapi/inherit__graph__14.md5 +1 -1
- data/doc/cxxapi/inherit__graph__14.png +0 -0
- data/doc/cxxapi/inherit__graph__15.map +1 -1
- data/doc/cxxapi/inherit__graph__15.md5 +1 -1
- data/doc/cxxapi/inherit__graph__15.png +0 -0
- data/doc/cxxapi/inherit__graph__16.map +1 -1
- data/doc/cxxapi/inherit__graph__16.md5 +1 -1
- data/doc/cxxapi/inherit__graph__16.png +0 -0
- data/doc/cxxapi/inherit__graph__17.png +0 -0
- data/doc/cxxapi/inherit__graph__18.png +0 -0
- data/doc/cxxapi/inherit__graph__19.png +0 -0
- data/doc/cxxapi/inherit__graph__2.map +1 -1
- data/doc/cxxapi/inherit__graph__2.md5 +1 -1
- data/doc/cxxapi/inherit__graph__2.png +0 -0
- data/doc/cxxapi/inherit__graph__20.map +1 -1
- data/doc/cxxapi/inherit__graph__20.md5 +1 -1
- data/doc/cxxapi/inherit__graph__20.png +0 -0
- data/doc/cxxapi/inherit__graph__21.map +1 -1
- data/doc/cxxapi/inherit__graph__21.md5 +1 -1
- data/doc/cxxapi/inherit__graph__21.png +0 -0
- data/doc/cxxapi/inherit__graph__3.map +1 -1
- data/doc/cxxapi/inherit__graph__3.md5 +1 -1
- data/doc/cxxapi/inherit__graph__3.png +0 -0
- data/doc/cxxapi/inherit__graph__4.map +1 -1
- data/doc/cxxapi/inherit__graph__4.md5 +1 -1
- data/doc/cxxapi/inherit__graph__4.png +0 -0
- data/doc/cxxapi/inherit__graph__5.map +2 -1
- data/doc/cxxapi/inherit__graph__5.md5 +1 -1
- data/doc/cxxapi/inherit__graph__5.png +0 -0
- data/doc/cxxapi/inherit__graph__6.map +1 -1
- data/doc/cxxapi/inherit__graph__6.md5 +1 -1
- data/doc/cxxapi/inherit__graph__6.png +0 -0
- data/doc/cxxapi/inherit__graph__7.map +1 -1
- data/doc/cxxapi/inherit__graph__7.md5 +1 -1
- data/doc/cxxapi/inherit__graph__7.png +0 -0
- data/doc/cxxapi/inherit__graph__8.map +1 -1
- data/doc/cxxapi/inherit__graph__8.md5 +1 -1
- data/doc/cxxapi/inherit__graph__8.png +0 -0
- data/doc/cxxapi/inherit__graph__9.map +1 -2
- data/doc/cxxapi/inherit__graph__9.md5 +1 -1
- data/doc/cxxapi/inherit__graph__9.png +0 -0
- data/doc/cxxapi/inherits.html +30 -31
- data/doc/cxxapi/main.html +1 -2
- data/doc/cxxapi/modules.html +1 -2
- data/doc/cxxapi/structPassenger_1_1AnythingToString-members.html +1 -2
- data/doc/cxxapi/structPassenger_1_1AnythingToString.html +2 -3
- data/doc/cxxapi/structPassenger_1_1AnythingToString_3_01vector_3_01string_01_4_01_4-members.html +1 -2
- data/doc/cxxapi/structPassenger_1_1AnythingToString_3_01vector_3_01string_01_4_01_4.html +2 -3
- data/doc/cxxapi/structPassenger_1_1PoolOptions-members.html +49 -0
- data/doc/cxxapi/structPassenger_1_1PoolOptions.html +404 -0
- data/doc/cxxapi/tree.html +18 -20
- data/doc/images/conservative_spawning.png +0 -0
- data/doc/images/conservative_spawning.svg +248 -0
- data/doc/images/smart-lv2.png +0 -0
- data/doc/images/smart-lv2.svg +320 -0
- data/doc/rdoc/classes/ConditionVariable.html +68 -34
- data/doc/rdoc/classes/Exception.html +16 -16
- data/doc/rdoc/classes/GC.html +9 -9
- data/doc/rdoc/classes/IO.html +36 -17
- data/doc/rdoc/classes/PhusionPassenger.html +183 -0
- data/doc/rdoc/classes/PhusionPassenger/AbstractRequestHandler.html +511 -0
- data/doc/rdoc/classes/{Passenger → PhusionPassenger}/AbstractServer.html +285 -242
- data/doc/rdoc/classes/{Passenger → PhusionPassenger}/AbstractServer/ServerAlreadyStarted.html +3 -3
- data/doc/rdoc/classes/{Passenger → PhusionPassenger}/AbstractServer/ServerError.html +3 -3
- data/doc/rdoc/classes/{Passenger → PhusionPassenger}/AbstractServer/ServerNotStarted.html +3 -3
- data/doc/rdoc/classes/{Passenger → PhusionPassenger}/AbstractServer/UnknownMessage.html +3 -3
- 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 +247 -0
- data/doc/rdoc/classes/PhusionPassenger/AdminTools/ControlProcess/Instance.html +138 -0
- data/doc/rdoc/classes/{Passenger → PhusionPassenger}/AppInitError.html +36 -19
- data/doc/rdoc/classes/{Passenger → PhusionPassenger}/Application.html +81 -96
- data/doc/rdoc/classes/{Passenger → PhusionPassenger}/ConsoleTextTemplate.html +18 -18
- data/doc/rdoc/classes/{Passenger → PhusionPassenger}/FrameworkInitError.html +20 -18
- data/doc/rdoc/classes/{Passenger → PhusionPassenger}/HTMLTemplate.html +18 -18
- data/doc/rdoc/classes/{Passenger → PhusionPassenger}/InitializationError.html +9 -9
- data/doc/rdoc/classes/PhusionPassenger/InvalidPath.html +92 -0
- data/doc/rdoc/classes/{Passenger → PhusionPassenger}/MessageChannel.html +93 -92
- data/doc/rdoc/classes/{Passenger → PhusionPassenger}/NativeSupport.html +55 -25
- data/doc/rdoc/classes/PhusionPassenger/Rack.html +91 -0
- data/doc/rdoc/classes/PhusionPassenger/Rack/ApplicationSpawner.html +185 -0
- data/doc/rdoc/classes/PhusionPassenger/Rack/RequestHandler.html +182 -0
- data/doc/rdoc/classes/PhusionPassenger/Railz.html +95 -0
- data/doc/rdoc/classes/PhusionPassenger/Railz/ApplicationSpawner.html +424 -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 +444 -0
- data/doc/rdoc/classes/PhusionPassenger/Railz/FrameworkSpawner/Error.html +98 -0
- data/doc/rdoc/classes/PhusionPassenger/Railz/RequestHandler.html +154 -0
- data/doc/rdoc/classes/PhusionPassenger/SpawnManager.html +408 -0
- data/doc/rdoc/classes/{Passenger → PhusionPassenger}/UnknownError.html +13 -13
- data/doc/rdoc/classes/PhusionPassenger/Utils.html +687 -0
- data/doc/rdoc/classes/{Passenger → PhusionPassenger}/VersionNotFound.html +8 -8
- 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 +663 -159
- data/doc/rdoc/classes/RakeExtensions.html +4 -4
- data/doc/rdoc/classes/Signal.html +134 -0
- data/doc/rdoc/created.rid +1 -1
- data/doc/rdoc/files/DEVELOPERS_TXT.html +15 -10
- data/doc/rdoc/files/README.html +5 -7
- data/doc/rdoc/files/ext/{passenger → phusion_passenger}/native_support_c.html +2 -2
- data/doc/rdoc/files/lib/{passenger → phusion_passenger}/abstract_request_handler_rb.html +7 -9
- data/doc/rdoc/files/lib/phusion_passenger/abstract_server_collection_rb.html +120 -0
- data/doc/rdoc/files/lib/{passenger → phusion_passenger}/abstract_server_rb.html +7 -10
- data/doc/rdoc/files/lib/phusion_passenger/admin_tools/control_process_rb.html +99 -0
- data/doc/rdoc/files/lib/phusion_passenger/admin_tools_rb.html +92 -0
- data/doc/rdoc/files/lib/{passenger → phusion_passenger}/application_rb.html +6 -8
- data/doc/rdoc/files/lib/{passenger → phusion_passenger}/console_text_template_rb.html +5 -7
- data/doc/rdoc/files/lib/{passenger → phusion_passenger}/constants_rb.html +4 -5
- data/doc/rdoc/files/lib/{passenger → phusion_passenger}/dependencies_rb.html +6 -8
- data/doc/rdoc/files/lib/phusion_passenger/events_rb.html +116 -0
- data/doc/rdoc/files/lib/{passenger → phusion_passenger}/exceptions_rb.html +5 -7
- data/doc/rdoc/files/lib/{passenger → phusion_passenger}/html_template_rb.html +5 -7
- data/doc/rdoc/files/lib/{passenger → phusion_passenger}/message_channel_rb.html +5 -7
- data/doc/rdoc/files/lib/{passenger → phusion_passenger}/platform_info_rb.html +6 -7
- data/doc/rdoc/files/lib/phusion_passenger/rack/application_spawner_rb.html +123 -0
- data/doc/rdoc/files/lib/phusion_passenger/rack/request_handler_rb.html +117 -0
- data/doc/rdoc/files/lib/{passenger/utils_rb.html → phusion_passenger/railz/application_spawner_rb.html} +24 -17
- 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 +139 -0
- data/doc/rdoc/files/lib/phusion_passenger/railz/request_handler_rb.html +118 -0
- data/doc/rdoc/files/lib/{passenger → phusion_passenger}/simple_benchmarking_rb.html +5 -7
- data/doc/rdoc/files/lib/{passenger → phusion_passenger}/spawn_manager_rb.html +40 -24
- data/doc/rdoc/files/lib/phusion_passenger/utils_rb.html +169 -0
- data/doc/rdoc/files/lib/phusion_passenger/wsgi/application_spawner_rb.html +120 -0
- data/doc/rdoc/files/lib/rake/extensions_rb.html +3 -4
- data/doc/rdoc/fr_class_index.html +37 -19
- data/doc/rdoc/fr_file_index.html +25 -14
- data/doc/rdoc/fr_method_index.html +145 -74
- data/ext/apache2/Application.h +145 -44
- data/ext/apache2/ApplicationPool.h +27 -29
- data/ext/apache2/ApplicationPoolServer.h +183 -72
- data/ext/apache2/ApplicationPoolServerExecutable.cpp +249 -42
- data/ext/apache2/Bucket.cpp +61 -9
- data/ext/apache2/Bucket.h +15 -8
- data/ext/apache2/CachedFileStat.cpp +114 -0
- data/ext/apache2/CachedFileStat.h +169 -0
- data/ext/apache2/Configuration.cpp +213 -22
- data/ext/apache2/Configuration.h +176 -13
- data/ext/apache2/DirectoryMapper.h +287 -0
- data/ext/apache2/Exceptions.h +30 -12
- data/ext/apache2/FileChecker.h +108 -0
- data/ext/apache2/Hooks.cpp +709 -493
- data/ext/apache2/LICENSE-CNRI.TXT +15 -0
- data/ext/apache2/Logging.h +26 -22
- data/ext/apache2/MessageChannel.h +124 -15
- data/ext/apache2/PoolOptions.h +283 -0
- data/ext/apache2/SpawnManager.h +75 -99
- data/ext/apache2/StandardApplicationPool.h +296 -195
- data/ext/apache2/SystemTime.cpp +28 -0
- data/ext/apache2/SystemTime.h +82 -0
- data/ext/apache2/Utils.cpp +172 -18
- data/ext/apache2/Utils.h +124 -19
- data/ext/boost/cstdint.hpp +4 -2
- data/ext/boost/current_function.hpp +67 -0
- data/ext/boost/detail/sp_counted_base.hpp +4 -4
- data/ext/boost/thread/exceptions.hpp +2 -1
- data/ext/boost/thread/pthread/thread.hpp +11 -3
- data/ext/boost/thread/pthread/thread_data.hpp +2 -1
- data/ext/oxt/backtrace.cpp +172 -0
- data/ext/oxt/backtrace.hpp +135 -0
- data/ext/oxt/detail/backtrace_disabled.hpp +39 -0
- data/ext/oxt/detail/backtrace_enabled.hpp +155 -0
- data/ext/oxt/detail/spin_lock_gcc_x86.hpp +82 -0
- data/ext/oxt/detail/spin_lock_portable.hpp +38 -0
- data/ext/oxt/detail/spin_lock_pthreads.hpp +97 -0
- data/ext/oxt/detail/tracable_exception_disabled.hpp +46 -0
- data/ext/oxt/detail/tracable_exception_enabled.hpp +48 -0
- data/ext/oxt/macros.hpp +58 -0
- data/ext/oxt/spin_lock.hpp +55 -0
- data/ext/{apache2/System.cpp → oxt/system_calls.cpp} +87 -52
- data/ext/oxt/system_calls.hpp +234 -0
- data/ext/oxt/thread.cpp +32 -0
- data/ext/oxt/thread.hpp +223 -0
- data/ext/oxt/tracable_exception.cpp +87 -0
- data/ext/oxt/tracable_exception.hpp +35 -0
- data/{lib/passenger/constants.rb → ext/phusion_passenger/extconf.rb} +14 -9
- data/ext/{passenger → phusion_passenger}/native_support.c +33 -6
- data/lib/{passenger → phusion_passenger}/abstract_request_handler.rb +209 -93
- data/lib/{passenger → phusion_passenger}/abstract_server.rb +23 -8
- data/lib/phusion_passenger/abstract_server_collection.rb +301 -0
- data/lib/phusion_passenger/admin_tools.rb +25 -0
- data/lib/phusion_passenger/admin_tools/control_process.rb +107 -0
- data/lib/{passenger → phusion_passenger}/application.rb +13 -16
- data/lib/{passenger → phusion_passenger}/console_text_template.rb +2 -2
- data/{ext/passenger/extconf.rb → lib/phusion_passenger/constants.rb} +5 -5
- data/lib/{passenger → phusion_passenger}/dependencies.rb +38 -32
- data/lib/phusion_passenger/events.rb +45 -0
- data/lib/{passenger → phusion_passenger}/exceptions.rb +12 -5
- data/lib/{passenger → phusion_passenger}/html_template.rb +2 -2
- data/lib/{passenger → phusion_passenger}/message_channel.rb +3 -2
- data/lib/phusion_passenger/platform_info.rb +500 -0
- data/lib/{passenger → phusion_passenger}/rack/application_spawner.rb +29 -22
- data/lib/{passenger → phusion_passenger}/rack/request_handler.rb +14 -9
- data/lib/{passenger → phusion_passenger}/railz/application_spawner.rb +94 -74
- data/lib/{passenger → phusion_passenger}/railz/cgi_fixed.rb +2 -2
- data/lib/{passenger → phusion_passenger}/railz/framework_spawner.rb +86 -98
- data/lib/{passenger → phusion_passenger}/railz/request_handler.rb +6 -6
- data/lib/{passenger → phusion_passenger}/simple_benchmarking.rb +0 -0
- data/lib/{passenger → phusion_passenger}/spawn_manager.rb +136 -128
- data/lib/{passenger → phusion_passenger}/templates/apache2_config_snippets.txt.erb +0 -0
- data/lib/{passenger → phusion_passenger}/templates/apache_must_be_compiled_with_compatible_mpm.txt.erb +0 -0
- data/lib/phusion_passenger/templates/app_exited_during_initialization.html.erb +38 -0
- data/lib/{passenger → phusion_passenger}/templates/app_init_error.html.erb +0 -0
- data/lib/{passenger → phusion_passenger}/templates/database_error.html.erb +0 -0
- data/lib/{passenger → phusion_passenger}/templates/deployment_example.txt.erb +1 -1
- data/lib/{passenger → phusion_passenger}/templates/error_layout.css +0 -0
- data/lib/{passenger → phusion_passenger}/templates/error_layout.html.erb +0 -0
- data/lib/{passenger → phusion_passenger}/templates/framework_init_error.html.erb +0 -0
- data/lib/{passenger → phusion_passenger}/templates/general_error.html.erb +0 -0
- data/lib/{passenger → phusion_passenger}/templates/invalid_app_root.html.erb +1 -1
- data/lib/{passenger → phusion_passenger}/templates/load_error.html.erb +0 -0
- data/lib/{passenger → phusion_passenger}/templates/no_write_permission_to_passenger_root.txt.erb +0 -0
- data/lib/{passenger → phusion_passenger}/templates/possible_solutions_for_compilation_and_installation_problems.txt.erb +0 -0
- data/lib/{passenger → phusion_passenger}/templates/run_installer_as_root.txt.erb +0 -0
- data/lib/{passenger → phusion_passenger}/templates/version_not_found.html.erb +0 -0
- data/lib/{passenger → phusion_passenger}/templates/welcome.txt.erb +0 -0
- data/lib/{passenger → phusion_passenger}/utils.rb +210 -44
- data/lib/{passenger → phusion_passenger}/wsgi/application_spawner.rb +18 -15
- data/lib/{passenger → phusion_passenger}/wsgi/request_handler.py +7 -1
- data/man/passenger-memory-stats.8 +1 -1
- data/misc/render_error_pages.rb +1 -1
- data/test/ApplicationPoolServerTest.cpp +0 -28
- data/test/ApplicationPoolServer_ApplicationPoolTest.cpp +4 -0
- data/test/ApplicationPoolTest.cpp +307 -69
- data/test/CachedFileStatTest.cpp +262 -0
- data/test/FileCheckerTest.cpp +79 -0
- data/test/MessageChannelTest.cpp +3 -3
- data/test/PoolOptionsTest.cpp +37 -0
- data/test/SpawnManagerTest.cpp +4 -4
- data/test/StandardApplicationPoolTest.cpp +4 -0
- data/test/SystemTimeTest.cpp +37 -0
- data/test/UtilsTest.cpp +137 -0
- data/test/integration_tests.rb +270 -23
- data/test/oxt/backtrace_test.cpp +128 -0
- data/test/oxt/oxt_test_main.cpp +25 -0
- data/test/oxt/syscall_interruption_test.cpp +50 -0
- data/test/ruby/abstract_request_handler_spec.rb +83 -0
- data/test/ruby/abstract_server_collection_spec.rb +246 -0
- data/test/ruby/application_spec.rb +3 -3
- data/test/ruby/message_channel_spec.rb +2 -2
- data/test/ruby/rack/application_spawner_spec.rb +3 -5
- data/test/ruby/rails/application_spawner_spec.rb +54 -15
- data/test/ruby/rails/framework_spawner_spec.rb +6 -8
- data/test/ruby/rails/minimal_spawner_spec.rb +29 -0
- data/test/ruby/rails/spawner_error_handling_spec.rb +1 -1
- data/test/ruby/rails/spawner_privilege_lowering_spec.rb +3 -3
- data/test/ruby/spawn_manager_spec.rb +23 -12
- data/test/ruby/utils_spec.rb +36 -2
- data/test/ruby/wsgi/application_spawner_spec.rb +47 -0
- data/test/stub/apache2/httpd.conf.erb +3 -5
- data/test/stub/message_channel.rb +2 -2
- data/test/stub/message_channel_2.rb +2 -2
- data/test/stub/message_channel_3.rb +3 -3
- data/test/stub/minimal-railsapp/README +0 -0
- data/test/stub/minimal-railsapp/config/application.rb +0 -0
- data/test/stub/minimal-railsapp/config/environment.rb +0 -0
- 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 -0
- 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 -0
- 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 -0
- 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 -0
- data/test/stub/minimal-railsapp/vendor/rails/railties/lib/ruby_version_check.rb +0 -0
- data/test/stub/rails_apps/foobar/app/controllers/foo_controller.rb +8 -0
- data/test/stub/rails_apps/foobar/config/environments/development.rb +1 -2
- data/test/stub/rails_apps/mycook/app/controllers/welcome_controller.rb +21 -1
- data/test/stub/rails_apps/mycook/sites/some.site/public/uploads.html +26 -0
- data/test/stub/rails_apps/mycook/sites/some.site/public/welcome/cached.html +26 -0
- data/test/stub/railsapp/app/controllers/application.rb +0 -0
- data/test/stub/railsapp/app/controllers/bar_controller_1.rb +0 -0
- data/test/stub/railsapp/app/controllers/bar_controller_2.rb +1 -1
- data/test/stub/railsapp/app/controllers/foo_controller.rb +4 -0
- data/test/stub/railsapp/app/helpers/application_helper.rb +0 -0
- data/test/stub/railsapp/config/boot.rb +0 -0
- data/test/stub/railsapp/config/database.yml +0 -0
- data/test/stub/railsapp/config/environment.rb +0 -0
- data/test/stub/railsapp/config/environments/development.rb +0 -0
- data/test/stub/railsapp/config/environments/production.rb +0 -0
- data/test/stub/railsapp/config/initializers/inflections.rb +0 -0
- data/test/stub/railsapp/config/initializers/mime_types.rb +0 -0
- data/test/stub/railsapp/config/routes.rb +0 -0
- data/test/stub/railsapp/public/useless.txt +0 -0
- data/test/stub/spawn_server.rb +3 -4
- data/test/stub/wsgi/passenger_wsgi.pyc +0 -0
- data/test/support/apache2_controller.rb +57 -7
- data/test/support/tut.h +15 -0
- data/vendor/README +12 -0
- data/vendor/README_FOR_PACKAGERS +1 -0
- data/vendor/rack-0.9.1/AUTHORS +8 -0
- data/vendor/rack-0.9.1/COPYING +18 -0
- data/vendor/rack-0.9.1/ChangeLog +1423 -0
- data/vendor/rack-0.9.1/KNOWN-ISSUES +18 -0
- data/vendor/rack-0.9.1/README +306 -0
- data/vendor/rack-0.9.1/Rakefile +188 -0
- data/vendor/rack-0.9.1/SPEC +129 -0
- data/vendor/rack-0.9.1/lib/rack.rb +86 -0
- data/vendor/rack-0.9.1/lib/rack/adapter/camping.rb +22 -0
- data/vendor/rack-0.9.1/lib/rack/auth/abstract/handler.rb +28 -0
- data/vendor/rack-0.9.1/lib/rack/auth/abstract/request.rb +37 -0
- data/vendor/rack-0.9.1/lib/rack/auth/basic.rb +58 -0
- data/vendor/rack-0.9.1/lib/rack/auth/digest/md5.rb +124 -0
- data/vendor/rack-0.9.1/lib/rack/auth/digest/nonce.rb +51 -0
- data/vendor/rack-0.9.1/lib/rack/auth/digest/params.rb +55 -0
- data/vendor/rack-0.9.1/lib/rack/auth/digest/request.rb +40 -0
- data/vendor/rack-0.9.1/lib/rack/auth/openid.rb +438 -0
- data/vendor/rack-0.9.1/lib/rack/builder.rb +67 -0
- data/vendor/rack-0.9.1/lib/rack/cascade.rb +36 -0
- data/vendor/rack-0.9.1/lib/rack/commonlogger.rb +61 -0
- data/vendor/rack-0.9.1/lib/rack/conditionalget.rb +43 -0
- data/vendor/rack-0.9.1/lib/rack/content_length.rb +25 -0
- data/vendor/rack-0.9.1/lib/rack/deflater.rb +87 -0
- data/vendor/rack-0.9.1/lib/rack/directory.rb +150 -0
- data/vendor/rack-0.9.1/lib/rack/file.rb +85 -0
- data/vendor/rack-0.9.1/lib/rack/handler.rb +48 -0
- data/vendor/rack-0.9.1/lib/rack/handler/cgi.rb +57 -0
- data/vendor/rack-0.9.1/lib/rack/handler/evented_mongrel.rb +8 -0
- data/vendor/rack-0.9.1/lib/rack/handler/fastcgi.rb +86 -0
- data/vendor/rack-0.9.1/lib/rack/handler/lsws.rb +52 -0
- data/vendor/rack-0.9.1/lib/rack/handler/mongrel.rb +82 -0
- data/vendor/rack-0.9.1/lib/rack/handler/scgi.rb +57 -0
- data/vendor/rack-0.9.1/lib/rack/handler/swiftiplied_mongrel.rb +8 -0
- data/vendor/rack-0.9.1/lib/rack/handler/thin.rb +15 -0
- data/vendor/rack-0.9.1/lib/rack/handler/webrick.rb +61 -0
- data/vendor/rack-0.9.1/lib/rack/head.rb +19 -0
- data/vendor/rack-0.9.1/lib/rack/lint.rb +465 -0
- data/vendor/rack-0.9.1/lib/rack/lobster.rb +65 -0
- data/vendor/rack-0.9.1/lib/rack/methodoverride.rb +27 -0
- data/vendor/rack-0.9.1/lib/rack/mime.rb +204 -0
- data/vendor/rack-0.9.1/lib/rack/mock.rb +160 -0
- data/vendor/rack-0.9.1/lib/rack/recursive.rb +57 -0
- data/vendor/rack-0.9.1/lib/rack/reloader.rb +64 -0
- data/vendor/rack-0.9.1/lib/rack/request.rb +218 -0
- data/vendor/rack-0.9.1/lib/rack/response.rb +171 -0
- data/vendor/rack-0.9.1/lib/rack/session/abstract/id.rb +153 -0
- data/vendor/rack-0.9.1/lib/rack/session/cookie.rb +89 -0
- data/vendor/rack-0.9.1/lib/rack/session/memcache.rb +97 -0
- data/vendor/rack-0.9.1/lib/rack/session/pool.rb +73 -0
- data/vendor/rack-0.9.1/lib/rack/showexceptions.rb +348 -0
- data/vendor/rack-0.9.1/lib/rack/showstatus.rb +106 -0
- data/vendor/rack-0.9.1/lib/rack/static.rb +38 -0
- data/vendor/rack-0.9.1/lib/rack/urlmap.rb +48 -0
- data/vendor/rack-0.9.1/lib/rack/utils.rb +347 -0
- metadata +1197 -1055
- data/doc/cxxapi/System_8h-source.html +0 -251
- data/doc/cxxapi/classDirectoryMapper-members.html +0 -38
- data/doc/cxxapi/classDirectoryMapper.html +0 -203
- data/doc/cxxapi/classPassenger_1_1Thread.html +0 -100
- data/doc/cxxapi/classboost_1_1this__thread_1_1disable__syscall__interruption.html +0 -46
- data/doc/cxxapi/classboost_1_1this__thread_1_1restore__syscall__interruption-members.html +0 -33
- data/doc/cxxapi/classboost_1_1this__thread_1_1restore__syscall__interruption.html +0 -44
- data/doc/cxxapi/namespacePassenger.html +0 -208
- data/doc/cxxapi/namespacePassenger_1_1InterruptableCalls.html +0 -43
- data/doc/cxxapi/namespacemembers.html +0 -70
- data/doc/cxxapi/namespacemembers_func.html +0 -66
- data/doc/cxxapi/namespacemembers_type.html +0 -46
- data/doc/cxxapi/namespaces.html +0 -35
- data/doc/rdoc/classes/Passenger.html +0 -136
- data/doc/rdoc/classes/Passenger/AbstractRequestHandler.html +0 -402
- data/doc/rdoc/classes/Passenger/SpawnManager.html +0 -379
- data/doc/rdoc/classes/Passenger/Utils.html +0 -578
- data/ext/apache2/System.h +0 -228
- data/lib/passenger/platform_info.rb +0 -302
- data/lib/passenger/templates/app_exited_during_initialization.html.erb +0 -19
- data/test/stub/apache2/httpd.conf +0 -75
- data/test/stub/rails_apps/foobar/config/environments/test.rb +0 -22
- data/test/stub/rails_apps/mycook/config/environments/test.rb +0 -22
- data/test/stub/railsapp/config/environments/test.rb +0 -22
- data/test/stub/railsapp2/config/environments/test.rb +0 -22
data/ext/apache2/Hooks.cpp
CHANGED
@@ -17,18 +17,6 @@
|
|
17
17
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
18
18
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
19
19
|
*/
|
20
|
-
#include <ap_config.h>
|
21
|
-
#include <httpd.h>
|
22
|
-
#include <http_config.h>
|
23
|
-
#include <http_core.h>
|
24
|
-
#include <http_request.h>
|
25
|
-
#include <http_protocol.h>
|
26
|
-
#include <http_log.h>
|
27
|
-
#include <util_script.h>
|
28
|
-
#include <apr_pools.h>
|
29
|
-
#include <apr_strings.h>
|
30
|
-
#include <apr_lib.h>
|
31
|
-
|
32
20
|
#include <boost/thread.hpp>
|
33
21
|
|
34
22
|
#include <sys/time.h>
|
@@ -37,6 +25,7 @@
|
|
37
25
|
#include <cstdio>
|
38
26
|
#include <unistd.h>
|
39
27
|
|
28
|
+
#include <oxt/macros.hpp>
|
40
29
|
#include "Hooks.h"
|
41
30
|
#include "Bucket.h"
|
42
31
|
#include "Configuration.h"
|
@@ -44,17 +33,34 @@
|
|
44
33
|
#include "Logging.h"
|
45
34
|
#include "ApplicationPoolServer.h"
|
46
35
|
#include "MessageChannel.h"
|
47
|
-
#include "
|
36
|
+
#include "DirectoryMapper.h"
|
37
|
+
|
38
|
+
/* The Apache/APR headers *must* come after the Boost headers, otherwise
|
39
|
+
* compilation will fail on OpenBSD.
|
40
|
+
*
|
41
|
+
* apr_want.h *must* come after MessageChannel.h, otherwise compilation will
|
42
|
+
* fail on platforms on which apr_want.h tries to redefine 'struct iovec'.
|
43
|
+
* http://tinyurl.com/b6aatw
|
44
|
+
*/
|
45
|
+
#include <ap_config.h>
|
46
|
+
#include <httpd.h>
|
47
|
+
#include <http_config.h>
|
48
|
+
#include <http_core.h>
|
49
|
+
#include <http_request.h>
|
50
|
+
#include <http_protocol.h>
|
51
|
+
#include <http_log.h>
|
52
|
+
#include <util_script.h>
|
53
|
+
#include <apr_pools.h>
|
54
|
+
#include <apr_strings.h>
|
55
|
+
#include <apr_lib.h>
|
48
56
|
|
49
57
|
using namespace std;
|
50
58
|
using namespace Passenger;
|
51
59
|
|
52
60
|
extern "C" module AP_MODULE_DECLARE_DATA passenger_module;
|
53
61
|
|
62
|
+
|
54
63
|
#define DEFAULT_RUBY_COMMAND "ruby"
|
55
|
-
#define DEFAULT_RAILS_ENV "production"
|
56
|
-
#define DEFAULT_RACK_ENV "production"
|
57
|
-
#define DEFAULT_WSGI_ENV "production"
|
58
64
|
|
59
65
|
/**
|
60
66
|
* If the HTTP client sends POST data larger than this value (in bytes),
|
@@ -65,261 +71,150 @@ extern "C" module AP_MODULE_DECLARE_DATA passenger_module;
|
|
65
71
|
|
66
72
|
|
67
73
|
/**
|
68
|
-
*
|
69
|
-
* Given a URI, it will determine whether that URI belongs to a Rails/Rack
|
70
|
-
* application, what the base URI of that application is, and what the
|
71
|
-
* associated 'public' directory is.
|
74
|
+
* Apache hook functions, wrapped in a class.
|
72
75
|
*
|
73
|
-
* @note This class is not thread-safe, but is reentrant.
|
74
76
|
* @ingroup Core
|
75
77
|
*/
|
76
|
-
class
|
77
|
-
public:
|
78
|
-
enum ApplicationType {
|
79
|
-
NONE,
|
80
|
-
RAILS,
|
81
|
-
RACK,
|
82
|
-
WSGI
|
83
|
-
};
|
84
|
-
|
78
|
+
class Hooks {
|
85
79
|
private:
|
86
|
-
|
87
|
-
|
88
|
-
bool baseURIKnown;
|
89
|
-
const char *baseURI;
|
90
|
-
ApplicationType appType;
|
91
|
-
|
92
|
-
inline bool shouldAutoDetectRails() {
|
93
|
-
return config->autoDetectRails == DirConfig::ENABLED ||
|
94
|
-
config->autoDetectRails == DirConfig::UNSET;
|
95
|
-
}
|
96
|
-
|
97
|
-
inline bool shouldAutoDetectRack() {
|
98
|
-
return config->autoDetectRack == DirConfig::ENABLED ||
|
99
|
-
config->autoDetectRack == DirConfig::UNSET;
|
100
|
-
}
|
101
|
-
|
102
|
-
inline bool shouldAutoDetectWSGI() {
|
103
|
-
return config->autoDetectWSGI == DirConfig::ENABLED ||
|
104
|
-
config->autoDetectWSGI == DirConfig::UNSET;
|
105
|
-
}
|
106
|
-
|
107
|
-
public:
|
108
|
-
/**
|
109
|
-
* @warning Do not use this object after the destruction of <tt>r</tt> or <tt>config</tt>.
|
110
|
-
*/
|
111
|
-
DirectoryMapper(request_rec *r, DirConfig *config) {
|
112
|
-
this->r = r;
|
113
|
-
this->config = config;
|
114
|
-
appType = NONE;
|
115
|
-
baseURIKnown = false;
|
116
|
-
baseURI = NULL;
|
117
|
-
}
|
118
|
-
|
119
|
-
/**
|
120
|
-
* Determine whether the given HTTP request falls under one of the specified
|
121
|
-
* RailsBaseURIs or RackBaseURIs. If yes, then the first matching base URI will
|
122
|
-
* be returned.
|
123
|
-
*
|
124
|
-
* If Rails/Rack autodetection was enabled in the configuration, and the document
|
125
|
-
* root seems to be a valid Rails/Rack 'public' folder, then this method will
|
126
|
-
* return "/".
|
127
|
-
*
|
128
|
-
* Otherwise, NULL will be returned.
|
129
|
-
*
|
130
|
-
* @throws SystemException An error occured while examening the filesystem.
|
131
|
-
* @warning The return value may only be used as long as <tt>config</tt>
|
132
|
-
* hasn't been destroyed.
|
133
|
-
*/
|
134
|
-
const char *getBaseURI() {
|
135
|
-
if (baseURIKnown) {
|
136
|
-
return baseURI;
|
137
|
-
}
|
138
|
-
|
139
|
-
set<string>::const_iterator it;
|
140
|
-
const char *uri = r->uri;
|
141
|
-
size_t uri_len = strlen(uri);
|
142
|
-
|
143
|
-
if (uri_len == 0 || uri[0] != '/') {
|
144
|
-
baseURIKnown = true;
|
145
|
-
return NULL;
|
146
|
-
}
|
147
|
-
|
148
|
-
for (it = config->railsBaseURIs.begin(); it != config->railsBaseURIs.end(); it++) {
|
149
|
-
const string &base(*it);
|
150
|
-
if ( base == "/"
|
151
|
-
|| ( uri_len == base.size() && memcmp(uri, base.c_str(), uri_len) == 0 )
|
152
|
-
|| ( uri_len > base.size() && memcmp(uri, base.c_str(), base.size()) == 0
|
153
|
-
&& uri[base.size()] == '/' )
|
154
|
-
) {
|
155
|
-
baseURIKnown = true;
|
156
|
-
baseURI = base.c_str();
|
157
|
-
appType = RAILS;
|
158
|
-
return baseURI;
|
159
|
-
}
|
160
|
-
}
|
161
|
-
|
162
|
-
for (it = config->rackBaseURIs.begin(); it != config->rackBaseURIs.end(); it++) {
|
163
|
-
const string &base(*it);
|
164
|
-
if ( base == "/"
|
165
|
-
|| ( uri_len == base.size() && memcmp(uri, base.c_str(), uri_len) == 0 )
|
166
|
-
|| ( uri_len > base.size() && memcmp(uri, base.c_str(), base.size()) == 0
|
167
|
-
&& uri[base.size()] == '/' )
|
168
|
-
) {
|
169
|
-
baseURIKnown = true;
|
170
|
-
baseURI = base.c_str();
|
171
|
-
appType = RACK;
|
172
|
-
return baseURI;
|
173
|
-
}
|
174
|
-
}
|
80
|
+
struct AprDestructable {
|
81
|
+
virtual ~AprDestructable() { }
|
175
82
|
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
appType = RAILS;
|
180
|
-
return baseURI;
|
181
|
-
}
|
182
|
-
if (shouldAutoDetectRack() && verifyRackDir(ap_document_root(r))) {
|
183
|
-
baseURIKnown = true;
|
184
|
-
baseURI = "/";
|
185
|
-
appType = RACK;
|
186
|
-
return baseURI;
|
187
|
-
}
|
188
|
-
if (shouldAutoDetectWSGI() && verifyWSGIDir(ap_document_root(r))) {
|
189
|
-
baseURIKnown = true;
|
190
|
-
baseURI = "/";
|
191
|
-
appType = WSGI;
|
192
|
-
return baseURI;
|
83
|
+
static apr_status_t cleanup(void *p) {
|
84
|
+
delete (AprDestructable *) p;
|
85
|
+
return APR_SUCCESS;
|
193
86
|
}
|
194
|
-
|
195
|
-
baseURIKnown = true;
|
196
|
-
return NULL;
|
197
|
-
}
|
87
|
+
};
|
198
88
|
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
*/
|
208
|
-
string getPublicDirectory() {
|
209
|
-
if (!baseURIKnown) {
|
210
|
-
getBaseURI();
|
211
|
-
}
|
212
|
-
if (baseURI == NULL) {
|
213
|
-
return "";
|
214
|
-
}
|
89
|
+
struct RequestNote: public AprDestructable {
|
90
|
+
DirectoryMapper mapper;
|
91
|
+
DirConfig *config;
|
92
|
+
bool forwardToBackend;
|
93
|
+
const char *handlerBeforeModRewrite;
|
94
|
+
char *filenameBeforeModRewrite;
|
95
|
+
apr_filetype_e oldFileType;
|
96
|
+
const char *handlerBeforeModAutoIndex;
|
215
97
|
|
216
|
-
const
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
if (docRoot[len - 1] == '/') {
|
221
|
-
path.assign(docRoot, len - 1);
|
222
|
-
} else {
|
223
|
-
path.assign(docRoot, len);
|
224
|
-
}
|
225
|
-
if (strcmp(baseURI, "/") != 0) {
|
226
|
-
path.append(baseURI);
|
227
|
-
}
|
228
|
-
return path;
|
229
|
-
} else {
|
230
|
-
return "";
|
98
|
+
RequestNote(const DirectoryMapper &m)
|
99
|
+
: mapper(m) {
|
100
|
+
forwardToBackend = false;
|
101
|
+
filenameBeforeModRewrite = NULL;
|
231
102
|
}
|
232
|
-
}
|
103
|
+
};
|
233
104
|
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
* @throws SystemException An error occured while examening the filesystem.
|
238
|
-
*/
|
239
|
-
ApplicationType getApplicationType() {
|
240
|
-
if (!baseURIKnown) {
|
241
|
-
getBaseURI();
|
242
|
-
}
|
243
|
-
return appType;
|
244
|
-
}
|
105
|
+
struct ErrorReport: public AprDestructable {
|
106
|
+
virtual int report(request_rec *r) = 0;
|
107
|
+
};
|
245
108
|
|
246
|
-
|
247
|
-
|
248
|
-
* with the HTTP request.
|
249
|
-
*
|
250
|
-
* @throws SystemException An error occured while examening the filesystem.
|
251
|
-
*/
|
252
|
-
const char *getApplicationTypeString() {
|
253
|
-
if (!baseURIKnown) {
|
254
|
-
getBaseURI();
|
255
|
-
}
|
256
|
-
switch (appType) {
|
257
|
-
case RAILS:
|
258
|
-
return "rails";
|
259
|
-
case RACK:
|
260
|
-
return "rack";
|
261
|
-
case WSGI:
|
262
|
-
return "wsgi";
|
263
|
-
default:
|
264
|
-
return NULL;
|
265
|
-
};
|
266
|
-
}
|
267
|
-
};
|
268
|
-
|
269
|
-
|
270
|
-
/**
|
271
|
-
* Apache hook functions, wrapped in a class.
|
272
|
-
*
|
273
|
-
* @ingroup Core
|
274
|
-
*/
|
275
|
-
class Hooks {
|
276
|
-
private:
|
277
|
-
struct Container {
|
278
|
-
Application::SessionPtr session;
|
109
|
+
struct ReportFileSystemError: public ErrorReport {
|
110
|
+
FileSystemException e;
|
279
111
|
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
112
|
+
ReportFileSystemError(const FileSystemException &ex): e(ex) { }
|
113
|
+
|
114
|
+
int report(request_rec *r) {
|
115
|
+
ap_set_content_type(r, "text/html; charset=UTF-8");
|
116
|
+
ap_rputs("<h1>Passenger error #2</h1>\n", r);
|
117
|
+
ap_rputs("An error occurred while trying to access '", r);
|
118
|
+
ap_rputs(ap_escape_html(r->pool, e.filename().c_str()), r);
|
119
|
+
ap_rputs("': ", r);
|
120
|
+
ap_rputs(ap_escape_html(r->pool, e.what()), r);
|
121
|
+
if (e.code() == EPERM) {
|
122
|
+
ap_rputs("<p>", r);
|
123
|
+
ap_rputs("Apache doesn't have read permissions to that file. ", r);
|
124
|
+
ap_rputs("Please fix the relevant file permissions.", r);
|
125
|
+
ap_rputs("</p>", r);
|
292
126
|
}
|
293
|
-
|
127
|
+
P_ERROR("A filesystem exception occured.\n" <<
|
128
|
+
" Message: " << e.what() << "\n" <<
|
129
|
+
" Backtrace:\n" << e.backtrace());
|
130
|
+
return OK;
|
294
131
|
}
|
295
132
|
};
|
133
|
+
|
134
|
+
enum Threeway { YES, NO, UNKNOWN };
|
296
135
|
|
297
136
|
ApplicationPoolServerPtr applicationPoolServer;
|
298
137
|
thread_specific_ptr<ApplicationPoolPtr> threadSpecificApplicationPool;
|
138
|
+
Threeway m_hasModRewrite, m_hasModDir, m_hasModAutoIndex;
|
139
|
+
CachedMultiFileStat *mstat;
|
299
140
|
|
300
|
-
DirConfig *getDirConfig(request_rec *r) {
|
141
|
+
inline DirConfig *getDirConfig(request_rec *r) {
|
301
142
|
return (DirConfig *) ap_get_module_config(r->per_dir_config, &passenger_module);
|
302
143
|
}
|
303
144
|
|
304
|
-
ServerConfig *getServerConfig(server_rec *s) {
|
145
|
+
inline ServerConfig *getServerConfig(server_rec *s) {
|
305
146
|
return (ServerConfig *) ap_get_module_config(s->module_config, &passenger_module);
|
306
147
|
}
|
307
148
|
|
149
|
+
inline RequestNote *getRequestNote(request_rec *r) {
|
150
|
+
// The union is needed in order to be compliant with
|
151
|
+
// C99/C++'s strict aliasing rules. http://tinyurl.com/g5hgh
|
152
|
+
union {
|
153
|
+
RequestNote *note;
|
154
|
+
void *pointer;
|
155
|
+
} u;
|
156
|
+
u.note = 0;
|
157
|
+
apr_pool_userdata_get(&u.pointer, "Phusion Passenger", r->pool);
|
158
|
+
return u.note;
|
159
|
+
}
|
160
|
+
|
308
161
|
/**
|
162
|
+
* Returns a usable ApplicationPool object.
|
163
|
+
*
|
309
164
|
* When using the worker MPM and global queuing, deadlocks can occur, for
|
310
165
|
* the same reason described in ApplicationPoolServer::connect(). This
|
311
166
|
* method allows us to avoid this deadlock by making sure that each
|
312
167
|
* thread gets its own connection to the application pool server.
|
168
|
+
*
|
169
|
+
* It also checks whether the currently cached ApplicationPool object
|
170
|
+
* is disconnected (which can happen if an error previously occured).
|
171
|
+
* If so, it will reconnect to the ApplicationPool server.
|
313
172
|
*/
|
314
173
|
ApplicationPoolPtr getApplicationPool() {
|
315
174
|
ApplicationPoolPtr *pool_ptr = threadSpecificApplicationPool.get();
|
316
175
|
if (pool_ptr == NULL) {
|
317
176
|
pool_ptr = new ApplicationPoolPtr(applicationPoolServer->connect());
|
318
177
|
threadSpecificApplicationPool.reset(pool_ptr);
|
178
|
+
} else if (!(*pool_ptr)->connected()) {
|
179
|
+
P_DEBUG("Reconnecting to ApplicationPool server");
|
180
|
+
*pool_ptr = applicationPoolServer->connect();
|
319
181
|
}
|
320
182
|
return *pool_ptr;
|
321
183
|
}
|
322
184
|
|
185
|
+
bool hasModRewrite() {
|
186
|
+
if (m_hasModRewrite == UNKNOWN) {
|
187
|
+
if (ap_find_linked_module("mod_rewrite.c")) {
|
188
|
+
m_hasModRewrite = YES;
|
189
|
+
} else {
|
190
|
+
m_hasModRewrite = NO;
|
191
|
+
}
|
192
|
+
}
|
193
|
+
return m_hasModRewrite == YES;
|
194
|
+
}
|
195
|
+
|
196
|
+
bool hasModDir() {
|
197
|
+
if (m_hasModDir == UNKNOWN) {
|
198
|
+
if (ap_find_linked_module("mod_dir.c")) {
|
199
|
+
m_hasModDir = YES;
|
200
|
+
} else {
|
201
|
+
m_hasModDir = NO;
|
202
|
+
}
|
203
|
+
}
|
204
|
+
return m_hasModDir == YES;
|
205
|
+
}
|
206
|
+
|
207
|
+
bool hasModAutoIndex() {
|
208
|
+
if (m_hasModAutoIndex == UNKNOWN) {
|
209
|
+
if (ap_find_linked_module("mod_autoindex.c")) {
|
210
|
+
m_hasModAutoIndex = YES;
|
211
|
+
} else {
|
212
|
+
m_hasModAutoIndex = NO;
|
213
|
+
}
|
214
|
+
}
|
215
|
+
return m_hasModAutoIndex == YES;
|
216
|
+
}
|
217
|
+
|
323
218
|
int reportDocumentRootDeterminationError(request_rec *r) {
|
324
219
|
ap_set_content_type(r, "text/html; charset=UTF-8");
|
325
220
|
ap_rputs("<h1>Passenger error #1</h1>\n", r);
|
@@ -327,28 +222,322 @@ private:
|
|
327
222
|
return OK;
|
328
223
|
}
|
329
224
|
|
330
|
-
int reportFileSystemError(request_rec *r, const FileSystemException &e) {
|
331
|
-
ap_set_content_type(r, "text/html; charset=UTF-8");
|
332
|
-
ap_rputs("<h1>Passenger error #2</h1>\n", r);
|
333
|
-
ap_rputs("An error occurred while trying to access '", r);
|
334
|
-
ap_rputs(ap_escape_html(r->pool, e.filename().c_str()), r);
|
335
|
-
ap_rputs("': ", r);
|
336
|
-
ap_rputs(ap_escape_html(r->pool, e.what()), r);
|
337
|
-
if (e.code() == EPERM) {
|
338
|
-
ap_rputs("<p>", r);
|
339
|
-
ap_rputs("Apache doesn't have read permissions to that file. ", r);
|
340
|
-
ap_rputs("Please fix the relevant file permissions.", r);
|
341
|
-
ap_rputs("</p>", r);
|
342
|
-
}
|
343
|
-
return OK;
|
344
|
-
}
|
345
|
-
|
346
225
|
int reportBusyException(request_rec *r) {
|
347
226
|
ap_custom_response(r, HTTP_SERVICE_UNAVAILABLE,
|
348
227
|
"This website is too busy right now. Please try again later.");
|
349
228
|
return HTTP_SERVICE_UNAVAILABLE;
|
350
229
|
}
|
351
230
|
|
231
|
+
/**
|
232
|
+
* Gather some information about the request and do some preparations. In this method,
|
233
|
+
* it will be determined whether the request URI should be served statically by Apache
|
234
|
+
* (in case of static assets or in case there's a page cache file available) or
|
235
|
+
* whether it should be forwarded to the backend application.
|
236
|
+
*
|
237
|
+
* The strategy is as follows:
|
238
|
+
*
|
239
|
+
* We check whether Phusion Passenger is enabled for this URI (A).
|
240
|
+
* If so, then we check whether the following situations are true:
|
241
|
+
* (B) There is a backend application defined for this URI.
|
242
|
+
* (C) r->filename already exists.
|
243
|
+
* (D) There is a page cache file for the URI.
|
244
|
+
*
|
245
|
+
* - If A is not true, or if B is not true, or if C is true, then won't do anything.
|
246
|
+
* Passenger will be disabled during the rest of this request.
|
247
|
+
* - If D is true, then we first transform r->filename to the page cache file's
|
248
|
+
* filename, and then we let Apache serve it statically.
|
249
|
+
* - If D is not true, then we forward the request to the backend application.
|
250
|
+
*
|
251
|
+
* @pre The (A) condition must be true.
|
252
|
+
* @param coreModuleWillBeRun Whether the core.c map_to_storage hook might be called after this.
|
253
|
+
* @return Whether the Passenger handler hook method should be run.
|
254
|
+
*/
|
255
|
+
bool prepareRequest(request_rec *r, DirConfig *config, const char *filename, bool coreModuleWillBeRun = false) {
|
256
|
+
TRACE_POINT();
|
257
|
+
DirectoryMapper mapper(r, config, mstat, config->getStatThrottleRate());
|
258
|
+
try {
|
259
|
+
if (mapper.getBaseURI() == NULL) {
|
260
|
+
// (B) is not true.
|
261
|
+
return false;
|
262
|
+
}
|
263
|
+
} catch (const FileSystemException &e) {
|
264
|
+
/* DirectoryMapper tried to examine the filesystem in order
|
265
|
+
* to autodetect the application type (e.g. by checking whether
|
266
|
+
* environment.rb exists. But something went wrong, probably
|
267
|
+
* because of a permission problem. This usually
|
268
|
+
* means that the user is trying to deploy an application, but
|
269
|
+
* set the wrong permissions on the relevant folders.
|
270
|
+
* Later, in the handler hook, we inform the user about this
|
271
|
+
* problem so that he can either disable Phusion Passenger's
|
272
|
+
* autodetection routines, or fix the permissions.
|
273
|
+
*/
|
274
|
+
apr_pool_userdata_set(new ReportFileSystemError(e),
|
275
|
+
"Phusion Passenger: error report",
|
276
|
+
ReportFileSystemError::cleanup,
|
277
|
+
r->pool);
|
278
|
+
return true;
|
279
|
+
}
|
280
|
+
|
281
|
+
/* Save some information for the hook methods that are called later.
|
282
|
+
* The existance of this note indicates that the URI belongs to a Phusion
|
283
|
+
* Passenger-served application.
|
284
|
+
*/
|
285
|
+
RequestNote *note = new RequestNote(mapper);
|
286
|
+
note->config = config;
|
287
|
+
apr_pool_userdata_set(note, "Phusion Passenger", RequestNote::cleanup, r->pool);
|
288
|
+
|
289
|
+
try {
|
290
|
+
// (B) is true.
|
291
|
+
FileType fileType = getFileType(filename);
|
292
|
+
if (fileType == FT_REGULAR) {
|
293
|
+
// (C) is true.
|
294
|
+
return false;
|
295
|
+
}
|
296
|
+
|
297
|
+
// (C) is not true. Check whether (D) is true.
|
298
|
+
char *pageCacheFile;
|
299
|
+
/* Only GET requests may hit the page cache. This is
|
300
|
+
* important because of REST conventions, e.g.
|
301
|
+
* 'POST /foo' maps to 'FooController#create',
|
302
|
+
* while 'GET /foo' maps to 'FooController#index'.
|
303
|
+
* We wouldn't want our page caching support to interfere
|
304
|
+
* with that.
|
305
|
+
*/
|
306
|
+
if (r->method_number == M_GET) {
|
307
|
+
if (fileType == FT_DIRECTORY) {
|
308
|
+
size_t len;
|
309
|
+
|
310
|
+
len = strlen(filename);
|
311
|
+
if (len > 0 && filename[len - 1] == '/') {
|
312
|
+
pageCacheFile = apr_pstrcat(r->pool, filename,
|
313
|
+
"index.html", NULL);
|
314
|
+
} else {
|
315
|
+
pageCacheFile = apr_pstrcat(r->pool, filename,
|
316
|
+
".html", NULL);
|
317
|
+
}
|
318
|
+
} else {
|
319
|
+
pageCacheFile = apr_pstrcat(r->pool, filename,
|
320
|
+
".html", NULL);
|
321
|
+
}
|
322
|
+
if (!fileExists(pageCacheFile)) {
|
323
|
+
pageCacheFile = NULL;
|
324
|
+
}
|
325
|
+
} else {
|
326
|
+
pageCacheFile = NULL;
|
327
|
+
}
|
328
|
+
if (pageCacheFile != NULL) {
|
329
|
+
// (D) is true.
|
330
|
+
r->filename = pageCacheFile;
|
331
|
+
r->canonical_filename = pageCacheFile;
|
332
|
+
if (!coreModuleWillBeRun) {
|
333
|
+
r->finfo.filetype = APR_NOFILE;
|
334
|
+
ap_set_content_type(r, "text/html");
|
335
|
+
ap_directory_walk(r);
|
336
|
+
ap_file_walk(r);
|
337
|
+
}
|
338
|
+
return false;
|
339
|
+
} else {
|
340
|
+
// (D) is not true.
|
341
|
+
note->forwardToBackend = true;
|
342
|
+
return true;
|
343
|
+
}
|
344
|
+
} catch (const FileSystemException &e) {
|
345
|
+
/* Something went wrong while accessing the directory in which
|
346
|
+
* r->filename lives. We already know that this URI belongs to
|
347
|
+
* a backend application, so this error probably means that the
|
348
|
+
* user set the wrong permissions for his 'public' folder. We
|
349
|
+
* don't let the handler hook run so that Apache can decide how
|
350
|
+
* to display the error.
|
351
|
+
*/
|
352
|
+
return false;
|
353
|
+
}
|
354
|
+
}
|
355
|
+
|
356
|
+
/**
|
357
|
+
* Most of the high-level logic for forwarding a request to a backend application
|
358
|
+
* is contained in this method.
|
359
|
+
*/
|
360
|
+
int handleRequest(request_rec *r) {
|
361
|
+
/* Check whether an error occured in prepareRequest() that should be reported
|
362
|
+
* to the browser.
|
363
|
+
*/
|
364
|
+
|
365
|
+
// The union is needed in order to be compliant with
|
366
|
+
// C99/C++'s strict aliasing rules. http://tinyurl.com/g5hgh
|
367
|
+
union {
|
368
|
+
ErrorReport *errorReport;
|
369
|
+
void *pointer;
|
370
|
+
} u;
|
371
|
+
|
372
|
+
u.errorReport = 0;
|
373
|
+
apr_pool_userdata_get(&u.pointer, "Phusion Passenger: error report", r->pool);
|
374
|
+
if (u.errorReport != 0) {
|
375
|
+
return u.errorReport->report(r);
|
376
|
+
}
|
377
|
+
|
378
|
+
RequestNote *note = getRequestNote(r);
|
379
|
+
if (note == 0 || !note->forwardToBackend) {
|
380
|
+
return DECLINED;
|
381
|
+
} else if (r->handler != NULL && strcmp(r->handler, "redirect-handler") == 0) {
|
382
|
+
// mod_rewrite is at work.
|
383
|
+
return DECLINED;
|
384
|
+
}
|
385
|
+
|
386
|
+
TRACE_POINT();
|
387
|
+
DirConfig *config = note->config;
|
388
|
+
DirectoryMapper &mapper(note->mapper);
|
389
|
+
|
390
|
+
if (mapper.getPublicDirectory().empty()) {
|
391
|
+
return reportDocumentRootDeterminationError(r);
|
392
|
+
}
|
393
|
+
|
394
|
+
int httpStatus = ap_setup_client_block(r, REQUEST_CHUNKED_ERROR);
|
395
|
+
if (httpStatus != OK) {
|
396
|
+
return httpStatus;
|
397
|
+
}
|
398
|
+
|
399
|
+
try {
|
400
|
+
this_thread::disable_interruption di;
|
401
|
+
this_thread::disable_syscall_interruption dsi;
|
402
|
+
apr_bucket_brigade *bb;
|
403
|
+
apr_bucket *b;
|
404
|
+
Application::SessionPtr session;
|
405
|
+
bool expectingUploadData;
|
406
|
+
shared_ptr<TempFile> uploadData;
|
407
|
+
|
408
|
+
expectingUploadData = ap_should_client_block(r);
|
409
|
+
if (expectingUploadData && atol(lookupHeader(r, "Content-Length"))
|
410
|
+
> UPLOAD_ACCELERATION_THRESHOLD) {
|
411
|
+
uploadData = receiveRequestBody(r);
|
412
|
+
}
|
413
|
+
|
414
|
+
UPDATE_TRACE_POINT();
|
415
|
+
try {
|
416
|
+
ServerConfig *sconfig = getServerConfig(r->server);
|
417
|
+
string appRoot(canonicalizePath(
|
418
|
+
config->getAppRoot(mapper.getPublicDirectory().c_str())
|
419
|
+
));
|
420
|
+
|
421
|
+
session = getApplicationPool()->get(PoolOptions(
|
422
|
+
appRoot,
|
423
|
+
true,
|
424
|
+
sconfig->getDefaultUser(),
|
425
|
+
mapper.getEnvironment(),
|
426
|
+
config->getSpawnMethodString(),
|
427
|
+
mapper.getApplicationTypeString(),
|
428
|
+
config->frameworkSpawnerTimeout,
|
429
|
+
config->appSpawnerTimeout,
|
430
|
+
config->getMaxRequests(),
|
431
|
+
config->getMemoryLimit(),
|
432
|
+
config->usingGlobalQueue(),
|
433
|
+
config->getStatThrottleRate(),
|
434
|
+
config->getRestartDir()
|
435
|
+
));
|
436
|
+
P_TRACE(3, "Forwarding " << r->uri << " to PID " << session->getPid());
|
437
|
+
} catch (const SpawnException &e) {
|
438
|
+
r->status = 500;
|
439
|
+
if (e.hasErrorPage()) {
|
440
|
+
ap_set_content_type(r, "text/html; charset=utf-8");
|
441
|
+
ap_rputs(e.getErrorPage().c_str(), r);
|
442
|
+
return OK;
|
443
|
+
} else {
|
444
|
+
throw;
|
445
|
+
}
|
446
|
+
} catch (const FileSystemException &e) {
|
447
|
+
/* The application root cannot be determined. This could
|
448
|
+
* happen if, for example, the user specified 'RailsBaseURI /foo'
|
449
|
+
* while there is no filesystem entry called "foo" in the virtual
|
450
|
+
* host's document root.
|
451
|
+
*/
|
452
|
+
return ReportFileSystemError(e).report(r);
|
453
|
+
} catch (const BusyException &e) {
|
454
|
+
return reportBusyException(r);
|
455
|
+
}
|
456
|
+
|
457
|
+
UPDATE_TRACE_POINT();
|
458
|
+
session->setReaderTimeout(r->server->timeout / 1000);
|
459
|
+
session->setWriterTimeout(r->server->timeout / 1000);
|
460
|
+
sendHeaders(r, session, mapper.getBaseURI());
|
461
|
+
if (expectingUploadData) {
|
462
|
+
if (uploadData != NULL) {
|
463
|
+
sendRequestBody(r, session, uploadData);
|
464
|
+
uploadData.reset();
|
465
|
+
} else {
|
466
|
+
sendRequestBody(r, session);
|
467
|
+
}
|
468
|
+
}
|
469
|
+
session->shutdownWriter();
|
470
|
+
|
471
|
+
UPDATE_TRACE_POINT();
|
472
|
+
apr_file_t *readerPipe = NULL;
|
473
|
+
int reader = session->getStream();
|
474
|
+
pid_t backendPid = session->getPid();
|
475
|
+
apr_os_pipe_put(&readerPipe, &reader, r->pool);
|
476
|
+
apr_file_pipe_timeout_set(readerPipe, r->server->timeout);
|
477
|
+
|
478
|
+
bb = apr_brigade_create(r->connection->pool, r->connection->bucket_alloc);
|
479
|
+
b = passenger_bucket_create(session, readerPipe, r->connection->bucket_alloc);
|
480
|
+
session.reset();
|
481
|
+
APR_BRIGADE_INSERT_TAIL(bb, b);
|
482
|
+
|
483
|
+
b = apr_bucket_eos_create(r->connection->bucket_alloc);
|
484
|
+
APR_BRIGADE_INSERT_TAIL(bb, b);
|
485
|
+
|
486
|
+
// I know the size because I read util_script.c's source. :-(
|
487
|
+
char backendData[MAX_STRING_LEN];
|
488
|
+
int result = ap_scan_script_header_err_brigade(r, bb, backendData);
|
489
|
+
if (result == OK) {
|
490
|
+
// The API documentation for ap_scan_script_err_brigade() says it
|
491
|
+
// returns HTTP_OK on success, but it actually returns OK.
|
492
|
+
|
493
|
+
// Manually set the Status header because
|
494
|
+
// ap_scan_script_header_err_brigade() filters it
|
495
|
+
// out. Some broken HTTP clients depend on the
|
496
|
+
// Status header for retrieving the HTTP status.
|
497
|
+
if (!r->status_line && *r->status_line == '\0') {
|
498
|
+
r->status_line = apr_psprintf(r->pool,
|
499
|
+
"%d Unknown Status",
|
500
|
+
r->status);
|
501
|
+
}
|
502
|
+
apr_table_setn(r->headers_out, "Status", r->status_line);
|
503
|
+
|
504
|
+
ap_pass_brigade(r->output_filters, bb);
|
505
|
+
return OK;
|
506
|
+
} else if (backendData[0] == '\0') {
|
507
|
+
P_ERROR("Backend process " << backendPid <<
|
508
|
+
" did not return a valid HTTP response. It returned no data.");
|
509
|
+
apr_table_setn(r->err_headers_out, "Status", "500 Internal Server Error");
|
510
|
+
return HTTP_INTERNAL_SERVER_ERROR;
|
511
|
+
} else {
|
512
|
+
P_ERROR("Backend process " << backendPid <<
|
513
|
+
" did not return a valid HTTP response. It returned: [" <<
|
514
|
+
backendData << "]");
|
515
|
+
apr_table_setn(r->err_headers_out, "Status", "500 Internal Server Error");
|
516
|
+
return HTTP_INTERNAL_SERVER_ERROR;
|
517
|
+
}
|
518
|
+
|
519
|
+
} catch (const thread_interrupted &e) {
|
520
|
+
P_TRACE(3, "A system call was interrupted during an HTTP request. Apache "
|
521
|
+
"is probably restarting or shutting down. Backtrace:\n" <<
|
522
|
+
e.backtrace());
|
523
|
+
return HTTP_INTERNAL_SERVER_ERROR;
|
524
|
+
|
525
|
+
} catch (const tracable_exception &e) {
|
526
|
+
P_ERROR("Unexpected error in mod_passenger: " <<
|
527
|
+
e.what() << "\n" << " Backtrace:\n" << e.backtrace());
|
528
|
+
return HTTP_INTERNAL_SERVER_ERROR;
|
529
|
+
|
530
|
+
} catch (const exception &e) {
|
531
|
+
P_ERROR("Unexpected error in mod_passenger: " <<
|
532
|
+
e.what() << "\n" << " Backtrace: not available");
|
533
|
+
return HTTP_INTERNAL_SERVER_ERROR;
|
534
|
+
|
535
|
+
} catch (...) {
|
536
|
+
P_ERROR("An unexpected, unknown error occured in mod_passenger.");
|
537
|
+
throw;
|
538
|
+
}
|
539
|
+
}
|
540
|
+
|
352
541
|
/**
|
353
542
|
* Convert an HTTP header name to a CGI environment name.
|
354
543
|
*/
|
@@ -391,32 +580,6 @@ private:
|
|
391
580
|
return lookupName(r->subprocess_env, name);
|
392
581
|
}
|
393
582
|
|
394
|
-
// This code is a duplicate of what's in util_script.c. We can't use
|
395
|
-
// r->unparsed_uri because it gets changed if there was a redirect.
|
396
|
-
char *originalURI(request_rec *r) {
|
397
|
-
char *first, *last;
|
398
|
-
|
399
|
-
if (r->the_request == NULL) {
|
400
|
-
return (char *) apr_pcalloc(r->pool, 1);
|
401
|
-
}
|
402
|
-
|
403
|
-
first = r->the_request; // use the request-line
|
404
|
-
|
405
|
-
while (*first && !apr_isspace(*first)) {
|
406
|
-
++first; // skip over the method
|
407
|
-
}
|
408
|
-
while (apr_isspace(*first)) {
|
409
|
-
++first; // and the space(s)
|
410
|
-
}
|
411
|
-
|
412
|
-
last = first;
|
413
|
-
while (*last && !apr_isspace(*last)) {
|
414
|
-
++last; // end at next whitespace
|
415
|
-
}
|
416
|
-
|
417
|
-
return apr_pstrmemdup(r->pool, first, last - first);
|
418
|
-
}
|
419
|
-
|
420
583
|
void inline addHeader(apr_table_t *table, const char *name, const char *value) {
|
421
584
|
if (name != NULL && value != NULL) {
|
422
585
|
apr_table_addn(table, name, value);
|
@@ -441,7 +604,7 @@ private:
|
|
441
604
|
addHeader(headers, "REMOTE_PORT", apr_psprintf(r->pool, "%d", r->connection->remote_addr->port));
|
442
605
|
addHeader(headers, "REMOTE_USER", r->user);
|
443
606
|
addHeader(headers, "REQUEST_METHOD", r->method);
|
444
|
-
addHeader(headers, "REQUEST_URI",
|
607
|
+
addHeader(headers, "REQUEST_URI", r->unparsed_uri);
|
445
608
|
addHeader(headers, "QUERY_STRING", r->args ? r->args : "");
|
446
609
|
if (strcmp(baseURI, "/") != 0) {
|
447
610
|
addHeader(headers, "SCRIPT_NAME", baseURI);
|
@@ -518,21 +681,38 @@ private:
|
|
518
681
|
}
|
519
682
|
|
520
683
|
shared_ptr<TempFile> receiveRequestBody(request_rec *r) {
|
684
|
+
TRACE_POINT();
|
521
685
|
shared_ptr<TempFile> tempFile(new TempFile());
|
522
686
|
char buf[1024 * 32];
|
523
687
|
apr_off_t len;
|
688
|
+
size_t total_written = 0;
|
524
689
|
|
525
690
|
while ((len = ap_get_client_block(r, buf, sizeof(buf))) > 0) {
|
526
691
|
size_t written = 0;
|
527
692
|
do {
|
528
693
|
size_t ret = fwrite(buf, 1, len - written, tempFile->handle);
|
529
|
-
if (ret
|
530
|
-
|
531
|
-
|
532
|
-
|
694
|
+
if (ret <= 0 || fflush(tempFile->handle) == EOF) {
|
695
|
+
int e = errno;
|
696
|
+
string message("An error occured while "
|
697
|
+
"buffering HTTP upload data to "
|
698
|
+
"a temporary file in ");
|
699
|
+
message.append(getTempDir());
|
700
|
+
if (e == ENOSPC) {
|
701
|
+
message.append(". Please make sure "
|
702
|
+
"that this directory has "
|
703
|
+
"enough disk space for "
|
704
|
+
"buffering file uploads, "
|
705
|
+
"or set the 'PassengerTempDir' "
|
706
|
+
"directive to a directory "
|
707
|
+
"that has enough disk space.");
|
708
|
+
throw RuntimeException(message);
|
709
|
+
} else {
|
710
|
+
throw SystemException(message, e);
|
711
|
+
}
|
533
712
|
}
|
534
713
|
written += ret;
|
535
714
|
} while (written < (size_t) len);
|
715
|
+
total_written += written;
|
536
716
|
}
|
537
717
|
if (len == -1) {
|
538
718
|
throw IOException("An error occurred while receiving HTTP upload data.");
|
@@ -544,8 +724,9 @@ private:
|
|
544
724
|
}
|
545
725
|
|
546
726
|
void sendRequestBody(request_rec *r, Application::SessionPtr &session, shared_ptr<TempFile> &uploadData) {
|
727
|
+
TRACE_POINT();
|
547
728
|
rewind(uploadData->handle);
|
548
|
-
P_DEBUG("Content-Length = " << lookupHeader(r, "Content-Length"));
|
729
|
+
P_DEBUG("File upload: Content-Length = " << lookupHeader(r, "Content-Length"));
|
549
730
|
while (!feof(uploadData->handle)) {
|
550
731
|
char buf[1024 * 32];
|
551
732
|
size_t size;
|
@@ -573,6 +754,10 @@ public:
|
|
573
754
|
passenger_config_merge_all_servers(pconf, s);
|
574
755
|
ServerConfig *config = getServerConfig(s);
|
575
756
|
Passenger::setLogLevel(config->logLevel);
|
757
|
+
m_hasModRewrite = UNKNOWN;
|
758
|
+
m_hasModDir = UNKNOWN;
|
759
|
+
m_hasModAutoIndex = UNKNOWN;
|
760
|
+
mstat = cached_multi_file_stat_new(1024);
|
576
761
|
|
577
762
|
P_DEBUG("Initializing Phusion Passenger...");
|
578
763
|
ap_add_version_component(pconf, "Phusion_Passenger/" PASSENGER_VERSION);
|
@@ -580,6 +765,22 @@ public:
|
|
580
765
|
const char *ruby, *user;
|
581
766
|
string applicationPoolServerExe, spawnServer;
|
582
767
|
|
768
|
+
if (config->tempDir != NULL) {
|
769
|
+
setenv("TMPDIR", config->tempDir, 1);
|
770
|
+
} else {
|
771
|
+
unsetenv("TMPDIR");
|
772
|
+
}
|
773
|
+
/*
|
774
|
+
* As described in the comment in init_module, upon (re)starting
|
775
|
+
* Apache, the Hooks constructor is called twice. We unset
|
776
|
+
* PHUSION_PASSENGER_TMP before calling createPassengerTmpDir()
|
777
|
+
* because we want the temp directory's name to contain the PID
|
778
|
+
* of the process in which the Hooks constructor was called for
|
779
|
+
* the second time.
|
780
|
+
*/
|
781
|
+
unsetenv("PHUSION_PASSENGER_TMP");
|
782
|
+
createPassengerTempDir();
|
783
|
+
|
583
784
|
ruby = (config->ruby != NULL) ? config->ruby : DEFAULT_RUBY_COMMAND;
|
584
785
|
if (config->userSwitching) {
|
585
786
|
user = "";
|
@@ -623,217 +824,204 @@ public:
|
|
623
824
|
pool->setMax(config->maxPoolSize);
|
624
825
|
pool->setMaxPerApp(config->maxInstancesPerApp);
|
625
826
|
pool->setMaxIdleTime(config->poolIdleTime);
|
626
|
-
pool->setUseGlobalQueue(config->getUseGlobalQueue());
|
627
827
|
}
|
628
828
|
|
629
|
-
|
829
|
+
~Hooks() {
|
830
|
+
cached_multi_file_stat_free(mstat);
|
831
|
+
removeDirTree(getPassengerTempDir().c_str());
|
832
|
+
}
|
833
|
+
|
834
|
+
int prepareRequestWhenInHighPerformanceMode(request_rec *r) {
|
630
835
|
DirConfig *config = getDirConfig(r);
|
631
|
-
|
632
|
-
|
836
|
+
if (config->isEnabled() && config->highPerformanceMode()) {
|
837
|
+
if (prepareRequest(r, config, r->filename, true)) {
|
838
|
+
return OK;
|
839
|
+
} else {
|
840
|
+
return DECLINED;
|
841
|
+
}
|
842
|
+
} else {
|
633
843
|
return DECLINED;
|
634
844
|
}
|
635
|
-
|
636
|
-
|
637
|
-
|
638
|
-
|
845
|
+
}
|
846
|
+
|
847
|
+
/**
|
848
|
+
* This is the hook method for the map_to_storage hook. Apache's final map_to_storage hook
|
849
|
+
* method (defined in core.c) will do the following:
|
850
|
+
*
|
851
|
+
* If r->filename doesn't exist, then it will change the filename to the
|
852
|
+
* following form:
|
853
|
+
*
|
854
|
+
* A/B
|
855
|
+
*
|
856
|
+
* A is top-most directory that exists. B is the first filename piece that
|
857
|
+
* normally follows A. For example, suppose that a website's DocumentRoot
|
858
|
+
* is /website, on server http://test.com/. Suppose that there's also a
|
859
|
+
* directory /website/images.
|
860
|
+
*
|
861
|
+
* If we access: then r->filename will be:
|
862
|
+
* http://test.com/foo/bar /website/foo
|
863
|
+
* http://test.com/foo/bar/baz /website/foo
|
864
|
+
* http://test.com/images/foo/bar /website/images/foo
|
865
|
+
*
|
866
|
+
* We obviously don't want this to happen because it'll interfere with our page
|
867
|
+
* cache file search code. So here we save the original value of r->filename so
|
868
|
+
* that we can use it later.
|
869
|
+
*/
|
870
|
+
int saveOriginalFilename(request_rec *r) {
|
871
|
+
apr_table_set(r->notes, "Phusion Passenger: original filename", r->filename);
|
872
|
+
return DECLINED;
|
873
|
+
}
|
874
|
+
|
875
|
+
int prepareRequestWhenNotInHighPerformanceMode(request_rec *r) {
|
876
|
+
DirConfig *config = getDirConfig(r);
|
877
|
+
if (config->isEnabled()) {
|
878
|
+
if (config->highPerformanceMode()) {
|
879
|
+
/* Preparations have already been done in the map_to_storage hook.
|
880
|
+
* Prevent other modules' fixups hooks from being run.
|
881
|
+
*/
|
882
|
+
return OK;
|
883
|
+
} else {
|
884
|
+
// core.c's map_to_storage hook will transform the filename, as
|
885
|
+
// described by saveOriginalFilename(). Here we restore the
|
886
|
+
// original filename.
|
887
|
+
const char *filename = apr_table_get(r->notes, "Phusion Passenger: original filename");
|
888
|
+
if (filename == NULL) {
|
889
|
+
return DECLINED;
|
890
|
+
} else {
|
891
|
+
prepareRequest(r, config, filename);
|
892
|
+
return DECLINED;
|
893
|
+
}
|
639
894
|
}
|
640
|
-
}
|
641
|
-
return
|
895
|
+
} else {
|
896
|
+
return DECLINED;
|
642
897
|
}
|
643
|
-
|
644
|
-
|
645
|
-
|
646
|
-
|
898
|
+
}
|
899
|
+
|
900
|
+
/**
|
901
|
+
* The default .htaccess provided by on Rails on Rails (that is, before version 2.1.0)
|
902
|
+
* has the following mod_rewrite rules in it:
|
903
|
+
*
|
904
|
+
* RewriteEngine on
|
905
|
+
* RewriteRule ^$ index.html [QSA]
|
906
|
+
* RewriteRule ^([^.]+)$ $1.html [QSA]
|
907
|
+
* RewriteCond %{REQUEST_FILENAME} !-f
|
908
|
+
* RewriteRule ^(.*)$ dispatch.cgi [QSA,L]
|
909
|
+
*
|
910
|
+
* As a result, all requests that do not map to a filename will be redirected to
|
911
|
+
* dispatch.cgi (or dispatch.fcgi, if the user so specified). We don't want that
|
912
|
+
* to happen, so before mod_rewrite applies its rules, we save the current state.
|
913
|
+
* After mod_rewrite has applied its rules, undoRedirectionToDispatchCgi() will
|
914
|
+
* check whether mod_rewrite attempted to perform an internal redirection to
|
915
|
+
* dispatch.(f)cgi. If so, then it will revert the state to the way it was before
|
916
|
+
* mod_rewrite took place.
|
917
|
+
*/
|
918
|
+
int saveStateBeforeRewriteRules(request_rec *r) {
|
919
|
+
RequestNote *note = getRequestNote(r);
|
920
|
+
if (note != 0 && hasModRewrite()) {
|
921
|
+
note->handlerBeforeModRewrite = r->handler;
|
922
|
+
note->filenameBeforeModRewrite = r->filename;
|
923
|
+
}
|
924
|
+
return DECLINED;
|
925
|
+
}
|
926
|
+
|
927
|
+
int undoRedirectionToDispatchCgi(request_rec *r) {
|
928
|
+
RequestNote *note = getRequestNote(r);
|
929
|
+
if (note == 0 || !hasModRewrite()) {
|
930
|
+
return DECLINED;
|
647
931
|
}
|
648
932
|
|
649
|
-
|
650
|
-
|
651
|
-
|
652
|
-
|
653
|
-
|
654
|
-
|
655
|
-
|
656
|
-
|
657
|
-
|
658
|
-
|
659
|
-
|
660
|
-
> UPLOAD_ACCELERATION_THRESHOLD) {
|
661
|
-
uploadData = receiveRequestBody(r);
|
662
|
-
}
|
663
|
-
|
664
|
-
try {
|
665
|
-
const char *defaultUser, *environment, *spawnMethod;
|
666
|
-
ServerConfig *sconfig;
|
667
|
-
|
668
|
-
sconfig = getServerConfig(r->server);
|
669
|
-
if (sconfig->defaultUser != NULL) {
|
670
|
-
defaultUser = sconfig->defaultUser;
|
671
|
-
} else {
|
672
|
-
defaultUser = "nobody";
|
673
|
-
}
|
674
|
-
if (mapper.getApplicationType() == DirectoryMapper::RAILS) {
|
675
|
-
if (config->railsEnv == NULL) {
|
676
|
-
environment = DEFAULT_RAILS_ENV;
|
677
|
-
} else {
|
678
|
-
environment = config->railsEnv;
|
679
|
-
}
|
680
|
-
} else if (mapper.getApplicationType() == DirectoryMapper::RACK) {
|
681
|
-
if (config->rackEnv == NULL) {
|
682
|
-
environment = DEFAULT_RACK_ENV;
|
683
|
-
} else {
|
684
|
-
environment = config->rackEnv;
|
685
|
-
}
|
686
|
-
} else {
|
687
|
-
environment = DEFAULT_WSGI_ENV;
|
688
|
-
}
|
689
|
-
if (config->spawnMethod == DirConfig::SM_CONSERVATIVE) {
|
690
|
-
spawnMethod = "conservative";
|
691
|
-
} else {
|
692
|
-
spawnMethod = "smart";
|
693
|
-
}
|
694
|
-
|
695
|
-
session = getApplicationPool()->get(
|
696
|
-
canonicalizePath(mapper.getPublicDirectory() + "/.."),
|
697
|
-
true, defaultUser, environment, spawnMethod,
|
698
|
-
mapper.getApplicationTypeString());
|
699
|
-
P_TRACE(3, "Forwarding " << r->uri << " to PID " << session->getPid());
|
700
|
-
} catch (const SpawnException &e) {
|
701
|
-
if (e.hasErrorPage()) {
|
702
|
-
r->status = 500;
|
703
|
-
ap_set_content_type(r, "text/html; charset=utf-8");
|
704
|
-
ap_rputs(e.getErrorPage().c_str(), r);
|
705
|
-
return OK;
|
706
|
-
} else {
|
707
|
-
throw;
|
708
|
-
}
|
709
|
-
} catch (const BusyException &e) {
|
710
|
-
return reportBusyException(r);
|
711
|
-
}
|
712
|
-
sendHeaders(r, session, mapper.getBaseURI());
|
713
|
-
if (expectingUploadData) {
|
714
|
-
if (uploadData != NULL) {
|
715
|
-
sendRequestBody(r, session, uploadData);
|
716
|
-
uploadData.reset();
|
717
|
-
} else {
|
718
|
-
sendRequestBody(r, session);
|
933
|
+
if (r->handler != NULL && strcmp(r->handler, "redirect-handler") == 0) {
|
934
|
+
// Check whether r->filename looks like "redirect:.../dispatch.(f)cgi"
|
935
|
+
size_t len = strlen(r->filename);
|
936
|
+
// 22 == strlen("redirect:/dispatch.cgi")
|
937
|
+
if (len >= 22 && memcmp(r->filename, "redirect:", 9) == 0
|
938
|
+
&& (memcmp(r->filename + len - 13, "/dispatch.cgi", 13) == 0
|
939
|
+
|| memcmp(r->filename + len - 14, "/dispatch.fcgi", 14) == 0)) {
|
940
|
+
if (note->filenameBeforeModRewrite != NULL) {
|
941
|
+
r->filename = note->filenameBeforeModRewrite;
|
942
|
+
r->canonical_filename = note->filenameBeforeModRewrite;
|
943
|
+
r->handler = note->handlerBeforeModRewrite;
|
719
944
|
}
|
720
945
|
}
|
721
|
-
session->shutdownWriter();
|
722
|
-
|
723
|
-
apr_file_t *readerPipe = NULL;
|
724
|
-
int reader = session->getStream();
|
725
|
-
apr_os_pipe_put(&readerPipe, &reader, r->pool);
|
726
|
-
|
727
|
-
bb = apr_brigade_create(r->connection->pool, r->connection->bucket_alloc);
|
728
|
-
b = passenger_bucket_create(readerPipe, r->connection->bucket_alloc);
|
729
|
-
APR_BRIGADE_INSERT_TAIL(bb, b);
|
730
|
-
|
731
|
-
b = apr_bucket_eos_create(r->connection->bucket_alloc);
|
732
|
-
APR_BRIGADE_INSERT_TAIL(bb, b);
|
733
|
-
|
734
|
-
ap_scan_script_header_err_brigade(r, bb, NULL);
|
735
|
-
ap_pass_brigade(r->output_filters, bb);
|
736
|
-
|
737
|
-
Container *container = new Container();
|
738
|
-
container->session = session;
|
739
|
-
apr_pool_cleanup_register(r->pool, container, Container::cleanup, apr_pool_cleanup_null);
|
740
|
-
|
741
|
-
return OK;
|
742
|
-
} catch (const thread_interrupted &) {
|
743
|
-
P_TRACE(3, "A system call was interrupted during an HTTP request. Apache "
|
744
|
-
"is probably restarting or shutting down.");
|
745
|
-
return HTTP_INTERNAL_SERVER_ERROR;
|
746
|
-
} catch (const exception &e) {
|
747
|
-
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "*** Unexpected error in Passenger: %s", e.what());
|
748
|
-
return HTTP_INTERNAL_SERVER_ERROR;
|
749
946
|
}
|
947
|
+
return DECLINED;
|
948
|
+
}
|
949
|
+
|
950
|
+
/**
|
951
|
+
* mod_dir does the following:
|
952
|
+
* If r->filename is a directory, and the URI doesn't end with a slash,
|
953
|
+
* then it will redirect the browser to an URI with a slash. For example,
|
954
|
+
* if you go to http://foo.com/images, then it will redirect you to
|
955
|
+
* http://foo.com/images/.
|
956
|
+
*
|
957
|
+
* This behavior is undesired. Suppose that there is an ImagesController,
|
958
|
+
* and there's also a 'public/images' folder used for storing page cache
|
959
|
+
* files. Then we don't want mod_dir to perform the redirection.
|
960
|
+
*
|
961
|
+
* So in startBlockingModDir(), we temporarily change some fields in the
|
962
|
+
* request structure in order to block mod_dir. In endBlockingModDir() we
|
963
|
+
* revert those fields to their old value.
|
964
|
+
*/
|
965
|
+
int startBlockingModDir(request_rec *r) {
|
966
|
+
RequestNote *note = getRequestNote(r);
|
967
|
+
if (note != 0 && hasModDir()) {
|
968
|
+
note->oldFileType = r->finfo.filetype;
|
969
|
+
r->finfo.filetype = APR_NOFILE;
|
970
|
+
}
|
971
|
+
return DECLINED;
|
972
|
+
}
|
973
|
+
|
974
|
+
int endBlockingModDir(request_rec *r) {
|
975
|
+
RequestNote *note = getRequestNote(r);
|
976
|
+
if (note != 0 && hasModDir()) {
|
977
|
+
r->finfo.filetype = note->oldFileType;
|
978
|
+
}
|
979
|
+
return DECLINED;
|
980
|
+
}
|
981
|
+
|
982
|
+
/**
|
983
|
+
* mod_autoindex will try to display a directory index for URIs that map to a directory.
|
984
|
+
* This is undesired because of page caching semantics. Suppose that a Rails application
|
985
|
+
* has an ImagesController which has page caching enabled, and thus also a 'public/images'
|
986
|
+
* directory. When the visitor visits /images we'll want the request to be forwarded to
|
987
|
+
* the Rails application, instead of displaying a directory index.
|
988
|
+
*
|
989
|
+
* So in this hook method, we temporarily change some fields in the request structure
|
990
|
+
* in order to block mod_autoindex. In endBlockingModAutoIndex(), we restore the request
|
991
|
+
* structure to its former state.
|
992
|
+
*/
|
993
|
+
int startBlockingModAutoIndex(request_rec *r) {
|
994
|
+
RequestNote *note = getRequestNote(r);
|
995
|
+
if (note != 0 && hasModAutoIndex()) {
|
996
|
+
note->handlerBeforeModAutoIndex = r->handler;
|
997
|
+
r->handler = "";
|
998
|
+
}
|
999
|
+
return DECLINED;
|
1000
|
+
}
|
1001
|
+
|
1002
|
+
int endBlockingModAutoIndex(request_rec *r) {
|
1003
|
+
RequestNote *note = getRequestNote(r);
|
1004
|
+
if (note != 0 && hasModAutoIndex()) {
|
1005
|
+
r->handler = note->handlerBeforeModAutoIndex;
|
1006
|
+
}
|
1007
|
+
return DECLINED;
|
750
1008
|
}
|
751
1009
|
|
752
|
-
int
|
753
|
-
mapToStorage(request_rec *r) {
|
1010
|
+
int handleRequestWhenInHighPerformanceMode(request_rec *r) {
|
754
1011
|
DirConfig *config = getDirConfig(r);
|
755
|
-
|
756
|
-
|
757
|
-
|
758
|
-
|
759
|
-
|
760
|
-
|
761
|
-
|
762
|
-
|
763
|
-
|
764
|
-
|
765
|
-
forwardToApplication = false;
|
766
|
-
} else if (r->method_number == M_GET) {
|
767
|
-
char *html_file;
|
768
|
-
size_t len;
|
769
|
-
|
770
|
-
len = strlen(r->filename);
|
771
|
-
if (len > 0 && r->filename[len - 1] == '/') {
|
772
|
-
html_file = apr_pstrcat(r->pool, r->filename, "index.html", NULL);
|
773
|
-
} else {
|
774
|
-
html_file = apr_pstrcat(r->pool, r->filename, ".html", NULL);
|
775
|
-
}
|
776
|
-
if (fileExists(html_file)) {
|
777
|
-
/* If a .html version of the URI exists, serve it directly.
|
778
|
-
* We're essentially accelerating Rails page caching.
|
779
|
-
*/
|
780
|
-
r->filename = html_file;
|
781
|
-
r->canonical_filename = html_file;
|
782
|
-
forwardToApplication = false;
|
783
|
-
} else {
|
784
|
-
forwardToApplication = true;
|
785
|
-
}
|
786
|
-
} else {
|
787
|
-
/*
|
788
|
-
* Non-GET requests are always forwarded to the application.
|
789
|
-
* This important because of REST conventions, e.g.
|
790
|
-
* 'POST /foo' maps to 'FooController.create',
|
791
|
-
* while 'GET /foo' maps to 'FooController.index'.
|
792
|
-
* We wouldn't want our page caching support to interfere
|
793
|
-
* with that.
|
794
|
-
*/
|
795
|
-
forwardToApplication = true;
|
796
|
-
}
|
797
|
-
|
798
|
-
if (forwardToApplication) {
|
799
|
-
/* Apache's default map_to_storage process does strange
|
800
|
-
* things with the filename. Suppose that the DocumentRoot
|
801
|
-
* is /website, on server http://test.com/. If we access
|
802
|
-
* http://test.com/foo/bar, and /website/foo/bar does not
|
803
|
-
* exist, then Apache will change the filename to
|
804
|
-
* /website/foo instead of the expected /website/bar.
|
805
|
-
* We make sure that doesn't happen.
|
806
|
-
*
|
807
|
-
* Incidentally, this also disables mod_rewrite. That is a
|
808
|
-
* good thing because the default Rails .htaccess file
|
809
|
-
* interferes with Passenger anyway (it delegates requests
|
810
|
-
* to the CGI script dispatch.cgi).
|
811
|
-
*/
|
812
|
-
if (config->allowModRewrite != DirConfig::ENABLED
|
813
|
-
&& mapper.getApplicationType() == DirectoryMapper::RAILS) {
|
814
|
-
/* Of course, we only do that if all of the following
|
815
|
-
* are true:
|
816
|
-
* - the config allows us to. Some people have complex
|
817
|
-
* mod_rewrite rules that they don't want to abandon.
|
818
|
-
* Those people will have to make sure that the Rails
|
819
|
-
* app's .htaccess doesn't interfere.
|
820
|
-
* - this is a Rails application.
|
821
|
-
*/
|
822
|
-
return OK;
|
823
|
-
} else if (strcmp(r->uri, mapper.getBaseURI()) == 0) {
|
824
|
-
/* If the request URI is the application's base URI,
|
825
|
-
* then we'll want to take over control. Otherwise,
|
826
|
-
* Apache will show a directory listing. This fixes issue #11.
|
827
|
-
*/
|
828
|
-
return OK;
|
829
|
-
} else {
|
830
|
-
return DECLINED;
|
831
|
-
}
|
832
|
-
} else {
|
833
|
-
return DECLINED;
|
834
|
-
}
|
835
|
-
} catch (const FileSystemException &e) {
|
1012
|
+
if (config->highPerformanceMode()) {
|
1013
|
+
return handleRequest(r);
|
1014
|
+
} else {
|
1015
|
+
return DECLINED;
|
1016
|
+
}
|
1017
|
+
}
|
1018
|
+
|
1019
|
+
int handleRequestWhenNotInHighPerformanceMode(request_rec *r) {
|
1020
|
+
DirConfig *config = getDirConfig(r);
|
1021
|
+
if (config->highPerformanceMode()) {
|
836
1022
|
return DECLINED;
|
1023
|
+
} else {
|
1024
|
+
return handleRequest(r);
|
837
1025
|
}
|
838
1026
|
}
|
839
1027
|
};
|
@@ -900,9 +1088,10 @@ init_module(apr_pool_t *pconf, apr_pool_t *plog, apr_pool_t *ptemp, server_rec *
|
|
900
1088
|
apr_pool_cleanup_null);
|
901
1089
|
return OK;
|
902
1090
|
|
903
|
-
} catch (const thread_interrupted &) {
|
1091
|
+
} catch (const thread_interrupted &e) {
|
904
1092
|
P_TRACE(2, "A system call was interrupted during mod_passenger "
|
905
|
-
"initialization. Apache might be restarting or shutting
|
1093
|
+
"initialization. Apache might be restarting or shutting "
|
1094
|
+
"down. Backtrace:\n" << e.backtrace());
|
906
1095
|
return DECLINED;
|
907
1096
|
|
908
1097
|
} catch (const thread_resource_error &e) {
|
@@ -911,7 +1100,14 @@ init_module(apr_pool_t *pconf, apr_pool_t *plog, apr_pool_t *ptemp, server_rec *
|
|
911
1100
|
|
912
1101
|
lim.rlim_cur = 0;
|
913
1102
|
lim.rlim_max = 0;
|
1103
|
+
|
1104
|
+
/* Solaris does not define the RLIMIT_NPROC limit. Setting it to infinity... */
|
1105
|
+
#ifdef RLIMIT_NPROC
|
914
1106
|
getrlimit(RLIMIT_NPROC, &lim);
|
1107
|
+
#else
|
1108
|
+
lim.rlim_cur = lim.rlim_max = RLIM_INFINITY;
|
1109
|
+
#endif
|
1110
|
+
|
915
1111
|
#ifdef PTHREAD_THREADS_MAX
|
916
1112
|
pthread_threads_max = toString(PTHREAD_THREADS_MAX);
|
917
1113
|
#else
|
@@ -951,32 +1147,52 @@ init_module(apr_pool_t *pconf, apr_pool_t *plog, apr_pool_t *ptemp, server_rec *
|
|
951
1147
|
}
|
952
1148
|
}
|
953
1149
|
|
954
|
-
|
955
|
-
|
956
|
-
|
957
|
-
|
958
|
-
|
959
|
-
|
1150
|
+
#define DEFINE_REQUEST_HOOK(c_name, cpp_name) \
|
1151
|
+
static int c_name(request_rec *r) { \
|
1152
|
+
if (OXT_LIKELY(hooks != NULL)) { \
|
1153
|
+
return hooks->cpp_name(r); \
|
1154
|
+
} else { \
|
1155
|
+
return DECLINED; \
|
1156
|
+
} \
|
960
1157
|
}
|
961
|
-
}
|
962
1158
|
|
963
|
-
|
964
|
-
|
965
|
-
|
966
|
-
|
967
|
-
|
968
|
-
|
969
|
-
|
970
|
-
|
1159
|
+
DEFINE_REQUEST_HOOK(prepare_request_when_in_high_performance_mode, prepareRequestWhenInHighPerformanceMode)
|
1160
|
+
DEFINE_REQUEST_HOOK(save_original_filename, saveOriginalFilename)
|
1161
|
+
DEFINE_REQUEST_HOOK(prepare_request_when_not_in_high_performance_mode, prepareRequestWhenNotInHighPerformanceMode)
|
1162
|
+
DEFINE_REQUEST_HOOK(save_state_before_rewrite_rules, saveStateBeforeRewriteRules)
|
1163
|
+
DEFINE_REQUEST_HOOK(undo_redirection_to_dispatch_cgi, undoRedirectionToDispatchCgi)
|
1164
|
+
DEFINE_REQUEST_HOOK(start_blocking_mod_dir, startBlockingModDir)
|
1165
|
+
DEFINE_REQUEST_HOOK(end_blocking_mod_dir, endBlockingModDir)
|
1166
|
+
DEFINE_REQUEST_HOOK(start_blocking_mod_autoindex, startBlockingModAutoIndex)
|
1167
|
+
DEFINE_REQUEST_HOOK(end_blocking_mod_autoindex, endBlockingModAutoIndex)
|
1168
|
+
DEFINE_REQUEST_HOOK(handle_request_when_in_high_performance_mode, handleRequestWhenInHighPerformanceMode)
|
1169
|
+
DEFINE_REQUEST_HOOK(handle_request_when_not_in_high_performance_mode, handleRequestWhenNotInHighPerformanceMode)
|
1170
|
+
|
971
1171
|
|
972
1172
|
/**
|
973
1173
|
* Apache hook registration function.
|
974
1174
|
*/
|
975
1175
|
void
|
976
1176
|
passenger_register_hooks(apr_pool_t *p) {
|
1177
|
+
static const char * const rewrite_module[] = { "mod_rewrite.c", NULL };
|
1178
|
+
static const char * const dir_module[] = { "mod_dir.c", NULL };
|
1179
|
+
static const char * const autoindex_module[] = { "mod_autoindex.c", NULL };
|
1180
|
+
|
977
1181
|
ap_hook_post_config(init_module, NULL, NULL, APR_HOOK_MIDDLE);
|
978
|
-
|
979
|
-
|
1182
|
+
|
1183
|
+
ap_hook_map_to_storage(prepare_request_when_in_high_performance_mode, NULL, NULL, APR_HOOK_FIRST);
|
1184
|
+
ap_hook_map_to_storage(save_original_filename, NULL, NULL, APR_HOOK_LAST);
|
1185
|
+
|
1186
|
+
ap_hook_fixups(prepare_request_when_not_in_high_performance_mode, NULL, rewrite_module, APR_HOOK_FIRST);
|
1187
|
+
ap_hook_fixups(save_state_before_rewrite_rules, NULL, rewrite_module, APR_HOOK_LAST);
|
1188
|
+
ap_hook_fixups(undo_redirection_to_dispatch_cgi, rewrite_module, NULL, APR_HOOK_FIRST);
|
1189
|
+
ap_hook_fixups(start_blocking_mod_dir, NULL, dir_module, APR_HOOK_MIDDLE);
|
1190
|
+
ap_hook_fixups(end_blocking_mod_dir, dir_module, NULL, APR_HOOK_MIDDLE);
|
1191
|
+
|
1192
|
+
ap_hook_handler(handle_request_when_in_high_performance_mode, NULL, NULL, APR_HOOK_FIRST);
|
1193
|
+
ap_hook_handler(start_blocking_mod_autoindex, NULL, autoindex_module, APR_HOOK_LAST);
|
1194
|
+
ap_hook_handler(end_blocking_mod_autoindex, autoindex_module, NULL, APR_HOOK_FIRST);
|
1195
|
+
ap_hook_handler(handle_request_when_not_in_high_performance_mode, NULL, NULL, APR_HOOK_LAST);
|
980
1196
|
}
|
981
1197
|
|
982
1198
|
/**
|