passenger 5.0.4 → 5.0.5
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of passenger might be problematic. Click here for more details.
- checksums.yaml +8 -8
- checksums.yaml.gz.asc +7 -7
- data.tar.gz.asc +7 -7
- data/.editorconfig +10 -0
- data/CHANGELOG +21 -0
- data/build/agents.rb +2 -2
- data/build/apache2.rb +6 -5
- data/build/common_library.rb +22 -7
- data/build/cxx_tests.rb +0 -3
- data/build/misc.rb +1 -1
- data/dev/parse_file_descriptor_log +119 -0
- data/doc/CloudLicensingConfiguration.html +387 -0
- data/doc/Design and Architecture.html +2430 -0
- data/doc/Packaging.html +488 -0
- data/doc/Security of user switching support.html +1833 -0
- data/doc/ServerOptimizationGuide.html +659 -0
- data/doc/ServerOptimizationGuide.txt.md +8 -0
- data/doc/Users guide Apache.html +9116 -0
- data/doc/Users guide Apache.idmap.txt +6 -2
- data/doc/Users guide Apache.txt +26 -7
- data/doc/Users guide Nginx.html +9025 -0
- data/doc/Users guide Nginx.idmap.txt +7 -3
- data/doc/Users guide Nginx.txt +29 -6
- data/doc/Users guide Standalone.html +3983 -0
- data/doc/Users guide.html +1748 -0
- data/doc/users_guide_snippets/installation.txt +4 -4
- data/ext/apache2/Configuration.cpp +16 -5
- data/ext/apache2/Configuration.hpp +4 -2
- data/ext/apache2/Hooks.cpp +44 -19
- data/ext/boost/libs/thread/src/pthread/once.cpp +2 -0
- data/ext/boost/libs/thread/src/pthread/once_atomic.cpp +6 -0
- data/ext/common/AgentsStarter.h +3 -2
- data/ext/common/ApplicationPool2/DirectSpawner.h +14 -4
- data/ext/common/ApplicationPool2/DummySpawner.h +12 -7
- data/ext/common/ApplicationPool2/Implementation.cpp +1 -1
- data/ext/common/ApplicationPool2/Process.h +2 -1
- data/ext/common/ApplicationPool2/Session.h +6 -6
- data/ext/common/ApplicationPool2/SmartSpawner.h +19 -4
- data/ext/common/ApplicationPool2/Socket.h +59 -27
- data/ext/common/ApplicationPool2/Spawner.h +2 -2
- data/ext/common/BackgroundEventLoop.cpp +6 -1
- data/ext/common/Constants.h +1 -1
- data/ext/common/EventedClient.h +1 -1
- data/ext/common/EventedServer.h +2 -2
- data/ext/common/FileDescriptor.h +25 -6
- data/ext/common/Logging.cpp +107 -52
- data/ext/common/Logging.h +146 -19
- data/ext/common/MessageClient.h +2 -2
- data/ext/common/MessageServer.h +3 -2
- data/ext/common/RandomGenerator.h +8 -7
- data/ext/common/SafeLibev.h +5 -1
- data/ext/common/ServerKit/AcceptLoadBalancer.h +9 -4
- data/ext/common/ServerKit/FdSinkChannel.h +5 -2
- data/ext/common/ServerKit/FdSourceChannel.h +5 -2
- data/ext/common/ServerKit/FileBufferedChannel.h +2 -0
- data/ext/common/ServerKit/FileBufferedFdSinkChannel.h +7 -2
- data/ext/common/ServerKit/HttpServer.h +6 -0
- data/ext/common/ServerKit/Server.h +40 -3
- data/ext/common/StaticString.h +20 -0
- data/ext/common/UnionStation/Connection.h +3 -1
- data/ext/common/UnionStation/Core.h +6 -4
- data/ext/common/Utils.cpp +4 -3
- data/ext/common/Utils/DateParsing.h +19 -5
- data/ext/common/Utils/FastStringStream.h +183 -0
- data/ext/common/Utils/IOUtils.cpp +47 -28
- data/ext/common/Utils/IOUtils.h +56 -12
- data/ext/common/Utils/MessagePassing.h +3 -3
- data/ext/common/Utils/ProcessMetricsCollector.h +2 -2
- data/ext/common/Utils/ScopeGuard.h +16 -5
- data/ext/common/Utils/SpeedMeter.h +2 -2
- data/ext/common/Utils/StrIntUtils.cpp +6 -6
- data/ext/common/Utils/StrIntUtils.h +2 -1
- data/ext/common/agents/Base.cpp +56 -4
- data/ext/common/agents/Base.h +2 -1
- data/ext/common/agents/HelperAgent/AdminServer.h +122 -11
- data/ext/common/agents/HelperAgent/Main.cpp +16 -5
- data/ext/common/agents/HelperAgent/OptionParser.h +7 -1
- data/ext/common/agents/HelperAgent/RequestHandler.h +1 -1
- data/ext/common/agents/HelperAgent/RequestHandler/Hooks.cpp +10 -1
- data/ext/common/agents/HelperAgent/RequestHandler/Request.h +8 -0
- data/ext/common/agents/HelperAgent/RequestHandler/TurboCaching.h +4 -3
- data/ext/common/agents/LoggingAgent/AdminServer.h +57 -11
- data/ext/common/agents/LoggingAgent/LoggingServer.h +3 -3
- data/ext/common/agents/LoggingAgent/Main.cpp +11 -3
- data/ext/common/agents/Watchdog/AdminServer.h +53 -11
- data/ext/common/agents/Watchdog/AgentWatcher.cpp +3 -3
- data/ext/common/agents/Watchdog/Main.cpp +13 -6
- data/ext/libeio/ecb.h +1 -1
- data/ext/libev/ev.c +13 -1
- data/ext/libev/ev.h +3 -0
- data/ext/nginx/Configuration.c +28 -6
- data/ext/nginx/Configuration.h +2 -1
- data/ext/nginx/ngx_http_passenger_module.c +5 -4
- data/ext/oxt/dynamic_thread_group.hpp +38 -5
- data/lib/phusion_passenger.rb +1 -1
- data/lib/phusion_passenger/common_library.rb +9 -5
- data/lib/phusion_passenger/config/reopen_logs_command.rb +2 -2
- data/lib/phusion_passenger/packaging.rb +23 -37
- data/passenger.gemspec +21 -21
- metadata +4 -453
- metadata.gz.asc +7 -7
- data/.gitignore +0 -68
- data/.travis.yml +0 -16
- data/Gemfile +0 -17
- data/Gemfile.lock +0 -39
- data/Vagrantfile +0 -54
- data/debian.template/README.Debian +0 -15
- data/debian.template/changelog +0 -316
- data/debian.template/compat +0 -1
- data/debian.template/control.erb +0 -91
- data/debian.template/copyright +0 -385
- data/debian.template/libapache2-mod-passenger.install +0 -3
- data/debian.template/libapache2-mod-passenger.postinst +0 -36
- data/debian.template/libapache2-mod-passenger.prerm +0 -15
- data/debian.template/locations.ini.erb +0 -14
- data/debian.template/passenger-dev.install.erb +0 -3
- data/debian.template/passenger-doc.install.erb +0 -2
- data/debian.template/passenger.conf +0 -6
- data/debian.template/passenger.docs +0 -4
- data/debian.template/passenger.install.erb +0 -14
- data/debian.template/passenger.load +0 -3
- data/debian.template/passenger.manpages +0 -3
- data/debian.template/patches/series +0 -0
- data/debian.template/rules.erb +0 -76
- data/debian.template/source/format +0 -1
- data/ext/common/EventedBufferedInput.h +0 -458
- data/packaging/rpm/LICENSE.txt +0 -19
- data/packaging/rpm/Makefile +0 -13
- data/packaging/rpm/README.md +0 -41
- data/packaging/rpm/Vagrantfile +0 -38
- data/packaging/rpm/Vagrantfile.centos +0 -30
- data/packaging/rpm/build +0 -170
- data/packaging/rpm/create_project +0 -41
- data/packaging/rpm/git_update +0 -88
- data/packaging/rpm/image/Dockerfile +0 -37
- data/packaging/rpm/image/Gemfile +0 -3
- data/packaging/rpm/image/Gemfile.lock +0 -12
- data/packaging/rpm/image/RPM-GPG-KEY-amazon-ga +0 -19
- data/packaging/rpm/image/amazon2014-i386.cfg +0 -96
- data/packaging/rpm/image/amazon2014-x86_64.cfg +0 -96
- data/packaging/rpm/image/site-defaults.cfg +0 -168
- data/packaging/rpm/internal/build_tasks.rb +0 -238
- data/packaging/rpm/internal/dummygpg +0 -11
- data/packaging/rpm/internal/exec_build +0 -42
- data/packaging/rpm/internal/get_distro_arch +0 -14
- data/packaging/rpm/internal/get_distro_id +0 -10
- data/packaging/rpm/internal/git_update +0 -27
- data/packaging/rpm/internal/inituidgid +0 -17
- data/packaging/rpm/internal/my_init +0 -344
- data/packaging/rpm/internal/python27 +0 -3
- data/packaging/rpm/internal/repo_update +0 -46
- data/packaging/rpm/internal/setuser +0 -26
- data/packaging/rpm/internal/tracking_helper +0 -40
- data/packaging/rpm/jenkins_release +0 -99
- data/packaging/rpm/lib/build_tasks_support.rb +0 -402
- data/packaging/rpm/lib/preprocessor.rb +0 -341
- data/packaging/rpm/nginx_spec/404.html +0 -119
- data/packaging/rpm/nginx_spec/50x.html +0 -119
- data/packaging/rpm/nginx_spec/index.html +0 -116
- data/packaging/rpm/nginx_spec/nginx-auto-cc-gcc.patch +0 -13
- data/packaging/rpm/nginx_spec/nginx-logo.png +0 -0
- data/packaging/rpm/nginx_spec/nginx-upgrade +0 -13
- data/packaging/rpm/nginx_spec/nginx-upgrade.8 +0 -151
- data/packaging/rpm/nginx_spec/nginx.conf +0 -131
- data/packaging/rpm/nginx_spec/nginx.init +0 -144
- data/packaging/rpm/nginx_spec/nginx.logrotate +0 -13
- data/packaging/rpm/nginx_spec/nginx.service +0 -15
- data/packaging/rpm/nginx_spec/nginx.spec.template +0 -560
- data/packaging/rpm/nginx_spec/nginx.sysconfig +0 -4
- data/packaging/rpm/nginx_spec/passenger.conf +0 -9
- data/packaging/rpm/nginx_spec/poweredby.png +0 -0
- data/packaging/rpm/passenger_spec/apache-passenger.conf.in +0 -26
- data/packaging/rpm/passenger_spec/config.json +0 -30
- data/packaging/rpm/passenger_spec/passenger.logrotate +0 -7
- data/packaging/rpm/passenger_spec/passenger.spec.template +0 -478
- data/packaging/rpm/passenger_spec/passenger_dynamic_thread_group.patch +0 -16
- data/packaging/rpm/passenger_spec/passenger_tests_default_config_example.patch +0 -44
- data/packaging/rpm/passenger_spec/rubygem-passenger-4.0.18-GLIBC_HAVE_LONG_LONG.patch +0 -21
- data/packaging/rpm/repo_update +0 -114
- data/packaging/rpm/setup-system +0 -61
- data/packaging/rpm/shell +0 -10
- data/test/.rspec +0 -4
- data/test/config.json.example +0 -42
- data/test/config.json.rpm-automation +0 -15
- data/test/config.json.travis +0 -15
- data/test/config.json.vagrant +0 -30
- data/test/cxx/ApplicationPool2/DirectSpawnerTest.cpp +0 -124
- data/test/cxx/ApplicationPool2/OptionsTest.cpp +0 -30
- data/test/cxx/ApplicationPool2/PoolTest.cpp +0 -2062
- data/test/cxx/ApplicationPool2/ProcessTest.cpp +0 -130
- data/test/cxx/ApplicationPool2/SmartSpawnerTest.cpp +0 -243
- data/test/cxx/ApplicationPool2/SpawnerTestCases.cpp +0 -823
- data/test/cxx/BufferedIOTest.cpp +0 -364
- data/test/cxx/CachedFileStatTest.cpp +0 -402
- data/test/cxx/CxxTestMain.cpp +0 -181
- data/test/cxx/DataStructures/LStringTest.cpp +0 -275
- data/test/cxx/DataStructures/StringKeyTableTest.cpp +0 -199
- data/test/cxx/DateParsingTest.cpp +0 -75
- data/test/cxx/DechunkerTest.cpp +0 -250
- data/test/cxx/EventedBufferedInputTest.cpp +0 -758
- data/test/cxx/EventedClientTest.cpp +0 -523
- data/test/cxx/FileChangeCheckerTest.cpp +0 -331
- data/test/cxx/FileDescriptorTest.cpp +0 -69
- data/test/cxx/FilterSupportTest.cpp +0 -433
- data/test/cxx/IOUtilsTest.cpp +0 -861
- data/test/cxx/MemoryKit/MbufTest.cpp +0 -213
- data/test/cxx/MessageIOTest.cpp +0 -360
- data/test/cxx/MessagePassingTest.cpp +0 -81
- data/test/cxx/MessageReadersWritersTest.cpp +0 -576
- data/test/cxx/MessageServerTest.cpp +0 -393
- data/test/cxx/ProcessMetricsCollectorTest.cpp +0 -123
- data/test/cxx/RequestHandlerTest.cpp +0 -1463
- data/test/cxx/ResponseCacheTest.cpp +0 -322
- data/test/cxx/ServerKit/ChannelTest.cpp +0 -1467
- data/test/cxx/ServerKit/CookieUtilsTest.cpp +0 -274
- data/test/cxx/ServerKit/FileBufferedChannelTest.cpp +0 -992
- data/test/cxx/ServerKit/HeaderTableTest.cpp +0 -177
- data/test/cxx/ServerKit/HttpServerTest.cpp +0 -1580
- data/test/cxx/ServerKit/ServerTest.cpp +0 -408
- data/test/cxx/StaticStringTest.cpp +0 -220
- data/test/cxx/StringMapTest.cpp +0 -131
- data/test/cxx/SystemTimeTest.cpp +0 -37
- data/test/cxx/TemplateTest.cpp +0 -118
- data/test/cxx/TestSupport.cpp +0 -207
- data/test/cxx/TestSupport.h +0 -333
- data/test/cxx/UnionStationTest.cpp +0 -741
- data/test/cxx/Utils/StrIntUtilsTest.cpp +0 -39
- data/test/cxx/UtilsTest.cpp +0 -672
- data/test/cxx/VariantMapTest.cpp +0 -191
- data/test/gdbinit.example +0 -34
- data/test/integration_tests/apache2_tests.rb +0 -585
- data/test/integration_tests/downloaded_binaries_tests.rb +0 -185
- data/test/integration_tests/native_packaging_spec.rb +0 -368
- data/test/integration_tests/nginx_tests.rb +0 -402
- data/test/integration_tests/shared/example_webapp_tests.rb +0 -289
- data/test/integration_tests/source_packaging_test.rb +0 -201
- data/test/integration_tests/spec_helper.rb +0 -22
- data/test/integration_tests/standalone_tests.rb +0 -392
- data/test/node/line_reader_spec.js +0 -338
- data/test/node/spec_helper.js +0 -65
- data/test/oxt/backtrace_test.cpp +0 -88
- data/test/oxt/counter.hpp +0 -55
- data/test/oxt/dynamic_thread_group_test.cpp +0 -131
- data/test/oxt/oxt_test_main.cpp +0 -27
- data/test/oxt/spin_lock_test.cpp +0 -59
- data/test/oxt/syscall_interruption_test.cpp +0 -39
- data/test/ruby/debug_logging_spec.rb +0 -145
- data/test/ruby/message_channel_spec.rb +0 -196
- data/test/ruby/rack/loader_spec.rb +0 -42
- data/test/ruby/rack/preloader_spec.rb +0 -48
- data/test/ruby/rails3.0/loader_spec.rb +0 -26
- data/test/ruby/rails3.0/preloader_spec.rb +0 -32
- data/test/ruby/rails3.1/loader_spec.rb +0 -26
- data/test/ruby/rails3.1/preloader_spec.rb +0 -32
- data/test/ruby/rails3.2/loader_spec.rb +0 -26
- data/test/ruby/rails3.2/preloader_spec.rb +0 -32
- data/test/ruby/rails4.0/loader_spec.rb +0 -28
- data/test/ruby/rails4.0/preloader_spec.rb +0 -34
- data/test/ruby/rails4.1/loader_spec.rb +0 -28
- data/test/ruby/rails4.1/preloader_spec.rb +0 -34
- data/test/ruby/request_handler_spec.rb +0 -747
- data/test/ruby/shared/loader_sharedspec.rb +0 -247
- data/test/ruby/shared/rails/union_station_extensions_sharedspec.rb +0 -357
- data/test/ruby/shared/ruby_loader_sharedspec.rb +0 -55
- data/test/ruby/spec_helper.rb +0 -114
- data/test/ruby/standalone/runtime_installer_spec.rb +0 -402
- data/test/ruby/union_station_spec.rb +0 -288
- data/test/ruby/utils/file_system_watcher_spec.rb +0 -229
- data/test/ruby/utils/hosts_file_parser.rb +0 -258
- data/test/ruby/utils/tee_input_spec.rb +0 -235
- data/test/ruby/utils/unseekable_socket_spec.rb +0 -66
- data/test/ruby/utils_spec.rb +0 -41
- data/test/stub/apache2/httpd.conf.erb +0 -122
- data/test/stub/apache2/mime.types +0 -748
- data/test/stub/garbage1.dat +0 -0
- data/test/stub/garbage2.dat +0 -0
- data/test/stub/garbage3.dat +0 -0
- data/test/stub/http_request.yml +0 -23
- data/test/stub/index.html +0 -1
- data/test/stub/nginx/koi-utf +0 -109
- data/test/stub/nginx/koi-win +0 -103
- data/test/stub/nginx/mime.types +0 -70
- data/test/stub/nginx/nginx.conf.erb +0 -70
- data/test/stub/nginx/win-utf +0 -126
- data/test/stub/node/app.js +0 -133
- data/test/stub/node/public/.gitignore +0 -0
- data/test/stub/node/tmp/.gitignore +0 -0
- data/test/stub/rack/config.ru +0 -95
- data/test/stub/rack/library.rb +0 -16
- data/test/stub/rack/public/.gitignore +0 -0
- data/test/stub/rack/start.rb +0 -52
- data/test/stub/rack/tmp/.gitignore +0 -0
- data/test/stub/rails3.0/.gitignore +0 -4
- data/test/stub/rails3.0/Gemfile +0 -22
- data/test/stub/rails3.0/Gemfile.lock +0 -80
- data/test/stub/rails3.0/Rakefile +0 -10
- data/test/stub/rails3.0/app/controllers/application_controller.rb +0 -4
- data/test/stub/rails3.0/app/helpers/application_helper.rb +0 -2
- data/test/stub/rails3.0/app/views/layouts/application.html.erb +0 -14
- data/test/stub/rails3.0/config.ru +0 -4
- data/test/stub/rails3.0/config/application.rb +0 -48
- data/test/stub/rails3.0/config/boot.rb +0 -13
- data/test/stub/rails3.0/config/database.yml +0 -22
- data/test/stub/rails3.0/config/environment.rb +0 -5
- data/test/stub/rails3.0/config/environments/development.rb +0 -19
- data/test/stub/rails3.0/config/environments/production.rb +0 -48
- data/test/stub/rails3.0/config/environments/test.rb +0 -32
- data/test/stub/rails3.0/config/initializers/backtrace_silencers.rb +0 -7
- data/test/stub/rails3.0/config/initializers/inflections.rb +0 -10
- data/test/stub/rails3.0/config/initializers/mime_types.rb +0 -5
- data/test/stub/rails3.0/config/initializers/passenger.rb +0 -2
- data/test/stub/rails3.0/config/initializers/secret_token.rb +0 -7
- data/test/stub/rails3.0/config/initializers/session_store.rb +0 -8
- data/test/stub/rails3.0/config/locales/en.yml +0 -5
- data/test/stub/rails3.0/config/routes.rb +0 -58
- data/test/stub/rails3.0/db/seeds.rb +0 -7
- data/test/stub/rails3.0/doc/README_FOR_APP +0 -2
- data/test/stub/rails3.0/lib/tasks/.gitkeep +0 -0
- data/test/stub/rails3.0/log/.gitignore +0 -0
- data/test/stub/rails3.0/public/404.html +0 -26
- data/test/stub/rails3.0/public/422.html +0 -26
- data/test/stub/rails3.0/public/500.html +0 -26
- data/test/stub/rails3.0/public/favicon.ico +0 -0
- data/test/stub/rails3.0/public/index.html +0 -279
- data/test/stub/rails3.0/public/robots.txt +0 -5
- data/test/stub/rails3.0/public/stylesheets/.gitkeep +0 -0
- data/test/stub/rails3.0/script/rails +0 -9
- data/test/stub/rails3.0/test/performance/browsing_test.rb +0 -9
- data/test/stub/rails3.0/test/test_helper.rb +0 -13
- data/test/stub/rails3.0/vendor/plugins/.gitkeep +0 -0
- data/test/stub/rails3.1/.gitignore +0 -15
- data/test/stub/rails3.1/Gemfile +0 -37
- data/test/stub/rails3.1/Gemfile.lock +0 -115
- data/test/stub/rails3.1/README +0 -261
- data/test/stub/rails3.1/Rakefile +0 -7
- data/test/stub/rails3.1/app/assets/images/rails.png +0 -0
- data/test/stub/rails3.1/app/assets/stylesheets/application.css +0 -7
- data/test/stub/rails3.1/app/controllers/application_controller.rb +0 -3
- data/test/stub/rails3.1/app/helpers/application_helper.rb +0 -2
- data/test/stub/rails3.1/app/mailers/.gitkeep +0 -0
- data/test/stub/rails3.1/app/models/.gitkeep +0 -0
- data/test/stub/rails3.1/app/views/layouts/application.html.erb +0 -14
- data/test/stub/rails3.1/config.ru +0 -4
- data/test/stub/rails3.1/config/application.rb +0 -48
- data/test/stub/rails3.1/config/boot.rb +0 -6
- data/test/stub/rails3.1/config/database.yml +0 -25
- data/test/stub/rails3.1/config/environment.rb +0 -5
- data/test/stub/rails3.1/config/environments/development.rb +0 -30
- data/test/stub/rails3.1/config/environments/production.rb +0 -60
- data/test/stub/rails3.1/config/environments/test.rb +0 -39
- data/test/stub/rails3.1/config/initializers/backtrace_silencers.rb +0 -7
- data/test/stub/rails3.1/config/initializers/inflections.rb +0 -10
- data/test/stub/rails3.1/config/initializers/mime_types.rb +0 -5
- data/test/stub/rails3.1/config/initializers/passenger.rb +0 -2
- data/test/stub/rails3.1/config/initializers/secret_token.rb +0 -7
- data/test/stub/rails3.1/config/initializers/session_store.rb +0 -8
- data/test/stub/rails3.1/config/initializers/wrap_parameters.rb +0 -14
- data/test/stub/rails3.1/config/locales/en.yml +0 -5
- data/test/stub/rails3.1/config/routes.rb +0 -58
- data/test/stub/rails3.1/db/seeds.rb +0 -7
- data/test/stub/rails3.1/doc/README_FOR_APP +0 -2
- data/test/stub/rails3.1/lib/assets/.gitkeep +0 -0
- data/test/stub/rails3.1/lib/tasks/.gitkeep +0 -0
- data/test/stub/rails3.1/log/.gitkeep +0 -0
- data/test/stub/rails3.1/public/404.html +0 -26
- data/test/stub/rails3.1/public/422.html +0 -26
- data/test/stub/rails3.1/public/500.html +0 -26
- data/test/stub/rails3.1/public/favicon.ico +0 -0
- data/test/stub/rails3.1/public/index.html +0 -241
- data/test/stub/rails3.1/public/robots.txt +0 -5
- data/test/stub/rails3.1/script/rails +0 -6
- data/test/stub/rails3.1/test/fixtures/.gitkeep +0 -0
- data/test/stub/rails3.1/test/functional/.gitkeep +0 -0
- data/test/stub/rails3.1/test/integration/.gitkeep +0 -0
- data/test/stub/rails3.1/test/performance/browsing_test.rb +0 -12
- data/test/stub/rails3.1/test/test_helper.rb +0 -13
- data/test/stub/rails3.1/test/unit/.gitkeep +0 -0
- data/test/stub/rails3.1/vendor/assets/stylesheets/.gitkeep +0 -0
- data/test/stub/rails3.1/vendor/plugins/.gitkeep +0 -0
- data/test/stub/rails3.2/.gitignore +0 -15
- data/test/stub/rails3.2/Gemfile +0 -39
- data/test/stub/rails3.2/Gemfile.lock +0 -113
- data/test/stub/rails3.2/Rakefile +0 -7
- data/test/stub/rails3.2/app/assets/images/rails.png +0 -0
- data/test/stub/rails3.2/app/assets/stylesheets/application.css +0 -13
- data/test/stub/rails3.2/app/controllers/application_controller.rb +0 -3
- data/test/stub/rails3.2/app/helpers/application_helper.rb +0 -2
- data/test/stub/rails3.2/app/mailers/.gitkeep +0 -0
- data/test/stub/rails3.2/app/models/.gitkeep +0 -0
- data/test/stub/rails3.2/app/views/layouts/application.html.erb +0 -14
- data/test/stub/rails3.2/config.ru +0 -4
- data/test/stub/rails3.2/config/application.rb +0 -62
- data/test/stub/rails3.2/config/boot.rb +0 -6
- data/test/stub/rails3.2/config/database.yml +0 -25
- data/test/stub/rails3.2/config/environment.rb +0 -5
- data/test/stub/rails3.2/config/environments/development.rb +0 -37
- data/test/stub/rails3.2/config/environments/production.rb +0 -67
- data/test/stub/rails3.2/config/environments/test.rb +0 -37
- data/test/stub/rails3.2/config/initializers/backtrace_silencers.rb +0 -7
- data/test/stub/rails3.2/config/initializers/inflections.rb +0 -15
- data/test/stub/rails3.2/config/initializers/mime_types.rb +0 -5
- data/test/stub/rails3.2/config/initializers/passenger.rb +0 -2
- data/test/stub/rails3.2/config/initializers/secret_token.rb +0 -7
- data/test/stub/rails3.2/config/initializers/session_store.rb +0 -8
- data/test/stub/rails3.2/config/initializers/wrap_parameters.rb +0 -14
- data/test/stub/rails3.2/config/locales/en.yml +0 -5
- data/test/stub/rails3.2/config/routes.rb +0 -58
- data/test/stub/rails3.2/db/seeds.rb +0 -7
- data/test/stub/rails3.2/doc/README_FOR_APP +0 -2
- data/test/stub/rails3.2/lib/assets/.gitkeep +0 -0
- data/test/stub/rails3.2/lib/tasks/.gitkeep +0 -0
- data/test/stub/rails3.2/log/.gitkeep +0 -0
- data/test/stub/rails3.2/public/404.html +0 -26
- data/test/stub/rails3.2/public/422.html +0 -26
- data/test/stub/rails3.2/public/500.html +0 -25
- data/test/stub/rails3.2/public/favicon.ico +0 -0
- data/test/stub/rails3.2/public/index.html +0 -241
- data/test/stub/rails3.2/public/robots.txt +0 -5
- data/test/stub/rails3.2/script/rails +0 -6
- data/test/stub/rails3.2/test/fixtures/.gitkeep +0 -0
- data/test/stub/rails3.2/test/functional/.gitkeep +0 -0
- data/test/stub/rails3.2/test/integration/.gitkeep +0 -0
- data/test/stub/rails3.2/test/performance/browsing_test.rb +0 -12
- data/test/stub/rails3.2/test/test_helper.rb +0 -13
- data/test/stub/rails3.2/test/unit/.gitkeep +0 -0
- data/test/stub/rails3.2/vendor/assets/stylesheets/.gitkeep +0 -0
- data/test/stub/rails3.2/vendor/plugins/.gitkeep +0 -0
- data/test/stub/rails4.0/.gitignore +0 -16
- data/test/stub/rails4.0/Gemfile +0 -45
- data/test/stub/rails4.0/Gemfile.lock +0 -126
- data/test/stub/rails4.0/README.rdoc +0 -28
- data/test/stub/rails4.0/Rakefile +0 -6
- data/test/stub/rails4.0/app/assets/images/.keep +0 -0
- data/test/stub/rails4.0/app/assets/javascripts/application.js +0 -16
- data/test/stub/rails4.0/app/assets/stylesheets/application.css +0 -13
- data/test/stub/rails4.0/app/controllers/application_controller.rb +0 -5
- data/test/stub/rails4.0/app/controllers/concerns/.keep +0 -0
- data/test/stub/rails4.0/app/helpers/application_helper.rb +0 -2
- data/test/stub/rails4.0/app/mailers/.keep +0 -0
- data/test/stub/rails4.0/app/models/.keep +0 -0
- data/test/stub/rails4.0/app/models/concerns/.keep +0 -0
- data/test/stub/rails4.0/app/views/layouts/application.html.erb +0 -14
- data/test/stub/rails4.0/bin/bundle +0 -3
- data/test/stub/rails4.0/bin/rails +0 -4
- data/test/stub/rails4.0/bin/rake +0 -4
- data/test/stub/rails4.0/config.ru +0 -4
- data/test/stub/rails4.0/config/application.rb +0 -23
- data/test/stub/rails4.0/config/boot.rb +0 -4
- data/test/stub/rails4.0/config/database.yml +0 -25
- data/test/stub/rails4.0/config/environment.rb +0 -5
- data/test/stub/rails4.0/config/environments/development.rb +0 -29
- data/test/stub/rails4.0/config/environments/production.rb +0 -80
- data/test/stub/rails4.0/config/environments/test.rb +0 -36
- data/test/stub/rails4.0/config/initializers/backtrace_silencers.rb +0 -7
- data/test/stub/rails4.0/config/initializers/filter_parameter_logging.rb +0 -4
- data/test/stub/rails4.0/config/initializers/inflections.rb +0 -16
- data/test/stub/rails4.0/config/initializers/mime_types.rb +0 -5
- data/test/stub/rails4.0/config/initializers/passenger.rb +0 -2
- data/test/stub/rails4.0/config/initializers/secret_token.rb +0 -12
- data/test/stub/rails4.0/config/initializers/session_store.rb +0 -3
- data/test/stub/rails4.0/config/initializers/wrap_parameters.rb +0 -14
- data/test/stub/rails4.0/config/locales/en.yml +0 -23
- data/test/stub/rails4.0/config/routes.rb +0 -57
- data/test/stub/rails4.0/db/seeds.rb +0 -7
- data/test/stub/rails4.0/lib/assets/.keep +0 -0
- data/test/stub/rails4.0/lib/tasks/.keep +0 -0
- data/test/stub/rails4.0/log/.keep +0 -0
- data/test/stub/rails4.0/public/404.html +0 -58
- data/test/stub/rails4.0/public/422.html +0 -58
- data/test/stub/rails4.0/public/500.html +0 -57
- data/test/stub/rails4.0/public/favicon.ico +0 -0
- data/test/stub/rails4.0/public/robots.txt +0 -5
- data/test/stub/rails4.0/test/controllers/.keep +0 -0
- data/test/stub/rails4.0/test/fixtures/.keep +0 -0
- data/test/stub/rails4.0/test/helpers/.keep +0 -0
- data/test/stub/rails4.0/test/integration/.keep +0 -0
- data/test/stub/rails4.0/test/mailers/.keep +0 -0
- data/test/stub/rails4.0/test/models/.keep +0 -0
- data/test/stub/rails4.0/test/test_helper.rb +0 -15
- data/test/stub/rails4.0/vendor/assets/javascripts/.keep +0 -0
- data/test/stub/rails4.0/vendor/assets/stylesheets/.keep +0 -0
- data/test/stub/rails4.1/.gitignore +0 -16
- data/test/stub/rails4.1/Gemfile +0 -45
- data/test/stub/rails4.1/Gemfile.lock +0 -129
- data/test/stub/rails4.1/README.rdoc +0 -28
- data/test/stub/rails4.1/Rakefile +0 -6
- data/test/stub/rails4.1/app/assets/images/.keep +0 -0
- data/test/stub/rails4.1/app/assets/javascripts/application.js +0 -16
- data/test/stub/rails4.1/app/assets/stylesheets/application.css +0 -13
- data/test/stub/rails4.1/app/controllers/application_controller.rb +0 -5
- data/test/stub/rails4.1/app/controllers/concerns/.keep +0 -0
- data/test/stub/rails4.1/app/helpers/application_helper.rb +0 -2
- data/test/stub/rails4.1/app/mailers/.keep +0 -0
- data/test/stub/rails4.1/app/models/.keep +0 -0
- data/test/stub/rails4.1/app/models/concerns/.keep +0 -0
- data/test/stub/rails4.1/app/views/layouts/application.html.erb +0 -14
- data/test/stub/rails4.1/bin/bundle +0 -3
- data/test/stub/rails4.1/bin/rails +0 -4
- data/test/stub/rails4.1/bin/rake +0 -4
- data/test/stub/rails4.1/config.ru +0 -4
- data/test/stub/rails4.1/config/application.rb +0 -23
- data/test/stub/rails4.1/config/boot.rb +0 -4
- data/test/stub/rails4.1/config/database.yml +0 -25
- data/test/stub/rails4.1/config/environment.rb +0 -5
- data/test/stub/rails4.1/config/environments/development.rb +0 -29
- data/test/stub/rails4.1/config/environments/production.rb +0 -80
- data/test/stub/rails4.1/config/environments/test.rb +0 -36
- data/test/stub/rails4.1/config/initializers/backtrace_silencers.rb +0 -7
- data/test/stub/rails4.1/config/initializers/filter_parameter_logging.rb +0 -4
- data/test/stub/rails4.1/config/initializers/inflections.rb +0 -16
- data/test/stub/rails4.1/config/initializers/mime_types.rb +0 -5
- data/test/stub/rails4.1/config/initializers/passenger.rb +0 -5
- data/test/stub/rails4.1/config/initializers/secret_token.rb +0 -12
- data/test/stub/rails4.1/config/initializers/session_store.rb +0 -3
- data/test/stub/rails4.1/config/initializers/wrap_parameters.rb +0 -14
- data/test/stub/rails4.1/config/locales/en.yml +0 -23
- data/test/stub/rails4.1/config/routes.rb +0 -57
- data/test/stub/rails4.1/db/seeds.rb +0 -7
- data/test/stub/rails4.1/lib/assets/.keep +0 -0
- data/test/stub/rails4.1/lib/tasks/.keep +0 -0
- data/test/stub/rails4.1/log/.keep +0 -0
- data/test/stub/rails4.1/public/404.html +0 -58
- data/test/stub/rails4.1/public/422.html +0 -58
- data/test/stub/rails4.1/public/500.html +0 -57
- data/test/stub/rails4.1/public/favicon.ico +0 -0
- data/test/stub/rails4.1/public/robots.txt +0 -5
- data/test/stub/rails4.1/test/controllers/.keep +0 -0
- data/test/stub/rails4.1/test/fixtures/.keep +0 -0
- data/test/stub/rails4.1/test/helpers/.keep +0 -0
- data/test/stub/rails4.1/test/integration/.keep +0 -0
- data/test/stub/rails4.1/test/mailers/.keep +0 -0
- data/test/stub/rails4.1/test/models/.keep +0 -0
- data/test/stub/rails4.1/test/test_helper.rb +0 -15
- data/test/stub/rails4.1/vendor/assets/javascripts/.keep +0 -0
- data/test/stub/rails4.1/vendor/assets/stylesheets/.keep +0 -0
- data/test/stub/start_error.pl +0 -24
- data/test/stub/upload_data.txt +0 -494
- data/test/stub/wsgi/passenger_wsgi.py +0 -212
- data/test/stub/wsgi/public/.gitignore +0 -0
- data/test/stub/wsgi/tmp/.gitignore +0 -0
- data/test/support/allocate_memory.c +0 -14
- data/test/support/apache2_controller.rb +0 -258
- data/test/support/multipart.rb +0 -62
- data/test/support/nginx_controller.rb +0 -97
- data/test/support/placebo-preloader.rb +0 -88
- data/test/support/test_helper.rb +0 -455
- data/test/support/valgrind.h +0 -2539
- data/test/tut/tut.h +0 -1310
- data/test/tut/tut_reporter.h +0 -256
- data/test/valgrind-osx.supp +0 -7
@@ -1,1463 +0,0 @@
|
|
1
|
-
#include <TestSupport.h>
|
2
|
-
#include <agents/HelperAgent/RequestHandler.h>
|
3
|
-
#include <agents/HelperAgent/RequestHandler.cpp>
|
4
|
-
#include <agents/HelperAgent/AgentOptions.h>
|
5
|
-
#include <ApplicationPool2/Pool.h>
|
6
|
-
#include <Utils/json.h>
|
7
|
-
#include <Utils/IOUtils.h>
|
8
|
-
#include <Utils/StrIntUtils.h>
|
9
|
-
#include <Utils/Timer.h>
|
10
|
-
#include <Utils/BufferedIO.h>
|
11
|
-
|
12
|
-
#include <boost/shared_array.hpp>
|
13
|
-
#include <string>
|
14
|
-
#include <vector>
|
15
|
-
#include <map>
|
16
|
-
#include <sstream>
|
17
|
-
#include <cstdarg>
|
18
|
-
#include <sys/socket.h>
|
19
|
-
|
20
|
-
using namespace std;
|
21
|
-
using namespace boost;
|
22
|
-
using namespace Passenger;
|
23
|
-
using namespace Passenger::ApplicationPool2;
|
24
|
-
|
25
|
-
namespace tut {
|
26
|
-
struct RequestHandlerTest {
|
27
|
-
InstanceDirectoryPtr instanceDir;
|
28
|
-
string serverFilename;
|
29
|
-
FileDescriptor requestSocket;
|
30
|
-
AgentOptions agentOptions;
|
31
|
-
|
32
|
-
BackgroundEventLoop bg;
|
33
|
-
SpawnerFactoryPtr spawnerFactory;
|
34
|
-
PoolPtr pool;
|
35
|
-
Pool::DebugSupportPtr debug;
|
36
|
-
boost::shared_ptr<RequestHandler> handler;
|
37
|
-
FileDescriptor connection;
|
38
|
-
map<string, string> defaultHeaders;
|
39
|
-
|
40
|
-
string root;
|
41
|
-
string rackAppPath, wsgiAppPath;
|
42
|
-
|
43
|
-
RequestHandlerTest() {
|
44
|
-
createInstanceDir(instanceDir);
|
45
|
-
spawnerFactory = boost::make_shared<SpawnerFactory>(
|
46
|
-
make_shared<SpawnerConfig>(*resourceLocator));
|
47
|
-
pool = boost::make_shared<Pool>(spawnerFactory);
|
48
|
-
pool->initialize();
|
49
|
-
serverFilename = instanceDir->getPath() + "/server";
|
50
|
-
requestSocket = createUnixServer(serverFilename);
|
51
|
-
setNonBlocking(requestSocket);
|
52
|
-
setLogLevel(LVL_WARN);
|
53
|
-
setPrintAppOutputAsDebuggingMessages(true);
|
54
|
-
|
55
|
-
agentOptions.passengerRoot = resourceLocator->getRoot();
|
56
|
-
agentOptions.defaultRubyCommand = DEFAULT_RUBY;
|
57
|
-
agentOptions.defaultUser = testConfig["default_user"].asString();
|
58
|
-
agentOptions.defaultGroup = testConfig["default_group"].asString();
|
59
|
-
root = resourceLocator->getRoot();
|
60
|
-
rackAppPath = root + "/test/stub/rack";
|
61
|
-
wsgiAppPath = root + "/test/stub/wsgi";
|
62
|
-
defaultHeaders["PASSENGER_LOAD_SHELL_ENVVARS"] = "false";
|
63
|
-
defaultHeaders["PASSENGER_APP_TYPE"] = "wsgi";
|
64
|
-
defaultHeaders["PASSENGER_SPAWN_METHOD"] = "direct";
|
65
|
-
defaultHeaders["REQUEST_METHOD"] = "GET";
|
66
|
-
}
|
67
|
-
|
68
|
-
~RequestHandlerTest() {
|
69
|
-
setLogLevel(DEFAULT_LOG_LEVEL);
|
70
|
-
setPrintAppOutputAsDebuggingMessages(false);
|
71
|
-
if (bg.isStarted()) {
|
72
|
-
bg.safe->runSync(boost::bind(&RequestHandlerTest::destroy, this));
|
73
|
-
} else {
|
74
|
-
destroy();
|
75
|
-
}
|
76
|
-
unlink(serverFilename.c_str());
|
77
|
-
}
|
78
|
-
|
79
|
-
void init() {
|
80
|
-
handler = boost::make_shared<RequestHandler>(bg.safe, requestSocket, pool, agentOptions);
|
81
|
-
bg.start();
|
82
|
-
}
|
83
|
-
|
84
|
-
void destroy() {
|
85
|
-
handler.reset();
|
86
|
-
pool->destroy();
|
87
|
-
pool.reset();
|
88
|
-
ev_break(bg.loop, EVBREAK_ALL);
|
89
|
-
}
|
90
|
-
|
91
|
-
void initPoolDebugging() {
|
92
|
-
pool->initDebugging();
|
93
|
-
debug = pool->debugSupport;
|
94
|
-
}
|
95
|
-
|
96
|
-
FileDescriptor &connect() {
|
97
|
-
connection = connectToUnixServer(serverFilename);
|
98
|
-
return connection;
|
99
|
-
}
|
100
|
-
|
101
|
-
void sendHeaders(const map<string, string> &headers, const char *header1,
|
102
|
-
const char *value1, ...)
|
103
|
-
{
|
104
|
-
va_list ap;
|
105
|
-
const char *arg;
|
106
|
-
map<string, string> finalHeaders;
|
107
|
-
map<string, string>::const_iterator it;
|
108
|
-
vector<StaticString> args;
|
109
|
-
unsigned int totalSize = 0;
|
110
|
-
|
111
|
-
for (it = headers.begin(); it != headers.end(); it++) {
|
112
|
-
string key = string(it->first.data(), it->first.size() + 1);
|
113
|
-
string value = string(it->second.data(), it->second.size() + 1);
|
114
|
-
finalHeaders[key] = value;
|
115
|
-
}
|
116
|
-
|
117
|
-
finalHeaders[makeStaticStringWithNull(header1)] =
|
118
|
-
makeStaticStringWithNull(value1);
|
119
|
-
|
120
|
-
va_start(ap, value1);
|
121
|
-
while ((arg = va_arg(ap, const char *)) != NULL) {
|
122
|
-
string key(arg, strlen(arg) + 1);
|
123
|
-
arg = va_arg(ap, const char *);
|
124
|
-
string value(arg, strlen(arg) + 1);
|
125
|
-
finalHeaders[key] = value;
|
126
|
-
}
|
127
|
-
va_end(ap);
|
128
|
-
|
129
|
-
for (it = finalHeaders.begin(); it != finalHeaders.end(); it++) {
|
130
|
-
args.push_back(it->first);
|
131
|
-
args.push_back(it->second);
|
132
|
-
totalSize += it->first.size();
|
133
|
-
totalSize += it->second.size();
|
134
|
-
}
|
135
|
-
|
136
|
-
char totalSizeString[10];
|
137
|
-
snprintf(totalSizeString, sizeof(totalSizeString), "%u:", totalSize);
|
138
|
-
args.insert(args.begin(), StaticString(totalSizeString));
|
139
|
-
args.push_back(",");
|
140
|
-
|
141
|
-
gatheredWrite(connection, &args[0], args.size(), NULL);
|
142
|
-
}
|
143
|
-
|
144
|
-
string stripHeaders(const string &str) {
|
145
|
-
string::size_type pos = str.find("\r\n\r\n");
|
146
|
-
if (pos == string::npos) {
|
147
|
-
return str;
|
148
|
-
} else {
|
149
|
-
string result = str;
|
150
|
-
result.erase(0, pos + 4);
|
151
|
-
return result;
|
152
|
-
}
|
153
|
-
}
|
154
|
-
|
155
|
-
string inspect() {
|
156
|
-
string result;
|
157
|
-
bg.safe->runSync(boost::bind(&RequestHandlerTest::real_inspect, this, &result));
|
158
|
-
return result;
|
159
|
-
}
|
160
|
-
|
161
|
-
void real_inspect(string *result) {
|
162
|
-
stringstream stream;
|
163
|
-
handler->inspect(stream);
|
164
|
-
*result = stream.str();
|
165
|
-
}
|
166
|
-
|
167
|
-
static void writeBody(FileDescriptor conn, string body) {
|
168
|
-
try {
|
169
|
-
writeExact(conn, body);
|
170
|
-
} catch (const SystemException &e) {
|
171
|
-
if (e.code() == EPIPE) {
|
172
|
-
// Ignore.
|
173
|
-
} else {
|
174
|
-
throw;
|
175
|
-
}
|
176
|
-
}
|
177
|
-
}
|
178
|
-
};
|
179
|
-
|
180
|
-
DEFINE_TEST_GROUP_WITH_LIMIT(RequestHandlerTest, 80);
|
181
|
-
|
182
|
-
|
183
|
-
/***** Basic tests *****/
|
184
|
-
|
185
|
-
TEST_METHOD(1) {
|
186
|
-
set_test_name("A request is forwarded to the app process, and its response is forwarded back.");
|
187
|
-
init();
|
188
|
-
connect();
|
189
|
-
sendHeaders(defaultHeaders,
|
190
|
-
"PASSENGER_APP_ROOT", wsgiAppPath.c_str(),
|
191
|
-
"PATH_INFO", "/",
|
192
|
-
NULL);
|
193
|
-
string response = readAll(connection);
|
194
|
-
string body = stripHeaders(response);
|
195
|
-
ensure("Status line is correct", containsSubstring(response, "HTTP/1.1 200 OK\r\n"));
|
196
|
-
ensure("Headers are correct", containsSubstring(response, "Content-Type: text/plain\r\n"));
|
197
|
-
ensure("Contains a Status header", containsSubstring(response, "Status: 200 OK\r\n"));
|
198
|
-
ensure_equals(body, "front page");
|
199
|
-
}
|
200
|
-
|
201
|
-
TEST_METHOD(2) {
|
202
|
-
set_test_name("It can handle multiple requests in serial.");
|
203
|
-
init();
|
204
|
-
for (int i = 0; i < 10; i++) {
|
205
|
-
connect();
|
206
|
-
sendHeaders(defaultHeaders,
|
207
|
-
"PASSENGER_APP_ROOT", wsgiAppPath.c_str(),
|
208
|
-
"PATH_INFO", "/",
|
209
|
-
NULL);
|
210
|
-
string response = readAll(connection);
|
211
|
-
string body = stripHeaders(response);
|
212
|
-
ensure("Status line is correct", containsSubstring(response, "HTTP/1.1 200 OK\r\n"));
|
213
|
-
ensure("Headers are correct", containsSubstring(response, "Content-Type: text/plain\r\n"));
|
214
|
-
ensure("Contains a Status header", containsSubstring(response, "Status: 200 OK\r\n"));
|
215
|
-
ensure_equals(body, "front page");
|
216
|
-
}
|
217
|
-
}
|
218
|
-
|
219
|
-
TEST_METHOD(3) {
|
220
|
-
set_test_name("It can handle request data that is sent piece-wise.");
|
221
|
-
defaultHeaders["PASSENGER_APP_ROOT"] = wsgiAppPath;
|
222
|
-
defaultHeaders["PATH_INFO"] = "/";
|
223
|
-
|
224
|
-
string request;
|
225
|
-
map<string, string>::const_iterator it, end = defaultHeaders.end();
|
226
|
-
for (it = defaultHeaders.begin(); it != end; it++) {
|
227
|
-
request.append(it->first);
|
228
|
-
request.append(1, '\0');
|
229
|
-
request.append(it->second);
|
230
|
-
request.append(1, '\0');
|
231
|
-
}
|
232
|
-
request = toString(request.size()) + ":" + request;
|
233
|
-
request.append(",");
|
234
|
-
|
235
|
-
init();
|
236
|
-
connect();
|
237
|
-
string::size_type i = 0;
|
238
|
-
while (i < request.size()) {
|
239
|
-
const string piece = const_cast<const string &>(request).substr(i, 5);
|
240
|
-
writeExact(connection, piece);
|
241
|
-
usleep(10000);
|
242
|
-
i += piece.size();
|
243
|
-
}
|
244
|
-
|
245
|
-
string response = readAll(connection);
|
246
|
-
string body = stripHeaders(response);
|
247
|
-
ensure("Status line is correct", containsSubstring(response, "HTTP/1.1 200 OK\r\n"));
|
248
|
-
ensure("Headers are correct", containsSubstring(response, "Content-Type: text/plain\r\n"));
|
249
|
-
ensure("Contains a Status header", containsSubstring(response, "Status: 200 OK\r\n"));
|
250
|
-
ensure_equals(body, "front page");
|
251
|
-
}
|
252
|
-
|
253
|
-
TEST_METHOD(4) {
|
254
|
-
set_test_name("It closes the connection with the application if the client has closed the connection.");
|
255
|
-
init();
|
256
|
-
connect();
|
257
|
-
sendHeaders(defaultHeaders,
|
258
|
-
"PASSENGER_APP_ROOT", wsgiAppPath.c_str(),
|
259
|
-
"PATH_INFO", "/stream",
|
260
|
-
NULL
|
261
|
-
);
|
262
|
-
BufferedIO io(connection);
|
263
|
-
ensure_equals(io.readLine(), "HTTP/1.1 200 OK\r\n");
|
264
|
-
ProcessPtr process;
|
265
|
-
{
|
266
|
-
LockGuard l(pool->syncher);
|
267
|
-
ensure_equals(pool->getProcessCount(false), 1u);
|
268
|
-
SuperGroupPtr superGroup = pool->superGroups.get(wsgiAppPath);
|
269
|
-
process = superGroup->defaultGroup->enabledProcesses.front();
|
270
|
-
ensure_equals(process->sessions, 1);
|
271
|
-
}
|
272
|
-
connection.close();
|
273
|
-
EVENTUALLY(5,
|
274
|
-
LockGuard l(pool->syncher);
|
275
|
-
result = process->sessions == 0;
|
276
|
-
);
|
277
|
-
}
|
278
|
-
|
279
|
-
|
280
|
-
/***** Connect password tests *****/
|
281
|
-
|
282
|
-
TEST_METHOD(5) {
|
283
|
-
set_test_name("It denies access if the connect password is wrong.");
|
284
|
-
agentOptions.requestSocketPassword = "hello world";
|
285
|
-
setLogLevel(LVL_ERROR);
|
286
|
-
init();
|
287
|
-
|
288
|
-
connect();
|
289
|
-
writeExact(connection, "hello world");
|
290
|
-
sendHeaders(defaultHeaders,
|
291
|
-
"PASSENGER_APP_ROOT", wsgiAppPath.c_str(),
|
292
|
-
"PATH_INFO", "/",
|
293
|
-
NULL
|
294
|
-
);
|
295
|
-
ensure(containsSubstring(readAll(connection), "front page"));
|
296
|
-
|
297
|
-
connect();
|
298
|
-
try {
|
299
|
-
sendHeaders(defaultHeaders,
|
300
|
-
"PASSENGER_APP_ROOT", wsgiAppPath.c_str(),
|
301
|
-
"PATH_INFO", "/",
|
302
|
-
NULL
|
303
|
-
);
|
304
|
-
} catch (const SystemException &e) {
|
305
|
-
ensure_equals(e.code(), EPIPE);
|
306
|
-
return;
|
307
|
-
}
|
308
|
-
string response;
|
309
|
-
try {
|
310
|
-
response = readAll(connection);
|
311
|
-
} catch (const SystemException &e) {
|
312
|
-
ensure_equals(e.code(), ECONNRESET);
|
313
|
-
return;
|
314
|
-
}
|
315
|
-
ensure_equals(response, "");
|
316
|
-
}
|
317
|
-
|
318
|
-
TEST_METHOD(6) {
|
319
|
-
set_test_name("It disconnects the client if the connect password is not sent within a certain time.");
|
320
|
-
agentOptions.requestSocketPassword = "hello world";
|
321
|
-
setLogLevel(LVL_ERROR);
|
322
|
-
handler = boost::make_shared<RequestHandler>(bg.safe, requestSocket, pool, agentOptions);
|
323
|
-
handler->connectPasswordTimeout = 40;
|
324
|
-
bg.start();
|
325
|
-
|
326
|
-
connect();
|
327
|
-
Timer timer;
|
328
|
-
readAll(connection);
|
329
|
-
timer.stop();
|
330
|
-
ensure(timer.elapsed() <= 60);
|
331
|
-
}
|
332
|
-
|
333
|
-
TEST_METHOD(7) {
|
334
|
-
set_test_name("It works correctly if the connect password is sent piece-wise.");
|
335
|
-
agentOptions.requestSocketPassword = "hello world";
|
336
|
-
init();
|
337
|
-
connect();
|
338
|
-
writeExact(connection, "hello");
|
339
|
-
usleep(10000);
|
340
|
-
writeExact(connection, " world");
|
341
|
-
usleep(10000);
|
342
|
-
sendHeaders(defaultHeaders,
|
343
|
-
"PASSENGER_APP_ROOT", wsgiAppPath.c_str(),
|
344
|
-
"PATH_INFO", "/",
|
345
|
-
NULL
|
346
|
-
);
|
347
|
-
ensure(containsSubstring(readAll(connection), "front page"));
|
348
|
-
}
|
349
|
-
|
350
|
-
|
351
|
-
/***** Error page tests *****/
|
352
|
-
|
353
|
-
TEST_METHOD(10) {
|
354
|
-
set_test_name("If the app crashes at startup without an error page, "
|
355
|
-
"and friendly error pages are turned on, then it renders a generic error page.");
|
356
|
-
TempDir tempdir("tmp.handler");
|
357
|
-
writeFile("tmp.handler/start.rb",
|
358
|
-
"STDERR.puts 'I have failed'");
|
359
|
-
|
360
|
-
setLogLevel(LVL_CRIT);
|
361
|
-
init();
|
362
|
-
connect();
|
363
|
-
sendHeaders(defaultHeaders,
|
364
|
-
"PASSENGER_APP_ROOT", (root + "/test/tmp.handler").c_str(),
|
365
|
-
"PASSENGER_APP_TYPE", "",
|
366
|
-
"PASSENGER_START_COMMAND", ("ruby\t" + root + "/test/tmp.handler/start.rb").c_str(),
|
367
|
-
"PASSENGER_FRIENDLY_ERROR_PAGES", "true",
|
368
|
-
"PATH_INFO", "/",
|
369
|
-
NULL);
|
370
|
-
string response = readAll(connection);
|
371
|
-
ensure(containsSubstring(response, "HTTP/1.1 500 Internal Server Error\r\n"));
|
372
|
-
ensure(containsSubstring(response, "Status: 500 Internal Server Error\r\n"));
|
373
|
-
ensure(containsSubstring(response, "I have failed"));
|
374
|
-
}
|
375
|
-
|
376
|
-
TEST_METHOD(11) {
|
377
|
-
set_test_name("If the app crashes at startup with an error page, "
|
378
|
-
"and friendly error pages are turned on, then it renders a friendly error page.");
|
379
|
-
TempDir tempdir("tmp.handler");
|
380
|
-
writeFile("tmp.handler/start.rb",
|
381
|
-
"STDERR.puts 'Error'\n"
|
382
|
-
"STDERR.puts\n"
|
383
|
-
"STDERR.puts 'I have failed'\n");
|
384
|
-
|
385
|
-
setLogLevel(LVL_CRIT);
|
386
|
-
init();
|
387
|
-
connect();
|
388
|
-
sendHeaders(defaultHeaders,
|
389
|
-
"PASSENGER_APP_ROOT", (root + "/test/tmp.handler").c_str(),
|
390
|
-
"PASSENGER_APP_TYPE", "",
|
391
|
-
"PASSENGER_START_COMMAND", ("ruby\t" + root + "/test/tmp.handler/start.rb").c_str(),
|
392
|
-
"PASSENGER_FRIENDLY_ERROR_PAGES", "true",
|
393
|
-
"PATH_INFO", "/",
|
394
|
-
NULL);
|
395
|
-
string response = readAll(connection);
|
396
|
-
ensure(containsSubstring(response, "HTTP/1.1 500 Internal Server Error\r\n"));
|
397
|
-
ensure(containsSubstring(response, "Status: 500 Internal Server Error\r\n"));
|
398
|
-
ensure(containsSubstring(response, "Content-Type: text/html; charset=UTF-8\r\n"));
|
399
|
-
ensure(containsSubstring(response, "<html>"));
|
400
|
-
ensure(containsSubstring(response, "I have failed"));
|
401
|
-
}
|
402
|
-
|
403
|
-
TEST_METHOD(12) {
|
404
|
-
set_test_name("If spawning fails because of an internal error, "
|
405
|
-
"and friendly error pages are on, then it reports the error appropriately.");
|
406
|
-
TempDir tempdir("tmp.handler");
|
407
|
-
writeFile("tmp.handler/start.rb", "");
|
408
|
-
|
409
|
-
setLogLevel(LVL_CRIT);
|
410
|
-
init();
|
411
|
-
connect();
|
412
|
-
sendHeaders(defaultHeaders,
|
413
|
-
"PASSENGER_APP_ROOT", (root + "/test/tmp.handler").c_str(),
|
414
|
-
"PASSENGER_APP_TYPE", "",
|
415
|
-
"PASSENGER_START_COMMAND", ("ruby\t" + root + "/test/tmp.handler/start.rb").c_str(),
|
416
|
-
"PASSENGER_FRIENDLY_ERROR_PAGES", "true",
|
417
|
-
"PASSENGER_RAISE_INTERNAL_ERROR", "true",
|
418
|
-
"PATH_INFO", "/",
|
419
|
-
NULL);
|
420
|
-
string response = readAll(connection);
|
421
|
-
ensure("(1)", containsSubstring(response, "HTTP/1.1 500 Internal Server Error\r\n"));
|
422
|
-
ensure("(2)", containsSubstring(response, "Status: 500 Internal Server Error\r\n"));
|
423
|
-
ensure("(3)", containsSubstring(response, "Content-Type: text/html; charset=UTF-8\r\n"));
|
424
|
-
ensure("(4)", containsSubstring(response, "<html>"));
|
425
|
-
ensure("(5)", containsSubstring(response, "An internal error occurred while trying to spawn the application."));
|
426
|
-
ensure("(6)", containsSubstring(response, "RuntimeException"));
|
427
|
-
ensure("(7)", containsSubstring(response, "An internal error!"));
|
428
|
-
ensure("(8)", containsSubstring(response, "Spawner.h"));
|
429
|
-
}
|
430
|
-
|
431
|
-
TEST_METHOD(13) {
|
432
|
-
set_test_name("Error pages respect the PASSENGER_STATUS_LINE option.");
|
433
|
-
TempDir tempdir("tmp.handler");
|
434
|
-
writeFile("tmp.handler/start.rb",
|
435
|
-
"STDERR.puts 'I have failed'");
|
436
|
-
|
437
|
-
setLogLevel(LVL_CRIT);
|
438
|
-
init();
|
439
|
-
connect();
|
440
|
-
sendHeaders(defaultHeaders,
|
441
|
-
"PASSENGER_APP_ROOT", (root + "/test/tmp.handler").c_str(),
|
442
|
-
"PASSENGER_APP_TYPE", "",
|
443
|
-
"PASSENGER_START_COMMAND", ("ruby\t" + root + "/test/tmp.handler/start.rb").c_str(),
|
444
|
-
"PASSENGER_FRIENDLY_ERROR_PAGES", "true",
|
445
|
-
"PASSENGER_STATUS_LINE", "false",
|
446
|
-
"PATH_INFO", "/",
|
447
|
-
NULL);
|
448
|
-
string response = readAll(connection);
|
449
|
-
ensure(!containsSubstring(response, "HTTP/1.1 "));
|
450
|
-
ensure(containsSubstring(response, "Status: 500 Internal Server Error\r\n"));
|
451
|
-
ensure(containsSubstring(response, "I have failed"));
|
452
|
-
}
|
453
|
-
|
454
|
-
TEST_METHOD(14) {
|
455
|
-
set_test_name("If PASSENGER_FRIENDLY_ERROR_PAGES is false then it does not render a friendly error page.");
|
456
|
-
TempDir tempdir("tmp.handler");
|
457
|
-
writeFile("tmp.handler/start.rb",
|
458
|
-
"STDERR.puts 'Error'\n"
|
459
|
-
"STDERR.puts\n"
|
460
|
-
"STDERR.puts 'I have failed'\n");
|
461
|
-
|
462
|
-
setLogLevel(LVL_CRIT);
|
463
|
-
init();
|
464
|
-
connect();
|
465
|
-
sendHeaders(defaultHeaders,
|
466
|
-
"PASSENGER_APP_ROOT", (root + "/test/tmp.handler").c_str(),
|
467
|
-
"PASSENGER_APP_TYPE", "",
|
468
|
-
"PASSENGER_START_COMMAND", ("ruby\t" + root + "/test/tmp.handler/start.rb").c_str(),
|
469
|
-
"PASSENGER_FRIENDLY_ERROR_PAGES", "false",
|
470
|
-
"PATH_INFO", "/",
|
471
|
-
NULL);
|
472
|
-
string response = readAll(connection);
|
473
|
-
ensure(containsSubstring(response, "HTTP/1.1 500 Internal Server Error\r\n"));
|
474
|
-
ensure(containsSubstring(response, "Status: 500 Internal Server Error\r\n"));
|
475
|
-
ensure(containsSubstring(response, "Content-Type: text/html; charset=UTF-8\r\n"));
|
476
|
-
ensure(containsSubstring(response, "<html>"));
|
477
|
-
ensure(!containsSubstring(response, "I have failed"));
|
478
|
-
ensure(containsSubstring(response, "We're sorry, but something went wrong"));
|
479
|
-
}
|
480
|
-
|
481
|
-
|
482
|
-
/***** Buffering tests *****/
|
483
|
-
|
484
|
-
TEST_METHOD(21) {
|
485
|
-
set_test_name("If PASSENGER_BUFFERING is true, and Content-Length is given, it buffers the request body.");
|
486
|
-
DeleteFileEventually file("tmp.output");
|
487
|
-
|
488
|
-
init();
|
489
|
-
connect();
|
490
|
-
sendHeaders(defaultHeaders,
|
491
|
-
"PASSENGER_APP_ROOT", wsgiAppPath.c_str(),
|
492
|
-
"PASSENGER_BUFFERING", "true",
|
493
|
-
"REQUEST_METHOD", "POST",
|
494
|
-
"PATH_INFO", "/raw_upload_to_file",
|
495
|
-
"CONTENT_LENGTH", "12",
|
496
|
-
"HTTP_X_OUTPUT", (root + "/test/tmp.output").c_str(),
|
497
|
-
NULL);
|
498
|
-
writeExact(connection, "hello\n");
|
499
|
-
SHOULD_NEVER_HAPPEN(200,
|
500
|
-
result = fileExists("tmp.output");
|
501
|
-
);
|
502
|
-
writeExact(connection, "world\n");
|
503
|
-
EVENTUALLY(1,
|
504
|
-
result = fileExists("tmp.output");
|
505
|
-
);
|
506
|
-
ensure_equals(stripHeaders(readAll(connection)), "ok");
|
507
|
-
}
|
508
|
-
|
509
|
-
TEST_METHOD(22) {
|
510
|
-
set_test_name("If PASSENGER_BUFFERING is true, and Transfer-Encoding is given, it buffers the request body.");
|
511
|
-
DeleteFileEventually file("tmp.output");
|
512
|
-
|
513
|
-
init();
|
514
|
-
connect();
|
515
|
-
sendHeaders(defaultHeaders,
|
516
|
-
"PASSENGER_APP_ROOT", wsgiAppPath.c_str(),
|
517
|
-
"PASSENGER_BUFFERING", "true",
|
518
|
-
"REQUEST_METHOD", "POST",
|
519
|
-
"PATH_INFO", "/raw_upload_to_file",
|
520
|
-
"HTTP_TRANSFER_ENCODING", "chunked",
|
521
|
-
"HTTP_X_OUTPUT", (root + "/test/tmp.output").c_str(),
|
522
|
-
NULL);
|
523
|
-
writeExact(connection, "hello\n");
|
524
|
-
SHOULD_NEVER_HAPPEN(200,
|
525
|
-
result = fileExists("tmp.output");
|
526
|
-
);
|
527
|
-
writeExact(connection, "world\n");
|
528
|
-
SHOULD_NEVER_HAPPEN(200,
|
529
|
-
result = fileExists("tmp.output");
|
530
|
-
);
|
531
|
-
shutdown(connection, SHUT_WR);
|
532
|
-
ensure_equals(stripHeaders(readAll(connection)), "ok");
|
533
|
-
}
|
534
|
-
|
535
|
-
TEST_METHOD(24) {
|
536
|
-
set_test_name("Test buffering of large request bodies that fit in neither the socket "
|
537
|
-
"buffer nor the FileBackedPipe memory buffer, and that the application "
|
538
|
-
"cannot read quickly enough.");
|
539
|
-
|
540
|
-
DeleteFileEventually d1("/tmp/wait.txt");
|
541
|
-
DeleteFileEventually d2("/tmp/output.txt");
|
542
|
-
|
543
|
-
// 2.6 MB of request body. Guaranteed not to fit in any socket buffer.
|
544
|
-
string requestBody;
|
545
|
-
for (int i = 0; i < 204800; i++) {
|
546
|
-
requestBody.append("hello world!\n");
|
547
|
-
}
|
548
|
-
|
549
|
-
init();
|
550
|
-
connect();
|
551
|
-
sendHeaders(defaultHeaders,
|
552
|
-
"PASSENGER_APP_ROOT", wsgiAppPath.c_str(),
|
553
|
-
"REQUEST_METHOD", "POST",
|
554
|
-
"PATH_INFO", "/raw_upload_to_file",
|
555
|
-
"PASSENGER_BUFFERING", "true",
|
556
|
-
"CONTENT_LENGTH", toString(requestBody.size()).c_str(),
|
557
|
-
"HTTP_X_WAIT_FOR_FILE", "/tmp/wait.txt",
|
558
|
-
"HTTP_X_OUTPUT", "/tmp/output.txt",
|
559
|
-
NULL);
|
560
|
-
|
561
|
-
// Should not block.
|
562
|
-
writeExact(connection, requestBody);
|
563
|
-
shutdown(connection, SHUT_WR);
|
564
|
-
|
565
|
-
EVENTUALLY(5,
|
566
|
-
result = containsSubstring(inspect(), "session initiated = true");
|
567
|
-
);
|
568
|
-
touchFile("/tmp/wait.txt");
|
569
|
-
|
570
|
-
string result = stripHeaders(readAll(connection));
|
571
|
-
ensure_equals(result, "ok");
|
572
|
-
struct stat buf;
|
573
|
-
ensure(stat("/tmp/output.txt", &buf) == 0);
|
574
|
-
ensure_equals(buf.st_size, (off_t) requestBody.size());
|
575
|
-
}
|
576
|
-
|
577
|
-
TEST_METHOD(25) {
|
578
|
-
set_test_name("Test handling of slow clients that can't receive response data fast enough (response buffering).");
|
579
|
-
init();
|
580
|
-
connect();
|
581
|
-
sendHeaders(defaultHeaders,
|
582
|
-
"PASSENGER_APP_ROOT", wsgiAppPath.c_str(),
|
583
|
-
"PATH_INFO", "/blob",
|
584
|
-
"HTTP_X_SIZE", "10485760",
|
585
|
-
NULL);
|
586
|
-
EVENTUALLY(10,
|
587
|
-
result = containsSubstring(inspect(), "appInput reachedEnd = true");
|
588
|
-
);
|
589
|
-
string result = stripHeaders(readAll(connection));
|
590
|
-
ensure_equals(result.size(), 10485760u);
|
591
|
-
const char *data = result.data();
|
592
|
-
const char *end = result.data() + result.size();
|
593
|
-
while (data < end) {
|
594
|
-
ensure_equals(*data, 'x');
|
595
|
-
data++;
|
596
|
-
}
|
597
|
-
}
|
598
|
-
|
599
|
-
|
600
|
-
/***** Header handling tests *****/
|
601
|
-
|
602
|
-
TEST_METHOD(26) {
|
603
|
-
set_test_name("It replaces HTTP_CONTENT_LENGTH with CONTENT_LENGTH.");
|
604
|
-
init();
|
605
|
-
connect();
|
606
|
-
sendHeaders(defaultHeaders,
|
607
|
-
"PASSENGER_APP_ROOT", wsgiAppPath.c_str(),
|
608
|
-
"REQUEST_METHOD", "POST",
|
609
|
-
"PATH_INFO", "/env",
|
610
|
-
"HTTP_CONTENT_LENGTH", "5",
|
611
|
-
NULL);
|
612
|
-
writeExact(connection, "hello");
|
613
|
-
string response = readAll(connection);
|
614
|
-
ensure(containsSubstring(response, "CONTENT_LENGTH = 5\n"));
|
615
|
-
ensure(!containsSubstring(response, "HTTP_CONTENT_LENGTH"));
|
616
|
-
}
|
617
|
-
|
618
|
-
TEST_METHOD(27) {
|
619
|
-
set_test_name("It replaces HTTP_CONTENT_TYPE with CONTENT_TYPE.");
|
620
|
-
init();
|
621
|
-
connect();
|
622
|
-
sendHeaders(defaultHeaders,
|
623
|
-
"PASSENGER_APP_ROOT", wsgiAppPath.c_str(),
|
624
|
-
"PATH_INFO", "/env",
|
625
|
-
"HTTP_CONTENT_TYPE", "application/json",
|
626
|
-
NULL);
|
627
|
-
string response = readAll(connection);
|
628
|
-
ensure(containsSubstring(response, "CONTENT_TYPE = application/json\n"));
|
629
|
-
ensure(!containsSubstring(response, "HTTP_CONTENT_TYPE"));
|
630
|
-
}
|
631
|
-
|
632
|
-
TEST_METHOD(28) {
|
633
|
-
set_test_name("The response doesn't contain an HTTP status line if PASSENGER_STATUS_LINE is false.");
|
634
|
-
init();
|
635
|
-
connect();
|
636
|
-
sendHeaders(defaultHeaders,
|
637
|
-
"PASSENGER_APP_ROOT", wsgiAppPath.c_str(),
|
638
|
-
"PASSENGER_STATUS_LINE", "false",
|
639
|
-
"PATH_INFO", "/",
|
640
|
-
NULL);
|
641
|
-
string response = readAll(connection);
|
642
|
-
ensure(!containsSubstring(response, "HTTP/1.1 "));
|
643
|
-
ensure(containsSubstring(response, "Status: 200 OK\r\n"));
|
644
|
-
}
|
645
|
-
|
646
|
-
TEST_METHOD(29) {
|
647
|
-
set_test_name("If the application outputs a status line without a reason phrase, then a reason phrase is automatically appended.");
|
648
|
-
init();
|
649
|
-
connect();
|
650
|
-
sendHeaders(defaultHeaders,
|
651
|
-
"PASSENGER_APP_ROOT", wsgiAppPath.c_str(),
|
652
|
-
"PATH_INFO", "/custom_status",
|
653
|
-
"HTTP_X_CUSTOM_STATUS", "201",
|
654
|
-
NULL);
|
655
|
-
string response = readAll(connection);
|
656
|
-
ensure(containsSubstring(response, "HTTP/1.1 201 Created\r\n"));
|
657
|
-
ensure(containsSubstring(response, "Status: 201 Created\r\n"));
|
658
|
-
}
|
659
|
-
|
660
|
-
TEST_METHOD(30) {
|
661
|
-
set_test_name("If the application outputs a status line with a custom reason phrase, then that reason phrase is used.");
|
662
|
-
init();
|
663
|
-
connect();
|
664
|
-
sendHeaders(defaultHeaders,
|
665
|
-
"PASSENGER_APP_ROOT", wsgiAppPath.c_str(),
|
666
|
-
"PATH_INFO", "/custom_status",
|
667
|
-
"HTTP_X_CUSTOM_STATUS", "201 Bunnies Jump",
|
668
|
-
NULL);
|
669
|
-
string response = readAll(connection);
|
670
|
-
ensure(containsSubstring(response, "HTTP/1.1 201 Bunnies Jump\r\n"));
|
671
|
-
ensure(containsSubstring(response, "Status: 201 Bunnies Jump\r\n"));
|
672
|
-
}
|
673
|
-
|
674
|
-
TEST_METHOD(31) {
|
675
|
-
set_test_name("It appends a Date header if the app doesn't output one.");
|
676
|
-
|
677
|
-
init();
|
678
|
-
connect();
|
679
|
-
sendHeaders(defaultHeaders,
|
680
|
-
"PASSENGER_APP_ROOT", wsgiAppPath.c_str(),
|
681
|
-
"PATH_INFO", "/pid",
|
682
|
-
NULL);
|
683
|
-
|
684
|
-
string result = readAll(connection);
|
685
|
-
ensure(result.find("Date: ") != string::npos);
|
686
|
-
}
|
687
|
-
|
688
|
-
TEST_METHOD(32) {
|
689
|
-
set_test_name("It rejects non-GET, non-HEAD requests with an Upgrade header.");
|
690
|
-
|
691
|
-
init();
|
692
|
-
connect();
|
693
|
-
sendHeaders(defaultHeaders,
|
694
|
-
"PASSENGER_APP_ROOT", wsgiAppPath.c_str(),
|
695
|
-
"PATH_INFO", "/",
|
696
|
-
"REQUEST_METHOD", "POST",
|
697
|
-
"HTTP_UPGRADE", "WebSocket",
|
698
|
-
NULL);
|
699
|
-
string response = readAll(connection);
|
700
|
-
ensure(containsSubstring(response, "HTTP/1.1 400 Bad Request"));
|
701
|
-
}
|
702
|
-
|
703
|
-
TEST_METHOD(33) {
|
704
|
-
set_test_name("It accepts GET/HEAD requests with a Content-Length header.");
|
705
|
-
|
706
|
-
DeleteFileEventually d("/tmp/output.txt");
|
707
|
-
|
708
|
-
init();
|
709
|
-
connect();
|
710
|
-
sendHeaders(defaultHeaders,
|
711
|
-
"PASSENGER_APP_ROOT", wsgiAppPath.c_str(),
|
712
|
-
"PATH_INFO", "/raw_upload_to_file",
|
713
|
-
"REQUEST_METHOD", "GET",
|
714
|
-
"CONTENT_LENGTH", "2",
|
715
|
-
"HTTP_X_OUTPUT", "/tmp/output.txt",
|
716
|
-
NULL);
|
717
|
-
writeExact(connection, "hi");
|
718
|
-
|
719
|
-
string result = stripHeaders(readAll(connection));
|
720
|
-
ensure_equals(result, "ok");
|
721
|
-
ensure_equals(readAll("/tmp/output.txt"), "hi");
|
722
|
-
|
723
|
-
connect();
|
724
|
-
sendHeaders(defaultHeaders,
|
725
|
-
"PASSENGER_APP_ROOT", wsgiAppPath.c_str(),
|
726
|
-
"PATH_INFO", "/raw_upload_to_file",
|
727
|
-
"REQUEST_METHOD", "HEAD",
|
728
|
-
"CONTENT_LENGTH", "2",
|
729
|
-
"HTTP_X_OUTPUT", "/tmp/output.txt",
|
730
|
-
NULL);
|
731
|
-
writeExact(connection, "ho");
|
732
|
-
|
733
|
-
result = stripHeaders(readAll(connection));
|
734
|
-
ensure_equals(result, "ok");
|
735
|
-
ensure_equals(readAll("/tmp/output.txt"), "ho");
|
736
|
-
}
|
737
|
-
|
738
|
-
TEST_METHOD(34) {
|
739
|
-
set_test_name("It rejects GET/HEAD requests with a Transfer-Encoding header.");
|
740
|
-
|
741
|
-
DeleteFileEventually d("/tmp/output.txt");
|
742
|
-
|
743
|
-
init();
|
744
|
-
connect();
|
745
|
-
sendHeaders(defaultHeaders,
|
746
|
-
"PASSENGER_APP_ROOT", wsgiAppPath.c_str(),
|
747
|
-
"PATH_INFO", "/raw_upload_to_file",
|
748
|
-
"REQUEST_METHOD", "GET",
|
749
|
-
"HTTP_TRANSFER_ENCODING", "chunked",
|
750
|
-
"HTTP_X_OUTPUT", "/tmp/output.txt",
|
751
|
-
NULL);
|
752
|
-
writeExact(connection, "hi");
|
753
|
-
shutdown(connection, SHUT_WR);
|
754
|
-
|
755
|
-
string result = stripHeaders(readAll(connection));
|
756
|
-
ensure_equals(result, "ok");
|
757
|
-
ensure_equals(readAll("/tmp/output.txt"), "hi");
|
758
|
-
|
759
|
-
connect();
|
760
|
-
sendHeaders(defaultHeaders,
|
761
|
-
"PASSENGER_APP_ROOT", wsgiAppPath.c_str(),
|
762
|
-
"PATH_INFO", "/raw_upload_to_file",
|
763
|
-
"REQUEST_METHOD", "HEAD",
|
764
|
-
"HTTP_TRANSFER_ENCODING", "chunked",
|
765
|
-
"HTTP_X_OUTPUT", "/tmp/output.txt",
|
766
|
-
NULL);
|
767
|
-
writeExact(connection, "ho");
|
768
|
-
shutdown(connection, SHUT_WR);
|
769
|
-
|
770
|
-
result = stripHeaders(readAll(connection));
|
771
|
-
ensure_equals(result, "ok");
|
772
|
-
ensure_equals(readAll("/tmp/output.txt"), "ho");
|
773
|
-
}
|
774
|
-
|
775
|
-
|
776
|
-
/***** Advanced connection handling tests *****/
|
777
|
-
|
778
|
-
TEST_METHOD(40) {
|
779
|
-
set_test_name("It streams the request body to the application.");
|
780
|
-
DeleteFileEventually file("tmp.output");
|
781
|
-
|
782
|
-
init();
|
783
|
-
connect();
|
784
|
-
sendHeaders(defaultHeaders,
|
785
|
-
"PASSENGER_APP_ROOT", wsgiAppPath.c_str(),
|
786
|
-
"REQUEST_METHOD", "POST",
|
787
|
-
"PATH_INFO", "/raw_upload_to_file",
|
788
|
-
"HTTP_TRANSFER_ENCODING", "chunked",
|
789
|
-
"HTTP_X_OUTPUT", (root + "/test/tmp.output").c_str(),
|
790
|
-
NULL);
|
791
|
-
writeExact(connection, "hello\n");
|
792
|
-
EVENTUALLY(5,
|
793
|
-
result = fileExists("tmp.output") && readAll("tmp.output") == "hello\n";
|
794
|
-
);
|
795
|
-
writeExact(connection, "world\n");
|
796
|
-
EVENTUALLY(3,
|
797
|
-
result = readAll("tmp.output") == "hello\nworld\n";
|
798
|
-
);
|
799
|
-
shutdown(connection, SHUT_WR);
|
800
|
-
ensure_equals(stripHeaders(readAll(connection)), "ok");
|
801
|
-
}
|
802
|
-
|
803
|
-
TEST_METHOD(41) {
|
804
|
-
set_test_name("If no Content-Length and no Transfer-Encoding are given, and buffering is on: "
|
805
|
-
"it does not pass any request body data.");
|
806
|
-
|
807
|
-
DeleteFileEventually d("/tmp/output.txt");
|
808
|
-
|
809
|
-
init();
|
810
|
-
connect();
|
811
|
-
sendHeaders(defaultHeaders,
|
812
|
-
"PASSENGER_APP_ROOT", wsgiAppPath.c_str(),
|
813
|
-
"PATH_INFO", "/raw_upload_to_file",
|
814
|
-
"REQUEST_METHOD", "POST",
|
815
|
-
"PASSENGER_BUFFERING", "true",
|
816
|
-
"HTTP_X_OUTPUT", "/tmp/output.txt",
|
817
|
-
NULL);
|
818
|
-
writeExact(connection, "hello\n");
|
819
|
-
|
820
|
-
string result = stripHeaders(readAll(connection));
|
821
|
-
ensure_equals(result, "ok");
|
822
|
-
struct stat buf;
|
823
|
-
ensure(stat("/tmp/output.txt", &buf) == 0);
|
824
|
-
ensure_equals(buf.st_size, (off_t) 0);
|
825
|
-
}
|
826
|
-
|
827
|
-
TEST_METHOD(42) {
|
828
|
-
set_test_name("If no Content-Length and no Transfer-Encoding are given, and buffering is off: "
|
829
|
-
"it does not pass any request body data.");
|
830
|
-
|
831
|
-
DeleteFileEventually d("/tmp/output.txt");
|
832
|
-
|
833
|
-
init();
|
834
|
-
connect();
|
835
|
-
sendHeaders(defaultHeaders,
|
836
|
-
"PASSENGER_APP_ROOT", wsgiAppPath.c_str(),
|
837
|
-
"PATH_INFO", "/raw_upload_to_file",
|
838
|
-
"REQUEST_METHOD", "POST",
|
839
|
-
"HTTP_X_OUTPUT", "/tmp/output.txt",
|
840
|
-
NULL);
|
841
|
-
writeExact(connection, "hello\n");
|
842
|
-
|
843
|
-
string result = stripHeaders(readAll(connection));
|
844
|
-
ensure_equals(result, "ok");
|
845
|
-
struct stat buf;
|
846
|
-
ensure(stat("/tmp/output.txt", &buf) == 0);
|
847
|
-
ensure_equals(buf.st_size, (off_t) 0);
|
848
|
-
}
|
849
|
-
|
850
|
-
TEST_METHOD(43) {
|
851
|
-
set_test_name("If Upgrade is given, it keeps passing the request body until end of stream.");
|
852
|
-
|
853
|
-
DeleteFileEventually d("/tmp/output.txt");
|
854
|
-
|
855
|
-
init();
|
856
|
-
connect();
|
857
|
-
sendHeaders(defaultHeaders,
|
858
|
-
"PASSENGER_APP_ROOT", wsgiAppPath.c_str(),
|
859
|
-
"PATH_INFO", "/raw_upload_to_file",
|
860
|
-
"HTTP_UPGRADE", "websocket",
|
861
|
-
"HTTP_X_OUTPUT", "/tmp/output.txt",
|
862
|
-
NULL);
|
863
|
-
writeExact(connection, "hello\n");
|
864
|
-
shutdown(connection, SHUT_WR);
|
865
|
-
|
866
|
-
string result = stripHeaders(readAll(connection));
|
867
|
-
ensure_equals(result, "ok");
|
868
|
-
struct stat buf;
|
869
|
-
ensure(stat("/tmp/output.txt", &buf) == 0);
|
870
|
-
ensure_equals(buf.st_size, (off_t) 6);
|
871
|
-
}
|
872
|
-
|
873
|
-
TEST_METHOD(45) {
|
874
|
-
set_test_name("If Content-Length is given, buffering is on, and request body is large: "
|
875
|
-
"it passes Content-Length bytes of the request body.");
|
876
|
-
|
877
|
-
DeleteFileEventually d("/tmp/output.txt");
|
878
|
-
|
879
|
-
// 2.6 MB of request body. Guaranteed not to fit in any socket buffer.
|
880
|
-
string requestBody;
|
881
|
-
for (int i = 0; i < 204800; i++) {
|
882
|
-
requestBody.append("hello world!\n");
|
883
|
-
}
|
884
|
-
|
885
|
-
init();
|
886
|
-
connect();
|
887
|
-
sendHeaders(defaultHeaders,
|
888
|
-
"PASSENGER_APP_ROOT", wsgiAppPath.c_str(),
|
889
|
-
"PATH_INFO", "/raw_upload_to_file",
|
890
|
-
"REQUEST_METHOD", "POST",
|
891
|
-
"CONTENT_LENGTH", toString(requestBody.size()).c_str(),
|
892
|
-
"PASSENGER_BUFFERING", "true",
|
893
|
-
"HTTP_X_OUTPUT", "/tmp/output.txt",
|
894
|
-
NULL);
|
895
|
-
writeExact(connection, requestBody);
|
896
|
-
|
897
|
-
string result = stripHeaders(readAll(connection));
|
898
|
-
ensure_equals(result, "ok");
|
899
|
-
struct stat buf;
|
900
|
-
ensure(stat("/tmp/output.txt", &buf) == 0);
|
901
|
-
ensure_equals(buf.st_size, (off_t) requestBody.size());
|
902
|
-
}
|
903
|
-
|
904
|
-
TEST_METHOD(46) {
|
905
|
-
set_test_name("If Content-Length is given, buffering is on, and request body is small: "
|
906
|
-
"it passes Content-Length bytes of the request body.");
|
907
|
-
|
908
|
-
DeleteFileEventually d("/tmp/output.txt");
|
909
|
-
string requestBody = "hello world";
|
910
|
-
|
911
|
-
init();
|
912
|
-
connect();
|
913
|
-
sendHeaders(defaultHeaders,
|
914
|
-
"PASSENGER_APP_ROOT", wsgiAppPath.c_str(),
|
915
|
-
"PATH_INFO", "/raw_upload_to_file",
|
916
|
-
"REQUEST_METHOD", "POST",
|
917
|
-
"CONTENT_LENGTH", toString(requestBody.size()).c_str(),
|
918
|
-
"PASSENGER_BUFFERING", "true",
|
919
|
-
"HTTP_X_OUTPUT", "/tmp/output.txt",
|
920
|
-
NULL);
|
921
|
-
writeExact(connection, requestBody);
|
922
|
-
|
923
|
-
string result = stripHeaders(readAll(connection));
|
924
|
-
ensure_equals(result, "ok");
|
925
|
-
struct stat buf;
|
926
|
-
ensure(stat("/tmp/output.txt", &buf) == 0);
|
927
|
-
ensure_equals(buf.st_size, (off_t) requestBody.size());
|
928
|
-
}
|
929
|
-
|
930
|
-
TEST_METHOD(47) {
|
931
|
-
set_test_name("If Content-Length is given, buffering is off, and request body is large: "
|
932
|
-
"it passes Content-Length bytes of the request body.");
|
933
|
-
|
934
|
-
DeleteFileEventually d("/tmp/output.txt");
|
935
|
-
|
936
|
-
// 2 MB of request body. Guaranteed not to fit in any socket buffer.
|
937
|
-
string requestBody;
|
938
|
-
for (int i = 0; i < 102400; i++) {
|
939
|
-
char buf[100];
|
940
|
-
snprintf(buf, sizeof(buf), "%06d: hello world!\n", i);
|
941
|
-
requestBody.append(buf);
|
942
|
-
}
|
943
|
-
|
944
|
-
init();
|
945
|
-
connect();
|
946
|
-
sendHeaders(defaultHeaders,
|
947
|
-
"PASSENGER_APP_ROOT", wsgiAppPath.c_str(),
|
948
|
-
"PATH_INFO", "/raw_upload_to_file",
|
949
|
-
"REQUEST_METHOD", "POST",
|
950
|
-
"CONTENT_LENGTH", toString(requestBody.size()).c_str(),
|
951
|
-
"HTTP_X_OUTPUT", "/tmp/output.txt",
|
952
|
-
NULL);
|
953
|
-
|
954
|
-
TempThread thr(boost::bind(RequestHandlerTest::writeBody, connection, requestBody));
|
955
|
-
|
956
|
-
string result = stripHeaders(readAll(connection));
|
957
|
-
ensure_equals(result, "ok");
|
958
|
-
struct stat buf;
|
959
|
-
ensure(stat("/tmp/output.txt", &buf) == 0);
|
960
|
-
ensure_equals(buf.st_size, (off_t) requestBody.size());
|
961
|
-
}
|
962
|
-
|
963
|
-
TEST_METHOD(48) {
|
964
|
-
set_test_name("If Content-Length is given, buffering is off, and request body is small: "
|
965
|
-
"it passes Content-Length bytes of the request body.");
|
966
|
-
|
967
|
-
DeleteFileEventually d("/tmp/output.txt");
|
968
|
-
string requestBody = "hello world";
|
969
|
-
|
970
|
-
init();
|
971
|
-
connect();
|
972
|
-
sendHeaders(defaultHeaders,
|
973
|
-
"PASSENGER_APP_ROOT", wsgiAppPath.c_str(),
|
974
|
-
"PATH_INFO", "/raw_upload_to_file",
|
975
|
-
"REQUEST_METHOD", "POST",
|
976
|
-
"CONTENT_LENGTH", toString(requestBody.size()).c_str(),
|
977
|
-
"HTTP_X_OUTPUT", "/tmp/output.txt",
|
978
|
-
NULL);
|
979
|
-
|
980
|
-
TempThread thr(boost::bind(RequestHandlerTest::writeBody, connection, requestBody));
|
981
|
-
|
982
|
-
string result = stripHeaders(readAll(connection));
|
983
|
-
ensure_equals(result, "ok");
|
984
|
-
struct stat buf;
|
985
|
-
ensure(stat("/tmp/output.txt", &buf) == 0);
|
986
|
-
ensure_equals(buf.st_size, (off_t) requestBody.size());
|
987
|
-
}
|
988
|
-
|
989
|
-
TEST_METHOD(49) {
|
990
|
-
set_test_name("If Transfer-Encoding is given and buffering is on: "
|
991
|
-
"it keeps passing the request body until end of stream.");
|
992
|
-
|
993
|
-
DeleteFileEventually d("/tmp/output.txt");
|
994
|
-
|
995
|
-
// 2.6 MB of request body. Guaranteed not to fit in any socket buffer.
|
996
|
-
string requestBody;
|
997
|
-
for (int i = 0; i < 204800; i++) {
|
998
|
-
requestBody.append("hello world!\n");
|
999
|
-
}
|
1000
|
-
|
1001
|
-
init();
|
1002
|
-
connect();
|
1003
|
-
sendHeaders(defaultHeaders,
|
1004
|
-
"PASSENGER_APP_ROOT", wsgiAppPath.c_str(),
|
1005
|
-
"PATH_INFO", "/raw_upload_to_file",
|
1006
|
-
"REQUEST_METHOD", "POST",
|
1007
|
-
"PASSENGER_BUFFERING", "true",
|
1008
|
-
"HTTP_TRANSFER_ENCODING", "chunked",
|
1009
|
-
"HTTP_X_OUTPUT", "/tmp/output.txt",
|
1010
|
-
NULL);
|
1011
|
-
writeExact(connection, requestBody);
|
1012
|
-
shutdown(connection, SHUT_WR);
|
1013
|
-
|
1014
|
-
string result = stripHeaders(readAll(connection));
|
1015
|
-
ensure_equals(result, "ok");
|
1016
|
-
struct stat buf;
|
1017
|
-
ensure(stat("/tmp/output.txt", &buf) == 0);
|
1018
|
-
ensure_equals(buf.st_size, (off_t) requestBody.size());
|
1019
|
-
}
|
1020
|
-
|
1021
|
-
TEST_METHOD(50) {
|
1022
|
-
set_test_name("If Transfer-Encoding is given and buffering is off: "
|
1023
|
-
"it keeps passing the request body until end of stream.");
|
1024
|
-
|
1025
|
-
DeleteFileEventually d("/tmp/output.txt");
|
1026
|
-
|
1027
|
-
// 2.6 MB of request body. Guaranteed not to fit in any socket buffer.
|
1028
|
-
string requestBody;
|
1029
|
-
for (int i = 0; i < 204800; i++) {
|
1030
|
-
requestBody.append("hello world!\n");
|
1031
|
-
}
|
1032
|
-
|
1033
|
-
init();
|
1034
|
-
connect();
|
1035
|
-
sendHeaders(defaultHeaders,
|
1036
|
-
"PASSENGER_APP_ROOT", wsgiAppPath.c_str(),
|
1037
|
-
"PATH_INFO", "/raw_upload_to_file",
|
1038
|
-
"REQUEST_METHOD", "POST",
|
1039
|
-
"HTTP_TRANSFER_ENCODING", "chunked",
|
1040
|
-
"HTTP_X_OUTPUT", "/tmp/output.txt",
|
1041
|
-
NULL);
|
1042
|
-
writeExact(connection, requestBody);
|
1043
|
-
shutdown(connection, SHUT_WR);
|
1044
|
-
|
1045
|
-
string result = stripHeaders(readAll(connection));
|
1046
|
-
ensure_equals(result, "ok");
|
1047
|
-
struct stat buf;
|
1048
|
-
ensure(stat("/tmp/output.txt", &buf) == 0);
|
1049
|
-
ensure_equals(buf.st_size, (off_t) requestBody.size());
|
1050
|
-
}
|
1051
|
-
|
1052
|
-
TEST_METHOD(51) {
|
1053
|
-
set_test_name("If Transfer-Encoding is given and the application socket uses the HTTP protocol, "
|
1054
|
-
"rechunk the body when forwarding it to the application.");
|
1055
|
-
|
1056
|
-
fprintf(stderr, "TODO: implement test 51\n");
|
1057
|
-
}
|
1058
|
-
|
1059
|
-
TEST_METHOD(54) {
|
1060
|
-
set_test_name("It writes an appropriate response if the request queue is overflown.");
|
1061
|
-
|
1062
|
-
initPoolDebugging();
|
1063
|
-
debug->restarting = false;
|
1064
|
-
debug->spawning = false;
|
1065
|
-
debug->testOverflowRequestQueue = true;
|
1066
|
-
init();
|
1067
|
-
connect();
|
1068
|
-
sendHeaders(defaultHeaders,
|
1069
|
-
"PASSENGER_APP_ROOT", wsgiAppPath.c_str(),
|
1070
|
-
"PATH_INFO", "/",
|
1071
|
-
NULL);
|
1072
|
-
string response = readAll(connection);
|
1073
|
-
ensure(response.find("Status: 503 Service Unavailable") != string::npos);
|
1074
|
-
ensure(response.find("This website is under heavy load") != string::npos);
|
1075
|
-
}
|
1076
|
-
|
1077
|
-
TEST_METHOD(55) {
|
1078
|
-
set_test_name("It uses the status code dictated by PASSENGER_REQUEST_QUEUE_OVERFLOW_STATUS_CODE "
|
1079
|
-
"if the request queue is overflown");
|
1080
|
-
|
1081
|
-
initPoolDebugging();
|
1082
|
-
debug->restarting = false;
|
1083
|
-
debug->spawning = false;
|
1084
|
-
debug->testOverflowRequestQueue = true;
|
1085
|
-
init();
|
1086
|
-
connect();
|
1087
|
-
sendHeaders(defaultHeaders,
|
1088
|
-
"PASSENGER_APP_ROOT", wsgiAppPath.c_str(),
|
1089
|
-
"PATH_INFO", "/",
|
1090
|
-
"PASSENGER_REQUEST_QUEUE_OVERFLOW_STATUS_CODE", "504",
|
1091
|
-
NULL);
|
1092
|
-
string response = readAll(connection);
|
1093
|
-
ensure(response.find("Status: 504 Gateway Timeout") != string::npos);
|
1094
|
-
ensure(response.find("This website is under heavy load") != string::npos);
|
1095
|
-
}
|
1096
|
-
|
1097
|
-
TEST_METHOD(56) {
|
1098
|
-
set_test_name("PASSENGER_REQUEST_QUEUE_OVERFLOW_STATUS_CODE should work even if it is an unknown code");
|
1099
|
-
|
1100
|
-
initPoolDebugging();
|
1101
|
-
debug->restarting = false;
|
1102
|
-
debug->spawning = false;
|
1103
|
-
debug->testOverflowRequestQueue = true;
|
1104
|
-
init();
|
1105
|
-
connect();
|
1106
|
-
sendHeaders(defaultHeaders,
|
1107
|
-
"PASSENGER_APP_ROOT", wsgiAppPath.c_str(),
|
1108
|
-
"PATH_INFO", "/",
|
1109
|
-
"PASSENGER_REQUEST_QUEUE_OVERFLOW_STATUS_CODE", "604",
|
1110
|
-
NULL);
|
1111
|
-
string response = readAll(connection);
|
1112
|
-
ensure(response.find("Status: 604 Unknown Reason-Phrase") != string::npos);
|
1113
|
-
ensure(response.find("This website is under heavy load") != string::npos);
|
1114
|
-
}
|
1115
|
-
|
1116
|
-
TEST_METHOD(57) {
|
1117
|
-
set_test_name("It relieves the application process after having read its entire response data.");
|
1118
|
-
|
1119
|
-
init();
|
1120
|
-
connect();
|
1121
|
-
sendHeaders(defaultHeaders,
|
1122
|
-
"PASSENGER_APP_ROOT", wsgiAppPath.c_str(),
|
1123
|
-
"PATH_INFO", "/blob",
|
1124
|
-
NULL);
|
1125
|
-
vector<ProcessPtr> processes;
|
1126
|
-
EVENTUALLY(5,
|
1127
|
-
processes = pool->getProcesses();
|
1128
|
-
result = processes.size() == 1;
|
1129
|
-
);
|
1130
|
-
EVENTUALLY(5,
|
1131
|
-
LockGuard l(pool->syncher);
|
1132
|
-
result = processes[0]->processed == 1;
|
1133
|
-
);
|
1134
|
-
{
|
1135
|
-
LockGuard l(pool->syncher);
|
1136
|
-
ensure_equals("The session is closed before the client is done reading",
|
1137
|
-
processes[0]->sessions, 0);
|
1138
|
-
}
|
1139
|
-
}
|
1140
|
-
|
1141
|
-
TEST_METHOD(58) {
|
1142
|
-
set_test_name("It supports responses in chunked transfer encoding.");
|
1143
|
-
|
1144
|
-
init();
|
1145
|
-
connect();
|
1146
|
-
sendHeaders(defaultHeaders,
|
1147
|
-
"PASSENGER_APP_ROOT", wsgiAppPath.c_str(),
|
1148
|
-
"PATH_INFO", "/chunked_stream",
|
1149
|
-
NULL
|
1150
|
-
);
|
1151
|
-
|
1152
|
-
char buf[1024 * 10];
|
1153
|
-
unsigned long long timeout = 500000;
|
1154
|
-
unsigned int size;
|
1155
|
-
try {
|
1156
|
-
size = readExact(connection, buf, sizeof(buf), &timeout);
|
1157
|
-
} catch (const TimeoutException &) {
|
1158
|
-
fail("RequestHandler did not correctly handle chunked EOF!");
|
1159
|
-
}
|
1160
|
-
|
1161
|
-
string response(buf, size);
|
1162
|
-
string body = stripHeaders(response);
|
1163
|
-
ensure(containsSubstring(response, "Counter: 0\n"));
|
1164
|
-
ensure(containsSubstring(response, "Counter: 1\n"));
|
1165
|
-
ensure(containsSubstring(response, "Counter: 2\n"));
|
1166
|
-
}
|
1167
|
-
|
1168
|
-
TEST_METHOD(59) {
|
1169
|
-
set_test_name("It supports switching protocols when communicating over application session sockets.");
|
1170
|
-
|
1171
|
-
init();
|
1172
|
-
connect();
|
1173
|
-
sendHeaders(defaultHeaders,
|
1174
|
-
"PASSENGER_APP_ROOT", wsgiAppPath.c_str(),
|
1175
|
-
"PATH_INFO", "/switch_protocol",
|
1176
|
-
"HTTP_UPGRADE", "raw",
|
1177
|
-
"HTTP_CONNECTION", "Upgrade",
|
1178
|
-
NULL
|
1179
|
-
);
|
1180
|
-
|
1181
|
-
BufferedIO io(connection);
|
1182
|
-
string header;
|
1183
|
-
bool done = false;
|
1184
|
-
|
1185
|
-
ensure_equals(io.readLine(), "HTTP/1.1 101 Switching Protocols\r\n");
|
1186
|
-
|
1187
|
-
do {
|
1188
|
-
string line = io.readLine();
|
1189
|
-
done = line.empty() || line == "\r\n";
|
1190
|
-
if (!done) {
|
1191
|
-
header.append(line);
|
1192
|
-
}
|
1193
|
-
} while (!done);
|
1194
|
-
|
1195
|
-
ensure("(1)", containsSubstring(header, "Upgrade: raw\r\n"));
|
1196
|
-
ensure("(2)", containsSubstring(header, "Connection: Upgrade\r\n"));
|
1197
|
-
|
1198
|
-
writeExact(connection, "hello\n");
|
1199
|
-
ensure_equals(io.readLine(), "Echo: hello\n");
|
1200
|
-
}
|
1201
|
-
|
1202
|
-
TEST_METHOD(60) {
|
1203
|
-
set_test_name("It supports switching protocols when communication over application http_session sockets.");
|
1204
|
-
|
1205
|
-
init();
|
1206
|
-
connect();
|
1207
|
-
sendHeaders(defaultHeaders,
|
1208
|
-
"_PASSENGER_FORCE_HTTP_SESSION", "true",
|
1209
|
-
"PASSENGER_APP_ROOT", rackAppPath.c_str(),
|
1210
|
-
"PASSENGER_APP_TYPE", "rack",
|
1211
|
-
"REQUEST_URI", "/switch_protocol",
|
1212
|
-
"PATH_INFO", "/switch_protocol",
|
1213
|
-
"HTTP_UPGRADE", "raw",
|
1214
|
-
"HTTP_CONNECTION", "Upgrade",
|
1215
|
-
NULL
|
1216
|
-
);
|
1217
|
-
|
1218
|
-
BufferedIO io(connection);
|
1219
|
-
string header;
|
1220
|
-
bool done = false;
|
1221
|
-
vector<ProcessPtr> processes;
|
1222
|
-
|
1223
|
-
ensure_equals(io.readLine(), "HTTP/1.1 101 Switching Protocols\r\n");
|
1224
|
-
processes = pool->getProcesses();
|
1225
|
-
{
|
1226
|
-
LockGuard l(pool->syncher);
|
1227
|
-
ProcessPtr process = processes[0];
|
1228
|
-
ensure_equals(process->sessionSockets.top()->protocol, "http_session");
|
1229
|
-
}
|
1230
|
-
|
1231
|
-
do {
|
1232
|
-
string line = io.readLine();
|
1233
|
-
done = line.empty() || line == "\r\n";
|
1234
|
-
if (!done) {
|
1235
|
-
header.append(line);
|
1236
|
-
}
|
1237
|
-
} while (!done);
|
1238
|
-
|
1239
|
-
ensure("(1)", containsSubstring(header, "Upgrade: raw\r\n"));
|
1240
|
-
ensure("(2)", containsSubstring(header, "Connection: Upgrade\r\n"));
|
1241
|
-
|
1242
|
-
writeExact(connection, "hello\n");
|
1243
|
-
ensure_equals(io.readLine(), "Echo: hello\n");
|
1244
|
-
}
|
1245
|
-
|
1246
|
-
TEST_METHOD(61) {
|
1247
|
-
set_test_name("If the response contains Transfer-Encoding chunked, "
|
1248
|
-
"it dechunks the response body and forwards it until the "
|
1249
|
-
"zero-length chunk is encountered.");
|
1250
|
-
|
1251
|
-
init();
|
1252
|
-
connect();
|
1253
|
-
sendHeaders(defaultHeaders,
|
1254
|
-
"PASSENGER_APP_ROOT", wsgiAppPath.c_str(),
|
1255
|
-
"PATH_INFO", "/chunked",
|
1256
|
-
NULL);
|
1257
|
-
|
1258
|
-
string response = readAll(connection);
|
1259
|
-
string body = stripHeaders(response);
|
1260
|
-
ensure_equals(body,
|
1261
|
-
"chunk1\n"
|
1262
|
-
"chunk2\n"
|
1263
|
-
"chunk3\n");
|
1264
|
-
}
|
1265
|
-
|
1266
|
-
TEST_METHOD(62) {
|
1267
|
-
set_test_name("If the response contains Transfer-Encoding chunked, "
|
1268
|
-
"it closes the connection with the app when the zero-length chunk is encountered.");
|
1269
|
-
|
1270
|
-
DeleteFileEventually statusFile("/tmp/passenger-tail-status.txt");
|
1271
|
-
createFile("/tmp/passenger-tail-status.txt", "",
|
1272
|
-
S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
|
1273
|
-
|
1274
|
-
init();
|
1275
|
-
connect();
|
1276
|
-
sendHeaders(defaultHeaders,
|
1277
|
-
"PASSENGER_APP_ROOT", wsgiAppPath.c_str(),
|
1278
|
-
"PATH_INFO", "/chunked",
|
1279
|
-
"HTTP_X_SLEEP_WHEN_DONE", "0.01",
|
1280
|
-
"HTTP_X_EXTRA_DATA", "true",
|
1281
|
-
"HTTP_X_TAIL_STATUS_FILE", "/tmp/passenger-tail-status.txt",
|
1282
|
-
NULL);
|
1283
|
-
|
1284
|
-
string response = readAll(connection);
|
1285
|
-
string body = stripHeaders(response);
|
1286
|
-
ensure_equals(body,
|
1287
|
-
"chunk1\n"
|
1288
|
-
"chunk2\n"
|
1289
|
-
"chunk3\n");
|
1290
|
-
EVENTUALLY(5,
|
1291
|
-
result = readAll("/tmp/passenger-tail-status.txt") == "False";
|
1292
|
-
);
|
1293
|
-
}
|
1294
|
-
|
1295
|
-
TEST_METHOD(63) {
|
1296
|
-
set_test_name("If the response contains Transfer-Encoding chunked, "
|
1297
|
-
"it discards any additional response body data after the zero-length chunk is encountered.");
|
1298
|
-
|
1299
|
-
init();
|
1300
|
-
connect();
|
1301
|
-
sendHeaders(defaultHeaders,
|
1302
|
-
"PASSENGER_APP_ROOT", wsgiAppPath.c_str(),
|
1303
|
-
"PATH_INFO", "/chunked",
|
1304
|
-
"HTTP_X_EXTRA_DATA", "true",
|
1305
|
-
NULL);
|
1306
|
-
|
1307
|
-
string response = readAll(connection);
|
1308
|
-
string body = stripHeaders(response);
|
1309
|
-
ensure_equals(body,
|
1310
|
-
"chunk1\n"
|
1311
|
-
"chunk2\n"
|
1312
|
-
"chunk3\n");
|
1313
|
-
}
|
1314
|
-
|
1315
|
-
TEST_METHOD(64) {
|
1316
|
-
set_test_name("If the response contains Content-Length, "
|
1317
|
-
"it forwards exactly Content-Length bytes of the response body.");
|
1318
|
-
|
1319
|
-
init();
|
1320
|
-
connect();
|
1321
|
-
sendHeaders(defaultHeaders,
|
1322
|
-
"PASSENGER_APP_ROOT", wsgiAppPath.c_str(),
|
1323
|
-
"PATH_INFO", "/blob",
|
1324
|
-
"HTTP_X_SIZE", "5000000",
|
1325
|
-
"HTTP_X_CONTENT_LENGTH", "true",
|
1326
|
-
NULL);
|
1327
|
-
|
1328
|
-
string response = readAll(connection);
|
1329
|
-
string body = stripHeaders(response);
|
1330
|
-
FILE *f = fopen("/tmp/debug.txt", "w");
|
1331
|
-
fwrite(response.data(), 1, response.size(), f);
|
1332
|
-
fclose(f);
|
1333
|
-
ensure_equals(body.size(), 5000000u);
|
1334
|
-
}
|
1335
|
-
|
1336
|
-
TEST_METHOD(65) {
|
1337
|
-
set_test_name("If the response contains Content-Length, "
|
1338
|
-
"it closes the connection with the app after forwarding exactly Content-Length bytes.");
|
1339
|
-
|
1340
|
-
DeleteFileEventually statusFile("/tmp/passenger-tail-status.txt");
|
1341
|
-
createFile("/tmp/passenger-tail-status.txt", "",
|
1342
|
-
S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
|
1343
|
-
|
1344
|
-
init();
|
1345
|
-
connect();
|
1346
|
-
sendHeaders(defaultHeaders,
|
1347
|
-
"PASSENGER_APP_ROOT", wsgiAppPath.c_str(),
|
1348
|
-
"PATH_INFO", "/blob",
|
1349
|
-
"HTTP_X_SIZE", "5000000",
|
1350
|
-
"HTTP_X_CONTENT_LENGTH", "true",
|
1351
|
-
"HTTP_X_SLEEP_WHEN_DONE", "0.01",
|
1352
|
-
"HTTP_X_EXTRA_DATA", "true",
|
1353
|
-
"HTTP_X_TAIL_STATUS_FILE", "/tmp/passenger-tail-status.txt",
|
1354
|
-
NULL);
|
1355
|
-
|
1356
|
-
string response = readAll(connection);
|
1357
|
-
string body = stripHeaders(response);
|
1358
|
-
ensure_equals(body.size(), 5000000u);
|
1359
|
-
EVENTUALLY(5,
|
1360
|
-
result = readAll("/tmp/passenger-tail-status.txt") == "False";
|
1361
|
-
);
|
1362
|
-
}
|
1363
|
-
|
1364
|
-
TEST_METHOD(66) {
|
1365
|
-
set_test_name("If the response contains Content-Length, "
|
1366
|
-
"it discards any additional response body data after Content-Length bytes.");
|
1367
|
-
|
1368
|
-
init();
|
1369
|
-
connect();
|
1370
|
-
sendHeaders(defaultHeaders,
|
1371
|
-
"PASSENGER_APP_ROOT", wsgiAppPath.c_str(),
|
1372
|
-
"PATH_INFO", "/blob",
|
1373
|
-
"HTTP_X_SIZE", "5000000",
|
1374
|
-
"HTTP_X_CONTENT_LENGTH", "true",
|
1375
|
-
"HTTP_X_EXTRA_DATA", "true",
|
1376
|
-
NULL);
|
1377
|
-
|
1378
|
-
string response = readAll(connection);
|
1379
|
-
string body = stripHeaders(response);
|
1380
|
-
ensure_equals(body.size(), 5000000u);
|
1381
|
-
}
|
1382
|
-
|
1383
|
-
TEST_METHOD(67) {
|
1384
|
-
set_test_name("If the response contains neither Transfer-Encoding chunked nor Content-Length, "
|
1385
|
-
"it forwards the response body until EOF.");
|
1386
|
-
|
1387
|
-
init();
|
1388
|
-
connect();
|
1389
|
-
sendHeaders(defaultHeaders,
|
1390
|
-
"PASSENGER_APP_ROOT", wsgiAppPath.c_str(),
|
1391
|
-
"PATH_INFO", "/blob",
|
1392
|
-
"HTTP_X_SIZE", "5000000",
|
1393
|
-
"HTTP_X_EXTRA_DATA", "true",
|
1394
|
-
NULL);
|
1395
|
-
|
1396
|
-
string response = readAll(connection);
|
1397
|
-
string body = stripHeaders(response);
|
1398
|
-
ensure_equals(body.size(), 5000004u);
|
1399
|
-
}
|
1400
|
-
|
1401
|
-
|
1402
|
-
/***** Out-of-band work tests *****/
|
1403
|
-
|
1404
|
-
TEST_METHOD(75) {
|
1405
|
-
set_test_name("If the application outputs a request oobw header, handler should remove the header, mark "
|
1406
|
-
"the process as oobw requested. The process should continue to process requests until the "
|
1407
|
-
"spawner spawns another process (to avoid the group being empty). As soon as the new "
|
1408
|
-
"process is spawned, the original process will make the oobw request. Afterwards, the "
|
1409
|
-
"original process is re-enabled.");
|
1410
|
-
init();
|
1411
|
-
connect();
|
1412
|
-
sendHeaders(defaultHeaders,
|
1413
|
-
"PASSENGER_APP_ROOT", wsgiAppPath.c_str(),
|
1414
|
-
"PATH_INFO", "/oobw",
|
1415
|
-
NULL);
|
1416
|
-
string response = readAll(connection);
|
1417
|
-
ensure("status is not 200", containsSubstring(response, "Status: 200 OK\r\n"));
|
1418
|
-
ensure("contains oowb header", !containsSubstring(response, "X-Passenger-Request-OOB-Work:"));
|
1419
|
-
pid_t origPid = atoi(stripHeaders(response));
|
1420
|
-
|
1421
|
-
// Get a reference to the orignal process and verify oobw has been requested.
|
1422
|
-
ProcessPtr origProcess;
|
1423
|
-
{
|
1424
|
-
LockGuard l(pool->syncher);
|
1425
|
-
origProcess = pool->superGroups.get(wsgiAppPath)->defaultGroup->disablingProcesses.front();
|
1426
|
-
ensure("OOBW requested", origProcess->oobwStatus == Process::OOBW_IN_PROGRESS);
|
1427
|
-
}
|
1428
|
-
ensure("sanity check", origPid == origProcess->pid); // just a sanity check
|
1429
|
-
|
1430
|
-
// Issue requests until the new process handles it.
|
1431
|
-
pid_t pid;
|
1432
|
-
EVENTUALLY(2,
|
1433
|
-
connect();
|
1434
|
-
sendHeaders(defaultHeaders,
|
1435
|
-
"PASSENGER_APP_ROOT", wsgiAppPath.c_str(),
|
1436
|
-
"PATH_INFO", "/pid",
|
1437
|
-
NULL);
|
1438
|
-
string response = readAll(connection);
|
1439
|
-
ensure("status is 200", containsSubstring(response, "Status: 200 OK\r\n"));
|
1440
|
-
pid = atoi(stripHeaders(response));
|
1441
|
-
result = (pid != origPid);
|
1442
|
-
);
|
1443
|
-
|
1444
|
-
// Wait for the original process to finish oobw request.
|
1445
|
-
EVENTUALLY(2,
|
1446
|
-
boost::unique_lock<boost::mutex> lock(pool->syncher);
|
1447
|
-
result = origProcess->oobwStatus == Process::OOBW_NOT_ACTIVE;
|
1448
|
-
);
|
1449
|
-
|
1450
|
-
// Final asserts.
|
1451
|
-
{
|
1452
|
-
boost::unique_lock<boost::mutex> lock(pool->syncher);
|
1453
|
-
ensure_equals("2 enabled processes", pool->superGroups.get(wsgiAppPath)->defaultGroup->enabledProcesses.size(), 2u);
|
1454
|
-
ensure_equals("oobw is reset", origProcess->oobwStatus, Process::OOBW_NOT_ACTIVE);
|
1455
|
-
ensure_equals("process is enabled", origProcess->enabled, Process::ENABLED);
|
1456
|
-
}
|
1457
|
-
}
|
1458
|
-
|
1459
|
-
// Test small response buffering.
|
1460
|
-
// Test large response buffering.
|
1461
|
-
|
1462
|
-
/***************************/
|
1463
|
-
}
|