passenger 2.1.3 → 2.2.0
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 +2 -0
- data/INSTALL +3 -1
- data/LICENSE +19 -355
- data/NEWS +3 -0
- data/README +11 -4
- data/Rakefile +435 -236
- data/bin/passenger-config +20 -14
- data/bin/passenger-install-apache2-module +67 -201
- data/bin/passenger-install-nginx-module +477 -0
- data/bin/passenger-make-enterprisey +17 -12
- data/bin/passenger-memory-stats +33 -23
- data/bin/passenger-spawn-server +17 -12
- data/bin/passenger-status +18 -13
- data/bin/passenger-stress-test +17 -12
- data/doc/{Users guide.html → Users guide Apache.html } +79 -61
- data/doc/{Users guide.txt → Users guide Apache.txt } +43 -939
- data/doc/Users guide Nginx.html +2276 -0
- data/doc/Users guide Nginx.txt +776 -0
- data/doc/cxxapi/ApplicationPoolServer_8h-source.html +9 -4
- data/doc/cxxapi/ApplicationPool_8h-source.html +9 -4
- data/doc/cxxapi/Application_8h-source.html +26 -21
- data/doc/cxxapi/Bucket_8h-source.html +54 -44
- data/doc/cxxapi/CachedFileStat_8h-source.html +9 -4
- data/doc/cxxapi/Configuration_8h-source.html +357 -339
- data/doc/cxxapi/DirectoryMapper_8h-source.html +294 -280
- data/doc/cxxapi/DummySpawnManager_8h-source.html +9 -4
- data/doc/cxxapi/Exceptions_8h-source.html +9 -4
- data/doc/cxxapi/FileChecker_8h-source.html +9 -4
- data/doc/cxxapi/Hooks_8h-source.html +50 -40
- data/doc/cxxapi/Logging_8h-source.html +9 -4
- data/doc/cxxapi/MessageChannel_8h-source.html +20 -15
- data/doc/cxxapi/PoolOptions_8h-source.html +10 -5
- data/doc/cxxapi/SpawnManager_8h-source.html +9 -4
- data/doc/cxxapi/StandardApplicationPool_8h-source.html +10 -5
- data/doc/cxxapi/SystemTime_8h-source.html +9 -4
- data/doc/cxxapi/Utils_8h-source.html +242 -214
- data/doc/cxxapi/annotated.html +4 -28
- data/doc/cxxapi/classClient-members.html +4 -4
- data/doc/cxxapi/classClient.html +14 -11
- data/doc/cxxapi/classHooks-members.html +4 -5
- data/doc/cxxapi/classHooks.html +26 -24
- data/doc/cxxapi/classPassenger_1_1Application-members.html +4 -4
- data/doc/cxxapi/classPassenger_1_1Application.html +40 -37
- data/doc/cxxapi/classPassenger_1_1ApplicationPool-members.html +4 -4
- data/doc/cxxapi/classPassenger_1_1ApplicationPool.html +95 -92
- data/doc/cxxapi/classPassenger_1_1ApplicationPoolServer-members.html +4 -4
- data/doc/cxxapi/classPassenger_1_1ApplicationPoolServer.html +26 -23
- data/doc/cxxapi/classPassenger_1_1ApplicationPool__inherit__graph.map +1 -1
- data/doc/cxxapi/classPassenger_1_1ApplicationPool__inherit__graph.md5 +1 -1
- data/doc/cxxapi/classPassenger_1_1ApplicationPool__inherit__graph.png +0 -0
- data/doc/cxxapi/classPassenger_1_1Application_1_1Session-members.html +17 -17
- data/doc/cxxapi/classPassenger_1_1Application_1_1Session.html +139 -136
- data/doc/cxxapi/classPassenger_1_1BufferedUpload-members.html +4 -4
- data/doc/cxxapi/classPassenger_1_1BufferedUpload.html +13 -10
- data/doc/cxxapi/classPassenger_1_1BusyException-members.html +4 -4
- data/doc/cxxapi/classPassenger_1_1BusyException.html +11 -8
- data/doc/cxxapi/classPassenger_1_1ConfigurationException-members.html +4 -4
- data/doc/cxxapi/classPassenger_1_1ConfigurationException.html +11 -8
- data/doc/cxxapi/classPassenger_1_1DirectoryMapper-members.html +4 -5
- data/doc/cxxapi/classPassenger_1_1DirectoryMapper.html +45 -43
- data/doc/cxxapi/classPassenger_1_1DummySpawnManager-members.html +4 -4
- data/doc/cxxapi/classPassenger_1_1DummySpawnManager.html +13 -10
- data/doc/cxxapi/classPassenger_1_1FileChecker-members.html +4 -4
- data/doc/cxxapi/classPassenger_1_1FileChecker.html +22 -19
- data/doc/cxxapi/classPassenger_1_1FileNotFoundException-members.html +4 -4
- data/doc/cxxapi/classPassenger_1_1FileNotFoundException.html +12 -9
- data/doc/cxxapi/classPassenger_1_1FileNotFoundException__inherit__graph.map +1 -1
- data/doc/cxxapi/classPassenger_1_1FileNotFoundException__inherit__graph.md5 +1 -1
- data/doc/cxxapi/classPassenger_1_1FileNotFoundException__inherit__graph.png +0 -0
- data/doc/cxxapi/classPassenger_1_1FileSystemException-members.html +4 -4
- data/doc/cxxapi/classPassenger_1_1FileSystemException.html +14 -11
- data/doc/cxxapi/classPassenger_1_1FileSystemException__inherit__graph.map +1 -1
- data/doc/cxxapi/classPassenger_1_1FileSystemException__inherit__graph.md5 +1 -1
- data/doc/cxxapi/classPassenger_1_1FileSystemException__inherit__graph.png +0 -0
- data/doc/cxxapi/classPassenger_1_1IOException-members.html +4 -4
- data/doc/cxxapi/classPassenger_1_1IOException.html +12 -9
- data/doc/cxxapi/classPassenger_1_1IOException__inherit__graph.map +1 -1
- data/doc/cxxapi/classPassenger_1_1IOException__inherit__graph.md5 +1 -1
- data/doc/cxxapi/classPassenger_1_1IOException__inherit__graph.png +0 -0
- data/doc/cxxapi/classPassenger_1_1MessageChannel-members.html +4 -4
- data/doc/cxxapi/classPassenger_1_1MessageChannel.html +228 -225
- data/doc/cxxapi/classPassenger_1_1RuntimeException-members.html +4 -4
- data/doc/cxxapi/classPassenger_1_1RuntimeException.html +11 -8
- data/doc/cxxapi/classPassenger_1_1SpawnException-members.html +4 -4
- data/doc/cxxapi/classPassenger_1_1SpawnException.html +14 -11
- data/doc/cxxapi/classPassenger_1_1SpawnManager-members.html +4 -4
- data/doc/cxxapi/classPassenger_1_1SpawnManager.html +50 -47
- data/doc/cxxapi/classPassenger_1_1StandardApplicationPool-members.html +4 -4
- data/doc/cxxapi/classPassenger_1_1StandardApplicationPool.html +73 -70
- data/doc/cxxapi/classPassenger_1_1StandardApplicationPool__inherit__graph.map +1 -1
- data/doc/cxxapi/classPassenger_1_1StandardApplicationPool__inherit__graph.md5 +1 -1
- data/doc/cxxapi/classPassenger_1_1StandardApplicationPool__inherit__graph.png +0 -0
- data/doc/cxxapi/classPassenger_1_1SystemException-members.html +4 -4
- data/doc/cxxapi/classPassenger_1_1SystemException.html +17 -14
- data/doc/cxxapi/classPassenger_1_1SystemException__inherit__graph.map +1 -1
- data/doc/cxxapi/classPassenger_1_1SystemException__inherit__graph.md5 +1 -1
- data/doc/cxxapi/classPassenger_1_1SystemException__inherit__graph.png +0 -0
- data/doc/cxxapi/classPassenger_1_1SystemTime-members.html +4 -4
- data/doc/cxxapi/classPassenger_1_1SystemTime.html +14 -11
- data/doc/cxxapi/classes.html +35 -0
- data/doc/cxxapi/definitions_8h-source.html +9 -4
- data/doc/cxxapi/doxygen.css +311 -303
- data/doc/cxxapi/files.html +9 -18
- data/doc/cxxapi/functions.html +5 -224
- data/doc/cxxapi/functions_func.html +5 -185
- data/doc/cxxapi/functions_type.html +4 -4
- data/doc/cxxapi/functions_vars.html +4 -4
- data/doc/cxxapi/graph_legend.dot +19 -19
- data/doc/cxxapi/graph_legend.html +5 -5
- data/doc/cxxapi/graph_legend.png +0 -0
- data/doc/cxxapi/group__Configuration.html +11 -13
- data/doc/cxxapi/group__Configuration.png +0 -0
- data/doc/cxxapi/group__Core.html +10 -12
- data/doc/cxxapi/group__Core.png +0 -0
- data/doc/cxxapi/group__Exceptions.html +5 -7
- data/doc/cxxapi/group__Hooks.html +5 -7
- data/doc/cxxapi/group__Hooks.png +0 -0
- data/doc/cxxapi/group__Support.html +5 -624
- data/doc/cxxapi/hierarchy.html +6 -6
- 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 +1 -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 -2
- 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 +2 -1
- 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.map +1 -1
- data/doc/cxxapi/inherit__graph__17.md5 +1 -1
- data/doc/cxxapi/inherit__graph__17.png +0 -0
- data/doc/cxxapi/inherit__graph__18.map +1 -1
- data/doc/cxxapi/inherit__graph__18.md5 +1 -1
- data/doc/cxxapi/inherit__graph__18.png +0 -0
- data/doc/cxxapi/inherit__graph__19.map +1 -1
- data/doc/cxxapi/inherit__graph__19.md5 +1 -1
- 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 +2 -2
- 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 +1 -2
- 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 +2 -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 -1
- data/doc/cxxapi/inherit__graph__9.md5 +1 -1
- data/doc/cxxapi/inherit__graph__9.png +0 -0
- data/doc/cxxapi/inherits.html +41 -41
- data/doc/cxxapi/main.html +4 -4
- data/doc/cxxapi/modules.html +4 -5
- data/doc/cxxapi/structPassenger_1_1AnythingToString-members.html +4 -4
- data/doc/cxxapi/structPassenger_1_1AnythingToString.html +13 -10
- data/doc/cxxapi/structPassenger_1_1AnythingToString_3_01vector_3_01string_01_4_01_4-members.html +5 -5
- data/doc/cxxapi/structPassenger_1_1AnythingToString_3_01vector_3_01string_01_4_01_4.html +16 -13
- data/doc/cxxapi/structPassenger_1_1PoolOptions-members.html +4 -4
- data/doc/cxxapi/structPassenger_1_1PoolOptions.html +63 -60
- data/doc/cxxapi/tabs.css +5 -2
- data/doc/cxxapi/tree.html +7 -81
- data/doc/rdoc/classes/ConditionVariable.html +59 -59
- data/doc/rdoc/classes/Exception.html +11 -11
- data/doc/rdoc/classes/GC.html +4 -4
- data/doc/rdoc/classes/IO.html +14 -14
- data/doc/rdoc/classes/PhusionPassenger.html +75 -20
- data/doc/rdoc/classes/PhusionPassenger/AbstractInstaller.html +153 -0
- data/doc/rdoc/classes/PhusionPassenger/AbstractRequestHandler.html +125 -130
- data/doc/rdoc/classes/PhusionPassenger/AbstractServer.html +236 -236
- data/doc/rdoc/classes/PhusionPassenger/AbstractServerCollection.html +213 -213
- data/doc/rdoc/classes/PhusionPassenger/AdminTools.html +28 -28
- data/doc/rdoc/classes/PhusionPassenger/AdminTools/ControlProcess.html +91 -75
- data/doc/rdoc/classes/PhusionPassenger/AppInitError.html +10 -10
- data/doc/rdoc/classes/PhusionPassenger/Application.html +64 -64
- data/doc/rdoc/classes/PhusionPassenger/ConsoleTextTemplate.html +34 -34
- data/doc/rdoc/classes/PhusionPassenger/FrameworkInitError.html +13 -13
- data/doc/rdoc/classes/PhusionPassenger/HTMLTemplate.html +30 -30
- data/doc/rdoc/classes/PhusionPassenger/InitializationError.html +10 -10
- data/doc/rdoc/classes/PhusionPassenger/MessageChannel.html +136 -136
- data/doc/rdoc/classes/PhusionPassenger/NativeSupport.html +24 -24
- data/doc/rdoc/classes/PhusionPassenger/Rack/ApplicationSpawner.html +42 -42
- data/doc/rdoc/classes/PhusionPassenger/Rack/RequestHandler.html +55 -53
- data/doc/rdoc/classes/PhusionPassenger/Railz.html +1 -1
- data/doc/rdoc/classes/PhusionPassenger/Railz/ApplicationSpawner.html +25 -30
- data/doc/rdoc/classes/PhusionPassenger/Railz/CGIFixed.html +23 -23
- data/doc/rdoc/classes/PhusionPassenger/Railz/FrameworkSpawner.html +116 -117
- data/doc/rdoc/classes/PhusionPassenger/Railz/RequestHandler.html +22 -22
- data/doc/rdoc/classes/PhusionPassenger/SpawnManager.html +118 -124
- data/doc/rdoc/classes/PhusionPassenger/UnknownError.html +10 -10
- data/doc/rdoc/classes/PhusionPassenger/Utils.html +354 -354
- data/doc/rdoc/classes/PhusionPassenger/VersionNotFound.html +9 -9
- data/doc/rdoc/classes/PhusionPassenger/WSGI/ApplicationSpawner.html +37 -37
- data/doc/rdoc/classes/PlatformInfo.html +282 -261
- data/doc/rdoc/classes/RakeExtensions.html +7 -7
- data/doc/rdoc/classes/Signal.html +26 -26
- data/doc/rdoc/created.rid +1 -1
- data/doc/rdoc/files/DEVELOPERS_TXT.html +6 -1
- data/doc/rdoc/files/README.html +15 -6
- data/doc/rdoc/files/ext/phusion_passenger/native_support_c.html +1 -1
- 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 +20 -13
- data/doc/rdoc/files/lib/phusion_passenger/abstract_server_collection_rb.html +19 -13
- data/doc/rdoc/files/lib/phusion_passenger/abstract_server_rb.html +19 -13
- data/doc/rdoc/files/lib/phusion_passenger/admin_tools/control_process_rb.html +31 -1
- data/doc/rdoc/files/lib/phusion_passenger/admin_tools_rb.html +31 -1
- data/doc/rdoc/files/lib/phusion_passenger/application_rb.html +19 -13
- data/doc/rdoc/files/lib/phusion_passenger/console_text_template_rb.html +19 -13
- data/doc/rdoc/files/lib/phusion_passenger/constants_rb.html +21 -12
- data/doc/rdoc/files/lib/phusion_passenger/dependencies_rb.html +19 -13
- data/doc/rdoc/files/lib/phusion_passenger/events_rb.html +19 -13
- data/doc/rdoc/files/lib/phusion_passenger/exceptions_rb.html +19 -13
- data/doc/rdoc/files/lib/phusion_passenger/html_template_rb.html +19 -13
- data/doc/rdoc/files/lib/phusion_passenger/message_channel_rb.html +19 -13
- data/doc/rdoc/files/lib/phusion_passenger/packaging_rb.html +122 -0
- data/doc/rdoc/files/lib/phusion_passenger/platform_info_rb.html +19 -13
- data/doc/rdoc/files/lib/phusion_passenger/rack/application_spawner_rb.html +22 -12
- data/doc/rdoc/files/lib/phusion_passenger/rack/request_handler_rb.html +21 -12
- data/doc/rdoc/files/lib/phusion_passenger/railz/application_spawner_rb.html +19 -13
- data/doc/rdoc/files/lib/phusion_passenger/railz/cgi_fixed_rb.html +1 -1
- data/doc/rdoc/files/lib/phusion_passenger/railz/framework_spawner_rb.html +19 -13
- data/doc/rdoc/files/lib/phusion_passenger/railz/request_handler_rb.html +21 -12
- data/doc/rdoc/files/lib/phusion_passenger/simple_benchmarking_rb.html +19 -13
- data/doc/rdoc/files/lib/phusion_passenger/spawn_manager_rb.html +19 -13
- data/doc/rdoc/files/lib/phusion_passenger/utils_rb.html +27 -21
- data/doc/rdoc/files/lib/phusion_passenger/wsgi/application_spawner_rb.html +21 -12
- data/doc/rdoc/files/misc/rake/extensions_rb.html +21 -12
- data/doc/rdoc/fr_class_index.html +1 -0
- data/doc/rdoc/fr_file_index.html +2 -0
- data/doc/rdoc/fr_method_index.html +116 -112
- data/doc/users_guide_snippets/analysis_and_system_maintenance_tools.txt +144 -0
- data/doc/users_guide_snippets/appendix_a_about.txt +13 -0
- data/doc/users_guide_snippets/appendix_b_terminology.txt +63 -0
- data/doc/users_guide_snippets/appendix_c_spawning_methods.txt +304 -0
- data/doc/users_guide_snippets/global_queueing_explained.txt +78 -0
- data/doc/users_guide_snippets/rackup_specifications.txt +75 -0
- data/doc/users_guide_snippets/rails_spawn_method.txt +48 -0
- data/doc/users_guide_snippets/tips.txt +173 -0
- data/ext/apache2/Bucket.cpp +17 -12
- data/ext/apache2/Bucket.h +17 -12
- data/ext/apache2/Configuration.cpp +17 -12
- data/ext/apache2/Configuration.h +27 -14
- data/ext/apache2/DirectoryMapper.h +21 -12
- data/ext/apache2/Hooks.cpp +67 -21
- data/ext/apache2/Hooks.h +17 -12
- data/ext/apache2/mod_passenger.c +17 -12
- data/ext/{apache2 → common}/Application.h +19 -14
- data/ext/{apache2 → common}/ApplicationPool.h +17 -12
- data/ext/{apache2 → common}/ApplicationPoolServer.h +18 -72
- data/ext/{apache2 → common}/ApplicationPoolServerExecutable.cpp +45 -104
- data/ext/common/ApplicationPoolStatusReporter.h +212 -0
- data/ext/{apache2 → common}/CachedFileStat.cpp +17 -12
- data/ext/{apache2 → common}/CachedFileStat.h +17 -12
- data/ext/{apache2 → common}/DummySpawnManager.h +17 -12
- data/ext/{apache2 → common}/Exceptions.h +17 -12
- data/ext/{apache2 → common}/FileChecker.h +17 -12
- data/ext/common/Logging.cpp +65 -0
- data/ext/{apache2 → common}/Logging.h +17 -12
- data/ext/{apache2 → common}/MessageChannel.h +17 -12
- data/ext/{apache2 → common}/PoolOptions.h +17 -12
- data/ext/{apache2 → common}/SpawnManager.h +17 -12
- data/ext/{apache2 → common}/StandardApplicationPool.h +17 -12
- data/ext/common/StaticString.h +147 -0
- data/ext/common/SystemTime.cpp +33 -0
- data/ext/{apache2 → common}/SystemTime.h +17 -12
- data/ext/{apache2 → common}/Utils.cpp +69 -12
- data/ext/{apache2 → common}/Utils.h +41 -12
- data/ext/nginx/Configuration.c +1091 -0
- data/ext/nginx/Configuration.h +71 -0
- data/ext/nginx/ContentHandler.c +1154 -0
- data/ext/nginx/ContentHandler.h +64 -0
- data/ext/nginx/HelperServer.cpp +857 -0
- data/ext/nginx/HttpStatusExtractor.h +161 -0
- data/ext/nginx/ScgiRequestParser.h +317 -0
- data/ext/nginx/StaticContentHandler.c +222 -0
- data/ext/nginx/StaticContentHandler.h +37 -0
- data/ext/nginx/config +41 -0
- data/ext/nginx/ngx_http_passenger_module.c +572 -0
- data/ext/nginx/ngx_http_passenger_module.h +72 -0
- data/ext/oxt/backtrace.cpp +8 -1
- data/ext/oxt/system_calls.cpp +40 -0
- data/ext/oxt/system_calls.hpp +14 -7
- data/ext/phusion_passenger/extconf.rb +17 -12
- data/ext/phusion_passenger/native_support.c +19 -12
- data/lib/phusion_passenger/abstract_installer.rb +196 -0
- data/lib/phusion_passenger/abstract_request_handler.rb +19 -24
- data/lib/phusion_passenger/abstract_server.rb +17 -12
- data/lib/phusion_passenger/abstract_server_collection.rb +17 -12
- data/lib/phusion_passenger/admin_tools.rb +23 -0
- data/lib/phusion_passenger/admin_tools/control_process.rb +39 -13
- data/lib/phusion_passenger/application.rb +17 -12
- data/lib/phusion_passenger/console_text_template.rb +17 -12
- data/lib/phusion_passenger/constants.rb +22 -11
- data/lib/phusion_passenger/dependencies.rb +47 -12
- data/lib/phusion_passenger/events.rb +17 -12
- data/lib/phusion_passenger/exceptions.rb +17 -12
- data/lib/phusion_passenger/html_template.rb +17 -12
- data/lib/phusion_passenger/message_channel.rb +17 -12
- data/lib/phusion_passenger/packaging.rb +39 -0
- data/lib/phusion_passenger/platform_info.rb +48 -22
- data/lib/phusion_passenger/rack/application_spawner.rb +22 -11
- data/lib/phusion_passenger/rack/request_handler.rb +21 -12
- data/lib/phusion_passenger/railz/application_spawner.rb +23 -23
- data/lib/phusion_passenger/railz/framework_spawner.rb +18 -14
- data/lib/phusion_passenger/railz/request_handler.rb +18 -11
- data/lib/phusion_passenger/simple_benchmarking.rb +17 -12
- data/lib/phusion_passenger/spawn_manager.rb +17 -20
- data/lib/phusion_passenger/templates/{apache_must_be_compiled_with_compatible_mpm.txt.erb → apache2/apache_must_be_compiled_with_compatible_mpm.txt.erb} +0 -0
- data/lib/phusion_passenger/templates/{apache2_config_snippets.txt.erb → apache2/config_snippets.txt.erb} +0 -0
- data/lib/phusion_passenger/templates/{deployment_example.txt.erb → apache2/deployment_example.txt.erb} +0 -0
- data/lib/phusion_passenger/templates/{no_write_permission_to_passenger_root.txt.erb → apache2/no_write_permission_to_passenger_root.txt.erb} +0 -0
- data/lib/phusion_passenger/templates/{possible_solutions_for_compilation_and_installation_problems.txt.erb → apache2/possible_solutions_for_compilation_and_installation_problems.txt.erb} +0 -0
- data/lib/phusion_passenger/templates/{run_installer_as_root.txt.erb → apache2/run_installer_as_root.txt.erb} +0 -0
- data/lib/phusion_passenger/templates/{welcome.txt.erb → apache2/welcome.txt.erb} +0 -0
- data/lib/phusion_passenger/templates/nginx/ask_for_extra_configure_flags.txt.erb +8 -0
- data/lib/phusion_passenger/templates/nginx/cannot_write_to_dir.txt.erb +11 -0
- data/lib/phusion_passenger/templates/nginx/config_snippets.txt.erb +17 -0
- data/lib/phusion_passenger/templates/nginx/config_snippets_inserted.txt.erb +20 -0
- data/lib/phusion_passenger/templates/nginx/confirm_extra_configure_flags.txt.erb +5 -0
- data/lib/phusion_passenger/templates/nginx/deployment_example.txt.erb +22 -0
- data/lib/phusion_passenger/templates/nginx/pcre_could_not_be_downloaded.txt.erb +11 -0
- data/lib/phusion_passenger/templates/nginx/pcre_could_not_be_extracted.txt.erb +11 -0
- data/lib/phusion_passenger/templates/nginx/possible_solutions_for_compilation_and_installation_problems.txt.erb +11 -0
- data/lib/phusion_passenger/templates/nginx/possible_solutions_for_download_and_extraction_problems.txt.erb +20 -0
- data/lib/phusion_passenger/templates/nginx/query_download_and_install.txt.erb +21 -0
- data/lib/phusion_passenger/templates/nginx/run_installer_as_root.txt.erb +8 -0
- data/lib/phusion_passenger/templates/nginx/welcome.txt.erb +15 -0
- data/lib/phusion_passenger/utils.rb +20 -15
- data/lib/phusion_passenger/wsgi/application_spawner.rb +18 -11
- data/lib/phusion_passenger/wsgi/request_handler.py +23 -0
- data/misc/copy_boost_headers.rb +23 -0
- data/misc/find_owner_pipe_leaks.rb +18 -11
- data/misc/rake/cplusplus.rb +18 -11
- data/misc/rake/extensions.rb +21 -14
- data/misc/render_error_pages.rb +18 -11
- data/test/ApplicationPoolServerTest.cpp +1 -3
- data/test/ApplicationPoolServer_ApplicationPoolTest.cpp +1 -1
- data/test/CxxTestMain.cpp +19 -3
- data/test/HttpStatusExtractorTest.cpp +181 -0
- data/test/ScgiRequestParserTest.cpp +337 -0
- data/test/StaticStringTest.cpp +51 -0
- data/test/UtilsTest.cpp +32 -0
- data/test/config.yml.example +5 -0
- data/test/{integration_tests.rb → integration_tests/apache2_tests.rb} +7 -299
- data/test/integration_tests/hello_world_rack_spec.rb +36 -0
- data/test/integration_tests/hello_world_wsgi_spec.rb +41 -0
- data/test/integration_tests/mycook_spec.rb +192 -0
- data/test/integration_tests/nginx_tests.rb +98 -0
- data/test/ruby/rack/application_spawner_spec.rb +40 -0
- data/test/stub/nginx/koi-utf +109 -0
- data/test/stub/nginx/koi-win +103 -0
- data/test/stub/nginx/mime.types +70 -0
- data/test/stub/nginx/nginx.conf.erb +57 -0
- data/test/stub/nginx/win-utf +126 -0
- data/test/stub/rails_apps/mycook/app/controllers/uploads_controller.rb +4 -0
- data/test/stub/rails_apps/mycook/config/routes.rb +1 -1
- data/test/stub/wsgi/passenger_wsgi.pyc +0 -0
- data/test/support/Support.h +40 -0
- data/test/support/nginx_controller.rb +98 -0
- data/test/support/test_helper.rb +79 -0
- metadata +1091 -1028
- data/benchmark/DummyRequestHandler.cpp +0 -101
- data/ext/apache2/Logging.cpp +0 -60
- data/ext/apache2/SystemTime.cpp +0 -28
@@ -0,0 +1,71 @@
|
|
1
|
+
/*
|
2
|
+
* Copyright (C) Igor Sysoev
|
3
|
+
* Copyright (C) 2007 Manlio Perillo (manlio.perillo@gmail.com)
|
4
|
+
* Copyright (C) 2008, 2009 Phusion
|
5
|
+
*
|
6
|
+
* Redistribution and use in source and binary forms, with or without
|
7
|
+
* modification, are permitted provided that the following conditions
|
8
|
+
* are met:
|
9
|
+
* 1. Redistributions of source code must retain the above copyright
|
10
|
+
* notice, this list of conditions and the following disclaimer.
|
11
|
+
* 2. Redistributions in binary form must reproduce the above copyright
|
12
|
+
* notice, this list of conditions and the following disclaimer in the
|
13
|
+
* documentation and/or other materials provided with the distribution.
|
14
|
+
*
|
15
|
+
* THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
16
|
+
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
17
|
+
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
18
|
+
* ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
|
19
|
+
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
20
|
+
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
21
|
+
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
22
|
+
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
23
|
+
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
24
|
+
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
25
|
+
* SUCH DAMAGE.
|
26
|
+
*/
|
27
|
+
|
28
|
+
#ifndef _PASSENGER_NGINX_CONFIGURATION_H_
|
29
|
+
#define _PASSENGER_NGINX_CONFIGURATION_H_
|
30
|
+
|
31
|
+
#include <ngx_config.h>
|
32
|
+
#include <ngx_http.h>
|
33
|
+
|
34
|
+
typedef struct {
|
35
|
+
ngx_http_upstream_conf_t upstream;
|
36
|
+
ngx_str_t index;
|
37
|
+
ngx_array_t *flushes;
|
38
|
+
ngx_array_t *vars_len;
|
39
|
+
ngx_array_t *vars;
|
40
|
+
ngx_array_t *vars_source;
|
41
|
+
|
42
|
+
ngx_flag_t enabled;
|
43
|
+
ngx_flag_t use_global_queue;
|
44
|
+
ngx_str_t environment;
|
45
|
+
ngx_str_t spawn_method;
|
46
|
+
int framework_spawner_idle_time;
|
47
|
+
int app_spawner_idle_time;
|
48
|
+
ngx_array_t *base_uris;
|
49
|
+
} passenger_loc_conf_t;
|
50
|
+
|
51
|
+
typedef struct {
|
52
|
+
ngx_str_t root_dir;
|
53
|
+
ngx_str_t ruby;
|
54
|
+
ngx_uint_t log_level;
|
55
|
+
ngx_uint_t max_pool_size;
|
56
|
+
ngx_uint_t max_instances_per_app;
|
57
|
+
ngx_uint_t pool_idle_time;
|
58
|
+
ngx_flag_t user_switching;
|
59
|
+
ngx_str_t default_user;
|
60
|
+
} passenger_main_conf_t;
|
61
|
+
|
62
|
+
extern const ngx_command_t passenger_commands[];
|
63
|
+
extern passenger_main_conf_t passenger_main_conf;
|
64
|
+
|
65
|
+
void *passenger_create_main_conf(ngx_conf_t *cf);
|
66
|
+
char *passenger_init_main_conf(ngx_conf_t *cf, void *conf_pointer);
|
67
|
+
void *passenger_create_loc_conf(ngx_conf_t *cf);
|
68
|
+
char *passenger_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child);
|
69
|
+
|
70
|
+
#endif /* _PASSENGER_NGINX_CONFIGURATION_H_ */
|
71
|
+
|
@@ -0,0 +1,1154 @@
|
|
1
|
+
/*
|
2
|
+
* Copyright (C) Igor Sysoev
|
3
|
+
* Copyright (C) 2007 Manlio Perillo (manlio.perillo@gmail.com)
|
4
|
+
* Copyright (C) 2008, 2009 Phusion
|
5
|
+
*
|
6
|
+
* Redistribution and use in source and binary forms, with or without
|
7
|
+
* modification, are permitted provided that the following conditions
|
8
|
+
* are met:
|
9
|
+
* 1. Redistributions of source code must retain the above copyright
|
10
|
+
* notice, this list of conditions and the following disclaimer.
|
11
|
+
* 2. Redistributions in binary form must reproduce the above copyright
|
12
|
+
* notice, this list of conditions and the following disclaimer in the
|
13
|
+
* documentation and/or other materials provided with the distribution.
|
14
|
+
*
|
15
|
+
* THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
16
|
+
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
17
|
+
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
18
|
+
* ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
|
19
|
+
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
20
|
+
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
21
|
+
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
22
|
+
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
23
|
+
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
24
|
+
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
25
|
+
* SUCH DAMAGE.
|
26
|
+
*/
|
27
|
+
|
28
|
+
#include <nginx.h>
|
29
|
+
#include "ngx_http_passenger_module.h"
|
30
|
+
#include "ContentHandler.h"
|
31
|
+
#include "StaticContentHandler.h"
|
32
|
+
#include "Configuration.h"
|
33
|
+
|
34
|
+
|
35
|
+
#define NGX_HTTP_SCGI_PARSE_NO_HEADER 20
|
36
|
+
|
37
|
+
typedef enum {
|
38
|
+
FT_ERROR,
|
39
|
+
FT_FILE,
|
40
|
+
FT_DIRECTORY,
|
41
|
+
FT_OTHER
|
42
|
+
} FileType;
|
43
|
+
|
44
|
+
|
45
|
+
static ngx_int_t reinit_request(ngx_http_request_t *r);
|
46
|
+
static ngx_int_t process_status_line(ngx_http_request_t *r);
|
47
|
+
static ngx_int_t parse_status_line(ngx_http_request_t *r,
|
48
|
+
passenger_context_t *context);
|
49
|
+
static ngx_int_t process_header(ngx_http_request_t *r);
|
50
|
+
static void abort_request(ngx_http_request_t *r);
|
51
|
+
static void finalize_request(ngx_http_request_t *r, ngx_int_t rc);
|
52
|
+
|
53
|
+
|
54
|
+
static void
|
55
|
+
uint_to_str(ngx_uint_t i, u_char *str, ngx_uint_t size) {
|
56
|
+
ngx_memzero(str, size);
|
57
|
+
ngx_snprintf(str, size, "%ui", i);
|
58
|
+
}
|
59
|
+
|
60
|
+
static FileType
|
61
|
+
get_file_type(const u_char *filename, unsigned int throttle_rate) {
|
62
|
+
struct stat buf;
|
63
|
+
int ret;
|
64
|
+
|
65
|
+
ret = cached_multi_file_stat_perform(passenger_stat_cache,
|
66
|
+
(const char *) filename,
|
67
|
+
&buf,
|
68
|
+
throttle_rate);
|
69
|
+
if (ret == 0) {
|
70
|
+
if (S_ISREG(buf.st_mode)) {
|
71
|
+
return FT_FILE;
|
72
|
+
} else if (S_ISDIR(buf.st_mode)) {
|
73
|
+
return FT_DIRECTORY;
|
74
|
+
} else {
|
75
|
+
return FT_OTHER;
|
76
|
+
}
|
77
|
+
} else {
|
78
|
+
return FT_ERROR;
|
79
|
+
}
|
80
|
+
}
|
81
|
+
|
82
|
+
static int
|
83
|
+
file_exists(const u_char *filename, unsigned int throttle_rate) {
|
84
|
+
return get_file_type(filename, throttle_rate) == FT_FILE;
|
85
|
+
}
|
86
|
+
|
87
|
+
static passenger_app_type_t
|
88
|
+
detect_application_type(const ngx_str_t *public_dir) {
|
89
|
+
u_char filename[NGX_MAX_PATH];
|
90
|
+
|
91
|
+
ngx_memzero(filename, sizeof(filename));
|
92
|
+
ngx_snprintf(filename, sizeof(filename), "%s/%s",
|
93
|
+
public_dir->data, "../config/environment.rb");
|
94
|
+
if (file_exists(filename, 1)) {
|
95
|
+
return AP_RAILS;
|
96
|
+
}
|
97
|
+
|
98
|
+
ngx_memzero(filename, sizeof(filename));
|
99
|
+
ngx_snprintf(filename, sizeof(filename), "%s/%s",
|
100
|
+
public_dir->data, "../config.ru");
|
101
|
+
if (file_exists(filename, 1)) {
|
102
|
+
return AP_RACK;
|
103
|
+
}
|
104
|
+
|
105
|
+
ngx_memzero(filename, sizeof(filename));
|
106
|
+
ngx_snprintf(filename, sizeof(filename), "%s/%s",
|
107
|
+
public_dir->data, "../config/passenger_wsgi.py");
|
108
|
+
if (file_exists(filename, 1)) {
|
109
|
+
return AP_WSGI;
|
110
|
+
}
|
111
|
+
|
112
|
+
return AP_NONE;
|
113
|
+
}
|
114
|
+
|
115
|
+
/**
|
116
|
+
* Maps the URI for the given request to a page cache file, if possible.
|
117
|
+
*
|
118
|
+
* @return Whether the URI has been successfully mapped to a page cache file.
|
119
|
+
* @param r The corresponding request.
|
120
|
+
* @param public_dir The web application's 'public' directory.
|
121
|
+
* @param filename The filename that the URI normally maps to.
|
122
|
+
* @param filename_len The length of the <tt>filename</tt> string.
|
123
|
+
* @param root The size of the root path in <tt>filename</tt>.
|
124
|
+
* @param page_cache_file If mapping was successful, then the page cache
|
125
|
+
* file's filename will be stored in here.
|
126
|
+
* <tt>page_cache_file.data</tt> must already point to
|
127
|
+
* a buffer, and <tt>page_cache_file.len</tt> must be set
|
128
|
+
* to the size of this buffer, including terminating NUL.
|
129
|
+
*/
|
130
|
+
static int
|
131
|
+
map_uri_to_page_cache_file(ngx_http_request_t *r, ngx_str_t *public_dir,
|
132
|
+
const u_char *filename, size_t filename_len,
|
133
|
+
ngx_str_t *page_cache_file)
|
134
|
+
{
|
135
|
+
u_char *end;
|
136
|
+
|
137
|
+
if ((r->method != NGX_HTTP_GET && r->method != NGX_HTTP_HEAD) || filename_len == 0) {
|
138
|
+
return 0;
|
139
|
+
}
|
140
|
+
|
141
|
+
/* From this point on we know that filename is not an empty string. */
|
142
|
+
|
143
|
+
/* Check whether filename is equal to public_dir. filename may also be equal to
|
144
|
+
* public_dir + "/" so check for that as well.
|
145
|
+
*/
|
146
|
+
if ((public_dir->len == filename_len && memcmp(public_dir->data, filename,
|
147
|
+
filename_len) == 0) ||
|
148
|
+
(public_dir->len == filename_len - 1 &&
|
149
|
+
filename[filename_len - 1] == '/' &&
|
150
|
+
memcmp(public_dir->data, filename, filename_len - 1) == 0)
|
151
|
+
) {
|
152
|
+
/* If the URI maps to the 'public' directory (i.e. the request is the
|
153
|
+
* base URI) then index.html is the page cache file.
|
154
|
+
*/
|
155
|
+
|
156
|
+
if (filename_len + sizeof("/index.html") > page_cache_file->len) {
|
157
|
+
/* Page cache filename doesn't fit in the buffer. */
|
158
|
+
return 0;
|
159
|
+
}
|
160
|
+
|
161
|
+
end = ngx_copy(page_cache_file->data, filename, filename_len);
|
162
|
+
if (filename[filename_len - 1] != '/') {
|
163
|
+
end = ngx_copy(end, "/", 1);
|
164
|
+
}
|
165
|
+
end = ngx_copy(end, "index.html", sizeof("index.html"));
|
166
|
+
|
167
|
+
} else {
|
168
|
+
/* Otherwise, the page cache file is just filename + ".html". */
|
169
|
+
|
170
|
+
if (filename_len + sizeof(".html") > page_cache_file->len) {
|
171
|
+
/* Page cache filename doesn't fit in the buffer. */
|
172
|
+
return 0;
|
173
|
+
}
|
174
|
+
|
175
|
+
end = ngx_copy(page_cache_file->data, filename, filename_len);
|
176
|
+
end = ngx_copy(end, ".html", sizeof(".html"));
|
177
|
+
}
|
178
|
+
|
179
|
+
if (file_exists(page_cache_file->data, 0)) {
|
180
|
+
page_cache_file->len = end - page_cache_file->data - 1;
|
181
|
+
return 1;
|
182
|
+
} else {
|
183
|
+
return 0;
|
184
|
+
}
|
185
|
+
}
|
186
|
+
|
187
|
+
static int
|
188
|
+
find_base_uri(ngx_http_request_t *r, const passenger_loc_conf_t *loc,
|
189
|
+
ngx_str_t *found_base_uri)
|
190
|
+
{
|
191
|
+
ngx_uint_t i;
|
192
|
+
ngx_str_t *base_uris, *base_uri, *uri;
|
193
|
+
|
194
|
+
if (loc->base_uris == NGX_CONF_UNSET_PTR) {
|
195
|
+
return 0;
|
196
|
+
} else {
|
197
|
+
base_uris = (ngx_str_t *) loc->base_uris->elts;
|
198
|
+
for (i = 0; i < loc->base_uris->nelts; i++) {
|
199
|
+
base_uri = &base_uris[i];
|
200
|
+
uri = &r->uri;
|
201
|
+
|
202
|
+
if (uri->len == 1 && uri->data[0] == '/') {
|
203
|
+
/* Ignore 'passenger_base_uri /' options. Users usually
|
204
|
+
* specify this out of ignorance.
|
205
|
+
*/
|
206
|
+
continue;
|
207
|
+
}
|
208
|
+
|
209
|
+
if (( uri->len == base_uri->len
|
210
|
+
&& ngx_strncmp(uri->data, base_uri->data, uri->len) == 0 )
|
211
|
+
|| ( uri->len > base_uri->len
|
212
|
+
&& ngx_strncmp(uri->data, base_uri->data, base_uri->len) == 0
|
213
|
+
&& uri->data[base_uri->len] == (u_char) '/' )) {
|
214
|
+
*found_base_uri = base_uris[i];
|
215
|
+
return 1;
|
216
|
+
}
|
217
|
+
}
|
218
|
+
return 0;
|
219
|
+
}
|
220
|
+
}
|
221
|
+
|
222
|
+
|
223
|
+
static ngx_int_t
|
224
|
+
create_request(ngx_http_request_t *r)
|
225
|
+
{
|
226
|
+
u_char ch;
|
227
|
+
u_char buf[sizeof("4294967296")];
|
228
|
+
size_t len, size, key_len, val_len, content_length;
|
229
|
+
const u_char *app_type_string;
|
230
|
+
size_t app_type_string_len;
|
231
|
+
u_char framework_spawner_idle_time_string[12];
|
232
|
+
u_char app_spawner_idle_time_string[12];
|
233
|
+
u_char *end;
|
234
|
+
ngx_uint_t i, n;
|
235
|
+
ngx_buf_t *b;
|
236
|
+
ngx_chain_t *cl, *body;
|
237
|
+
ngx_list_part_t *part;
|
238
|
+
ngx_table_elt_t *header;
|
239
|
+
ngx_http_script_code_pt code;
|
240
|
+
ngx_http_script_engine_t e, le;
|
241
|
+
passenger_loc_conf_t *slcf;
|
242
|
+
passenger_main_conf_t *main_conf;
|
243
|
+
passenger_context_t *context;
|
244
|
+
ngx_http_script_len_code_pt lcode;
|
245
|
+
|
246
|
+
slcf = ngx_http_get_module_loc_conf(r, ngx_http_passenger_module);
|
247
|
+
main_conf = &passenger_main_conf;
|
248
|
+
context = ngx_http_get_module_ctx(r, ngx_http_passenger_module);
|
249
|
+
if (context == NULL) {
|
250
|
+
return NGX_HTTP_INTERNAL_SERVER_ERROR;
|
251
|
+
}
|
252
|
+
|
253
|
+
switch (context->app_type) {
|
254
|
+
case AP_RAILS:
|
255
|
+
app_type_string = (const u_char *) "rails";
|
256
|
+
app_type_string_len = sizeof("rails");
|
257
|
+
break;
|
258
|
+
case AP_RACK:
|
259
|
+
app_type_string = (const u_char *) "rack";
|
260
|
+
app_type_string_len = sizeof("rack");
|
261
|
+
break;
|
262
|
+
case AP_WSGI:
|
263
|
+
app_type_string = (const u_char *) "wsgi";
|
264
|
+
app_type_string_len = sizeof("wsgi");
|
265
|
+
break;
|
266
|
+
default:
|
267
|
+
app_type_string = (const u_char *) "rails";
|
268
|
+
app_type_string_len = sizeof("rails");
|
269
|
+
break;
|
270
|
+
}
|
271
|
+
|
272
|
+
|
273
|
+
/**************************************************
|
274
|
+
* Determine the request header length.
|
275
|
+
**************************************************/
|
276
|
+
|
277
|
+
/* Length of the Content-Length header. */
|
278
|
+
if (r->headers_in.content_length_n < 0) {
|
279
|
+
content_length = 0;
|
280
|
+
} else {
|
281
|
+
content_length = r->headers_in.content_length_n;
|
282
|
+
}
|
283
|
+
uint_to_str(content_length, buf, sizeof(buf));
|
284
|
+
/* +1 for trailing null */
|
285
|
+
len = sizeof("CONTENT_LENGTH") + ngx_strlen(buf) + 1;
|
286
|
+
|
287
|
+
/* DOCUMENT_ROOT, PATH_INFO and base URI */
|
288
|
+
len += sizeof("DOCUMENT_ROOT") + context->public_dir.len + 1;
|
289
|
+
len += sizeof("PATH_INFO") + context->public_dir.len + 1;
|
290
|
+
if (context->base_uri.len > 0) {
|
291
|
+
len += sizeof("RAILS_RELATIVE_URL_ROOT") +
|
292
|
+
context->base_uri.len + 1;
|
293
|
+
}
|
294
|
+
|
295
|
+
/* Various other HTTP headers. */
|
296
|
+
if (r->headers_in.content_type != NULL
|
297
|
+
&& r->headers_in.content_type->value.len > 0) {
|
298
|
+
len += sizeof("CONTENT_TYPE") + r->headers_in.content_type->value.len + 1;
|
299
|
+
}
|
300
|
+
|
301
|
+
|
302
|
+
/* Lengths of Passenger application pool options. */
|
303
|
+
if (slcf->use_global_queue) {
|
304
|
+
len += sizeof("PASSENGER_USE_GLOBAL_QUEUE") + sizeof("true");
|
305
|
+
} else {
|
306
|
+
len += sizeof("PASSENGER_USE_GLOBAL_QUEUE") + sizeof("false");
|
307
|
+
}
|
308
|
+
len += sizeof("PASSENGER_ENVIRONMENT") + slcf->environment.len + 1;
|
309
|
+
len += sizeof("PASSENGER_SPAWN_METHOD") + slcf->spawn_method.len + 1;
|
310
|
+
len += sizeof("PASSENGER_APP_TYPE") + app_type_string_len;
|
311
|
+
|
312
|
+
end = ngx_snprintf(framework_spawner_idle_time_string,
|
313
|
+
sizeof(framework_spawner_idle_time_string) - 1,
|
314
|
+
"%d", slcf->framework_spawner_idle_time);
|
315
|
+
*end = '\0';
|
316
|
+
len += sizeof("PASSENGER_FRAMEWORK_SPAWNER_IDLE_TIME") +
|
317
|
+
ngx_strlen(framework_spawner_idle_time_string) + 1;
|
318
|
+
|
319
|
+
end = ngx_snprintf(app_spawner_idle_time_string,
|
320
|
+
sizeof(app_spawner_idle_time_string) - 1,
|
321
|
+
"%d", slcf->app_spawner_idle_time);
|
322
|
+
*end = '\0';
|
323
|
+
len += sizeof("PASSENGER_APP_SPAWNER_IDLE_TIME") +
|
324
|
+
ngx_strlen(app_spawner_idle_time_string) + 1;
|
325
|
+
|
326
|
+
/* Lengths of various CGI variables. */
|
327
|
+
if (slcf->vars_len) {
|
328
|
+
ngx_memzero(&le, sizeof(ngx_http_script_engine_t));
|
329
|
+
|
330
|
+
ngx_http_script_flush_no_cacheable_variables(r, slcf->flushes);
|
331
|
+
le.flushed = 1;
|
332
|
+
|
333
|
+
le.ip = slcf->vars_len->elts;
|
334
|
+
le.request = r;
|
335
|
+
|
336
|
+
while (*(uintptr_t *) le.ip) {
|
337
|
+
|
338
|
+
lcode = *(ngx_http_script_len_code_pt *) le.ip;
|
339
|
+
key_len = lcode(&le);
|
340
|
+
|
341
|
+
for (val_len = 0; *(uintptr_t *) le.ip; val_len += lcode(&le)) {
|
342
|
+
lcode = *(ngx_http_script_len_code_pt *) le.ip;
|
343
|
+
}
|
344
|
+
le.ip += sizeof(uintptr_t);
|
345
|
+
|
346
|
+
len += key_len + val_len;
|
347
|
+
}
|
348
|
+
}
|
349
|
+
|
350
|
+
/* Lengths of HTTP headers. */
|
351
|
+
if (slcf->upstream.pass_request_headers) {
|
352
|
+
|
353
|
+
part = &r->headers_in.headers.part;
|
354
|
+
header = part->elts;
|
355
|
+
|
356
|
+
for (i = 0; /* void */; i++) {
|
357
|
+
|
358
|
+
if (i >= part->nelts) {
|
359
|
+
if (part->next == NULL) {
|
360
|
+
break;
|
361
|
+
}
|
362
|
+
|
363
|
+
part = part->next;
|
364
|
+
header = part->elts;
|
365
|
+
i = 0;
|
366
|
+
}
|
367
|
+
|
368
|
+
len += sizeof("HTTP_") - 1 + header[i].key.len + 1
|
369
|
+
+ header[i].value.len + 1;
|
370
|
+
}
|
371
|
+
}
|
372
|
+
|
373
|
+
|
374
|
+
/**************************************************
|
375
|
+
* Build the request header data.
|
376
|
+
**************************************************/
|
377
|
+
|
378
|
+
size = passenger_helper_server_password.len +
|
379
|
+
/* netstring length + ":" + trailing "," */
|
380
|
+
/* note: 10 == sizeof("4294967296") - 1 */
|
381
|
+
len + 10 + 1 + 1;
|
382
|
+
|
383
|
+
b = ngx_create_temp_buf(r->pool, size);
|
384
|
+
if (b == NULL) {
|
385
|
+
return NGX_ERROR;
|
386
|
+
}
|
387
|
+
|
388
|
+
cl = ngx_alloc_chain_link(r->pool);
|
389
|
+
if (cl == NULL) {
|
390
|
+
return NGX_ERROR;
|
391
|
+
}
|
392
|
+
|
393
|
+
cl->buf = b;
|
394
|
+
|
395
|
+
/* Build SCGI header netstring length part. */
|
396
|
+
b->last = ngx_copy(b->last, passenger_helper_server_password.data,
|
397
|
+
passenger_helper_server_password.len);
|
398
|
+
|
399
|
+
b->last = ngx_snprintf(b->last, 10, "%ui", len);
|
400
|
+
*b->last++ = (u_char) ':';
|
401
|
+
|
402
|
+
/* Build CONTENT_LENGTH header. This must always be sent, even if 0. */
|
403
|
+
b->last = ngx_copy(b->last, "CONTENT_LENGTH",
|
404
|
+
sizeof("CONTENT_LENGTH"));
|
405
|
+
|
406
|
+
b->last = ngx_snprintf(b->last, 10, "%ui", content_length);
|
407
|
+
*b->last++ = (u_char) 0;
|
408
|
+
|
409
|
+
/* Build DOCUMENT_ROOT and base URI. */
|
410
|
+
b->last = ngx_copy(b->last, "DOCUMENT_ROOT", sizeof("DOCUMENT_ROOT"));
|
411
|
+
b->last = ngx_copy(b->last, context->public_dir.data,
|
412
|
+
context->public_dir.len + 1);
|
413
|
+
|
414
|
+
b->last = ngx_copy(b->last, "PATH_INFO", sizeof("PATH_INFO"));
|
415
|
+
b->last = ngx_copy(b->last, context->public_dir.data,
|
416
|
+
context->public_dir.len + 1);
|
417
|
+
|
418
|
+
if (context->base_uri.len > 0) {
|
419
|
+
b->last = ngx_copy(b->last, "RAILS_RELATIVE_URL_ROOT",
|
420
|
+
sizeof("RAILS_RELATIVE_URL_ROOT"));
|
421
|
+
b->last = ngx_copy(b->last, context->base_uri.data,
|
422
|
+
context->base_uri.len + 1);
|
423
|
+
}
|
424
|
+
|
425
|
+
/* Various other HTTP headers. */
|
426
|
+
if (r->headers_in.content_type != NULL
|
427
|
+
&& r->headers_in.content_type->value.len > 0) {
|
428
|
+
b->last = ngx_copy(b->last, "CONTENT_TYPE", sizeof("CONTENT_TYPE"));
|
429
|
+
b->last = ngx_copy(b->last, r->headers_in.content_type->value.data,
|
430
|
+
r->headers_in.content_type->value.len + 1);
|
431
|
+
}
|
432
|
+
|
433
|
+
|
434
|
+
/* Build Passenger application pool option headers. */
|
435
|
+
b->last = ngx_copy(b->last, "PASSENGER_USE_GLOBAL_QUEUE",
|
436
|
+
sizeof("PASSENGER_USE_GLOBAL_QUEUE"));
|
437
|
+
if (slcf->use_global_queue) {
|
438
|
+
b->last = ngx_copy(b->last, "true", sizeof("true"));
|
439
|
+
} else {
|
440
|
+
b->last = ngx_copy(b->last, "false", sizeof("false"));
|
441
|
+
}
|
442
|
+
|
443
|
+
b->last = ngx_copy(b->last, "PASSENGER_ENVIRONMENT",
|
444
|
+
sizeof("PASSENGER_ENVIRONMENT"));
|
445
|
+
b->last = ngx_copy(b->last, slcf->environment.data,
|
446
|
+
slcf->environment.len + 1);
|
447
|
+
|
448
|
+
b->last = ngx_copy(b->last, "PASSENGER_SPAWN_METHOD",
|
449
|
+
sizeof("PASSENGER_SPAWN_METHOD"));
|
450
|
+
b->last = ngx_copy(b->last, slcf->spawn_method.data,
|
451
|
+
slcf->spawn_method.len + 1);
|
452
|
+
|
453
|
+
b->last = ngx_copy(b->last, "PASSENGER_APP_TYPE",
|
454
|
+
sizeof("PASSENGER_APP_TYPE"));
|
455
|
+
b->last = ngx_copy(b->last, app_type_string, app_type_string_len);
|
456
|
+
|
457
|
+
b->last = ngx_copy(b->last, "PASSENGER_FRAMEWORK_SPAWNER_IDLE_TIME",
|
458
|
+
sizeof("PASSENGER_FRAMEWORK_SPAWNER_IDLE_TIME"));
|
459
|
+
b->last = ngx_copy(b->last, framework_spawner_idle_time_string,
|
460
|
+
ngx_strlen(framework_spawner_idle_time_string) + 1);
|
461
|
+
|
462
|
+
b->last = ngx_copy(b->last, "PASSENGER_APP_SPAWNER_IDLE_TIME",
|
463
|
+
sizeof("PASSENGER_APP_SPAWNER_IDLE_TIME"));
|
464
|
+
b->last = ngx_copy(b->last, app_spawner_idle_time_string,
|
465
|
+
ngx_strlen(app_spawner_idle_time_string) + 1);
|
466
|
+
|
467
|
+
if (slcf->vars_len) {
|
468
|
+
ngx_memzero(&e, sizeof(ngx_http_script_engine_t));
|
469
|
+
|
470
|
+
e.ip = slcf->vars->elts;
|
471
|
+
e.pos = b->last;
|
472
|
+
e.request = r;
|
473
|
+
e.flushed = 1;
|
474
|
+
|
475
|
+
le.ip = slcf->vars_len->elts;
|
476
|
+
|
477
|
+
while (*(uintptr_t *) le.ip) {
|
478
|
+
|
479
|
+
lcode = *(ngx_http_script_len_code_pt *) le.ip;
|
480
|
+
(void) lcode(&le);
|
481
|
+
|
482
|
+
for (val_len = 0; *(uintptr_t *) le.ip; val_len += lcode(&le)) {
|
483
|
+
lcode = *(ngx_http_script_len_code_pt *) le.ip;
|
484
|
+
}
|
485
|
+
le.ip += sizeof(uintptr_t);
|
486
|
+
|
487
|
+
while (*(uintptr_t *) e.ip) {
|
488
|
+
code = *(ngx_http_script_code_pt *) e.ip;
|
489
|
+
code((ngx_http_script_engine_t *) &e);
|
490
|
+
}
|
491
|
+
e.ip += sizeof(uintptr_t);
|
492
|
+
}
|
493
|
+
|
494
|
+
b->last = e.pos;
|
495
|
+
}
|
496
|
+
|
497
|
+
|
498
|
+
if (slcf->upstream.pass_request_headers) {
|
499
|
+
|
500
|
+
part = &r->headers_in.headers.part;
|
501
|
+
header = part->elts;
|
502
|
+
|
503
|
+
for (i = 0; /* void */; i++) {
|
504
|
+
|
505
|
+
if (i >= part->nelts) {
|
506
|
+
if (part->next == NULL) {
|
507
|
+
break;
|
508
|
+
}
|
509
|
+
|
510
|
+
part = part->next;
|
511
|
+
header = part->elts;
|
512
|
+
i = 0;
|
513
|
+
}
|
514
|
+
|
515
|
+
b->last = ngx_cpymem(b->last, "HTTP_", sizeof("HTTP_") - 1);
|
516
|
+
|
517
|
+
for (n = 0; n < header[i].key.len; n++) {
|
518
|
+
ch = header[i].key.data[n];
|
519
|
+
|
520
|
+
if (ch >= 'a' && ch <= 'z') {
|
521
|
+
ch &= ~0x20;
|
522
|
+
|
523
|
+
} else if (ch == '-') {
|
524
|
+
ch = '_';
|
525
|
+
}
|
526
|
+
|
527
|
+
*b->last++ = ch;
|
528
|
+
}
|
529
|
+
|
530
|
+
*b->last++ = (u_char) 0;
|
531
|
+
|
532
|
+
b->last = ngx_copy(b->last, header[i].value.data,
|
533
|
+
header[i].value.len);
|
534
|
+
*b->last++ = (u_char) 0;
|
535
|
+
}
|
536
|
+
}
|
537
|
+
|
538
|
+
|
539
|
+
*b->last++ = (u_char) ',';
|
540
|
+
|
541
|
+
if (slcf->upstream.pass_request_body) {
|
542
|
+
|
543
|
+
body = r->upstream->request_bufs;
|
544
|
+
r->upstream->request_bufs = cl;
|
545
|
+
|
546
|
+
while (body) {
|
547
|
+
b = ngx_alloc_buf(r->pool);
|
548
|
+
if (b == NULL) {
|
549
|
+
return NGX_ERROR;
|
550
|
+
}
|
551
|
+
|
552
|
+
ngx_memcpy(b, body->buf, sizeof(ngx_buf_t));
|
553
|
+
|
554
|
+
cl->next = ngx_alloc_chain_link(r->pool);
|
555
|
+
if (cl->next == NULL) {
|
556
|
+
return NGX_ERROR;
|
557
|
+
}
|
558
|
+
|
559
|
+
cl = cl->next;
|
560
|
+
cl->buf = b;
|
561
|
+
|
562
|
+
body = body->next;
|
563
|
+
}
|
564
|
+
|
565
|
+
b->flush = 1;
|
566
|
+
|
567
|
+
} else {
|
568
|
+
r->upstream->request_bufs = cl;
|
569
|
+
}
|
570
|
+
|
571
|
+
|
572
|
+
cl->next = NULL;
|
573
|
+
|
574
|
+
return NGX_OK;
|
575
|
+
}
|
576
|
+
|
577
|
+
|
578
|
+
static ngx_int_t
|
579
|
+
reinit_request(ngx_http_request_t *r)
|
580
|
+
{
|
581
|
+
passenger_context_t *context;
|
582
|
+
|
583
|
+
context = ngx_http_get_module_ctx(r, ngx_http_passenger_module);
|
584
|
+
|
585
|
+
if (context == NULL) {
|
586
|
+
return NGX_OK;
|
587
|
+
}
|
588
|
+
|
589
|
+
context->status = 0;
|
590
|
+
context->status_count = 0;
|
591
|
+
context->status_start = NULL;
|
592
|
+
context->status_end = NULL;
|
593
|
+
|
594
|
+
r->upstream->process_header = process_status_line;
|
595
|
+
|
596
|
+
return NGX_OK;
|
597
|
+
}
|
598
|
+
|
599
|
+
|
600
|
+
static ngx_int_t
|
601
|
+
process_status_line(ngx_http_request_t *r)
|
602
|
+
{
|
603
|
+
ngx_int_t rc;
|
604
|
+
ngx_http_upstream_t *u;
|
605
|
+
passenger_context_t *context;
|
606
|
+
|
607
|
+
context = ngx_http_get_module_ctx(r, ngx_http_passenger_module);
|
608
|
+
|
609
|
+
if (context == NULL) {
|
610
|
+
return NGX_HTTP_INTERNAL_SERVER_ERROR;
|
611
|
+
}
|
612
|
+
|
613
|
+
rc = parse_status_line(r, context);
|
614
|
+
|
615
|
+
if (rc == NGX_AGAIN) {
|
616
|
+
return rc;
|
617
|
+
}
|
618
|
+
|
619
|
+
u = r->upstream;
|
620
|
+
|
621
|
+
if (rc == NGX_HTTP_SCGI_PARSE_NO_HEADER) {
|
622
|
+
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
|
623
|
+
"upstream sent no valid HTTP/1.0 header");
|
624
|
+
|
625
|
+
#if 0
|
626
|
+
if (u->accel) {
|
627
|
+
return NGX_HTTP_UPSTREAM_INVALID_HEADER;
|
628
|
+
}
|
629
|
+
#endif
|
630
|
+
|
631
|
+
r->http_version = NGX_HTTP_VERSION_9;
|
632
|
+
u->headers_in.status_n = NGX_HTTP_OK;
|
633
|
+
u->state->status = NGX_HTTP_OK;
|
634
|
+
|
635
|
+
return NGX_OK;
|
636
|
+
}
|
637
|
+
|
638
|
+
u->headers_in.status_n = context->status;
|
639
|
+
u->state->status = context->status;
|
640
|
+
|
641
|
+
u->headers_in.status_line.len = context->status_end - context->status_start;
|
642
|
+
u->headers_in.status_line.data = ngx_palloc(r->pool,
|
643
|
+
u->headers_in.status_line.len);
|
644
|
+
if (u->headers_in.status_line.data == NULL) {
|
645
|
+
return NGX_HTTP_INTERNAL_SERVER_ERROR;
|
646
|
+
}
|
647
|
+
|
648
|
+
ngx_memcpy(u->headers_in.status_line.data, context->status_start,
|
649
|
+
u->headers_in.status_line.len);
|
650
|
+
|
651
|
+
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
|
652
|
+
"http scgi status %ui \"%V\"",
|
653
|
+
u->headers_in.status_n, &u->headers_in.status_line);
|
654
|
+
|
655
|
+
u->process_header = process_header;
|
656
|
+
|
657
|
+
return process_header(r);
|
658
|
+
}
|
659
|
+
|
660
|
+
|
661
|
+
static ngx_int_t
|
662
|
+
parse_status_line(ngx_http_request_t *r, passenger_context_t *context)
|
663
|
+
{
|
664
|
+
u_char ch;
|
665
|
+
u_char *pos;
|
666
|
+
ngx_http_upstream_t *u;
|
667
|
+
enum {
|
668
|
+
sw_start = 0,
|
669
|
+
sw_H,
|
670
|
+
sw_HT,
|
671
|
+
sw_HTT,
|
672
|
+
sw_HTTP,
|
673
|
+
sw_first_major_digit,
|
674
|
+
sw_major_digit,
|
675
|
+
sw_first_minor_digit,
|
676
|
+
sw_minor_digit,
|
677
|
+
sw_status,
|
678
|
+
sw_space_after_status,
|
679
|
+
sw_status_text,
|
680
|
+
sw_almost_done
|
681
|
+
} state;
|
682
|
+
|
683
|
+
u = r->upstream;
|
684
|
+
|
685
|
+
state = r->state;
|
686
|
+
|
687
|
+
for (pos = u->buffer.pos; pos < u->buffer.last; pos++) {
|
688
|
+
ch = *pos;
|
689
|
+
|
690
|
+
switch (state) {
|
691
|
+
|
692
|
+
/* "HTTP/" */
|
693
|
+
case sw_start:
|
694
|
+
switch (ch) {
|
695
|
+
case 'H':
|
696
|
+
state = sw_H;
|
697
|
+
break;
|
698
|
+
default:
|
699
|
+
return NGX_HTTP_SCGI_PARSE_NO_HEADER;
|
700
|
+
}
|
701
|
+
break;
|
702
|
+
|
703
|
+
case sw_H:
|
704
|
+
switch (ch) {
|
705
|
+
case 'T':
|
706
|
+
state = sw_HT;
|
707
|
+
break;
|
708
|
+
default:
|
709
|
+
return NGX_HTTP_SCGI_PARSE_NO_HEADER;
|
710
|
+
}
|
711
|
+
break;
|
712
|
+
|
713
|
+
case sw_HT:
|
714
|
+
switch (ch) {
|
715
|
+
case 'T':
|
716
|
+
state = sw_HTT;
|
717
|
+
break;
|
718
|
+
default:
|
719
|
+
return NGX_HTTP_SCGI_PARSE_NO_HEADER;
|
720
|
+
}
|
721
|
+
break;
|
722
|
+
|
723
|
+
case sw_HTT:
|
724
|
+
switch (ch) {
|
725
|
+
case 'P':
|
726
|
+
state = sw_HTTP;
|
727
|
+
break;
|
728
|
+
default:
|
729
|
+
return NGX_HTTP_SCGI_PARSE_NO_HEADER;
|
730
|
+
}
|
731
|
+
break;
|
732
|
+
|
733
|
+
case sw_HTTP:
|
734
|
+
switch (ch) {
|
735
|
+
case '/':
|
736
|
+
state = sw_first_major_digit;
|
737
|
+
break;
|
738
|
+
default:
|
739
|
+
return NGX_HTTP_SCGI_PARSE_NO_HEADER;
|
740
|
+
}
|
741
|
+
break;
|
742
|
+
|
743
|
+
/* the first digit of major HTTP version */
|
744
|
+
case sw_first_major_digit:
|
745
|
+
if (ch < '1' || ch > '9') {
|
746
|
+
return NGX_HTTP_SCGI_PARSE_NO_HEADER;
|
747
|
+
}
|
748
|
+
|
749
|
+
state = sw_major_digit;
|
750
|
+
break;
|
751
|
+
|
752
|
+
/* the major HTTP version or dot */
|
753
|
+
case sw_major_digit:
|
754
|
+
if (ch == '.') {
|
755
|
+
state = sw_first_minor_digit;
|
756
|
+
break;
|
757
|
+
}
|
758
|
+
|
759
|
+
if (ch < '0' || ch > '9') {
|
760
|
+
return NGX_HTTP_SCGI_PARSE_NO_HEADER;
|
761
|
+
}
|
762
|
+
|
763
|
+
break;
|
764
|
+
|
765
|
+
/* the first digit of minor HTTP version */
|
766
|
+
case sw_first_minor_digit:
|
767
|
+
if (ch < '0' || ch > '9') {
|
768
|
+
return NGX_HTTP_SCGI_PARSE_NO_HEADER;
|
769
|
+
}
|
770
|
+
|
771
|
+
state = sw_minor_digit;
|
772
|
+
break;
|
773
|
+
|
774
|
+
/* the minor HTTP version or the end of the request line */
|
775
|
+
case sw_minor_digit:
|
776
|
+
if (ch == ' ') {
|
777
|
+
state = sw_status;
|
778
|
+
break;
|
779
|
+
}
|
780
|
+
|
781
|
+
if (ch < '0' || ch > '9') {
|
782
|
+
return NGX_HTTP_SCGI_PARSE_NO_HEADER;
|
783
|
+
}
|
784
|
+
|
785
|
+
break;
|
786
|
+
|
787
|
+
/* HTTP status code */
|
788
|
+
case sw_status:
|
789
|
+
if (ch == ' ') {
|
790
|
+
break;
|
791
|
+
}
|
792
|
+
|
793
|
+
if (ch < '0' || ch > '9') {
|
794
|
+
return NGX_HTTP_SCGI_PARSE_NO_HEADER;
|
795
|
+
}
|
796
|
+
|
797
|
+
context->status = context->status * 10 + ch - '0';
|
798
|
+
|
799
|
+
if (++context->status_count == 3) {
|
800
|
+
state = sw_space_after_status;
|
801
|
+
context->status_start = pos - 2;
|
802
|
+
}
|
803
|
+
|
804
|
+
break;
|
805
|
+
|
806
|
+
/* space or end of line */
|
807
|
+
case sw_space_after_status:
|
808
|
+
switch (ch) {
|
809
|
+
case ' ':
|
810
|
+
state = sw_status_text;
|
811
|
+
break;
|
812
|
+
case '.': /* IIS may send 403.1, 403.2, etc */
|
813
|
+
state = sw_status_text;
|
814
|
+
break;
|
815
|
+
case CR:
|
816
|
+
state = sw_almost_done;
|
817
|
+
break;
|
818
|
+
case LF:
|
819
|
+
goto done;
|
820
|
+
default:
|
821
|
+
return NGX_HTTP_SCGI_PARSE_NO_HEADER;
|
822
|
+
}
|
823
|
+
break;
|
824
|
+
|
825
|
+
/* any text until end of line */
|
826
|
+
case sw_status_text:
|
827
|
+
switch (ch) {
|
828
|
+
case CR:
|
829
|
+
state = sw_almost_done;
|
830
|
+
|
831
|
+
break;
|
832
|
+
case LF:
|
833
|
+
goto done;
|
834
|
+
}
|
835
|
+
break;
|
836
|
+
|
837
|
+
/* end of status line */
|
838
|
+
case sw_almost_done:
|
839
|
+
context->status_end = pos - 1;
|
840
|
+
switch (ch) {
|
841
|
+
case LF:
|
842
|
+
goto done;
|
843
|
+
default:
|
844
|
+
return NGX_HTTP_SCGI_PARSE_NO_HEADER;
|
845
|
+
}
|
846
|
+
}
|
847
|
+
}
|
848
|
+
|
849
|
+
u->buffer.pos = pos;
|
850
|
+
r->state = state;
|
851
|
+
|
852
|
+
return NGX_AGAIN;
|
853
|
+
|
854
|
+
done:
|
855
|
+
|
856
|
+
u->buffer.pos = pos + 1;
|
857
|
+
|
858
|
+
if (context->status_end == NULL) {
|
859
|
+
context->status_end = pos;
|
860
|
+
}
|
861
|
+
|
862
|
+
r->state = sw_start;
|
863
|
+
|
864
|
+
return NGX_OK;
|
865
|
+
}
|
866
|
+
|
867
|
+
|
868
|
+
static ngx_int_t
|
869
|
+
process_header(ngx_http_request_t *r)
|
870
|
+
{
|
871
|
+
ngx_int_t rc;
|
872
|
+
ngx_uint_t i;
|
873
|
+
ngx_table_elt_t *h;
|
874
|
+
ngx_http_upstream_header_t *hh;
|
875
|
+
ngx_http_upstream_main_conf_t *umcf;
|
876
|
+
|
877
|
+
umcf = ngx_http_get_module_main_conf(r, ngx_http_upstream_module);
|
878
|
+
|
879
|
+
for ( ;; ) {
|
880
|
+
|
881
|
+
#if NGINX_VERSION_NUM >= 7000
|
882
|
+
rc = ngx_http_parse_header_line(r, &r->upstream->buffer, 1);
|
883
|
+
#else
|
884
|
+
rc = ngx_http_parse_header_line(r, &r->upstream->buffer);
|
885
|
+
#endif
|
886
|
+
|
887
|
+
if (rc == NGX_OK) {
|
888
|
+
|
889
|
+
/* a header line has been parsed successfully */
|
890
|
+
|
891
|
+
h = ngx_list_push(&r->upstream->headers_in.headers);
|
892
|
+
if (h == NULL) {
|
893
|
+
return NGX_HTTP_INTERNAL_SERVER_ERROR;
|
894
|
+
}
|
895
|
+
|
896
|
+
h->hash = r->header_hash;
|
897
|
+
|
898
|
+
h->key.len = r->header_name_end - r->header_name_start;
|
899
|
+
h->value.len = r->header_end - r->header_start;
|
900
|
+
|
901
|
+
h->key.data = ngx_palloc(r->pool,
|
902
|
+
h->key.len + 1 + h->value.len + 1 + h->key.len);
|
903
|
+
if (h->key.data == NULL) {
|
904
|
+
return NGX_HTTP_INTERNAL_SERVER_ERROR;
|
905
|
+
}
|
906
|
+
|
907
|
+
h->value.data = h->key.data + h->key.len + 1;
|
908
|
+
h->lowcase_key = h->key.data + h->key.len + 1 + h->value.len + 1;
|
909
|
+
|
910
|
+
ngx_cpystrn(h->key.data, r->header_name_start, h->key.len + 1);
|
911
|
+
ngx_cpystrn(h->value.data, r->header_start, h->value.len + 1);
|
912
|
+
|
913
|
+
if (h->key.len == r->lowcase_index) {
|
914
|
+
ngx_memcpy(h->lowcase_key, r->lowcase_header, h->key.len);
|
915
|
+
|
916
|
+
} else {
|
917
|
+
for (i = 0; i < h->key.len; i++) {
|
918
|
+
h->lowcase_key[i] = ngx_tolower(h->key.data[i]);
|
919
|
+
}
|
920
|
+
}
|
921
|
+
|
922
|
+
hh = ngx_hash_find(&umcf->headers_in_hash, h->hash,
|
923
|
+
h->lowcase_key, h->key.len);
|
924
|
+
|
925
|
+
if (hh && hh->handler(r, h, hh->offset) != NGX_OK) {
|
926
|
+
return NGX_HTTP_INTERNAL_SERVER_ERROR;
|
927
|
+
}
|
928
|
+
|
929
|
+
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
|
930
|
+
"http scgi header: \"%V: %V\"",
|
931
|
+
&h->key, &h->value);
|
932
|
+
|
933
|
+
continue;
|
934
|
+
}
|
935
|
+
|
936
|
+
if (rc == NGX_HTTP_PARSE_HEADER_DONE) {
|
937
|
+
|
938
|
+
/* a whole header has been parsed successfully */
|
939
|
+
|
940
|
+
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
|
941
|
+
"http scgi header done");
|
942
|
+
|
943
|
+
/*
|
944
|
+
* if no "Server" and "Date" in header line,
|
945
|
+
* then add the default headers
|
946
|
+
*/
|
947
|
+
|
948
|
+
if (r->upstream->headers_in.server == NULL) {
|
949
|
+
h = ngx_list_push(&r->upstream->headers_in.headers);
|
950
|
+
if (h == NULL) {
|
951
|
+
return NGX_HTTP_INTERNAL_SERVER_ERROR;
|
952
|
+
}
|
953
|
+
|
954
|
+
h->hash = ngx_hash(ngx_hash(ngx_hash(ngx_hash(
|
955
|
+
ngx_hash('s', 'e'), 'r'), 'v'), 'e'), 'r');
|
956
|
+
|
957
|
+
h->key.len = sizeof("Server") - 1;
|
958
|
+
h->key.data = (u_char *) "Server";
|
959
|
+
h->value.data = (u_char *) (NGINX_VER " + Phusion Passenger (mod_rails/mod_rack)");
|
960
|
+
h->value.len = ngx_strlen(h->value.data);
|
961
|
+
h->lowcase_key = (u_char *) "server";
|
962
|
+
}
|
963
|
+
|
964
|
+
if (r->upstream->headers_in.date == NULL) {
|
965
|
+
h = ngx_list_push(&r->upstream->headers_in.headers);
|
966
|
+
if (h == NULL) {
|
967
|
+
return NGX_HTTP_INTERNAL_SERVER_ERROR;
|
968
|
+
}
|
969
|
+
|
970
|
+
h->hash = ngx_hash(ngx_hash(ngx_hash('d', 'a'), 't'), 'e');
|
971
|
+
|
972
|
+
h->key.len = sizeof("Date") - 1;
|
973
|
+
h->key.data = (u_char *) "Date";
|
974
|
+
h->value.len = 0;
|
975
|
+
h->value.data = NULL;
|
976
|
+
h->lowcase_key = (u_char *) "date";
|
977
|
+
}
|
978
|
+
|
979
|
+
return NGX_OK;
|
980
|
+
}
|
981
|
+
|
982
|
+
if (rc == NGX_AGAIN) {
|
983
|
+
return NGX_AGAIN;
|
984
|
+
}
|
985
|
+
|
986
|
+
/* there was error while a header line parsing */
|
987
|
+
|
988
|
+
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
|
989
|
+
"upstream sent invalid header");
|
990
|
+
|
991
|
+
return NGX_HTTP_UPSTREAM_INVALID_HEADER;
|
992
|
+
}
|
993
|
+
}
|
994
|
+
|
995
|
+
|
996
|
+
static void
|
997
|
+
abort_request(ngx_http_request_t *r)
|
998
|
+
{
|
999
|
+
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
|
1000
|
+
"abort Passenger request");
|
1001
|
+
}
|
1002
|
+
|
1003
|
+
|
1004
|
+
static void
|
1005
|
+
finalize_request(ngx_http_request_t *r, ngx_int_t rc)
|
1006
|
+
{
|
1007
|
+
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
|
1008
|
+
"finalize Passenger request");
|
1009
|
+
}
|
1010
|
+
|
1011
|
+
|
1012
|
+
ngx_int_t
|
1013
|
+
passenger_content_handler(ngx_http_request_t *r)
|
1014
|
+
{
|
1015
|
+
ngx_int_t rc;
|
1016
|
+
ngx_http_upstream_t *u;
|
1017
|
+
passenger_loc_conf_t *slcf;
|
1018
|
+
ngx_str_t path, base_uri;
|
1019
|
+
u_char *path_last, *end;
|
1020
|
+
u_char root_path_str[NGX_MAX_PATH + 1];
|
1021
|
+
ngx_str_t root_path;
|
1022
|
+
size_t root, len;
|
1023
|
+
u_char page_cache_file_str[NGX_MAX_PATH + 1];
|
1024
|
+
ngx_str_t page_cache_file;
|
1025
|
+
passenger_context_t *context;
|
1026
|
+
|
1027
|
+
if (r->subrequest_in_memory) {
|
1028
|
+
ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
|
1029
|
+
"ngx_http_passenger_module does not support "
|
1030
|
+
"subrequest in memory");
|
1031
|
+
return NGX_HTTP_INTERNAL_SERVER_ERROR;
|
1032
|
+
}
|
1033
|
+
|
1034
|
+
slcf = ngx_http_get_module_loc_conf(r, ngx_http_passenger_module);
|
1035
|
+
|
1036
|
+
/* Let the next content handler take care of this request if Phusion
|
1037
|
+
* Passenger is disabled for this URL.
|
1038
|
+
*/
|
1039
|
+
if (!slcf->enabled) {
|
1040
|
+
return NGX_DECLINED;
|
1041
|
+
}
|
1042
|
+
|
1043
|
+
/* Let the next content handler take care of this request if this URL
|
1044
|
+
* maps to an existing file.
|
1045
|
+
*/
|
1046
|
+
path_last = ngx_http_map_uri_to_path(r, &path, &root, 0);
|
1047
|
+
if (path_last != NULL && file_exists(path.data, 0)) {
|
1048
|
+
return NGX_DECLINED;
|
1049
|
+
}
|
1050
|
+
|
1051
|
+
/* Create a string containing the root path. This path already
|
1052
|
+
* contains a trailing slash.
|
1053
|
+
*/
|
1054
|
+
end = ngx_copy(root_path_str, path.data, root);
|
1055
|
+
*end = '\0';
|
1056
|
+
root_path.data = root_path_str;
|
1057
|
+
root_path.len = root;
|
1058
|
+
|
1059
|
+
|
1060
|
+
context = ngx_pcalloc(r->pool, sizeof(passenger_context_t));
|
1061
|
+
if (context == NULL) {
|
1062
|
+
return NGX_HTTP_INTERNAL_SERVER_ERROR;
|
1063
|
+
}
|
1064
|
+
ngx_http_set_ctx(r, context, ngx_http_passenger_module);
|
1065
|
+
|
1066
|
+
|
1067
|
+
/* Find the base URI for this web application, if any. */
|
1068
|
+
if (find_base_uri(r, slcf, &base_uri)) {
|
1069
|
+
/* Store the found base URI in context->public_dir. We infer that the 'public'
|
1070
|
+
* directory of the web application is document root + base URI.
|
1071
|
+
*/
|
1072
|
+
len = root_path.len + base_uri.len + 1;
|
1073
|
+
context->public_dir.data = ngx_palloc(r->pool, sizeof(u_char) * len);
|
1074
|
+
end = ngx_copy(context->public_dir.data, root_path.data, root_path.len);
|
1075
|
+
end = ngx_copy(end, base_uri.data, base_uri.len);
|
1076
|
+
*end = '\0';
|
1077
|
+
context->public_dir.len = len - 1;
|
1078
|
+
context->base_uri = base_uri;
|
1079
|
+
} else {
|
1080
|
+
/* No base URI directives are applicable for this request. So assume that
|
1081
|
+
* the web application's public directory is the document root.
|
1082
|
+
* context->base_uri is now a NULL string.
|
1083
|
+
*/
|
1084
|
+
len = sizeof(u_char *) * (root_path.len + 1);
|
1085
|
+
context->public_dir.data = ngx_palloc(r->pool, len);
|
1086
|
+
end = ngx_copy(context->public_dir.data, root_path.data,
|
1087
|
+
root_path.len);
|
1088
|
+
*end = '\0';
|
1089
|
+
context->public_dir.len = root_path.len;
|
1090
|
+
}
|
1091
|
+
|
1092
|
+
/* If there's a corresponding page cache file for this URL, then serve that
|
1093
|
+
* file instead.
|
1094
|
+
*/
|
1095
|
+
page_cache_file.data = page_cache_file_str;
|
1096
|
+
page_cache_file.len = sizeof(page_cache_file_str);
|
1097
|
+
if (map_uri_to_page_cache_file(r, &context->public_dir, path.data,
|
1098
|
+
path_last - path.data, &page_cache_file)) {
|
1099
|
+
return passenger_static_content_handler(r, &page_cache_file);
|
1100
|
+
}
|
1101
|
+
|
1102
|
+
context->app_type = detect_application_type(&context->public_dir);
|
1103
|
+
if (context->app_type == AP_NONE) {
|
1104
|
+
return NGX_DECLINED;
|
1105
|
+
}
|
1106
|
+
|
1107
|
+
|
1108
|
+
/* Setup upstream stuff and prepare sending the request to the backend. */
|
1109
|
+
|
1110
|
+
u = ngx_pcalloc(r->pool, sizeof(ngx_http_upstream_t));
|
1111
|
+
if (u == NULL) {
|
1112
|
+
return NGX_HTTP_INTERNAL_SERVER_ERROR;
|
1113
|
+
}
|
1114
|
+
|
1115
|
+
#if NGINX_VERSION_NUM >= 7000
|
1116
|
+
u->schema = passenger_schema_string;
|
1117
|
+
#endif
|
1118
|
+
|
1119
|
+
u->peer.log = r->connection->log;
|
1120
|
+
u->peer.log_error = NGX_ERROR_ERR;
|
1121
|
+
#if (NGX_THREADS)
|
1122
|
+
u->peer.lock = &r->connection->lock;
|
1123
|
+
#endif
|
1124
|
+
|
1125
|
+
u->output.tag = (ngx_buf_tag_t) &ngx_http_passenger_module;
|
1126
|
+
|
1127
|
+
u->conf = &slcf->upstream;
|
1128
|
+
|
1129
|
+
u->create_request = create_request;
|
1130
|
+
u->reinit_request = reinit_request;
|
1131
|
+
u->process_header = process_status_line;
|
1132
|
+
u->abort_request = abort_request;
|
1133
|
+
u->finalize_request = finalize_request;
|
1134
|
+
|
1135
|
+
u->buffering = 1;
|
1136
|
+
|
1137
|
+
u->pipe = ngx_pcalloc(r->pool, sizeof(ngx_event_pipe_t));
|
1138
|
+
if (u->pipe == NULL) {
|
1139
|
+
return NGX_HTTP_INTERNAL_SERVER_ERROR;
|
1140
|
+
}
|
1141
|
+
|
1142
|
+
u->pipe->input_filter = ngx_event_pipe_copy_input_filter;
|
1143
|
+
|
1144
|
+
r->upstream = u;
|
1145
|
+
|
1146
|
+
rc = ngx_http_read_client_request_body(r, ngx_http_upstream_init);
|
1147
|
+
|
1148
|
+
if (rc >= NGX_HTTP_SPECIAL_RESPONSE) {
|
1149
|
+
return rc;
|
1150
|
+
}
|
1151
|
+
|
1152
|
+
return NGX_DONE;
|
1153
|
+
}
|
1154
|
+
|