passenger 4.0.44 → 4.0.45

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.

Files changed (110) hide show
  1. checksums.yaml +8 -8
  2. checksums.yaml.gz.asc +7 -7
  3. data.tar.gz.asc +7 -7
  4. data/.travis.yml +3 -0
  5. data/CHANGELOG +31 -0
  6. data/CONTRIBUTING.md +70 -10
  7. data/CONTRIBUTORS +4 -0
  8. data/README.md +1 -1
  9. data/Vagrantfile +50 -0
  10. data/bin/passenger-install-nginx-module +7 -2
  11. data/build/basics.rb +4 -1
  12. data/build/documentation.rb +6 -0
  13. data/build/node_tests.rb +7 -1
  14. data/build/packaging.rb +5 -0
  15. data/build/test_basics.rb +3 -3
  16. data/debian.template/copyright +1 -1
  17. data/debian.template/passenger.manpages +0 -1
  18. data/dev/rack.test/config.ru +5 -0
  19. data/dev/rack.test/public/asset.txt +1 -0
  20. data/dev/vagrant/apache_default_site.conf +35 -0
  21. data/dev/vagrant/apache_passenger.conf +5 -0
  22. data/dev/vagrant/apache_passenger.load +1 -0
  23. data/dev/vagrant/apache_ports.conf +24 -0
  24. data/dev/vagrant/apache_rack_test.conf +9 -0
  25. data/dev/vagrant/bashrc +21 -0
  26. data/dev/vagrant/nginx.conf +39 -0
  27. data/dev/vagrant/nginx_rakefile +34 -0
  28. data/dev/vagrant/nginx_start +32 -0
  29. data/dev/vagrant/provision.sh +115 -0
  30. data/dev/vagrant/sudoers.conf +5 -0
  31. data/doc/Design and Architecture.txt +515 -0
  32. data/doc/DeveloperQuickstart.md +70 -0
  33. data/doc/Users guide Apache.idmap.txt +24 -18
  34. data/doc/Users guide Apache.txt +200 -62
  35. data/doc/Users guide Nginx.idmap.txt +53 -45
  36. data/doc/Users guide Nginx.txt +501 -360
  37. data/doc/Users guide Standalone.txt +8 -0
  38. data/doc/images/direct_spawning.png +0 -0
  39. data/doc/images/direct_spawning.svg +16 -13
  40. data/doc/images/helper_agent_core_architecture.png +0 -0
  41. data/doc/images/passenger_architecture_overview.png +0 -0
  42. data/doc/images/smart_spawning.png +0 -0
  43. data/doc/images/{smart.svg → smart_spawning.svg} +23 -20
  44. data/doc/images/spawning_preparation_work.png +0 -0
  45. data/doc/images/startup_sequence.png +0 -0
  46. data/doc/users_guide_snippets/appendix_c_spawning_methods.txt +82 -121
  47. data/doc/users_guide_snippets/environment_variables.txt +1 -1
  48. data/doc/users_guide_snippets/support_information.txt +2 -0
  49. data/doc/users_guide_snippets/tips.txt +117 -9
  50. data/ext/apache2/Configuration.hpp +4 -2
  51. data/ext/apache2/ConfigurationCommands.cpp +14 -0
  52. data/ext/apache2/ConfigurationFields.hpp +4 -0
  53. data/ext/apache2/ConfigurationSetters.cpp +22 -0
  54. data/ext/apache2/CreateDirConfig.cpp +2 -0
  55. data/ext/apache2/Hooks.cpp +30 -14
  56. data/ext/apache2/MergeDirConfig.cpp +14 -0
  57. data/ext/apache2/SetHeaders.cpp +8 -0
  58. data/ext/common/ApplicationPool2/AppTypes.cpp +6 -1
  59. data/ext/common/ApplicationPool2/Implementation.cpp +1 -1
  60. data/ext/common/ApplicationPool2/Session.h +1 -1
  61. data/ext/common/Constants.h +9 -7
  62. data/ext/common/Utils/HttpHeaderBufferer.h +23 -4
  63. data/ext/common/Utils/StrIntUtils.h +35 -0
  64. data/ext/common/Utils/StringScanning.h +4 -10
  65. data/ext/common/agents/HelperAgent/RequestHandler.h +90 -49
  66. data/ext/nginx/CacheLocationConfig.c +40 -0
  67. data/ext/nginx/ConfigurationCommands.c +20 -0
  68. data/ext/nginx/ConfigurationFields.h +4 -0
  69. data/ext/nginx/ContentHandler.c +1 -1
  70. data/ext/nginx/CreateLocationConfig.c +9 -0
  71. data/ext/nginx/MergeLocationConfig.c +12 -0
  72. data/ext/nginx/config +2 -2
  73. data/ext/nginx/ngx_http_passenger_module.c +4 -4
  74. data/helper-scripts/node-loader.js +40 -27
  75. data/lib/phusion_passenger.rb +1 -1
  76. data/lib/phusion_passenger/apache2/config_options.rb +14 -2
  77. data/lib/phusion_passenger/constants.rb +7 -6
  78. data/lib/phusion_passenger/loader_shared_helpers.rb +11 -1
  79. data/lib/phusion_passenger/nginx/config_options.rb +8 -0
  80. data/lib/phusion_passenger/packaging.rb +8 -3
  81. data/lib/phusion_passenger/platform_info/apache.rb +3 -0
  82. data/lib/phusion_passenger/platform_info/ruby.rb +4 -1
  83. data/lib/phusion_passenger/standalone/command.rb +0 -1
  84. data/lib/phusion_passenger/standalone/package_runtime_command.rb +1 -0
  85. data/lib/phusion_passenger/standalone/start_command.rb +80 -62
  86. data/lib/phusion_passenger/standalone/status_command.rb +1 -0
  87. data/lib/phusion_passenger/standalone/stop_command.rb +1 -0
  88. data/man/passenger-config.1 +1 -1
  89. data/man/passenger-memory-stats.8 +1 -1
  90. data/man/passenger-status.8 +1 -1
  91. data/npm-shrinkwrap.json +229 -0
  92. data/package.json +28 -0
  93. data/resources/templates/standalone/config.erb +2 -0
  94. data/rpm/Vagrantfile +0 -3
  95. data/test/config.json.vagrant +30 -0
  96. data/test/cxx/HttpHeaderBuffererTest.cpp +64 -10
  97. data/test/cxx/RequestHandlerTest.cpp +35 -13
  98. data/test/integration_tests/apache2_tests.rb +1 -0
  99. data/test/stub/node/app.js +26 -18
  100. metadata +28 -13
  101. metadata.gz.asc +7 -7
  102. data/doc/Architectural overview.idmap.txt +0 -36
  103. data/doc/Architectural overview.txt +0 -410
  104. data/doc/images/smart.png +0 -0
  105. data/ext/common/ApplicationPool2/README.md +0 -56
  106. data/man/passenger-stress-test.1 +0 -43
  107. data/node_lib/phusion_passenger/httplib_emulation.js +0 -215
  108. data/node_lib/phusion_passenger/request_handler.js +0 -73
  109. data/node_lib/phusion_passenger/session_protocol_parser.js +0 -113
  110. data/test/node/httplib_emulation_spec.js +0 -623
@@ -429,6 +429,26 @@
429
429
  NULL
430
430
  },
431
431
 
432
+ {
433
+
434
+ ngx_string("passenger_sticky_sessions"),
435
+ NGX_HTTP_MAIN_CONF | NGX_HTTP_SRV_CONF | NGX_HTTP_LOC_CONF | NGX_HTTP_LIF_CONF | NGX_CONF_FLAG,
436
+ ngx_conf_set_flag_slot,
437
+ NGX_HTTP_LOC_CONF_OFFSET,
438
+ offsetof(passenger_loc_conf_t, sticky_sessions),
439
+ NULL
440
+ },
441
+
442
+ {
443
+
444
+ ngx_string("passenger_sticky_sessions_cookie_name"),
445
+ NGX_HTTP_MAIN_CONF | NGX_HTTP_SRV_CONF | NGX_HTTP_LOC_CONF | NGX_HTTP_LIF_CONF | NGX_CONF_TAKE1,
446
+ ngx_conf_set_str_slot,
447
+ NGX_HTTP_LOC_CONF_OFFSET,
448
+ offsetof(passenger_loc_conf_t, sticky_sessions_cookie_name),
449
+ NULL
450
+ },
451
+
432
452
  {
433
453
 
434
454
  ngx_string("passenger_fly_with"),
@@ -65,6 +65,8 @@
65
65
 
66
66
  ngx_int_t start_timeout;
67
67
 
68
+ ngx_int_t sticky_sessions;
69
+
68
70
  ngx_array_t *union_station_filters;
69
71
 
70
72
  ngx_int_t union_station_support;
@@ -97,6 +99,8 @@
97
99
 
98
100
  ngx_str_t startup_file;
99
101
 
102
+ ngx_str_t sticky_sessions_cookie_name;
103
+
100
104
  ngx_str_t union_station_key;
101
105
 
102
106
  ngx_str_t user;
@@ -1378,7 +1378,7 @@ passenger_content_handler(ngx_http_request_t *r)
1378
1378
  }
1379
1379
 
1380
1380
 
1381
- /* Setup upstream stuff and prepare sending the request to the backend. */
1381
+ /* Setup upstream stuff and prepare sending the request to the HelperAgent. */
1382
1382
 
1383
1383
  if (ngx_http_upstream_create(r) != NGX_OK) {
1384
1384
  return NGX_HTTP_INTERNAL_SERVER_ERROR;
@@ -178,3 +178,12 @@
178
178
  conf->startup_file.len = 0;
179
179
 
180
180
 
181
+
182
+ conf->sticky_sessions = NGX_CONF_UNSET;
183
+
184
+
185
+
186
+ conf->sticky_sessions_cookie_name.data = NULL;
187
+ conf->sticky_sessions_cookie_name.len = 0;
188
+
189
+
@@ -207,3 +207,15 @@
207
207
  NULL);
208
208
 
209
209
 
210
+
211
+ ngx_conf_merge_value(conf->sticky_sessions,
212
+ prev->sticky_sessions,
213
+ NGX_CONF_UNSET);
214
+
215
+
216
+
217
+ ngx_conf_merge_str_value(conf->sticky_sessions_cookie_name,
218
+ prev->sticky_sessions_cookie_name,
219
+ NULL);
220
+
221
+
data/ext/nginx/config CHANGED
@@ -1,8 +1,8 @@
1
1
  # passenger-config is run with the 'ruby' command in $PATH, even when natively packaged,
2
2
  # so we check whether 'ruby' is correctly in $PATH.
3
3
  if ! ruby -v >/dev/null 2>/dev/null; then
4
- echo '*** ERROR: Cannot find the "ruby" command in $PATH. Please fix your $PATH. You can learn more about $PATH at: http://www.modrails.com/documentation/Users%20guide%20Nginx.html#_the_path_environment_variable'
5
- echo '*** Do you think that you set $PATH correctly, and you happen to be using sudo or rvmsudo? Read this: http://www.modrails.com/documentation/Users%20guide%20Nginx.html#env_vars_and_sudo'
4
+ echo '*** ERROR: Cannot find the "ruby" command in $PATH. Please fix your $PATH. You can learn more about $PATH at: https://www.phusionpassenger.com/documentation/Users%20guide%20Nginx.html#_the_path_environment_variable'
5
+ echo '*** Do you think that you set $PATH correctly, and you happen to be using sudo or rvmsudo? Read this: https://www.phusionpassenger.com/documentation/Users%20guide%20Nginx.html#env_vars_and_sudo'
6
6
  exit 1
7
7
  fi
8
8
 
@@ -237,13 +237,13 @@ create_file(ngx_cycle_t *cycle, const u_char *filename, const u_char *contents,
237
237
  }
238
238
 
239
239
  /**
240
- * Start the helper server and save its runtime information into various variables.
240
+ * Start the watchdog and save the runtime information into various variables.
241
241
  *
242
- * @pre The helper server isn't already started.
242
+ * @pre The watchdog isn't already started.
243
243
  * @pre The Nginx configuration has been loaded.
244
244
  */
245
245
  static ngx_int_t
246
- start_helper_server(ngx_cycle_t *cycle) {
246
+ start_watchdog(ngx_cycle_t *cycle) {
247
247
  ngx_core_conf_t *core_conf;
248
248
  ngx_int_t ret, result;
249
249
  ngx_uint_t i;
@@ -427,7 +427,7 @@ init_module(ngx_cycle_t *cycle) {
427
427
  ignore_sigpipe();
428
428
  first_start = 0;
429
429
  }
430
- if (start_helper_server(cycle) != NGX_OK) {
430
+ if (start_watchdog(cycle) != NGX_OK) {
431
431
  passenger_main_conf.root_dir.len = 0;
432
432
  return NGX_OK;
433
433
  }
@@ -29,8 +29,6 @@ var net = require('net');
29
29
  var http = require('http');
30
30
 
31
31
  var LineReader = require('phusion_passenger/line_reader').LineReader;
32
- var RequestHandler = require('phusion_passenger/request_handler').RequestHandler;
33
- var HttplibEmulation = require('phusion_passenger/httplib_emulation');
34
32
 
35
33
  module.isApplicationLoader = true; // https://groups.google.com/forum/#!topic/compoundjs/4txxkNtROQg
36
34
  GLOBAL.PhusionPassenger = exports.PhusionPassenger = new EventEmitter();
@@ -78,7 +76,6 @@ function readOptions() {
78
76
  function setupEnvironment(options) {
79
77
  PhusionPassenger.options = options;
80
78
  PhusionPassenger.configure = configure;
81
- PhusionPassenger._requestHandler = new RequestHandler(loadApplication);
82
79
  PhusionPassenger._appInstalled = false;
83
80
  process.title = 'Passenger NodeApp: ' + options.app_root;
84
81
  http.Server.prototype.originalListen = http.Server.prototype.listen;
@@ -88,6 +85,8 @@ function setupEnvironment(options) {
88
85
  stdinReader = undefined;
89
86
  process.stdin.on('end', shutdown);
90
87
  process.stdin.resume();
88
+
89
+ loadApplication();
91
90
  }
92
91
 
93
92
  /**
@@ -124,37 +123,51 @@ function extractCallback(args) {
124
123
  }
125
124
  }
126
125
 
126
+ function generateServerSocketPath() {
127
+ return PhusionPassenger.options.generation_dir + "/backends/"
128
+ + process.pid + "." + ((Math.random() * 0xFFFFFFFF) & 0xFFFFFFF);
129
+ }
130
+
127
131
  function installServer() {
128
132
  var server = this;
129
133
  if (!PhusionPassenger._appInstalled) {
130
134
  PhusionPassenger._appInstalled = true;
131
135
  PhusionPassenger._server = server;
132
- server.address = function() {
133
- return 'passenger';
134
- }
135
- finalizeStartup();
136
-
137
- PhusionPassenger.on('request', function(headers, socket, bodyBegin) {
138
- var req, res;
139
- if (headers['HTTP_UPGRADE']) {
140
- if (EventEmitter.listenerCount(server, 'upgrade') > 0) {
141
- req = HttplibEmulation.createIncomingMessage(headers, socket, bodyBegin);
142
- server.emit('upgrade', req, socket, bodyBegin);
136
+
137
+ var listenTries = 0;
138
+ doListen(extractCallback(arguments));
139
+
140
+ function doListen(callback) {
141
+ function errorHandler(error) {
142
+ if (error.errno == 'EADDRINUSE') {
143
+ if (listenTries == 100) {
144
+ server.emit('error', new Error(
145
+ 'Phusion Passenger could not find suitable socket address to bind on'));
146
+ } else {
147
+ // Try again with another socket path.
148
+ listenTries++;
149
+ doListen(callback);
150
+ }
143
151
  } else {
144
- socket.destroy();
152
+ server.emit('error', error);
145
153
  }
146
- } else {
147
- req = HttplibEmulation.createIncomingMessage(headers, socket, bodyBegin);
148
- res = HttplibEmulation.createServerResponse(req);
149
- server.emit('request', req, res);
150
154
  }
151
- });
152
155
 
153
- var callback = extractCallback(arguments);
154
- if (callback) {
155
- server.once('listening', callback);
156
+ server.once('error', errorHandler);
157
+ server.originalListen(generateServerSocketPath(), function() {
158
+ server.removeListener('error', errorHandler);
159
+ doneListening(callback);
160
+ process.nextTick(finalizeStartup);
161
+ });
156
162
  }
157
- server.emit('listening');
163
+
164
+ function doneListening(callback) {
165
+ if (callback) {
166
+ server.once('listening', callback);
167
+ }
168
+ server.emit('listening');
169
+ }
170
+
158
171
  return server;
159
172
  } else {
160
173
  throw new Error("http.Server.listen() was called more than once, which " +
@@ -181,9 +194,9 @@ function listenAndMaybeInstall(port) {
181
194
 
182
195
  function finalizeStartup() {
183
196
  process.stdout.write("!> Ready\n");
184
- process.stdout.write("!> socket: main;tcp://127.0.0.1:" +
185
- PhusionPassenger._requestHandler.server.address().port +
186
- ";session;0\n");
197
+ process.stdout.write("!> socket: main;unix:" +
198
+ PhusionPassenger._server.address() +
199
+ ";http_session;0\n");
187
200
  process.stdout.write("!> \n");
188
201
  }
189
202
 
@@ -30,7 +30,7 @@ module PhusionPassenger
30
30
 
31
31
  PACKAGE_NAME = 'passenger'
32
32
  # Run 'rake ext/common/Constants.h' after changing this number.
33
- VERSION_STRING = '4.0.44'
33
+ VERSION_STRING = '4.0.45'
34
34
 
35
35
  PREFERRED_NGINX_VERSION = '1.6.0'
36
36
  NGINX_SHA256_CHECKSUM = '943ad757a1c3e8b3df2d5c4ddacc508861922e36fa10ea6f8e3a348fc9abfc1a'
@@ -173,8 +173,20 @@ APACHE2_DIRECTORY_CONFIGURATION_OPTIONS = [
173
173
  },
174
174
  {
175
175
  :name => 'PassengerStartupFile',
176
+ :type => :string,
177
+ :context => ["OR_ALL"],
178
+ :desc => "Force specific startup file."
179
+ },
180
+ {
181
+ :name => 'PassengerStickySessions',
182
+ :type => :flag,
183
+ :context => ["OR_ALL"],
184
+ :desc => "Whether to enable sticky sessions."
185
+ },
186
+ {
187
+ :name => 'PassengerStickySessionsCookieName',
188
+ :type => :flag,
176
189
  :context => ["OR_ALL"],
177
- :desc => "Force specific startup file.",
178
- :type => :string
190
+ :desc => "The cookie name to use for sticky sessions."
179
191
  }
180
192
  ]
@@ -41,6 +41,7 @@ module PhusionPassenger
41
41
  DEFAULT_START_TIMEOUT = 90_000
42
42
  DEFAULT_WEB_APP_USER = "nobody"
43
43
  DEFAULT_CONCURRENCY_MODEL = "process"
44
+ DEFAULT_STICKY_SESSIONS_COOKIE_NAME = "_passenger_route"
44
45
  DEFAULT_THREAD_COUNT = 1
45
46
  DEFAULT_ANALYTICS_LOG_USER = DEFAULT_WEB_APP_USER
46
47
  DEFAULT_ANALYTICS_LOG_GROUP = ""
@@ -67,12 +68,12 @@ module PhusionPassenger
67
68
  # Misc
68
69
  FEEDBACK_FD = 3
69
70
  PROGRAM_NAME = "Phusion Passenger"
70
- INDEX_DOC_URL = "http://www.modrails.com/documentation/Users%20guide.html"
71
- APACHE2_DOC_URL = "http://www.modrails.com/documentation/Users%20guide%20Apache.html"
72
- NGINX_DOC_URL = "http://www.modrails.com/documentation/Users%20guide%20Nginx.html"
73
- STANDALONE_DOC_URL = "http://www.modrails.com/documentation/Users%20guide%20Standalone.html"
74
- SUPPORT_URL = "http://www.phusionpassenger.com/support"
75
- ENTERPRISE_URL = "http://www.phusionpassenger.com/enterprise"
71
+ INDEX_DOC_URL = "https://www.phusionpassenger.com/documentation/Users%20guide.html"
72
+ APACHE2_DOC_URL = "https://www.phusionpassenger.com/documentation/Users%20guide%20Apache.html"
73
+ NGINX_DOC_URL = "https://www.phusionpassenger.com/documentation/Users%20guide%20Nginx.html"
74
+ STANDALONE_DOC_URL = "https://www.phusionpassenger.com/documentation/Users%20guide%20Standalone.html"
75
+ SUPPORT_URL = "https://www.phusionpassenger.com/documentation_and_support"
76
+ ENTERPRISE_URL = "https://www.phusionpassenger.com/enterprise"
76
77
  DEB_MAIN_PACKAGE = "passenger"
77
78
  DEB_DEV_PACKAGE = "passenger-dev"
78
79
  DEB_APACHE_MODULE_PACKAGE = "libapache2-mod-passenger"
@@ -25,6 +25,7 @@
25
25
  PhusionPassenger.require_passenger_lib 'constants'
26
26
  PhusionPassenger.require_passenger_lib 'public_api'
27
27
  PhusionPassenger.require_passenger_lib 'debug_logging'
28
+ require 'shellwords'
28
29
 
29
30
  module PhusionPassenger
30
31
 
@@ -157,7 +158,16 @@ module LoaderSharedHelpers
157
158
 
158
159
  def dump_system_metrics
159
160
  if dir = ENV['PASSENGER_DEBUG_DIR']
160
- contents = `"#{PhusionPassenger.bin_dir}/passenger-config" system-metrics`
161
+ # When invoked through Passenger Standalone, we want passenger-config
162
+ # to use the HelperAgent in the Passsenger Standalone buildout directory,
163
+ # because the one in the source root may not exist.
164
+ command = [
165
+ "env",
166
+ "PASSENGER_LOCATION_CONFIGURATION_FILE=#{PhusionPassenger.source_root}",
167
+ "#{PhusionPassenger.bin_dir}/passenger-config",
168
+ "system-metrics"
169
+ ]
170
+ contents = `#{Shellwords.join(command)}`
161
171
  if $? && $?.exitstatus == 0
162
172
  File.open("#{dir}/system_metrics", "wb") do |f|
163
173
  f.write(contents)
@@ -274,6 +274,14 @@ LOCATION_CONFIGURATION_OPTIONS = [
274
274
  :name => 'passenger_startup_file',
275
275
  :type => :string
276
276
  },
277
+ {
278
+ :name => 'passenger_sticky_sessions',
279
+ :type => :flag
280
+ },
281
+ {
282
+ :name => 'passenger_sticky_sessions_cookie_name',
283
+ :type => :string
284
+ },
277
285
 
278
286
  ###### Enterprise features ######
279
287
  {
@@ -31,7 +31,7 @@ module Packaging
31
31
  'doc/Users guide Nginx.html',
32
32
  'doc/Users guide Standalone.html',
33
33
  'doc/Security of user switching support.html',
34
- 'doc/Architectural overview.html'
34
+ 'doc/Design and Architecture.html'
35
35
  ]
36
36
 
37
37
  # Files that must be generated before packaging.
@@ -70,6 +70,7 @@ module Packaging
70
70
  '.travis.yml',
71
71
  'configure',
72
72
  'Rakefile',
73
+ 'Vagrantfile',
73
74
  'README.md',
74
75
  'CONTRIBUTORS',
75
76
  'CONTRIBUTING.md',
@@ -77,6 +78,8 @@ module Packaging
77
78
  'CHANGELOG',
78
79
  'INSTALL.md',
79
80
  'NEWS',
81
+ 'package.json',
82
+ 'npm-shrinkwrap.json',
80
83
  'passenger.gemspec',
81
84
  'build/*.rb',
82
85
  'lib/*.rb',
@@ -107,12 +110,13 @@ module Packaging
107
110
  'ext/oxt/*.txt',
108
111
  'ext/oxt/detail/*.hpp',
109
112
  'ext/ruby/*.{c,rb}',
110
- 'dev/*',
113
+ 'dev/**/*',
111
114
  'resources/**/*',
112
115
  'test/.rspec',
113
116
  'test/*.example',
114
117
  'test/*.travis',
115
118
  'test/*.rpm-automation',
119
+ 'test/*.vagrant',
116
120
  'test/*.supp',
117
121
  'test/support/*.{c,cpp,h,rb}',
118
122
  'test/tut/*',
@@ -137,7 +141,8 @@ module Packaging
137
141
 
138
142
  # Files and directories that should be excluded from the Homebrew installation.
139
143
  HOMEBREW_EXCLUDE = [
140
- "dev", "test", ".gitignore", ".travis.yml", "debian.template", "rpm"
144
+ "dev", "test", ".gitignore", ".travis.yml", "debian.template", "rpm",
145
+ "Vagrantfile", "package.json", "npm-shrinkwrap.json"
141
146
  ]
142
147
 
143
148
  def self.files
@@ -239,6 +239,9 @@ module PlatformInfo
239
239
  if config_file = httpd_default_config_file(options)
240
240
  begin
241
241
  contents = File.open(config_file, "rb") { |f| f.read }
242
+ rescue Errno::ENOENT
243
+ log "#{config_file} does not exist"
244
+ return nil
242
245
  rescue Errno::EACCES
243
246
  log "Unable to open #{config_file} for reading"
244
247
  return nil
@@ -227,7 +227,10 @@ module PlatformInfo
227
227
  next if path.nil?
228
228
  path = File.expand_path(path)
229
229
  rubies_path = File.join(path, 'rubies')
230
- if File.directory?(path) && File.directory?(rubies_path)
230
+ wrappers_path = File.join(path, 'wrappers')
231
+ gems_path = File.join(path, 'gems')
232
+ if File.directory?(path) && (File.directory?(rubies_path) ||
233
+ File.directory?(wrappers_path) || File.directory?(gems_path))
231
234
  result << path
232
235
  end
233
236
  end
@@ -119,7 +119,6 @@ private
119
119
  opts.banner = "Usage: passenger #{command_name} [options]"
120
120
  opts.separator description if description
121
121
  opts.separator " "
122
- opts.separator "Options:"
123
122
  yield opts
124
123
  opts.on("-h", "--help", "Show this help message") do
125
124
  help = true
@@ -41,6 +41,7 @@ class PackageRuntimeCommand < Command
41
41
  "Package the Phusion Passenger Standalone runtime into the specified directory.\n" <<
42
42
  "If DIRECTORY is not given then #{destdir} will be used."
43
43
  parse_options!("package [directory]", description) do |opts|
44
+ opts.separator "Options:"
44
45
  opts.on("--nginx-version VERSION", String,
45
46
  wrap_desc("Nginx version to use as core (default: #{@options[:nginx_version]})")) do |value|
46
47
  @options[:nginx_version] = value
@@ -50,7 +50,6 @@ class StartCommand < Command
50
50
 
51
51
  def run
52
52
  parse_my_options
53
- sanity_check_options
54
53
 
55
54
  PhusionPassenger.require_passenger_lib 'standalone/runtime_locator'
56
55
  @runtime_locator = RuntimeLocator.new(@options[:runtime_dir],
@@ -62,6 +61,7 @@ class StartCommand < Command
62
61
  @app_finder = AppFinder.new(@args, @options)
63
62
  @apps = @app_finder.scan
64
63
  @options = @app_finder.global_options
64
+ sanity_check_server_options
65
65
  determine_various_resource_locations
66
66
  @plugin.call_hook(:found_apps, @apps)
67
67
 
@@ -125,6 +125,7 @@ private
125
125
  def parse_my_options
126
126
  description = "Starts Phusion Passenger Standalone and serve one or more Ruby web applications."
127
127
  parse_options!("start [directory]", description) do |opts|
128
+ opts.separator "Server options:"
128
129
  opts.on("-a", "--address HOST", String,
129
130
  wrap_desc("Bind to HOST address (default: #{@options[:address]})")) do |value|
130
131
  @options[:address] = value
@@ -139,8 +140,46 @@ private
139
140
  wrap_desc("Bind to Unix domain socket instead of TCP socket")) do |value|
140
141
  @options[:socket_file] = value
141
142
  end
143
+ opts.on("--ssl",
144
+ wrap_desc("Enable SSL support")) do
145
+ @options[:ssl] = true
146
+ end
147
+ opts.on("--ssl-certificate PATH", String,
148
+ wrap_desc("Specify the SSL certificate path")) do |val|
149
+ @options[:ssl_certificate] = File.expand_path(val)
150
+ end
151
+ opts.on("--ssl-certificate-key PATH", String,
152
+ wrap_desc("Specify the SSL key path")) do |val|
153
+ @options[:ssl_certificate_key] = File.expand_path(val)
154
+ end
155
+ opts.on("--ssl-port PORT", Integer,
156
+ wrap_desc("Listen for SSL on this port, while listening for HTTP on the normal port")) do |val|
157
+ @options[:ssl_port] = val
158
+ end
159
+ opts.on("-d", "--daemonize",
160
+ wrap_desc("Daemonize into the background")) do
161
+ @options[:daemonize] = true
162
+ end
163
+ opts.on("--user USERNAME", String,
164
+ wrap_desc("User to run as. Ignored unless running as root.")) do |value|
165
+ @options[:user] = value
166
+ end
167
+ opts.on("--log-file FILENAME", String,
168
+ wrap_desc("Where to write log messages (default: console, or /dev/null when daemonized)")) do |value|
169
+ @options[:log_file] = value
170
+ end
171
+ opts.on("--pid-file FILENAME", String,
172
+ wrap_desc("Where to store the PID file")) do |value|
173
+ @options[:pid_file] = value
174
+ end
175
+ opts.on("--temp-dir PATH", String,
176
+ wrap_desc("Use the given temp dir")) do |value|
177
+ ENV['TMPDIR'] = value
178
+ @options[:temp_dir] = value
179
+ end
142
180
 
143
181
  opts.separator ""
182
+ opts.separator "Application loading options:"
144
183
  opts.on("-e", "--environment ENV", String,
145
184
  wrap_desc("Framework environment (default: #{@options[:environment]})")) do |value|
146
185
  @options[:environment] = value
@@ -158,6 +197,29 @@ private
158
197
  wrap_desc("Force given startup file to be used")) do |value|
159
198
  @options[:startup_file] = value
160
199
  end
200
+ opts.on("--spawn-method NAME", String,
201
+ wrap_desc("The spawn method to use (default: #{@options[:spawn_method]})")) do |value|
202
+ @options[:spawn_method] = value
203
+ end
204
+ opts.on("--static-files-dir PATH", String,
205
+ wrap_desc("Specify the static files dir")) do |val|
206
+ @options[:static_files_dir] = File.expand_path(val)
207
+ end
208
+ opts.on("--restart-dir PATH", String,
209
+ wrap_desc("Specify the restart dir")) do |val|
210
+ @options[:restart_dir] = File.expand_path(val)
211
+ end
212
+ opts.on("--friendly-error-pages",
213
+ wrap_desc("Turn on friendly error pages")) do
214
+ @options[:friendly_error_pages] = true
215
+ end
216
+ opts.on("--no-friendly-error-pages",
217
+ wrap_desc("Turn off friendly error pages")) do
218
+ @options[:friendly_error_pages] = false
219
+ end
220
+
221
+ opts.separator ""
222
+ opts.separator "Process management options:"
161
223
  opts.on("--max-pool-size NUMBER", Integer,
162
224
  wrap_desc("Maximum number of application processes (default: #{@options[:max_pool_size]})")) do |value|
163
225
  @options[:max_pool_size] = value
@@ -166,10 +228,6 @@ private
166
228
  wrap_desc("Minimum number of processes per application (default: #{@options[:min_instances]})")) do |value|
167
229
  @options[:min_instances] = value
168
230
  end
169
- opts.on("--spawn-method NAME", String,
170
- wrap_desc("The spawn method to use (default: #{@options[:spawn_method]})")) do |value|
171
- @options[:spawn_method] = value
172
- end
173
231
  opts.on("--concurrency-model NAME", String,
174
232
  wrap_desc("The concurrency model to use, either 'process' or 'thread' (default: #{@options[:concurrency_model]}) (Enterprise only)")) do |value|
175
233
  @options[:concurrency_model] = value
@@ -186,38 +244,20 @@ private
186
244
  wrap_desc("Enable deployment error resistance (Enterprise only)")) do
187
245
  @options[:resist_deployment_errors] = true
188
246
  end
189
- opts.on("--friendly-error-pages",
190
- wrap_desc("Turn on friendly error pages")) do
191
- @options[:friendly_error_pages] = true
192
- end
193
- opts.on("--no-friendly-error-pages",
194
- wrap_desc("Turn off friendly error pages")) do
195
- @options[:friendly_error_pages] = false
196
- end
197
- opts.on("--ssl",
198
- wrap_desc("Enable SSL support")) do
199
- @options[:ssl] = true
200
- end
201
- opts.on("--ssl-certificate PATH", String,
202
- wrap_desc("Specify the SSL certificate path")) do |val|
203
- @options[:ssl_certificate] = File.expand_path(val)
204
- end
205
- opts.on("--ssl-certificate-key PATH", String,
206
- wrap_desc("Specify the SSL key path")) do |val|
207
- @options[:ssl_certificate_key] = File.expand_path(val)
208
- end
209
- opts.on("--ssl-port PORT", Integer,
210
- wrap_desc("Listen for SSL on this port, while listening for HTTP on the normal port")) do |val|
211
- @options[:ssl_port] = val
212
- end
213
- opts.on("--static-files-dir PATH", String,
214
- wrap_desc("Specify the static files dir")) do |val|
215
- @options[:static_files_dir] = File.expand_path(val)
247
+
248
+ opts.separator ""
249
+ opts.separator "Request handling options:"
250
+ opts.on("--sticky-sessions",
251
+ wrap_desc("Enable sticky sessions")) do
252
+ @options[:sticky_sessions] = true
216
253
  end
217
- opts.on("--restart-dir PATH", String,
218
- wrap_desc("Specify the restart dir")) do |val|
219
- @options[:restart_dir] = File.expand_path(val)
254
+ opts.on("--sticky-sessions-cookie-name", String,
255
+ wrap_desc("Cookie name to use for sticky sessions (default: #{DEFAULT_STICKY_SESSIONS_COOKIE_NAME})")) do |val|
256
+ @options[:sticky_sessions_cookie_name] = val
220
257
  end
258
+
259
+ opts.separator ""
260
+ opts.separator "Union Station options:"
221
261
  opts.on("--union-station-gateway HOST:PORT", String,
222
262
  wrap_desc("Specify Union Station Gateway host and port")) do |value|
223
263
  host, port = value.split(":", 2)
@@ -232,36 +272,11 @@ private
232
272
  end
233
273
 
234
274
  opts.separator ""
275
+ opts.separator "Advanced options:"
235
276
  opts.on("--ping-port NUMBER", Integer,
236
277
  wrap_desc("Use the given port number for checking whether Nginx is alive (default: same as the normal port)")) do |value|
237
278
  @options[:ping_port] = value
238
279
  end
239
- @plugin.call_hook(:parse_options, opts)
240
-
241
- opts.separator ""
242
- opts.on("-d", "--daemonize",
243
- wrap_desc("Daemonize into the background")) do
244
- @options[:daemonize] = true
245
- end
246
- opts.on("--user USERNAME", String,
247
- wrap_desc("User to run as. Ignored unless running as root.")) do |value|
248
- @options[:user] = value
249
- end
250
- opts.on("--log-file FILENAME", String,
251
- wrap_desc("Where to write log messages (default: console, or /dev/null when daemonized)")) do |value|
252
- @options[:log_file] = value
253
- end
254
- opts.on("--pid-file FILENAME", String,
255
- wrap_desc("Where to store the PID file")) do |value|
256
- @options[:pid_file] = value
257
- end
258
- opts.on("--temp-dir PATH", String,
259
- wrap_desc("Use the given temp dir")) do |value|
260
- ENV['TMPDIR'] = value
261
- @options[:temp_dir] = value
262
- end
263
-
264
- opts.separator ""
265
280
  opts.on("--nginx-bin FILENAME", String,
266
281
  wrap_desc("Nginx binary to use as core")) do |value|
267
282
  @options[:nginx_bin] = value
@@ -300,11 +315,14 @@ private
300
315
  wrap_desc("Abort if runtime must be compiled")) do
301
316
  @options[:dont_compile_runtime] = true
302
317
  end
318
+
319
+ @plugin.call_hook(:parse_options, opts)
320
+ opts.separator ""
303
321
  end
304
322
  @plugin.call_hook(:done_parsing_options)
305
323
  end
306
324
 
307
- def sanity_check_options
325
+ def sanity_check_server_options
308
326
  if @options[:tcp_explicitly_given] && @options[:socket_file]
309
327
  error "You cannot specify both --address/--port and --socket. Please choose either one."
310
328
  exit 1