passenger 5.0.6 → 5.0.7

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 (74) hide show
  1. checksums.yaml +8 -8
  2. checksums.yaml.gz.asc +7 -7
  3. data.tar.gz.asc +7 -7
  4. data/CHANGELOG +26 -0
  5. data/Rakefile +0 -1
  6. data/bin/passenger-install-apache2-module +46 -12
  7. data/bin/passenger-status +6 -3
  8. data/build/packaging.rb +9 -1
  9. data/dev/ci/run_travis.sh +0 -36
  10. data/doc/ServerOptimizationGuide.html +12 -11
  11. data/doc/ServerOptimizationGuide.txt.md +12 -11
  12. data/doc/Users guide Apache.html +81 -75
  13. data/doc/Users guide Apache.idmap.txt +15 -13
  14. data/doc/Users guide Apache.txt +9 -1
  15. data/doc/Users guide Nginx.html +81 -76
  16. data/doc/Users guide Nginx.idmap.txt +15 -13
  17. data/doc/Users guide Nginx.txt +8 -0
  18. data/doc/Users guide Standalone.html +183 -24
  19. data/doc/Users guide Standalone.idmap.txt +19 -11
  20. data/doc/Users guide Standalone.txt +4 -0
  21. data/doc/users_guide_snippets/environment_variables.txt +2 -1
  22. data/doc/users_guide_snippets/installation.txt +15 -2
  23. data/doc/users_guide_snippets/tips.txt +19 -31
  24. data/doc/users_guide_snippets/under_the_hood/relationship_with_ruby.txt +7 -0
  25. data/ext/apache2/ConfigurationCommands.cpp +7 -0
  26. data/ext/apache2/ConfigurationFields.hpp +2 -0
  27. data/ext/apache2/ConfigurationSetters.cpp +8 -0
  28. data/ext/apache2/CreateDirConfig.cpp +1 -0
  29. data/ext/apache2/MergeDirConfig.cpp +7 -0
  30. data/ext/apache2/SetHeaders.cpp +5 -0
  31. data/ext/common/ApplicationPool2/Options.h +9 -0
  32. data/ext/common/Constants.h +3 -1
  33. data/ext/common/Logging.cpp +2 -2
  34. data/ext/common/ServerKit/HttpHeaderParser.h +13 -1
  35. data/ext/common/ServerKit/Implementation.cpp +7 -1
  36. data/ext/common/agents/Base.cpp +1 -1
  37. data/ext/common/agents/HelperAgent/OptionParser.h +15 -0
  38. data/ext/common/agents/HelperAgent/RequestHandler.h +3 -1
  39. data/ext/common/agents/HelperAgent/RequestHandler/BufferBody.cpp +3 -3
  40. data/ext/common/agents/HelperAgent/RequestHandler/InitRequest.cpp +12 -1
  41. data/ext/common/agents/HelperAgent/RequestHandler/Utils.cpp +7 -3
  42. data/ext/common/agents/HelperAgent/ResponseCache.h +7 -1
  43. data/ext/common/agents/LoggingAgent/Main.cpp +4 -1
  44. data/ext/nginx/CacheLocationConfig.c +20 -0
  45. data/ext/nginx/Configuration.c +7 -0
  46. data/ext/nginx/ConfigurationCommands.c +10 -0
  47. data/ext/nginx/ConfigurationFields.h +2 -0
  48. data/ext/nginx/ContentHandler.c +10 -0
  49. data/ext/nginx/CreateLocationConfig.c +5 -0
  50. data/ext/nginx/MergeLocationConfig.c +6 -0
  51. data/helper-scripts/meteor-loader.rb +15 -2
  52. data/helper-scripts/rack-loader.rb +2 -6
  53. data/helper-scripts/rack-preloader.rb +1 -5
  54. data/lib/phusion_passenger.rb +3 -3
  55. data/lib/phusion_passenger/apache2/config_options.rb +5 -0
  56. data/lib/phusion_passenger/config/command.rb +9 -0
  57. data/lib/phusion_passenger/config/install_standalone_runtime_command.rb +4 -0
  58. data/lib/phusion_passenger/config/validate_install_command.rb +478 -46
  59. data/lib/phusion_passenger/constants.rb +1 -0
  60. data/lib/phusion_passenger/loader_shared_helpers.rb +26 -3
  61. data/lib/phusion_passenger/nginx/config_options.rb +4 -0
  62. data/lib/phusion_passenger/packaging.rb +0 -8
  63. data/lib/phusion_passenger/platform_info/apache.rb +40 -28
  64. data/lib/phusion_passenger/platform_info/apache_detector.rb +29 -3
  65. data/lib/phusion_passenger/rack/thread_handler_extension.rb +12 -7
  66. data/lib/phusion_passenger/request_handler/thread_handler.rb +5 -0
  67. data/lib/phusion_passenger/standalone/start_command.rb +46 -5
  68. data/lib/phusion_passenger/standalone/start_command/builtin_engine.rb +5 -3
  69. data/resources/templates/apache2/config_snippets.txt.erb +1 -1
  70. data/resources/templates/apache2/run_installer_as_root_for_apache_analysis.txt.erb +9 -0
  71. data/resources/templates/standalone/config.erb +16 -1
  72. metadata +3 -3
  73. metadata.gz.asc +7 -7
  74. data/build/debian.rb +0 -213
@@ -157,42 +157,30 @@ Phusion Passenger automatically leverages operating system virtual memory copy-o
157
157
  - MRI Ruby >= 2.0. Versions prior to 2.0 did not have a copy-on-write friendly garbage collector.
158
158
  - http://www.rubyenterpriseedition.com/[Ruby Enterprise Edition], which was Phusion's branch of MRI Ruby 1.8 with a copy-on-write friendly garbage collector and other enhancement. It has reached End-Of-Life as of 2012, but remains available for legacy systems.
159
159
 
160
+ [[tuning_sse_websockets]]
161
+ === Tuning for Server Sent Events and WebSockets ===
160
162
 
161
- [[capistrano]]
162
- === Capistrano recipe ===
163
+ Phusion Passenger supports Server Sent Events (SSE) and WebSockets out of the box with no configuration, but there are some things you need to know.
163
164
 
164
- Phusion Passenger can be combined with link:http://capify.org/[Capistrano].
165
- The following Capistrano recipe demonstrates Phusion Passenger support.
166
- It assumes that you're using Git as version control system.
165
+ First, WebSockets are link:https://github.com/phusion/passenger/issues/1202[not yet supported when using the Apache integration mode].
167
166
 
168
- --------------------------------------------------
169
- set :application, "myapp"
170
- set :domain, "example.com"
171
- set :repository, "ssh://#{domain}/path-to-your-git-repo/#{application}.git"
172
- set :use_sudo, false
173
- set :deploy_to, "/path-to-your-web-app-directory/#{application}"
174
- set :scm, "git"
175
-
176
- role :app, domain
177
- role :web, domain
178
- role :db, domain, :primary => true
179
-
180
- namespace :deploy do
181
- task :start, :roles => :app do
182
- run "touch #{current_release}/tmp/restart.txt"
183
- end
184
-
185
- task :stop, :roles => :app do
186
- # Do nothing.
187
- end
188
-
189
- desc "Restart Application"
190
- task :restart, :roles => :app do
191
- run "touch #{current_release}/tmp/restart.txt"
192
- end
167
+ Second, for Ruby apps only, you need to insert a configuration snippet inside your `config.ru`:
168
+
169
+ [code,ruby]
170
+ ----------------------------------------------------------
171
+ if defined?(PhusionPassenger)
172
+ PhusionPassenger.advertised_concurrency_level = 0
193
173
  end
194
- --------------------------------------------------
174
+ ----------------------------------------------------------
175
+
176
+ [NOTE]
177
+ ==========================================================
178
+ This snippet tells Passenger that your Ruby app will handle SSE and WebSockets. In response, Passenger will adjust the connection concurrency settings for your app. Without this configuration snippet, SSE and WebSockets still work, but with degraded performance.
179
+
180
+ This configuration snippet is currently necessary because of the way Passenger is implemented. We are link:https://github.com/phusion/passenger/issues/1195[working on improving this mechanism]. One day, the above configuration snippet will no longer be necessary. For now, you should include the above configuration snippet for optimal SSE and WebSocket performance.
181
+ ==========================================================
195
182
 
183
+ Finally, you can find Passenger SSE and WebSocket demo apps on link:https://www.phusionpassenger.com/documentation_and_support[the Passenger documentation overview page], under section "Demos".
196
184
 
197
185
  [[bundler_support]]
198
186
  === Bundler support ===
@@ -13,6 +13,10 @@ endif::[]
13
13
  ifdef::nginx[]
14
14
  <<PassengerPreStart,passenger_pre_start>>)
15
15
  endif::[]
16
+ ifdef::standalone[]
17
+ <<PassengerPreStart,passenger_pre_start>>)
18
+ endif::[]
19
+
16
20
  are written in Ruby as well.
17
21
  * Ruby web application support is implemented in Ruby.
18
22
  * If you use <<flying_passenger,Flying Passenger>>, then the Flying Passenger daemon is written in Ruby. The daemon is a small (less than 500 lines of code) and offloads most tasks to the C++ core.
@@ -33,6 +37,9 @@ endif::[]
33
37
  ifdef::nginx[]
34
38
  <<PassengerRuby,passenger_ruby>>
35
39
  endif::[]
40
+ ifdef::standalone[]
41
+ <<PassengerRuby,passenger_ruby>>
42
+ endif::[]
36
43
  directive to learn how run different web applications under different Ruby interpreters.
37
44
 
38
45
  .Caveat: RVM and RVM gemsets
@@ -61,6 +61,13 @@
61
61
  "The Node.js command to use."),
62
62
 
63
63
 
64
+ AP_INIT_TAKE1("PassengerMeteorAppSettings",
65
+ (Take1Func) cmd_passenger_meteor_app_settings,
66
+ NULL,
67
+ OR_OPTIONS | ACCESS_CONF | RSRC_CONF,
68
+ "Settings file for (non-bundled) Meteor apps."),
69
+
70
+
64
71
  AP_INIT_TAKE1("PassengerAppEnv",
65
72
  (Take1Func) cmd_passenger_app_env,
66
73
  NULL,
@@ -76,6 +76,8 @@
76
76
  const char *appType;
77
77
  /** The group that Ruby applications must run as. */
78
78
  const char *group;
79
+ /** Settings file for (non-bundled) Meteor apps. */
80
+ const char *meteorAppSettings;
79
81
  /** The Node.js command to use. */
80
82
  const char *nodejs;
81
83
  /** The Python interpreter to use. */
@@ -63,6 +63,14 @@
63
63
  }
64
64
 
65
65
 
66
+ static const char *
67
+ cmd_passenger_meteor_app_settings(cmd_parms *cmd, void *pcfg, const char *arg) {
68
+ DirConfig *config = (DirConfig *) pcfg;
69
+ config->meteorAppSettings = arg;
70
+ return NULL;
71
+ }
72
+
73
+
66
74
  static const char *
67
75
  cmd_passenger_app_env(cmd_parms *cmd, void *pcfg, const char *arg) {
68
76
  DirConfig *config = (DirConfig *) pcfg;
@@ -41,6 +41,7 @@
41
41
  config->ruby = NULL;
42
42
  config->python = NULL;
43
43
  config->nodejs = NULL;
44
+ config->meteorAppSettings = NULL;
44
45
  config->appEnv = NULL;
45
46
  config->minInstances = UNSET_INT_VALUE;
46
47
  config->maxInstancesPerApp = UNSET_INT_VALUE;
@@ -61,6 +61,13 @@
61
61
 
62
62
 
63
63
 
64
+ config->meteorAppSettings =
65
+ (add->meteorAppSettings == NULL) ?
66
+ base->meteorAppSettings :
67
+ add->meteorAppSettings;
68
+
69
+
70
+
64
71
  config->appEnv =
65
72
  (add->appEnv == NULL) ?
66
73
  base->appEnv :
@@ -55,6 +55,11 @@
55
55
 
56
56
 
57
57
 
58
+ addHeader(result, StaticString("!~PASSENGER_METEOR_APP_SETTINGS",
59
+ sizeof("!~PASSENGER_METEOR_APP_SETTINGS") - 1), config->meteorAppSettings);
60
+
61
+
62
+
58
63
  addHeader(result, StaticString("!~PASSENGER_APP_ENV",
59
64
  sizeof("!~PASSENGER_APP_ENV") - 1), config->appEnv);
60
65
 
@@ -105,6 +105,8 @@ private:
105
105
  result.push_back(&options.ruby);
106
106
  result.push_back(&options.python);
107
107
  result.push_back(&options.nodejs);
108
+ result.push_back(&options.meteorAppSettings);
109
+
108
110
  result.push_back(&options.environmentVariables);
109
111
  result.push_back(&options.loggingAgentAddress);
110
112
  result.push_back(&options.loggingAgentUsername);
@@ -260,6 +262,12 @@ public:
260
262
  */
261
263
  StaticString nodejs;
262
264
 
265
+ /**
266
+ * When running meteor in non-bundled mode, settings for the application need to be specified
267
+ * via --settings (instead of through the METEOR_SETTINGS environment variable),
268
+ */
269
+ StaticString meteorAppSettings;
270
+
263
271
  /**
264
272
  * Any rights that the spawned application process may have. The SpawnManager
265
273
  * will create a new account for each spawned app, and that account will be
@@ -588,6 +596,7 @@ public:
588
596
  appendKeyValue (vec, "ruby", ruby);
589
597
  appendKeyValue (vec, "python", python);
590
598
  appendKeyValue (vec, "nodejs", nodejs);
599
+ appendKeyValue (vec, "meteor_app_settings", meteorAppSettings);
591
600
  appendKeyValue (vec, "logging_agent_address", loggingAgentAddress);
592
601
  appendKeyValue (vec, "logging_agent_username", loggingAgentUsername);
593
602
  appendKeyValue (vec, "logging_agent_password", loggingAgentPassword);
@@ -114,7 +114,7 @@
114
114
 
115
115
  #define NGINX_DOC_URL "https://www.phusionpassenger.com/documentation/Users%20guide%20Nginx.html"
116
116
 
117
- #define PASSENGER_VERSION "5.0.6"
117
+ #define PASSENGER_VERSION "5.0.7"
118
118
 
119
119
  #define POOL_HELPER_THREAD_STACK_SIZE 262144
120
120
 
@@ -140,6 +140,8 @@
140
140
 
141
141
  #define SERVER_TOKEN_NAME "Phusion_Passenger"
142
142
 
143
+ #define SHORT_PROGRAM_NAME "Passenger"
144
+
143
145
  #define STANDALONE_DOC_URL "https://www.phusionpassenger.com/documentation/Users%20guide%20Standalone.html"
144
146
 
145
147
  #define STANDALONE_NGINX_CONFIGURE_OPTIONS "--with-cc-opt='-Wno-error' --without-http_fastcgi_module --without-http_scgi_module --without-http_uwsgi_module --with-http_gzip_static_module --with-http_stub_status_module --with-http_ssl_module"
@@ -130,10 +130,10 @@ _prepareLogEntry(FastStringStream<> &sstream, const char *file, unsigned int lin
130
130
  gettimeofday(&tv, NULL);
131
131
  localtime_r(&tv.tv_sec, &the_tm);
132
132
  datetime_size = snprintf(datetime_buf, sizeof(datetime_buf),
133
- "%d-%02d-%02d %02d:%02d:%02d.%04u",
133
+ "%d-%02d-%02d %02d:%02d:%02d.%04llu",
134
134
  the_tm.tm_year + 1900, the_tm.tm_mon + 1, the_tm.tm_mday,
135
135
  the_tm.tm_hour, the_tm.tm_min, the_tm.tm_sec,
136
- tv.tv_usec / 100);
136
+ (unsigned long long) tv.tv_usec / 100);
137
137
  sstream <<
138
138
  "[ " << StaticString(datetime_buf, datetime_size) <<
139
139
  " " << std::dec << getpid() << "/" <<
@@ -1,6 +1,6 @@
1
1
  /*
2
2
  * Phusion Passenger - https://www.phusionpassenger.com/
3
- * Copyright (c) 2014 Phusion
3
+ * Copyright (c) 2014-2015 Phusion
4
4
  *
5
5
  * "Phusion Passenger" is a trademark of Hongli Lai & Ninh Bui.
6
6
  *
@@ -44,6 +44,10 @@ namespace Passenger {
44
44
  namespace ServerKit {
45
45
 
46
46
 
47
+ extern const HashedStaticString HTTP_CONTENT_LENGTH;
48
+ extern const HashedStaticString HTTP_X_SENDFILE;
49
+ extern const HashedStaticString HTTP_X_ACCEL_REDIRECT;
50
+
47
51
  struct HttpParseRequest {};
48
52
  struct HttpParseResponse {};
49
53
 
@@ -366,6 +370,14 @@ private:
366
370
  message->httpState = Message::ONEHUNDRED_CONTINUE;
367
371
  }
368
372
  message->bodyType = Message::RBT_NO_BODY;
373
+ } else if (message->headers.lookup(HTTP_X_SENDFILE) != NULL
374
+ || message->headers.lookup(HTTP_X_ACCEL_REDIRECT) != NULL)
375
+ {
376
+ // Ignore Content-Length when X-Sendfile or X-Accel-Redirect is set.
377
+ // See https://github.com/phusion/passenger/issues/1376
378
+ message->httpState = Message::COMPLETE;
379
+ message->bodyType = Message::RBT_NO_BODY;
380
+ message->headers.erase(HTTP_CONTENT_LENGTH);
369
381
  } else if (state->parser.flags & F_CHUNKED) {
370
382
  if (contentLength == std::numeric_limits<boost::uint64_t>::max()) {
371
383
  message->httpState = Message::PARSING_CHUNKED_BODY;
@@ -1,6 +1,6 @@
1
1
  /*
2
2
  * Phusion Passenger - https://www.phusionpassenger.com/
3
- * Copyright (c) 2014 Phusion
3
+ * Copyright (c) 2014-2015 Phusion
4
4
  *
5
5
  * "Phusion Passenger" is a trademark of Hongli Lai & Ninh Bui.
6
6
  *
@@ -31,6 +31,9 @@ namespace ServerKit {
31
31
  // Define 'extern' so that the compiler doesn't output warnings.
32
32
  extern const HashedStaticString HTTP_COOKIE;
33
33
  extern const HashedStaticString HTTP_SET_COOKIE;
34
+ extern const HashedStaticString HTTP_CONTENT_LENGTH;
35
+ extern const HashedStaticString HTTP_X_SENDFILE;
36
+ extern const HashedStaticString HTTP_X_ACCEL_REDIRECT;
34
37
  extern const char DEFAULT_INTERNAL_SERVER_ERROR_RESPONSE[];
35
38
  extern const unsigned int DEFAULT_INTERNAL_SERVER_ERROR_RESPONSE_SIZE;
36
39
 
@@ -45,6 +48,9 @@ const unsigned int DEFAULT_INTERNAL_SERVER_ERROR_RESPONSE_SIZE =
45
48
  sizeof(DEFAULT_INTERNAL_SERVER_ERROR_RESPONSE) - 1;
46
49
  const HashedStaticString HTTP_COOKIE("cookie");
47
50
  const HashedStaticString HTTP_SET_COOKIE("set-cookie");
51
+ const HashedStaticString HTTP_CONTENT_LENGTH("content-length");
52
+ const HashedStaticString HTTP_X_SENDFILE("x-sendfile");
53
+ const HashedStaticString HTTP_X_ACCEL_REDIRECT("x-accel-redirect");
48
54
 
49
55
 
50
56
  } // namespace ServerKit
@@ -96,7 +96,7 @@ static bool _feedbackFdAvailable = false;
96
96
  static const char digits[] = {
97
97
  '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'
98
98
  };
99
- static const char hex_chars[] = "01234567890abcdef";
99
+ static const char hex_chars[] = "0123456789abcdef";
100
100
 
101
101
  static bool shouldDumpWithCrashWatch = true;
102
102
  static bool beepOnAbort = false;
@@ -41,6 +41,7 @@ using namespace std;
41
41
 
42
42
  inline void
43
43
  serverUsage() {
44
+ // ....|---------------Keep output within standard terminal width (80 chars)------------|
44
45
  printf("Usage: " AGENT_EXE " server <OPTIONS...> [APP DIRECTORY]\n");
45
46
  printf("Runs the " PROGRAM_NAME " standalone HTTP server agent.\n");
46
47
  printf("\n");
@@ -110,6 +111,11 @@ serverUsage() {
110
111
  printf(" Force friendly error pages to be always off\n");
111
112
  printf("\n");
112
113
  printf(" --ruby PATH Default Ruby interpreter to use.\n");
114
+ printf(" --nodejs PATH Default NodeJs interpreter to use.\n");
115
+ printf(" --python PATH Default Python interpreter to use.\n");
116
+ printf(" --meteor-app-settings PATH\n");
117
+ printf(" File with settings for a Meteor (non-bundled) app.\n");
118
+ printf(" (passed to Meteor using --settings)\n");
113
119
  printf(" --debugger Enable Ruby debugger support (Enterprise only)\n");
114
120
  printf("\n");
115
121
  printf(" --rolling-restarts Enable rolling restarts (Enterprise only)\n");
@@ -294,6 +300,15 @@ parseServerOption(int argc, const char *argv[], int &i, VariantMap &options) {
294
300
  } else if (p.isValueFlag(argc, i, argv[i], '\0', "--ruby")) {
295
301
  options.set("default_ruby", argv[i + 1]);
296
302
  i += 2;
303
+ } else if (p.isValueFlag(argc, i, argv[i], '\0', "--nodejs")) {
304
+ options.set("default_nodejs", argv[i + 1]);
305
+ i += 2;
306
+ } else if (p.isValueFlag(argc, i, argv[i], '\0', "--python")) {
307
+ options.set("default_python", argv[i + 1]);
308
+ i += 2;
309
+ } else if (p.isValueFlag(argc, i, argv[i], '\0', "--meteor-app-settings")) {
310
+ options.set("meteor_app_settings", argv[i + 1]);
311
+ i += 2;
297
312
  } else if (p.isFlag(argv[i], '\0', "--debugger")) {
298
313
  options.setBool("debugger", true);
299
314
  i++;
@@ -131,6 +131,7 @@ private:
131
131
  StaticString defaultVaryTurbocacheByCookie;
132
132
 
133
133
  HashedStaticString PASSENGER_APP_GROUP_NAME;
134
+ HashedStaticString PASSENGER_ENV_VARS;
134
135
  HashedStaticString PASSENGER_MAX_REQUESTS;
135
136
  HashedStaticString PASSENGER_STICKY_SESSIONS;
136
137
  HashedStaticString PASSENGER_STICKY_SESSIONS_COOKIE_NAME;
@@ -195,6 +196,7 @@ public:
195
196
  poolOptionsCache(4),
196
197
 
197
198
  PASSENGER_APP_GROUP_NAME("!~PASSENGER_APP_GROUP_NAME"),
199
+ PASSENGER_ENV_VARS("!~PASSENGER_ENV_VARS"),
198
200
  PASSENGER_MAX_REQUESTS("!~PASSENGER_MAX_REQUESTS"),
199
201
  PASSENGER_STICKY_SESSIONS("!~PASSENGER_STICKY_SESSIONS"),
200
202
  PASSENGER_STICKY_SESSIONS_COOKIE_NAME("!~PASSENGER_STICKY_SESSIONS_COOKIE_NAME"),
@@ -431,7 +433,7 @@ public:
431
433
  }
432
434
  }
433
435
 
434
- if (req->session != NULL || resp->httpState != AppResponse::PARSING_HEADERS) {
436
+ if (req->appResponseInitialized) {
435
437
  doc["app_response_http_state"] = resp->getHttpStateString();
436
438
  doc["app_response_http_major"] = resp->httpMajor;
437
439
  doc["app_response_http_minor"] = resp->httpMinor;
@@ -60,13 +60,13 @@ whenBufferingBody_onRequestBody(Client *client, Request *req,
60
60
  // The data that we've stored in the body buffer is dechunked, so when forwarding
61
61
  // the buffered body to the app we must advertise it as being a fixed-length,
62
62
  // non-chunked body.
63
+ const unsigned int UINT64_STRSIZE = sizeof("18446744073709551615");
63
64
  SKC_TRACE(client, 2, "Adjusting forwarding headers as fixed-length, non-chunked");
64
65
  ServerKit::Header *header = (ServerKit::Header *)
65
66
  psg_palloc(req->pool, sizeof(ServerKit::Header));
66
- char *contentLength = (char *) psg_pnalloc(req->pool,
67
- sizeof("18446744073709551615"));
67
+ char *contentLength = (char *) psg_pnalloc(req->pool, UINT64_STRSIZE);
68
68
  unsigned int size = integerToOtherBase<boost::uint64_t, 10>(
69
- req->bodyBytesBuffered, contentLength, sizeof(contentLength));
69
+ req->bodyBytesBuffered, contentLength, UINT64_STRSIZE);
70
70
 
71
71
  psg_lstr_init(&header->key);
72
72
  psg_lstr_append(&header->key, req->pool, "content-length",
@@ -200,6 +200,7 @@ initializePoolOptions(Client *client, Request *req, RequestAnalysis &analysis) {
200
200
  }
201
201
 
202
202
  if (!req->ended()) {
203
+ fillPoolOption(req, req->options.environmentVariables, PASSENGER_ENV_VARS);
203
204
  fillPoolOption(req, req->options.maxRequests, PASSENGER_MAX_REQUESTS);
204
205
  }
205
206
  }
@@ -207,6 +208,16 @@ initializePoolOptions(Client *client, Request *req, RequestAnalysis &analysis) {
207
208
  void
208
209
  fillPoolOptionsFromAgentsOptions(Options &options) {
209
210
  options.ruby = defaultRuby;
211
+ if (agentsOptions->has("default_nodejs")) {
212
+ options.nodejs = agentsOptions->get("default_nodejs");
213
+ }
214
+ if (agentsOptions->has("default_python")) {
215
+ options.python = agentsOptions->get("default_python");
216
+ }
217
+ if (agentsOptions->has("meteor_app_settings")) {
218
+ options.meteorAppSettings = agentsOptions->get("meteor_app_settings");
219
+ }
220
+
210
221
  options.logLevel = getLogLevel();
211
222
  options.loggingAgentAddress = loggingAgentAddress;
212
223
  options.loggingAgentUsername = P_STATIC_STRING("logging");
@@ -350,6 +361,7 @@ createNewPoolOptions(Client *client, Request *req, const HashedStaticString &app
350
361
  fillPoolOption(req, options.ruby, "!~PASSENGER_RUBY");
351
362
  fillPoolOption(req, options.python, "!~PASSENGER_PYTHON");
352
363
  fillPoolOption(req, options.nodejs, "!~PASSENGER_NODEJS");
364
+ fillPoolOption(req, options.meteorAppSettings, "!~PASSENGER_METEOR_APP_SETTINGS");
353
365
  fillPoolOption(req, options.user, "!~PASSENGER_USER");
354
366
  fillPoolOption(req, options.group, "!~PASSENGER_GROUP");
355
367
  fillPoolOption(req, options.minProcesses, "!~PASSENGER_MIN_PROCESSES");
@@ -362,7 +374,6 @@ createNewPoolOptions(Client *client, Request *req, const HashedStaticString &app
362
374
  fillPoolOption(req, options.restartDir, "!~PASSENGER_RESTART_DIR");
363
375
  fillPoolOption(req, options.startupFile, "!~PASSENGER_STARTUP_FILE");
364
376
  fillPoolOption(req, options.loadShellEnvvars, "!~PASSENGER_LOAD_SHELL_ENVVARS");
365
- fillPoolOption(req, options.environmentVariables, "!~PASSENGER_ENV_VARS");
366
377
  fillPoolOption(req, options.raiseInternalError, "!~PASSENGER_RAISE_INTERNAL_ERROR");
367
378
  /******************/
368
379
 
@@ -192,10 +192,10 @@ gatherBuffers(char * restrict dest, unsigned int size, const struct iovec *buffe
192
192
  // `path` MUST be NULL-terminated. Returns a contiguous LString.
193
193
  static LString *
194
194
  resolveSymlink(const StaticString &path, psg_pool_t *pool) {
195
- char linkbuf[PATH_MAX];
195
+ char linkbuf[PATH_MAX + 1];
196
196
  ssize_t size;
197
197
 
198
- size = readlink(path.data(), linkbuf, sizeof(linkbuf) - 1);
198
+ size = readlink(path.data(), linkbuf, PATH_MAX);
199
199
  if (size == -1) {
200
200
  if (errno == EINVAL) {
201
201
  return psg_lstr_create(pool, path);
@@ -215,7 +215,11 @@ resolveSymlink(const StaticString &path, psg_pool_t *pool) {
215
215
  throw FileSystemException(message, ENOENT, path.data());
216
216
  } else if (linkbuf[0] == '/') {
217
217
  // Symlink points to an absolute path.
218
- return psg_lstr_create(pool, linkbuf, strlen(linkbuf));
218
+ size_t len = strlen(linkbuf);
219
+ char *data = (char *) psg_pnalloc(pool, len + 1);
220
+ memcpy(data, linkbuf, len);
221
+ data[len] = '\0';
222
+ return psg_lstr_create(pool, data, len);
219
223
  } else {
220
224
  // Symlink points to a relative path.
221
225
  // We do not use absolutizePath() because it's too slow.
@@ -130,6 +130,8 @@ private:
130
130
  HashedStaticString AUTHORIZATION;
131
131
  HashedStaticString VARY;
132
132
  HashedStaticString WWW_AUTHENTICATE;
133
+ HashedStaticString X_SENDFILE;
134
+ HashedStaticString X_ACCEL_REDIRECT;
133
135
  HashedStaticString EXPIRES;
134
136
  HashedStaticString LAST_MODIFIED;
135
137
  HashedStaticString LOCATION;
@@ -412,6 +414,8 @@ public:
412
414
  AUTHORIZATION("authorization"),
413
415
  VARY("vary"),
414
416
  WWW_AUTHENTICATE("www-authenticate"),
417
+ X_SENDFILE("x-sendfile"),
418
+ X_ACCEL_REDIRECT("x-accel-redirect"),
415
419
  EXPIRES("expires"),
416
420
  LAST_MODIFIED("last-modified"),
417
421
  LOCATION("location"),
@@ -591,7 +595,9 @@ public:
591
595
 
592
596
  if (req->headers.lookup(AUTHORIZATION) != NULL
593
597
  || respHeaders.lookup(VARY) != NULL
594
- || respHeaders.lookup(WWW_AUTHENTICATE) != NULL)
598
+ || respHeaders.lookup(WWW_AUTHENTICATE) != NULL
599
+ || respHeaders.lookup(X_SENDFILE) != NULL
600
+ || respHeaders.lookup(X_ACCEL_REDIRECT) != NULL)
595
601
  {
596
602
  return false;
597
603
  }