passenger 6.0.22 → 6.0.23

Sign up to get free protection for your applications and to get access to all the features.
Files changed (45) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +34 -1
  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/nginx/config_options.rb +5 -0
  37. data/src/ruby_supportlib/phusion_passenger/platform_info/depcheck_specs/gems.rb +10 -0
  38. data/src/ruby_supportlib/phusion_passenger/rack/handler.rb +73 -0
  39. data/src/ruby_supportlib/phusion_passenger/rack_handler.rb +30 -56
  40. data/src/ruby_supportlib/phusion_passenger/standalone/config_options_list.rb +5 -0
  41. data/src/ruby_supportlib/phusion_passenger/standalone/start_command/builtin_engine.rb +1 -0
  42. data/src/ruby_supportlib/phusion_passenger/utils/json.rb +2 -197
  43. data/src/ruby_supportlib/phusion_passenger/utils/strscan.rb +67 -0
  44. data/src/ruby_supportlib/phusion_passenger.rb +5 -5
  45. metadata +20 -4
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: cf8796ca602a79def60593ff7881de810c3806c6eed5edcd77401d7226e81e83
4
- data.tar.gz: 04c1c5114b75ab4dffe2cd42d62f5a1fef1d9600b6ba7fd28489f5b350661ab6
3
+ metadata.gz: '090896f92fb435c62847f46a39df880b08d3081323c925b35be422bb701d44a4'
4
+ data.tar.gz: 7c41513aef78b37d5ac93573afc01992f3d5ec6fe08101103ee0a0a2a8ab1cd4
5
5
  SHA512:
6
- metadata.gz: 791507cfb77d4d7b26f4e467927ae4e9761a861d3cb171d7bf13fd1bb93efbe0a8963a55ba67e3aec0006587f3814b44f0f4d1eecb73bdbd25162694285fb926
7
- data.tar.gz: cd5231323420031e8af25388ebce3e287c5aad181f1a213a14f79fbf07f353bbfa525fbfc1b3b36b5161aec69e03f984c9e363ecf95ca2373347ad5c362ee72a
6
+ metadata.gz: 3c6daa23ca3426ebafa54f7d94b018467bbc6d2572799a50ddf111f0628673d5e308ead07dd8e7d06e9d6a8b63bbdc28090c1c581ef06e6a6fce1a143956a6ac
7
+ data.tar.gz: 12130ca0f74963de002f8d1a777a2ce4563631a4e6ea7a654325efec072dd4e44e40989df4cbe9addad1b12664cdfd53d6ceeb9e76133f3ca169dc2b334ff478
data/CHANGELOG CHANGED
@@ -1,4 +1,37 @@
1
- Release 6.0.22 (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
2
35
  -------------
3
36
  * [RPM] Fix dependency on selinux-policy. Closes GH-2545.
4
37
  * Fix Amazon Linux detection. Closes GH-3296.
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.22")
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.22")
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.22")
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.22"
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
@@ -51,6 +51,8 @@ passenger_create_autogenerated_loc_conf(passenger_autogenerated_loc_conf_t *con
51
51
  conf->environment.data = NULL;
52
52
  conf->environment.len = 0;
53
53
  conf->friendly_error_pages = NGX_CONF_UNSET;
54
+ conf->custom_error_page.data = NULL;
55
+ conf->custom_error_page.len = 0;
54
56
  conf->min_instances = NGX_CONF_UNSET_UINT;
55
57
  conf->start_timeout = NGX_CONF_UNSET_UINT;
56
58
  conf->user.data = NULL;
@@ -128,6 +130,10 @@ passenger_create_autogenerated_loc_conf(passenger_autogenerated_loc_conf_t *con
128
130
  conf->friendly_error_pages_source_file.len = 0;
129
131
  conf->friendly_error_pages_source_line = 0;
130
132
  conf->friendly_error_pages_explicitly_set = 0;
133
+ conf->custom_error_page_source_file.data = NULL;
134
+ conf->custom_error_page_source_file.len = 0;
135
+ conf->custom_error_page_source_line = 0;
136
+ conf->custom_error_page_explicitly_set = 0;
131
137
  conf->min_instances_source_file.data = NULL;
132
138
  conf->min_instances_source_file.len = 0;
133
139
  conf->min_instances_source_line = 0;