passenger 6.0.21 → 6.0.23

Sign up to get free protection for your applications and to get access to all the features.
Files changed (46) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +42 -3
  3. data/Rakefile +9 -2
  4. data/bin/passenger-install-nginx-module +1 -0
  5. data/build/test_basics.rb +30 -11
  6. data/passenger.gemspec +4 -2
  7. data/resources/templates/standalone/server.erb +1 -0
  8. data/src/agent/Core/ApplicationPool/Group/StateInspection.cpp +1 -1
  9. data/src/agent/Core/ApplicationPool/Pool/StateInspection.cpp +0 -3
  10. data/src/agent/Core/Config.h +2 -1
  11. data/src/agent/Core/Controller/CheckoutSession.cpp +24 -1
  12. data/src/agent/Core/Controller/Config.h +5 -1
  13. data/src/agent/Core/Controller.h +1 -0
  14. data/src/agent/Core/OptionParser.h +3 -0
  15. data/src/agent/Core/SpawningKit/ErrorRenderer.h +5 -0
  16. data/src/agent/Watchdog/Config.h +2 -1
  17. data/src/apache2_module/ConfigGeneral/AutoGeneratedDefinitions.cpp +5 -0
  18. data/src/apache2_module/ConfigGeneral/AutoGeneratedSetterFuncs.cpp +15 -0
  19. data/src/apache2_module/DirConfig/AutoGeneratedCreateFunction.cpp +5 -0
  20. data/src/apache2_module/DirConfig/AutoGeneratedHeaderSerialization.cpp +3 -0
  21. data/src/apache2_module/DirConfig/AutoGeneratedManifestGeneration.cpp +13 -0
  22. data/src/apache2_module/DirConfig/AutoGeneratedMergeFunction.cpp +7 -0
  23. data/src/apache2_module/DirConfig/AutoGeneratedStruct.h +13 -0
  24. data/src/cxx_supportlib/Constants.h +1 -1
  25. data/src/cxx_supportlib/DataStructures/LString.h +4 -0
  26. data/src/nginx_module/ConfigGeneral/AutoGeneratedDefinitions.c +8 -0
  27. data/src/nginx_module/ConfigGeneral/AutoGeneratedSetterFuncs.c +12 -0
  28. data/src/nginx_module/Configuration.c +7 -2
  29. data/src/nginx_module/LocationConfig/AutoGeneratedCreateFunction.c +6 -0
  30. data/src/nginx_module/LocationConfig/AutoGeneratedHeaderSerialization.c +15 -0
  31. data/src/nginx_module/LocationConfig/AutoGeneratedManifestGeneration.c +14 -0
  32. data/src/nginx_module/LocationConfig/AutoGeneratedMergeFunction.c +3 -0
  33. data/src/nginx_module/LocationConfig/AutoGeneratedStruct.h +4 -0
  34. data/src/ruby_native_extension/passenger_native_support.c +1 -0
  35. data/src/ruby_supportlib/phusion_passenger/apache2/config_options.rb +5 -0
  36. data/src/ruby_supportlib/phusion_passenger/common_library.rb +1 -1
  37. data/src/ruby_supportlib/phusion_passenger/nginx/config_options.rb +5 -0
  38. data/src/ruby_supportlib/phusion_passenger/platform_info/depcheck_specs/gems.rb +10 -0
  39. data/src/ruby_supportlib/phusion_passenger/rack/handler.rb +73 -0
  40. data/src/ruby_supportlib/phusion_passenger/rack_handler.rb +30 -56
  41. data/src/ruby_supportlib/phusion_passenger/standalone/config_options_list.rb +5 -0
  42. data/src/ruby_supportlib/phusion_passenger/standalone/start_command/builtin_engine.rb +1 -0
  43. data/src/ruby_supportlib/phusion_passenger/utils/json.rb +2 -197
  44. data/src/ruby_supportlib/phusion_passenger/utils/strscan.rb +67 -0
  45. data/src/ruby_supportlib/phusion_passenger.rb +5 -5
  46. metadata +20 -4
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 90f1e1bc52e55a73ecec3a43986b9bd90543267b64dae5d81c30322260a60bcd
4
- data.tar.gz: ab48a44989e4f30661c2f149fb7bb9ed1155a82c44752b351aa9d7caf5021833
3
+ metadata.gz: '090896f92fb435c62847f46a39df880b08d3081323c925b35be422bb701d44a4'
4
+ data.tar.gz: 7c41513aef78b37d5ac93573afc01992f3d5ec6fe08101103ee0a0a2a8ab1cd4
5
5
  SHA512:
6
- metadata.gz: 1541930bafaf6b29a215e2bae21af6ec97efaa367c837b09824d2cf53cf1aaa3878ba5a028d7054006598f115dc80bac2046e542adfb7e169691e5ccb5107930
7
- data.tar.gz: 07346e8767eb64c6fd052200d2fab65bb0f744aa11e70a47618b7a9a1d093784a5cb27db86289c2ca052f44ecdc0fa4e8139caf0a652e6edc071208b76c61fa1
6
+ metadata.gz: 3c6daa23ca3426ebafa54f7d94b018467bbc6d2572799a50ddf111f0628673d5e308ead07dd8e7d06e9d6a8b63bbdc28090c1c581ef06e6a6fce1a143956a6ac
7
+ data.tar.gz: 12130ca0f74963de002f8d1a777a2ce4563631a4e6ea7a654325efec072dd4e44e40989df4cbe9addad1b12664cdfd53d6ceeb9e76133f3ca169dc2b334ff478
data/CHANGELOG CHANGED
@@ -1,4 +1,43 @@
1
- Release 6.0.21 (Not yet released)
1
+ Release 6.0.23 (Not yet released)
2
+ -------------
3
+ * [Enterprise] The rolling restart feature now replaces app processes in newest-to-oldest order, to make more efficient use of alive processes during the rolling-restart's duration. Closes GH-2551.
4
+ * [Ruby] Improve Rack 3 compatibility.
5
+ * [Nginx] Upgrades preferred Nginx to 1.26.1 from 1.26.0.
6
+ * [Debian] Remove packages for Debian 10 Buster. (EOL 2024-07).
7
+ * [Ubuntu] Add packages for Ubuntu 24.04 "noble".
8
+ * [RPMs] Remove EL7 RPMs, CentOS7 is EOL.
9
+ * Fixes compatibility with Ruby apps whose Gemfile.lock depends on strscan.
10
+ * Adds option to render a custom error page when app fails to launch. Closes GH-2515.
11
+ - Apache: PassengerCustomErrorPage "public/error.html"
12
+ - Nginx: passenger_custom_error_page public/error.html;
13
+ - Standalone: --custom-error-page public/error.html
14
+ * Updated various library versions used in precompiled binaries (used for e.g. gem installs):
15
+ - glibc 2.17 -> 2.28
16
+ - ccache 4.9.1 -> 4.10.1
17
+ - cmake 3.29.3 -> 3.30.1
18
+ - curl 8.7.1 -> 8.8.0
19
+ - git 2.45.0 -> 2.45.2
20
+ - openssl 3.3.0 -> 3.3.1
21
+ - pcre2 10.43 -> 10.44
22
+ - libassuan 2.5.7 -> 3.0.1
23
+ - libgcrypt 1.10.3 -> 1.11.0
24
+ - libgpg_error 1.49 -> 1.50
25
+ - libksba 1.6.6 -> 1.6.7
26
+ - pinentry 1.3.0 -> 1.3.1
27
+ - rubygems 3.5.10 -> 3.5.16
28
+ - rubies:
29
+ - dropped 3.0.7
30
+ - 3.1.5 -> 3.1.6
31
+ - 3.3.1 -> 3.3.4
32
+
33
+
34
+ Release 6.0.22
35
+ -------------
36
+ * [RPM] Fix dependency on selinux-policy. Closes GH-2545.
37
+ * Fix Amazon Linux detection. Closes GH-3296.
38
+
39
+
40
+ Release 6.0.21
2
41
  -------------
3
42
  * [Python] Fix version of Python when imp module is replaced with importlib. Contributed by Grigory Ponomarenko.
4
43
  * [Ubuntu] Remove packages for Ubuntu 23.10 "mantic".
@@ -7,9 +46,9 @@ Release 6.0.21 (Not yet released)
7
46
  * [RPM] The Passenger Nginx module rpm package for EL9 (RHEL, Rocky, Alma) will now require Nginx 1.24.0 as per the policy of supporting the newest Nginx module stream available.
8
47
  * [Standalone] Fixes security update checker with builtin engine.
9
48
  * [Enterprise] Ability to enforce hard memory limits on application processes (`PassengerHardMemoryLimit`/`passenger_hard_memory_limit`/`--hard-memory-limit``). Unlike the soft memory limit, the hard memory limit doesn't wait for the request to finish. Useful for preventing high memory usage from taking down the entire machine or container.
10
- * [Enterprise] Ability to throttle memory metrics collection (`PassengerAnalyticsCollectionRate`/`passenger_analytics_collection_rate`). This allows you to control the frequency that Passenger Enterpprise measures the app memory use at.
49
+ * [Enterprise] Ability to throttle memory metrics collection (`PassengerAnalyticsCollectionRate`/`passenger_analytics_collection_rate`). This allows you to control the frequency that Passenger Enterprise measures the app memory use at.
11
50
  * Swaps http-parser for llhttp.
12
- * Fixes crash-watch hanging when lldb is used as backend.
51
+ * Fixes crash-watch hanging when lldb is used as the backend.
13
52
  * Fixes Apache module unload crash due to not properly cleaning up all threads.
14
53
  * Workaround compilation error on clang on x86_64.
15
54
  * Upgrades Boost from 1.83 -> 1.85.
data/Rakefile CHANGED
@@ -27,8 +27,15 @@ $LOAD_PATH.unshift("#{SOURCE_ROOT}/src/ruby_supportlib")
27
27
  # timing-sensitive tests like those in the C++ test suite.
28
28
  if defined?(Bundler)
29
29
  clean_env = nil
30
- Bundler.with_clean_env do
31
- clean_env = ENV.to_hash
30
+
31
+ if Bundler.method_defined?(:with_unbundled_env)
32
+ Bundler.with_unbundled_env do
33
+ clean_env = ENV.to_hash
34
+ end
35
+ else
36
+ Bundler.with_clean_env do
37
+ clean_env = ENV.to_hash
38
+ end
32
39
  end
33
40
  ENV.replace(clean_env)
34
41
  ARGV.each do |arg|
@@ -576,6 +576,7 @@ private
576
576
  system("(gcc -I/usr/local/include -I/usr/include/pcre2 " <<
577
577
  "-I/usr/pkg/include -I/opt/local/include " <<
578
578
  "-I/opt/homebrew/include " <<
579
+ "-DPCRE2_CODE_UNIT_WIDTH=8 " <<
579
580
  "-c passenger-check.c) >/dev/null 2>/dev/null")
580
581
  end
581
582
  ensure
data/build/test_basics.rb CHANGED
@@ -22,6 +22,8 @@
22
22
  # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23
23
  # THE SOFTWARE.
24
24
 
25
+ require 'rubygems/version.rb'
26
+
25
27
  TEST_BOOST_OXT_LIBRARY = LIBBOOST_OXT
26
28
  TEST_COMMON_LIBRARY = COMMON_LIBRARY
27
29
  TEST_COMMON_CFLAGS = "-DTESTING_APPLICATION_POOL"
@@ -49,10 +51,13 @@ task 'test:install_deps' do
49
51
  default = boolean_option('DEVDEPS_DEFAULT', true)
50
52
  install_base_deps = boolean_option('BASE_DEPS', default)
51
53
 
54
+ bundle_args = []
52
55
  if deps_target = string_option('DEPS_TARGET')
53
- bundle_args = "--path #{shesc deps_target} #{ENV['BUNDLE_ARGS']}".strip
54
- else
55
- bundle_args = ENV['BUNDLE_ARGS'].to_s
56
+ if bundler_too_new?
57
+ sh "bundle config set --local path #{shesc deps_target}"
58
+ else
59
+ bundle_args.concat(["--path", shesc(deps_target)])
60
+ end
56
61
  end
57
62
 
58
63
  npm_args = ENV['NPM_ARGS'].to_s
@@ -62,22 +67,36 @@ task 'test:install_deps' do
62
67
  end
63
68
 
64
69
  if install_base_deps
65
- if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new('3.0.0') || RUBY_PLATFORM =~ /darwin/
66
- sh "bundle install #{bundle_args} --without="
67
- else
68
- sh "bundle install #{bundle_args} --without future"
70
+ unless Gem::Version.new(RUBY_VERSION) >= Gem::Version.new('3.0.0') || RUBY_PLATFORM =~ /darwin/
71
+ if bundler_too_new?
72
+ sh "bundle config set --local without future"
73
+ else
74
+ bundle_args.concat(["--without", "future"])
75
+ end
69
76
  end
70
77
  else
71
- sh "bundle install #{bundle_args} --without base future"
78
+ if bundler_too_new?
79
+ sh "bundle config set --local without 'base future'"
80
+ else
81
+ bundle_args.concat(["--without", "base", "future"])
82
+ end
72
83
  end
84
+ sh "bundle install #{bundle_args.join(' ')} #{ENV['BUNDLE_ARGS']}"
73
85
 
74
86
  if boolean_option('NODE_MODULES', default)
75
87
  sh "npm install #{npm_args}"
76
88
  end
77
89
  end
78
90
 
79
- def bundler_too_old?
91
+ def bundler_version
80
92
  `bundle --version` =~ /version (.+)/
81
- version = $1.split('.').map { |x| x.to_i }
82
- version[0] < 1 || version[0] == 1 && version[1] < 10
93
+ Gem::Version.new($1)
94
+ end
95
+
96
+ def bundler_too_old?
97
+ Gem::Version.new(bundler_version) < Gem::Version.new("1.1.10")
98
+ end
99
+
100
+ def bundler_too_new?
101
+ Gem::Version.new(bundler_version) >= Gem::Version.new("2.1.0")
83
102
  end
data/passenger.gemspec CHANGED
@@ -1,5 +1,6 @@
1
1
  source_root = File.expand_path(File.dirname(__FILE__))
2
2
  $LOAD_PATH.unshift("#{source_root}/src/ruby_supportlib")
3
+ require 'rubygems'
3
4
  require 'phusion_passenger'
4
5
  PhusionPassenger.locate_directories
5
6
  PhusionPassenger.require_passenger_lib 'packaging'
@@ -22,8 +23,9 @@ Gem::Specification.new do |s|
22
23
  "mailing_list_uri" => "https://www.phusionpassenger.com/contact",
23
24
  "wiki_uri" => "https://github.com/phusion/passenger/wiki"
24
25
  }
25
- s.add_dependency 'rake', '>= 0.8.1'
26
- s.add_dependency 'rack'
26
+ s.add_dependency 'rake', '>= 12.3.3'
27
+ s.add_dependency 'rack', '>= 1.6.13'
28
+ s.add_dependency 'rackup'
27
29
  s.files = Dir[*PhusionPassenger::Packaging::GLOB] -
28
30
  Dir[*PhusionPassenger::Packaging::EXCLUDE_GLOB]
29
31
  s.executables = PhusionPassenger::Packaging::USER_EXECUTABLES +
@@ -55,6 +55,7 @@ passenger_enabled on;
55
55
  <%= nginx_option(app, :preload_bundler) %>
56
56
  <%= nginx_option(app, :app_file_descriptor_ulimit) %>
57
57
  <%= nginx_option(app, :friendly_error_pages) %>
58
+ <%= nginx_option(app, :custom_error_page) %>
58
59
  <%= nginx_option(app, :abort_websockets_on_process_shutdown) %>
59
60
  <%= nginx_option(app, :force_max_concurrent_requests_per_process) %>
60
61
  <%= nginx_option(app, :max_requests) %>
@@ -291,7 +291,7 @@ Group::inspectConfigInAdminPanelFormat(Json::Value &result) const {
291
291
  result["environment_variables"] = VAL(Json::objectValue, Json::objectValue);
292
292
  }
293
293
 
294
- // Missing: sticky_sessions, sticky_session_cookie_name, friendly_error_pages
294
+ // Missing: sticky_sessions, sticky_session_cookie_name, friendly_error_pages, custom_error_page
295
295
 
296
296
  /******************/
297
297
 
@@ -81,15 +81,12 @@ Pool::inspectProcessList(const InspectOptions &options, stringstream &result,
81
81
 
82
82
  if (process->metrics.isValid()) {
83
83
  snprintf(cpubuf, sizeof(cpubuf), "%d%%", (int) process->metrics.cpu);
84
- #pragma clang diagnostic push
85
- #pragma clang diagnostic ignored "-Wformat-truncation"
86
84
  #pragma GCC diagnostic push
87
85
  #pragma GCC diagnostic ignored "-Wformat-truncation"
88
86
  //don't worry about format-truncation here, no one has 9.3PB RAM
89
87
  snprintf(membuf, sizeof(membuf), "%ldM",
90
88
  (unsigned long) (process->metrics.realMemory() / 1024));
91
89
  #pragma GCC diagnostic pop
92
- #pragma clang diagnostic pop
93
90
  } else {
94
91
  snprintf(cpubuf, sizeof(cpubuf), "0%%");
95
92
  snprintf(membuf, sizeof(membuf), "0M");
@@ -118,6 +118,7 @@ using namespace std;
118
118
  * default_abort_websockets_on_process_shutdown boolean - default(true)
119
119
  * default_app_file_descriptor_ulimit unsigned integer - -
120
120
  * default_bind_address string - default("127.0.0.1")
121
+ * default_custom_error_page string - default("")
121
122
  * default_environment string - default("production")
122
123
  * default_force_max_concurrent_requests_per_process integer - default(-1)
123
124
  * default_friendly_error_pages string - default("auto")
@@ -166,7 +167,7 @@ using namespace std;
166
167
  * security_update_checker_interval unsigned integer - default(86400)
167
168
  * security_update_checker_proxy_url string - -
168
169
  * security_update_checker_url string - default("https://securitycheck.phusionpassenger.com/v1/check.json")
169
- * server_software string - default("Phusion_Passenger/6.0.21")
170
+ * server_software string - default("Phusion_Passenger/6.0.23")
170
171
  * show_version_in_header boolean - default(true)
171
172
  * single_app_mode_app_root string - default,read_only
172
173
  * single_app_mode_app_start_command string - read_only
@@ -23,6 +23,7 @@
23
23
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24
24
  * THE SOFTWARE.
25
25
  */
26
+ #include "DataStructures/LString.h"
26
27
  #include <Core/Controller.h>
27
28
  #include <Core/SpawningKit/ErrorRenderer.h>
28
29
 
@@ -351,8 +352,17 @@ Controller::endRequestWithErrorResponse(Client **c, Request **r,
351
352
  Request *req = *r;
352
353
  SpawningKit::ErrorRenderer renderer(*appPool->getSpawningKitContext());
353
354
  string data;
355
+ const LString *path = customErrorPageEnabled(req);
354
356
 
355
- if (friendlyErrorPagesEnabled(req)) {
357
+ if (!psg_lstr_cmp(path, StaticString(""))) {
358
+ try {
359
+ data = renderer.renderCustom(StaticString(path->start->data, path->size));
360
+ } catch (const SystemException &e2) {
361
+ SKC_ERROR(client, "Cannot render an error page: " << e2.what() <<
362
+ "\n" << e2.backtrace());
363
+ data = "<h2>Internal server error</h2>";
364
+ }
365
+ } else if (friendlyErrorPagesEnabled(req)) {
356
366
  try {
357
367
  data = renderer.renderWithDetails(e);
358
368
  } catch (const SystemException &e2) {
@@ -373,6 +383,19 @@ Controller::endRequestWithErrorResponse(Client **c, Request **r,
373
383
  endRequestWithSimpleResponse(c, r, psg_pstrdup(req->pool, data), statusCode);
374
384
  }
375
385
 
386
+ const LString*
387
+ Controller::customErrorPageEnabled(Request *req) {
388
+ const StaticString name = "!~PASSENGER_CUSTOM_ERROR_PAGE";
389
+ LString* customErrorPagePath = req->secureHeaders.lookup(name);
390
+ if (customErrorPagePath != NULL && customErrorPagePath->size > 0) {
391
+ return psg_lstr_make_contiguous(customErrorPagePath, req->pool);
392
+ } else {
393
+ customErrorPagePath = (LString *) psg_palloc(req->pool, sizeof(LString));
394
+ psg_lstr_init(customErrorPagePath);
395
+ return customErrorPagePath;
396
+ }
397
+ }
398
+
376
399
  bool
377
400
  Controller::friendlyErrorPagesEnabled(Request *req) {
378
401
  bool defaultValue;
@@ -88,6 +88,7 @@ parseControllerBenchmarkMode(const StaticString &mode) {
88
88
  * default_abort_websockets_on_process_shutdown boolean - default(true)
89
89
  * default_app_file_descriptor_ulimit unsigned integer - -
90
90
  * default_bind_address string - default("127.0.0.1")
91
+ * default_custom_error_page string - default("")
91
92
  * default_environment string - default("production")
92
93
  * default_force_max_concurrent_requests_per_process integer - default(-1)
93
94
  * default_friendly_error_pages string - default("auto")
@@ -116,7 +117,7 @@ parseControllerBenchmarkMode(const StaticString &mode) {
116
117
  * multi_app boolean - default(true),read_only
117
118
  * request_freelist_limit unsigned integer - default(1024)
118
119
  * response_buffer_high_watermark unsigned integer - default(134217728)
119
- * server_software string - default("Phusion_Passenger/6.0.21")
120
+ * server_software string - default("Phusion_Passenger/6.0.23")
120
121
  * show_version_in_header boolean - default(true)
121
122
  * start_reading_after_accept boolean - default(true)
122
123
  * stat_throttle_rate unsigned integer - default(10)
@@ -161,6 +162,7 @@ private:
161
162
  add("server_software", STRING_TYPE, OPTIONAL, SERVER_TOKEN_NAME "/" PASSENGER_VERSION);
162
163
  add("vary_turbocache_by_cookie", STRING_TYPE, OPTIONAL);
163
164
 
165
+ add("default_custom_error_page", STRING_TYPE, OPTIONAL, "");
164
166
  add("default_friendly_error_pages", STRING_TYPE, OPTIONAL, "auto");
165
167
  add("default_environment", STRING_TYPE, OPTIONAL, DEFAULT_APP_ENV);
166
168
  add("default_spawn_method", STRING_TYPE, OPTIONAL, DEFAULT_SPAWN_METHOD);
@@ -428,6 +430,7 @@ public:
428
430
  StaticString defaultStickySessionsCookieAttributes;
429
431
  StaticString defaultVaryTurbocacheByCookie;
430
432
 
433
+ StaticString defaultCustomErrorPage;
431
434
  StaticString defaultFriendlyErrorPages;
432
435
  StaticString defaultEnvironment;
433
436
  StaticString defaultSpawnMethod;
@@ -463,6 +466,7 @@ public:
463
466
  defaultStickySessionsCookieAttributes(psg_pstrdup(pool, config["default_sticky_sessions_cookie_attributes"].asString())),
464
467
  defaultVaryTurbocacheByCookie(psg_pstrdup(pool, config["vary_turbocache_by_cookie"].asString())),
465
468
 
469
+ defaultCustomErrorPage(psg_pstrdup(pool, config["default_custom_error_page"].asString())),
466
470
  defaultFriendlyErrorPages(psg_pstrdup(pool, config["default_friendly_error_pages"].asString())),
467
471
  defaultEnvironment(psg_pstrdup(pool, config["default_environment"].asString())),
468
472
  defaultSpawnMethod(psg_pstrdup(pool, config["default_spawn_method"].asString())),
@@ -216,6 +216,7 @@ private:
216
216
  const ExceptionPtr &e);
217
217
  void endRequestWithErrorResponse(Client **c, Request **r,
218
218
  const SpawningKit::SpawnException &e, int statusCode);
219
+ const LString* customErrorPageEnabled(Request *req);
219
220
  bool friendlyErrorPagesEnabled(Request *req);
220
221
 
221
222
 
@@ -339,6 +339,9 @@ parseCoreOption(int argc, const char *argv[], int &i, Json::Value &updates) {
339
339
  } else if (p.isFlag(argv[i], '\0', "--multi-app")) {
340
340
  updates["multi_app"] = true;
341
341
  i++;
342
+ } else if (p.isFlag(argv[i], '\0', "--custom-error-page")) {
343
+ updates["custom_error_page"] = argv[i + 1];
344
+ i+=2;
342
345
  } else if (p.isFlag(argv[i], '\0', "--force-friendly-error-pages")) {
343
346
  updates["default_friendly_error_pages"] = true;
344
347
  i++;
@@ -33,6 +33,7 @@
33
33
  #include <jsoncpp/json.h>
34
34
 
35
35
  #include <Constants.h>
36
+ #include <DataStructures/LString.h>
36
37
  #include <StaticString.h>
37
38
  #include <FileTools/FileManip.h>
38
39
  #include <StrIntTools/Template.h>
@@ -108,6 +109,10 @@ public:
108
109
 
109
110
  return Template::apply(unsafeReadFile(htmlFile), params);
110
111
  }
112
+
113
+ string renderCustom(const StaticString &htmlFile) const {
114
+ return unsafeReadFile(htmlFile);
115
+ }
111
116
  };
112
117
 
113
118
 
@@ -104,6 +104,7 @@ using namespace std;
104
104
  * default_abort_websockets_on_process_shutdown boolean - default(true)
105
105
  * default_app_file_descriptor_ulimit unsigned integer - -
106
106
  * default_bind_address string - default("127.0.0.1")
107
+ * default_custom_error_page string - default("")
107
108
  * default_environment string - default("production")
108
109
  * default_force_max_concurrent_requests_per_process integer - default(-1)
109
110
  * default_friendly_error_pages string - default("auto")
@@ -154,7 +155,7 @@ using namespace std;
154
155
  * security_update_checker_interval unsigned integer - default(86400)
155
156
  * security_update_checker_proxy_url string - -
156
157
  * security_update_checker_url string - default("https://securitycheck.phusionpassenger.com/v1/check.json")
157
- * server_software string - default("Phusion_Passenger/6.0.21")
158
+ * server_software string - default("Phusion_Passenger/6.0.23")
158
159
  * setsid boolean - default(false)
159
160
  * show_version_in_header boolean - default(true)
160
161
  * single_app_mode_app_root string - default,read_only
@@ -142,6 +142,11 @@ extern "C" const command_rec passenger_commands[] = {
142
142
  NULL,
143
143
  RSRC_CONF,
144
144
  "Set advanced Phusion Passenger(R) options."),
145
+ AP_INIT_TAKE1("PassengerCustomErrorPage",
146
+ (Take1Func) cmd_passenger_custom_error_page,
147
+ NULL,
148
+ RSRC_CONF | ACCESS_CONF,
149
+ "Path to html file to use for Passenger generated error pages."),
145
150
  AP_INIT_TAKE1("PassengerDataBufferDir",
146
151
  (Take1Func) cmd_passenger_data_buffer_dir,
147
152
  NULL,
@@ -259,6 +259,21 @@ cmd_passenger_buffer_upload(cmd_parms *cmd, void *pcfg, const char *arg) {
259
259
  return NULL;
260
260
  }
261
261
 
262
+ static const char *
263
+ cmd_passenger_custom_error_page(cmd_parms *cmd, void *pcfg, const char *arg) {
264
+ const char *err = ap_check_cmd_context(cmd, NOT_IN_FILES);
265
+ if (err != NULL) {
266
+ return err;
267
+ }
268
+
269
+ DirConfig *config = (DirConfig *) pcfg;
270
+ config->mCustomErrorPageSourceFile = cmd->directive->filename;
271
+ config->mCustomErrorPageSourceLine = cmd->directive->line_num;
272
+ config->mCustomErrorPageExplicitlySet = true;
273
+ config->mCustomErrorPage = arg;
274
+ return NULL;
275
+ }
276
+
262
277
  static const char *
263
278
  cmd_passenger_data_buffer_dir(cmd_parms *cmd, void *pcfg, const char *arg) {
264
279
  const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
@@ -75,6 +75,9 @@ createDirConfig_autoGenerated(DirConfig *config) {
75
75
  */
76
76
  config->mBufferResponse = Apache2Module::UNSET;
77
77
  config->mBufferUpload = Apache2Module::UNSET;
78
+ /*
79
+ * config->mCustomErrorPage: default initialized
80
+ */
78
81
  /*
79
82
  * config->mDirectInstanceRequestAddress: default initialized
80
83
  */
@@ -139,6 +142,7 @@ createDirConfig_autoGenerated(DirConfig *config) {
139
142
  config->mBaseURIsSourceLine = 0;
140
143
  config->mBufferResponseSourceLine = 0;
141
144
  config->mBufferUploadSourceLine = 0;
145
+ config->mCustomErrorPageSourceLine = 0;
142
146
  config->mDirectInstanceRequestAddressSourceLine = 0;
143
147
  config->mEnabledSourceLine = 0;
144
148
  config->mErrorOverrideSourceLine = 0;
@@ -177,6 +181,7 @@ createDirConfig_autoGenerated(DirConfig *config) {
177
181
  config->mBaseURIsExplicitlySet = false;
178
182
  config->mBufferResponseExplicitlySet = false;
179
183
  config->mBufferUploadExplicitlySet = false;
184
+ config->mCustomErrorPageExplicitlySet = false;
180
185
  config->mDirectInstanceRequestAddressExplicitlySet = false;
181
186
  config->mEnabledExplicitlySet = false;
182
187
  config->mErrorOverrideExplicitlySet = false;
@@ -61,6 +61,9 @@ constructRequestHeaders_autoGenerated(request_rec *r, DirConfig *config, std::st
61
61
  addHeader(result, StaticString("!~PASSENGER_APP_LOG_FILE",
62
62
  sizeof("!~PASSENGER_APP_LOG_FILE") - 1),
63
63
  config->mAppLogFile);
64
+ addHeader(result, StaticString("!~PASSENGER_CUSTOM_ERROR_PAGE",
65
+ sizeof("!~PASSENGER_CUSTOM_ERROR_PAGE") - 1),
66
+ config->mCustomErrorPage);
64
67
  addHeader(result, StaticString("!~PASSENGER_DIRECT_INSTANCE_REQUEST_ADDRESS",
65
68
  sizeof("!~PASSENGER_DIRECT_INSTANCE_REQUEST_ADDRESS") - 1),
66
69
  config->mDirectInstanceRequestAddress);
@@ -176,6 +176,19 @@ ConfigManifestGenerator::autoGenerated_generateConfigManifestForDirConfig(server
176
176
  pdconf->mBufferUploadSourceLine);
177
177
  hierarchyMember["value"] = pdconf->mBufferUpload == Apache2Module::ENABLED;
178
178
  }
179
+ if (pdconf->mCustomErrorPageExplicitlySet) {
180
+ findOrCreateAppAndLocOptionsContainers(serverRec, csconf, cdconf,
181
+ pdconf, context, &appOptionsContainer, &locOptionsContainer);
182
+ Json::Value &optionContainer = findOrCreateOptionContainer(*appOptionsContainer,
183
+ "PassengerCustomErrorPage",
184
+ sizeof("PassengerCustomErrorPage") - 1);
185
+ Json::Value &hierarchyMember = addOptionContainerHierarchyMember(optionContainer,
186
+ pdconf->mCustomErrorPageSourceFile,
187
+ pdconf->mCustomErrorPageSourceLine);
188
+ hierarchyMember["value"] = Json::Value(
189
+ pdconf->mCustomErrorPage.data(),
190
+ pdconf->mCustomErrorPage.data() + pdconf->mCustomErrorPage.size());
191
+ }
179
192
  if (pdconf->mDirectInstanceRequestAddressExplicitlySet) {
180
193
  findOrCreateAppAndLocOptionsContainers(serverRec, csconf, cdconf,
181
194
  pdconf, context, &appOptionsContainer, &locOptionsContainer);
@@ -88,6 +88,10 @@ mergeDirConfig_autoGenerated(DirConfig *config, DirConfig *base, DirConfig *add)
88
88
  (add->mBufferUpload != Apache2Module::UNSET)
89
89
  ? add->mBufferUpload
90
90
  : base->mBufferUpload;
91
+ config->mCustomErrorPage =
92
+ (!add->mCustomErrorPage.empty())
93
+ ? add->mCustomErrorPage
94
+ : base->mCustomErrorPage;
91
95
  config->mDirectInstanceRequestAddress =
92
96
  (!add->mDirectInstanceRequestAddress.empty())
93
97
  ? add->mDirectInstanceRequestAddress
@@ -207,6 +211,7 @@ mergeDirConfig_autoGenerated(DirConfig *config, DirConfig *base, DirConfig *add)
207
211
  config->mBaseURIsSourceFile = add->mBaseURIsSourceFile;
208
212
  config->mBufferResponseSourceFile = add->mBufferResponseSourceFile;
209
213
  config->mBufferUploadSourceFile = add->mBufferUploadSourceFile;
214
+ config->mCustomErrorPageSourceFile = add->mCustomErrorPageSourceFile;
210
215
  config->mDirectInstanceRequestAddressSourceFile = add->mDirectInstanceRequestAddressSourceFile;
211
216
  config->mEnabledSourceFile = add->mEnabledSourceFile;
212
217
  config->mErrorOverrideSourceFile = add->mErrorOverrideSourceFile;
@@ -245,6 +250,7 @@ mergeDirConfig_autoGenerated(DirConfig *config, DirConfig *base, DirConfig *add)
245
250
  config->mBaseURIsSourceLine = add->mBaseURIsSourceLine;
246
251
  config->mBufferResponseSourceLine = add->mBufferResponseSourceLine;
247
252
  config->mBufferUploadSourceLine = add->mBufferUploadSourceLine;
253
+ config->mCustomErrorPageSourceLine = add->mCustomErrorPageSourceLine;
248
254
  config->mDirectInstanceRequestAddressSourceLine = add->mDirectInstanceRequestAddressSourceLine;
249
255
  config->mEnabledSourceLine = add->mEnabledSourceLine;
250
256
  config->mErrorOverrideSourceLine = add->mErrorOverrideSourceLine;
@@ -283,6 +289,7 @@ mergeDirConfig_autoGenerated(DirConfig *config, DirConfig *base, DirConfig *add)
283
289
  config->mBaseURIsExplicitlySet = add->mBaseURIsExplicitlySet;
284
290
  config->mBufferResponseExplicitlySet = add->mBufferResponseExplicitlySet;
285
291
  config->mBufferUploadExplicitlySet = add->mBufferUploadExplicitlySet;
292
+ config->mCustomErrorPageExplicitlySet = add->mCustomErrorPageExplicitlySet;
286
293
  config->mDirectInstanceRequestAddressExplicitlySet = add->mDirectInstanceRequestAddressExplicitlySet;
287
294
  config->mEnabledExplicitlySet = add->mEnabledExplicitlySet;
288
295
  config->mErrorOverrideExplicitlySet = add->mErrorOverrideExplicitlySet;
@@ -171,6 +171,11 @@ struct AutoGeneratedDirConfig {
171
171
  */
172
172
  StaticString mAppType;
173
173
 
174
+ /*
175
+ * Path to html file to use for Passenger generated error pages.
176
+ */
177
+ StaticString mCustomErrorPage;
178
+
174
179
  /*
175
180
  * The address that Passenger binds to in order to allow sending HTTP requests to individual application processes.
176
181
  */
@@ -265,6 +270,7 @@ struct AutoGeneratedDirConfig {
265
270
  StaticString mAppRootSourceFile;
266
271
  StaticString mAppStartCommandSourceFile;
267
272
  StaticString mAppTypeSourceFile;
273
+ StaticString mCustomErrorPageSourceFile;
268
274
  StaticString mDirectInstanceRequestAddressSourceFile;
269
275
  StaticString mGroupSourceFile;
270
276
  StaticString mMeteorAppSettingsSourceFile;
@@ -303,6 +309,7 @@ struct AutoGeneratedDirConfig {
303
309
  unsigned int mAppRootSourceLine;
304
310
  unsigned int mAppStartCommandSourceLine;
305
311
  unsigned int mAppTypeSourceLine;
312
+ unsigned int mCustomErrorPageSourceLine;
306
313
  unsigned int mDirectInstanceRequestAddressSourceLine;
307
314
  unsigned int mGroupSourceLine;
308
315
  unsigned int mMeteorAppSettingsSourceLine;
@@ -341,6 +348,7 @@ struct AutoGeneratedDirConfig {
341
348
  bool mAppRootExplicitlySet: 1;
342
349
  bool mAppStartCommandExplicitlySet: 1;
343
350
  bool mAppTypeExplicitlySet: 1;
351
+ bool mCustomErrorPageExplicitlySet: 1;
344
352
  bool mDirectInstanceRequestAddressExplicitlySet: 1;
345
353
  bool mGroupExplicitlySet: 1;
346
354
  bool mMeteorAppSettingsExplicitlySet: 1;
@@ -540,6 +548,11 @@ struct AutoGeneratedDirConfig {
540
548
  return mAppType;
541
549
  }
542
550
 
551
+ StaticString
552
+ getCustomErrorPage() const {
553
+ return mCustomErrorPage;
554
+ }
555
+
543
556
  StaticString
544
557
  getDirectInstanceRequestAddress() const {
545
558
  if (mDirectInstanceRequestAddress.empty()) {
@@ -83,7 +83,7 @@
83
83
  #define PASSENGER_API_VERSION_MAJOR 0
84
84
  #define PASSENGER_API_VERSION_MINOR 3
85
85
  #define PASSENGER_DEFAULT_USER "nobody"
86
- #define PASSENGER_VERSION "6.0.21"
86
+ #define PASSENGER_VERSION "6.0.23"
87
87
  #define POOL_HELPER_THREAD_STACK_SIZE 262144
88
88
  #define PROCESS_SHUTDOWN_TIMEOUT 60
89
89
  #define PROCESS_SHUTDOWN_TIMEOUT_DISPLAY "1 minute"
@@ -257,6 +257,10 @@ psg_lstr_cmp(const LString *str, const StaticString &other) {
257
257
  const LString::Part *part;
258
258
  const char *b;
259
259
 
260
+ if (str == NULL) {
261
+ return false;
262
+ }
263
+
260
264
  // Fast check: check length match
261
265
  if (str->size != other.size()) {
262
266
  return false;
@@ -350,6 +350,14 @@
350
350
  offsetof(passenger_loc_conf_t, autogenerated.friendly_error_pages),
351
351
  NULL
352
352
  },
353
+ {
354
+ ngx_string("passenger_custom_error_page"),
355
+ NGX_HTTP_MAIN_CONF | NGX_HTTP_SRV_CONF | NGX_HTTP_LOC_CONF | NGX_HTTP_LIF_CONF | NGX_CONF_TAKE1,
356
+ passenger_conf_set_custom_error_page,
357
+ NGX_HTTP_LOC_CONF_OFFSET,
358
+ offsetof(passenger_loc_conf_t, autogenerated.custom_error_page),
359
+ NULL
360
+ },
353
361
  {
354
362
  ngx_string("passenger_min_instances"),
355
363
  NGX_HTTP_MAIN_CONF | NGX_HTTP_SRV_CONF | NGX_HTTP_LOC_CONF | NGX_HTTP_LIF_CONF | NGX_CONF_TAKE1,
@@ -541,6 +541,18 @@ passenger_conf_set_friendly_error_pages(ngx_conf_t *cf, ngx_command_t *cmd, void
541
541
  return ngx_conf_set_flag_slot(cf, cmd, conf);
542
542
  }
543
543
 
544
+ static char *
545
+ passenger_conf_set_custom_error_page(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) {
546
+ passenger_loc_conf_t *passenger_conf = conf;
547
+
548
+ passenger_conf->autogenerated.custom_error_page_explicitly_set = 1;
549
+ record_loc_conf_source_location(cf, passenger_conf,
550
+ &passenger_conf->autogenerated.custom_error_page_source_file,
551
+ &passenger_conf->autogenerated.custom_error_page_source_line);
552
+
553
+ return ngx_conf_set_str_slot(cf, cmd, conf);
554
+ }
555
+
544
556
  static char *
545
557
  passenger_conf_set_min_instances(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) {
546
558
  passenger_loc_conf_t *passenger_conf = conf;
@@ -224,7 +224,9 @@ passenger_create_loc_conf(ngx_conf_t *cf)
224
224
 
225
225
  conf->upstream_config.send_lowat = NGX_CONF_UNSET_SIZE;
226
226
  conf->upstream_config.buffer_size = NGX_CONF_UNSET_SIZE;
227
- #if NGINX_VERSION_NUM >= 1007007
227
+ #if NGINX_VERSION_NUM >= 1027000
228
+ conf->upstream_config.limit_rate = NGX_CONF_UNSET_PTR;
229
+ #elif NGINX_VERSION_NUM >= 1007007
228
230
  conf->upstream_config.limit_rate = NGX_CONF_UNSET_SIZE;
229
231
  #endif
230
232
 
@@ -465,7 +467,10 @@ passenger_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
465
467
  prev->upstream_config.buffer_size,
466
468
  16 * 1024);
467
469
 
468
- #if NGINX_VERSION_NUM >= 1007007
470
+ #if NGINX_VERSION_NUM >= 1027000
471
+ ngx_conf_merge_ptr_value(conf->upstream_config.limit_rate,
472
+ prev->upstream_config.limit_rate, NULL);
473
+ #elif NGINX_VERSION_NUM >= 1007007
469
474
  ngx_conf_merge_size_value(conf->upstream_config.limit_rate,
470
475
  prev->upstream_config.limit_rate, 0);
471
476
  #endif