passenger 5.0.21 → 5.0.22

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 (203) hide show
  1. checksums.yaml +8 -8
  2. checksums.yaml.gz.asc +7 -7
  3. data.tar.gz.asc +7 -7
  4. data/CHANGELOG +38 -2
  5. data/CONTRIBUTORS +3 -0
  6. data/README.md +5 -1
  7. data/bin/passenger-status +2 -7
  8. data/build/agent.rb +2 -0
  9. data/build/cxx_dependency_map.rb +1464 -162
  10. data/build/node_tests.rb +1 -1
  11. data/build/packaging.rb +1 -1
  12. data/dev/ci/run_travis.sh +1 -1
  13. data/dev/vagrant/provision.sh +1 -1
  14. data/npm-shrinkwrap.json +635 -125
  15. data/package.json +1 -1
  16. data/resources/templates/standalone/config.erb +33 -161
  17. data/resources/templates/standalone/global.erb +15 -0
  18. data/resources/templates/standalone/http.erb +40 -0
  19. data/resources/templates/standalone/mass_deployment_default_server.erb +11 -0
  20. data/resources/templates/standalone/rails_asset_pipeline.erb +22 -0
  21. data/resources/templates/standalone/server.erb +58 -0
  22. data/src/agent/Core/ApiServer.h +37 -32
  23. data/src/agent/Core/ApplicationPool/BasicGroupInfo.h +1 -1
  24. data/src/agent/Core/ApplicationPool/BasicProcessInfo.h +6 -0
  25. data/src/agent/Core/ApplicationPool/Common.h +1 -1
  26. data/src/agent/Core/ApplicationPool/Group/OutOfBandWork.cpp +1 -1
  27. data/src/agent/Core/ApplicationPool/Group/ProcessListManagement.cpp +4 -0
  28. data/src/agent/Core/ApplicationPool/Implementation.cpp +2 -2
  29. data/src/agent/Core/ApplicationPool/Options.h +18 -1
  30. data/src/agent/Core/ApplicationPool/Pool.h +1 -1
  31. data/src/agent/Core/ApplicationPool/Pool/AnalyticsCollection.cpp +6 -6
  32. data/src/agent/Core/ApplicationPool/Pool/GeneralUtils.cpp +3 -3
  33. data/src/agent/Core/ApplicationPool/Pool/InitializationAndShutdown.cpp +1 -1
  34. data/src/agent/Core/ApplicationPool/Pool/Miscellaneous.cpp +6 -0
  35. data/src/agent/Core/ApplicationPool/Process.h +6 -1
  36. data/src/agent/Core/ApplicationPool/Socket.h +9 -12
  37. data/src/agent/Core/Controller.h +422 -0
  38. data/src/agent/Core/{RequestHandler → Controller}/AppResponse.h +2 -0
  39. data/src/agent/Core/{RequestHandler → Controller}/BufferBody.cpp +27 -5
  40. data/src/agent/Core/{RequestHandler → Controller}/CheckoutSession.cpp +61 -31
  41. data/src/agent/Core/{RequestHandler → Controller}/Client.h +5 -2
  42. data/src/agent/Core/{RequestHandler → Controller}/ForwardResponse.cpp +93 -42
  43. data/src/agent/Core/{RequestHandler → Controller}/Hooks.cpp +107 -60
  44. data/src/agent/Core/Controller/Implementation.cpp +38 -0
  45. data/src/agent/Core/{RequestHandler → Controller}/InitRequest.cpp +134 -80
  46. data/src/agent/Core/Controller/InitializationAndShutdown.cpp +165 -0
  47. data/src/agent/Core/{RequestHandler/Utils.cpp → Controller/InternalUtils.cpp} +49 -32
  48. data/src/agent/Core/Controller/Miscellaneous.cpp +116 -0
  49. data/src/agent/Core/{RequestHandler → Controller}/Request.h +6 -4
  50. data/src/agent/Core/{RequestHandler → Controller}/SendRequest.cpp +205 -130
  51. data/src/agent/Core/Controller/StateInspectionAndConfiguration.cpp +161 -0
  52. data/src/agent/Core/{RequestHandler → Controller}/TurboCaching.h +3 -0
  53. data/src/agent/Core/CoreMain.cpp +62 -51
  54. data/src/agent/Core/OptionParser.h +24 -0
  55. data/src/agent/Core/ResponseCache.h +5 -5
  56. data/src/agent/Core/SpawningKit/Config.h +2 -2
  57. data/src/agent/Core/SpawningKit/SmartSpawner.h +1 -1
  58. data/src/agent/Core/UnionStation/{Core.h → Context.h} +14 -18
  59. data/src/agent/Core/UnionStation/StopwatchLog.h +3 -2
  60. data/src/agent/Core/UnionStation/Transaction.h +7 -7
  61. data/src/agent/Shared/ApiServerUtils.h +9 -1
  62. data/src/agent/UstRouter/ApiServer.h +5 -2
  63. data/src/agent/UstRouter/Controller.h +27 -9
  64. data/src/agent/UstRouter/UstRouterMain.cpp +1 -0
  65. data/src/agent/Watchdog/ApiServer.h +5 -2
  66. data/src/apache2_module/ConfigurationCommands.cpp +7 -0
  67. data/src/apache2_module/ConfigurationFields.hpp +2 -0
  68. data/src/apache2_module/ConfigurationSetters.cpp +24 -0
  69. data/src/apache2_module/CreateDirConfig.cpp +1 -0
  70. data/src/apache2_module/Hooks.cpp +6 -5
  71. data/src/apache2_module/MergeDirConfig.cpp +7 -0
  72. data/src/apache2_module/SetHeaders.cpp +5 -0
  73. data/src/cxx_supportlib/Constants.h +5 -3
  74. data/src/cxx_supportlib/SafeLibev.h +2 -1
  75. data/src/cxx_supportlib/UnionStationFilterSupport.h +2 -1
  76. data/src/cxx_supportlib/Utils/ReleaseableScopedPointer.h +70 -0
  77. data/src/cxx_supportlib/vendor-modified/boost/libs/regex/src/regex_raw_buffer.cpp +6 -6
  78. data/src/helper-scripts/node-loader.js +59 -0
  79. data/src/nginx_module/CacheLocationConfig.c +48 -0
  80. data/src/nginx_module/ConfigurationCommands.c +20 -0
  81. data/src/nginx_module/ConfigurationFields.h +4 -0
  82. data/src/nginx_module/CreateLocationConfig.c +8 -0
  83. data/src/nginx_module/MergeLocationConfig.c +12 -0
  84. data/src/nodejs_supportlib/phusion_passenger/log_express.js +106 -0
  85. data/src/nodejs_supportlib/phusion_passenger/log_mongodb.js +203 -0
  86. data/src/nodejs_supportlib/phusion_passenger/ustreporter.js +227 -0
  87. data/src/nodejs_supportlib/phusion_passenger/ustrouter_connector.js +446 -0
  88. data/src/nodejs_supportlib/vendor-copy/codify/codify.js +44 -0
  89. data/src/nodejs_supportlib/vendor-copy/codify/package.json +29 -0
  90. data/src/nodejs_supportlib/vendor-copy/continuation-local-storage/context.js +200 -0
  91. data/src/nodejs_supportlib/vendor-copy/continuation-local-storage/node_modules/async-listener/glue.js +488 -0
  92. data/src/nodejs_supportlib/vendor-copy/continuation-local-storage/node_modules/async-listener/index.js +407 -0
  93. data/src/nodejs_supportlib/vendor-copy/continuation-local-storage/node_modules/async-listener/node_modules/shimmer/index.js +90 -0
  94. data/src/nodejs_supportlib/vendor-copy/continuation-local-storage/node_modules/async-listener/node_modules/shimmer/package.json +40 -0
  95. data/src/nodejs_supportlib/vendor-copy/continuation-local-storage/node_modules/async-listener/package.json +54 -0
  96. data/src/nodejs_supportlib/vendor-copy/continuation-local-storage/node_modules/emitter-listener/listener.js +160 -0
  97. data/src/nodejs_supportlib/vendor-copy/continuation-local-storage/node_modules/emitter-listener/node_modules/shimmer/index.js +90 -0
  98. data/src/nodejs_supportlib/vendor-copy/continuation-local-storage/node_modules/emitter-listener/node_modules/shimmer/package.json +40 -0
  99. data/src/nodejs_supportlib/vendor-copy/continuation-local-storage/node_modules/emitter-listener/package.json +46 -0
  100. data/src/nodejs_supportlib/vendor-copy/continuation-local-storage/package.json +56 -0
  101. data/src/nodejs_supportlib/vendor-copy/network-byte-order/lib/index.js +102 -0
  102. data/src/nodejs_supportlib/vendor-copy/network-byte-order/package.json +51 -0
  103. data/src/nodejs_supportlib/vendor-copy/winston/LICENSE +19 -0
  104. data/src/nodejs_supportlib/vendor-copy/winston/lib/winston.js +165 -0
  105. data/src/nodejs_supportlib/vendor-copy/winston/lib/winston/common.js +483 -0
  106. data/src/nodejs_supportlib/vendor-copy/winston/lib/winston/config.js +62 -0
  107. data/src/nodejs_supportlib/vendor-copy/winston/lib/winston/config/cli-config.js +35 -0
  108. data/src/nodejs_supportlib/vendor-copy/winston/lib/winston/config/npm-config.js +27 -0
  109. data/src/nodejs_supportlib/vendor-copy/winston/lib/winston/config/syslog-config.js +31 -0
  110. data/src/nodejs_supportlib/vendor-copy/winston/lib/winston/container.js +127 -0
  111. data/src/nodejs_supportlib/vendor-copy/winston/lib/winston/exception.js +56 -0
  112. data/src/nodejs_supportlib/vendor-copy/winston/lib/winston/logger.js +701 -0
  113. data/src/nodejs_supportlib/vendor-copy/winston/lib/winston/transports.js +34 -0
  114. data/src/nodejs_supportlib/vendor-copy/winston/lib/winston/transports/console.js +128 -0
  115. data/src/nodejs_supportlib/vendor-copy/winston/lib/winston/transports/daily-rotate-file.js +601 -0
  116. data/src/nodejs_supportlib/vendor-copy/winston/lib/winston/transports/file.js +675 -0
  117. data/src/nodejs_supportlib/vendor-copy/winston/lib/winston/transports/http.js +232 -0
  118. data/src/nodejs_supportlib/vendor-copy/winston/lib/winston/transports/memory.js +89 -0
  119. data/src/nodejs_supportlib/vendor-copy/winston/lib/winston/transports/transport.js +135 -0
  120. data/src/nodejs_supportlib/vendor-copy/winston/lib/winston/transports/webhook.js +146 -0
  121. data/src/nodejs_supportlib/vendor-copy/winston/node_modules/async/LICENSE +19 -0
  122. data/src/nodejs_supportlib/vendor-copy/winston/node_modules/async/lib/async.js +1283 -0
  123. data/src/nodejs_supportlib/vendor-copy/winston/node_modules/async/package.json +66 -0
  124. data/src/nodejs_supportlib/vendor-copy/winston/node_modules/async/support/sync-package-managers.js +53 -0
  125. data/src/nodejs_supportlib/vendor-copy/winston/node_modules/colors/MIT-LICENSE.txt +23 -0
  126. data/src/nodejs_supportlib/vendor-copy/winston/node_modules/colors/lib/colors.js +176 -0
  127. data/src/nodejs_supportlib/vendor-copy/winston/node_modules/colors/lib/custom/trap.js +45 -0
  128. data/src/nodejs_supportlib/vendor-copy/winston/node_modules/colors/lib/custom/zalgo.js +104 -0
  129. data/src/nodejs_supportlib/vendor-copy/winston/node_modules/colors/lib/extendStringPrototype.js +118 -0
  130. data/src/nodejs_supportlib/vendor-copy/winston/node_modules/colors/lib/index.js +12 -0
  131. data/src/nodejs_supportlib/vendor-copy/winston/node_modules/colors/lib/maps/america.js +12 -0
  132. data/src/nodejs_supportlib/vendor-copy/winston/node_modules/colors/lib/maps/rainbow.js +13 -0
  133. data/src/nodejs_supportlib/vendor-copy/winston/node_modules/colors/lib/maps/random.js +8 -0
  134. data/src/nodejs_supportlib/vendor-copy/winston/node_modules/colors/lib/maps/zebra.js +5 -0
  135. data/src/nodejs_supportlib/vendor-copy/winston/node_modules/colors/lib/styles.js +77 -0
  136. data/src/nodejs_supportlib/vendor-copy/winston/node_modules/colors/lib/system/supports-colors.js +61 -0
  137. data/src/nodejs_supportlib/vendor-copy/winston/node_modules/colors/package.json +35 -0
  138. data/src/nodejs_supportlib/vendor-copy/winston/node_modules/colors/safe.js +9 -0
  139. data/src/nodejs_supportlib/vendor-copy/winston/node_modules/colors/themes/generic-logging.js +12 -0
  140. data/src/nodejs_supportlib/vendor-copy/winston/node_modules/cycle/cycle.js +170 -0
  141. data/src/nodejs_supportlib/vendor-copy/winston/node_modules/cycle/package.json +30 -0
  142. data/src/nodejs_supportlib/vendor-copy/winston/node_modules/eyes/LICENSE +20 -0
  143. data/src/nodejs_supportlib/vendor-copy/winston/node_modules/eyes/lib/eyes.js +236 -0
  144. data/src/nodejs_supportlib/vendor-copy/winston/node_modules/eyes/package.json +42 -0
  145. data/src/nodejs_supportlib/vendor-copy/winston/node_modules/isstream/LICENSE.md +11 -0
  146. data/src/nodejs_supportlib/vendor-copy/winston/node_modules/isstream/isstream.js +27 -0
  147. data/src/nodejs_supportlib/vendor-copy/winston/node_modules/isstream/package.json +42 -0
  148. data/src/nodejs_supportlib/vendor-copy/winston/node_modules/pkginfo/LICENSE +19 -0
  149. data/src/nodejs_supportlib/vendor-copy/winston/node_modules/pkginfo/lib/pkginfo.js +136 -0
  150. data/src/nodejs_supportlib/vendor-copy/winston/node_modules/pkginfo/package.json +56 -0
  151. data/src/nodejs_supportlib/vendor-copy/winston/node_modules/stack-trace/License +19 -0
  152. data/src/nodejs_supportlib/vendor-copy/winston/node_modules/stack-trace/lib/stack-trace.js +111 -0
  153. data/src/nodejs_supportlib/vendor-copy/winston/node_modules/stack-trace/package.json +33 -0
  154. data/src/nodejs_supportlib/vendor-copy/winston/package.json +87 -0
  155. data/src/ruby_supportlib/phusion_passenger.rb +3 -4
  156. data/src/ruby_supportlib/phusion_passenger/admin_tools/instance.rb +19 -2
  157. data/src/ruby_supportlib/phusion_passenger/apache2/config_options.rb +8 -0
  158. data/src/ruby_supportlib/phusion_passenger/config/list_instances_command.rb +2 -6
  159. data/src/ruby_supportlib/phusion_passenger/config/reopen_logs_command.rb +13 -0
  160. data/src/ruby_supportlib/phusion_passenger/config/restart_app_command.rb +3 -0
  161. data/src/ruby_supportlib/phusion_passenger/config/utils.rb +9 -7
  162. data/src/ruby_supportlib/phusion_passenger/config/validate_install_command.rb +8 -1
  163. data/src/ruby_supportlib/phusion_passenger/constants.rb +3 -1
  164. data/src/ruby_supportlib/phusion_passenger/native_support.rb +20 -4
  165. data/src/ruby_supportlib/phusion_passenger/nginx/config_options.rb +8 -0
  166. data/src/ruby_supportlib/phusion_passenger/packaging.rb +1 -0
  167. data/src/ruby_supportlib/phusion_passenger/platform_info/apache_detector.rb +1 -1
  168. data/src/ruby_supportlib/phusion_passenger/platform_info/operating_system.rb +11 -4
  169. data/src/ruby_supportlib/phusion_passenger/rack/thread_handler_extension.rb +1 -1
  170. data/src/ruby_supportlib/phusion_passenger/standalone/config_options_list.rb +647 -0
  171. data/src/ruby_supportlib/phusion_passenger/standalone/config_utils.rb +229 -15
  172. data/src/ruby_supportlib/phusion_passenger/standalone/start_command.rb +35 -323
  173. data/src/ruby_supportlib/phusion_passenger/standalone/start_command/builtin_engine.rb +36 -12
  174. data/src/ruby_supportlib/phusion_passenger/standalone/start_command/nginx_engine.rb +123 -14
  175. data/src/ruby_supportlib/phusion_passenger/standalone/status_command.rb +32 -17
  176. data/src/ruby_supportlib/phusion_passenger/standalone/stop_command.rb +32 -21
  177. data/src/ruby_supportlib/phusion_passenger/standalone/version_command.rb +5 -5
  178. data/src/ruby_supportlib/phusion_passenger/vendor/union_station_hooks_core/README.md +2 -2
  179. data/src/ruby_supportlib/phusion_passenger/vendor/union_station_hooks_core/Rakefile +5 -1
  180. data/src/ruby_supportlib/phusion_passenger/vendor/union_station_hooks_core/lib/union_station_hooks_core.rb +68 -24
  181. data/src/ruby_supportlib/phusion_passenger/vendor/union_station_hooks_core/lib/union_station_hooks_core/api.rb +9 -1
  182. data/src/ruby_supportlib/phusion_passenger/vendor/union_station_hooks_core/lib/union_station_hooks_core/context.rb +9 -7
  183. data/src/ruby_supportlib/phusion_passenger/vendor/union_station_hooks_core/lib/union_station_hooks_core/request_reporter.rb +3 -2
  184. data/src/ruby_supportlib/phusion_passenger/vendor/union_station_hooks_core/lib/union_station_hooks_core/request_reporter/basics.rb +8 -5
  185. data/src/ruby_supportlib/phusion_passenger/vendor/union_station_hooks_core/lib/union_station_hooks_core/simple_json.rb +395 -0
  186. data/src/ruby_supportlib/phusion_passenger/vendor/union_station_hooks_core/lib/union_station_hooks_core/transaction.rb +10 -7
  187. data/src/ruby_supportlib/phusion_passenger/vendor/union_station_hooks_core/lib/union_station_hooks_core/utils.rb +14 -0
  188. data/src/ruby_supportlib/phusion_passenger/vendor/union_station_hooks_core/lib/union_station_hooks_core/version_data.rb +2 -2
  189. data/src/ruby_supportlib/phusion_passenger/vendor/union_station_hooks_core/ruby_versions.yml +4 -2
  190. data/src/ruby_supportlib/phusion_passenger/vendor/union_station_hooks_core/ruby_versions.yml.example +2 -2
  191. data/src/ruby_supportlib/phusion_passenger/vendor/union_station_hooks_core/ruby_versions.yml.travis +2 -2
  192. data/src/ruby_supportlib/phusion_passenger/vendor/union_station_hooks_core/ruby_versions.yml.travis-with-sudo +16 -0
  193. data/src/ruby_supportlib/phusion_passenger/vendor/union_station_hooks_rails/Gemfile +1 -1
  194. data/src/ruby_supportlib/phusion_passenger/vendor/union_station_hooks_rails/Gemfile.lock +2 -2
  195. data/src/ruby_supportlib/phusion_passenger/vendor/union_station_hooks_rails/README.md +1 -1
  196. data/src/ruby_supportlib/phusion_passenger/vendor/union_station_hooks_rails/lib/union_station_hooks_rails.rb +44 -17
  197. data/src/ruby_supportlib/phusion_passenger/vendor/union_station_hooks_rails/lib/union_station_hooks_rails/active_support_cache_subscriber.rb +16 -7
  198. data/src/ruby_supportlib/phusion_passenger/vendor/union_station_hooks_rails/lib/union_station_hooks_rails/version_data.rb +2 -2
  199. data/src/ruby_supportlib/phusion_passenger/vendor/union_station_hooks_rails/union_station_hooks_rails.gemspec +1 -1
  200. metadata +99 -16
  201. metadata.gz.asc +7 -7
  202. data/resources/oss-binaries.phusionpassenger.com.crt +0 -248
  203. data/src/agent/Core/RequestHandler.h +0 -471
@@ -23,37 +23,78 @@
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 <Core/Controller.h>
26
27
 
27
- // This file is included inside the RequestHandler class.
28
+ /*************************************************************************
29
+ *
30
+ * Hook functions for Core::Controller. This pertains the hooks that the
31
+ * parent classes (ServerKit::HttpServer and ServerKit::Server) provide,
32
+ * as well as hooks by libraries such as libev.
33
+ *
34
+ *************************************************************************/
28
35
 
29
- public:
36
+ namespace Passenger {
37
+ namespace Core {
30
38
 
31
- virtual unsigned int getClientName(const Client *client, char *buf, size_t size) const {
32
- char *pos = buf;
33
- const char *end = buf + size - 1;
34
- // WARNING: If you change the format, be sure to change
35
- // ApiServer::extractThreadNumberFromClientName() too.
36
- pos += uintToString(threadNumber, pos, end - pos);
37
- pos = appendData(pos, end, "-", 1);
38
- pos += uintToString(client->number, pos, end - pos);
39
- *pos = '\0';
40
- return pos - buf;
39
+ using namespace std;
40
+ using namespace boost;
41
+
42
+
43
+ /****************************
44
+ *
45
+ * Private methods
46
+ *
47
+ ****************************/
48
+
49
+
50
+ ServerKit::Channel::Result
51
+ Controller::onBodyBufferData(Channel *_channel, const MemoryKit::mbuf &buffer, int errcode) {
52
+ FileBufferedChannel *channel = reinterpret_cast<FileBufferedChannel *>(_channel);
53
+ Request *req = static_cast<Request *>(static_cast<
54
+ ServerKit::BaseHttpRequest *>(channel->getHooks()->userData));
55
+ Client *client = static_cast<Client *>(req->client);
56
+ Controller *self = static_cast<Controller *>(getServerFromClient(client));
57
+ SKC_LOG_EVENT_FROM_STATIC(self, Controller, client, "onBodyBufferData");
58
+
59
+ assert(req->requestBodyBuffering);
60
+ return self->whenSendingRequest_onRequestBody(client, req, buffer, errcode);
41
61
  }
42
62
 
43
- virtual StaticString getServerName() const {
44
- return serverLogName;
63
+ #ifdef DEBUG_CC_EVENT_LOOP_BLOCKING
64
+ void
65
+ Controller::onEventLoopPrepare(EV_P_ struct ev_prepare *w, int revents) {
66
+ Controller *self = static_cast<Controller *>(w->data);
67
+ ev_now_update(EV_A);
68
+ self->timeBeforeBlocking = ev_now(EV_A);
69
+ }
70
+ #endif
71
+
72
+ void
73
+ Controller::onEventLoopCheck(EV_P_ struct ev_check *w, int revents) {
74
+ Controller *self = static_cast<Controller *>(w->data);
75
+ self->turboCaching.updateState(ev_now(EV_A));
76
+ #ifdef DEBUG_CC_EVENT_LOOP_BLOCKING
77
+ self->reportLargeTimeDiff(NULL, "Event loop slept",
78
+ self->timeBeforeBlocking, ev_now(EV_A));
79
+ #endif
45
80
  }
46
81
 
47
- protected:
48
82
 
49
- virtual void
50
- onClientAccepted(Client *client) {
83
+ /****************************
84
+ *
85
+ * Protected methods
86
+ *
87
+ ****************************/
88
+
89
+
90
+ void
91
+ Controller::onClientAccepted(Client *client) {
51
92
  ParentClass::onClientAccepted(client);
52
93
  client->connectedAt = ev_now(getLoop());
53
94
  }
54
95
 
55
- virtual void
56
- onRequestObjectCreated(Client *client, Request *req) {
96
+ void
97
+ Controller::onRequestObjectCreated(Client *client, Request *req) {
57
98
  ParentClass::onRequestObjectCreated(client, req);
58
99
 
59
100
  req->appSink.setContext(getContext());
@@ -68,17 +109,19 @@ onRequestObjectCreated(Client *client, Request *req) {
68
109
  req->bodyBuffer.setDataCallback(onBodyBufferData);
69
110
  }
70
111
 
71
- virtual void deinitializeClient(Client *client) {
112
+ void
113
+ Controller::deinitializeClient(Client *client) {
72
114
  ParentClass::deinitializeClient(client);
73
115
  client->output.setBuffersFlushedCallback(NULL);
74
116
  client->output.setDataFlushedCallback(getClientOutputDataFlushedCallback());
75
117
  }
76
118
 
77
- virtual void reinitializeRequest(Client *client, Request *req) {
119
+ void
120
+ Controller::reinitializeRequest(Client *client, Request *req) {
78
121
  ParentClass::reinitializeRequest(client, req);
79
122
 
80
- // bodyBuffer is initialized in RequestHandler::beginBufferingBody().
81
- // appSink and appSource are initialized in RequestHandler::checkoutSession().
123
+ // bodyBuffer is initialized in Controller::beginBufferingBody().
124
+ // appSink and appSource are initialized in Controller::checkoutSession().
82
125
 
83
126
  req->startedAt = 0;
84
127
  req->state = Request::ANALYZING_REQUEST;
@@ -98,7 +141,7 @@ virtual void reinitializeRequest(Client *client, Request *req) {
98
141
  req->varyCookie = NULL;
99
142
  req->envvars = NULL;
100
143
 
101
- #ifdef DEBUG_RH_EVENT_LOOP_BLOCKING
144
+ #ifdef DEBUG_CC_EVENT_LOOP_BLOCKING
102
145
  req->timedAppPoolGet = false;
103
146
  req->timeBeforeAccessingApplicationPool = 0;
104
147
  req->timeOnRequestHeaderSent = 0;
@@ -108,12 +151,13 @@ virtual void reinitializeRequest(Client *client, Request *req) {
108
151
  /***************/
109
152
  }
110
153
 
111
- virtual void deinitializeRequest(Client *client, Request *req) {
154
+ void
155
+ Controller::deinitializeRequest(Client *client, Request *req) {
112
156
  req->session.reset();
113
157
 
114
- req->endStopwatchLog(&req->stopwatchLogs.requestProxying, false);
115
158
  req->endStopwatchLog(&req->stopwatchLogs.getFromPool, false);
116
159
  req->endStopwatchLog(&req->stopwatchLogs.bufferingRequestBody, false);
160
+ req->endStopwatchLog(&req->stopwatchLogs.requestProxying, false);
117
161
  req->endStopwatchLog(&req->stopwatchLogs.requestProcessing, false);
118
162
 
119
163
  req->options.transaction.reset();
@@ -133,7 +177,8 @@ virtual void deinitializeRequest(Client *client, Request *req) {
133
177
  ParentClass::deinitializeRequest(client, req);
134
178
  }
135
179
 
136
- void reinitializeAppResponse(Client *client, Request *req) {
180
+ void
181
+ Controller::reinitializeAppResponse(Client *client, Request *req) {
137
182
  AppResponse *resp = &req->appResponse;
138
183
 
139
184
  req->appResponseInitialized = true;
@@ -160,7 +205,8 @@ void reinitializeAppResponse(Client *client, Request *req) {
160
205
  psg_lstr_init(&resp->bodyCacheBuffer);
161
206
  }
162
207
 
163
- void deinitializeAppResponse(Client *client, Request *req) {
208
+ void
209
+ Controller::deinitializeAppResponse(Client *client, Request *req) {
164
210
  AppResponse *resp = &req->appResponse;
165
211
 
166
212
  req->appResponseInitialized = false;
@@ -197,8 +243,8 @@ void deinitializeAppResponse(Client *client, Request *req) {
197
243
  psg_lstr_deinit(&resp->bodyCacheBuffer);
198
244
  }
199
245
 
200
- virtual Channel::Result
201
- onRequestBody(Client *client, Request *req, const MemoryKit::mbuf &buffer,
246
+ ServerKit::Channel::Result
247
+ Controller::onRequestBody(Client *client, Request *req, const MemoryKit::mbuf &buffer,
202
248
  int errcode)
203
249
  {
204
250
  switch (req->state) {
@@ -212,41 +258,42 @@ onRequestBody(Client *client, Request *req, const MemoryKit::mbuf &buffer,
212
258
  }
213
259
  }
214
260
 
215
- virtual bool
216
- shouldDisconnectClientOnShutdown(Client *client) {
261
+ bool
262
+ Controller::shouldDisconnectClientOnShutdown(Client *client) {
217
263
  return ParentClass::shouldDisconnectClientOnShutdown(client) || !gracefulExit;
218
264
  }
219
265
 
220
- private:
266
+ bool
267
+ Controller::supportsUpgrade(Client *client, Request *req) {
268
+ return true;
269
+ }
221
270
 
222
- static Channel::Result
223
- onBodyBufferData(Channel *_channel, const MemoryKit::mbuf &buffer, int errcode) {
224
- FileBufferedChannel *channel = reinterpret_cast<FileBufferedChannel *>(_channel);
225
- Request *req = static_cast<Request *>(static_cast<
226
- ServerKit::BaseHttpRequest *>(channel->getHooks()->userData));
227
- Client *client = static_cast<Client *>(req->client);
228
- RequestHandler *self = static_cast<RequestHandler *>(getServerFromClient(client));
229
- SKC_LOG_EVENT_FROM_STATIC(self, RequestHandler, client, "onBodyBufferData");
230
271
 
231
- assert(req->requestBodyBuffering);
232
- return self->whenSendingRequest_onRequestBody(client, req, buffer, errcode);
233
- }
272
+ /****************************
273
+ *
274
+ * Public methods
275
+ *
276
+ ****************************/
234
277
 
235
- #ifdef DEBUG_RH_EVENT_LOOP_BLOCKING
236
- static void
237
- onEventLoopPrepare(EV_P_ struct ev_prepare *w, int revents) {
238
- RequestHandler *self = static_cast<RequestHandler *>(w->data);
239
- ev_now_update(EV_A);
240
- self->timeBeforeBlocking = ev_now(EV_A);
241
- }
242
- #endif
243
278
 
244
- static void
245
- onEventLoopCheck(EV_P_ struct ev_check *w, int revents) {
246
- RequestHandler *self = static_cast<RequestHandler *>(w->data);
247
- self->turboCaching.updateState(ev_now(EV_A));
248
- #ifdef DEBUG_RH_EVENT_LOOP_BLOCKING
249
- self->reportLargeTimeDiff(NULL, "Event loop slept",
250
- self->timeBeforeBlocking, ev_now(EV_A));
251
- #endif
279
+ unsigned int
280
+ Controller::getClientName(const Client *client, char *buf, size_t size) const {
281
+ char *pos = buf;
282
+ const char *end = buf + size - 1;
283
+ // WARNING: If you change the format, be sure to change
284
+ // ApiServer::extractThreadNumberFromClientName() too.
285
+ pos += uintToString(threadNumber, pos, end - pos);
286
+ pos = appendData(pos, end, "-", 1);
287
+ pos += uintToString(client->number, pos, end - pos);
288
+ *pos = '\0';
289
+ return pos - buf;
252
290
  }
291
+
292
+ StaticString
293
+ Controller::getServerName() const {
294
+ return serverLogName;
295
+ }
296
+
297
+
298
+ } // namespace Core
299
+ } // namespace Passenger
@@ -0,0 +1,38 @@
1
+ /*
2
+ * Phusion Passenger - https://www.phusionpassenger.com/
3
+ * Copyright (c) 2015 Phusion Holding B.V.
4
+ *
5
+ * "Passenger", "Phusion Passenger" and "Union Station" are registered
6
+ * trademarks of Phusion Holding B.V.
7
+ *
8
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
9
+ * of this software and associated documentation files (the "Software"), to deal
10
+ * in the Software without restriction, including without limitation the rights
11
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12
+ * copies of the Software, and to permit persons to whom the Software is
13
+ * furnished to do so, subject to the following conditions:
14
+ *
15
+ * The above copyright notice and this permission notice shall be included in
16
+ * all copies or substantial portions of the Software.
17
+ *
18
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24
+ * THE SOFTWARE.
25
+ */
26
+
27
+ #include <Core/Controller.h>
28
+ #include <Core/Controller/InitRequest.cpp>
29
+ #include <Core/Controller/BufferBody.cpp>
30
+ #include <Core/Controller/CheckoutSession.cpp>
31
+ #include <Core/Controller/SendRequest.cpp>
32
+ #include <Core/Controller/ForwardResponse.cpp>
33
+ #include <Core/Controller/Hooks.cpp>
34
+ #include <Core/Controller/InitializationAndShutdown.cpp>
35
+ #include <Core/Controller/InternalUtils.cpp>
36
+ #include <Core/Controller/Miscellaneous.cpp>
37
+ #include <Core/Controller/StateInspectionAndConfiguration.cpp>
38
+
@@ -23,76 +23,38 @@
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 <Core/Controller.h>
26
27
 
27
- // This file is included inside the RequestHandler class.
28
-
29
- protected:
28
+ /*************************************************************************
29
+ *
30
+ * Implements Core::Controller methods pertaining the initialization
31
+ * of a request.
32
+ *
33
+ *************************************************************************/
30
34
 
31
- struct RequestAnalysis {
32
- const LString *flags;
33
- ServerKit::HeaderTable::Cell *appGroupNameCell;
34
- bool unionStationSupport;
35
- };
35
+ namespace Passenger {
36
+ namespace Core {
36
37
 
37
- virtual void
38
- onRequestBegin(Client *client, Request *req) {
39
- ParentClass::onRequestBegin(client, req);
38
+ using namespace std;
39
+ using namespace boost;
40
40
 
41
- RH_BENCHMARK_POINT(client, req, BM_AFTER_ACCEPT);
42
41
 
43
- {
44
- // Perform hash table operations as close to header parsing as possible,
45
- // and localize them as much as possible, for better CPU caching.
46
- RequestAnalysis analysis;
47
- analysis.flags = req->secureHeaders.lookup(FLAGS);
48
- analysis.appGroupNameCell = singleAppMode
49
- ? NULL
50
- : req->secureHeaders.lookupCell(PASSENGER_APP_GROUP_NAME);
51
- analysis.unionStationSupport = unionStationCore != NULL
52
- && getBoolOption(req, UNION_STATION_SUPPORT, false);
53
- req->stickySession = getBoolOption(req, PASSENGER_STICKY_SESSIONS,
54
- this->stickySessions);
55
- req->host = req->headers.lookup(HTTP_HOST);
56
-
57
- /***************/
58
- /***************/
59
-
60
- SKC_TRACE(client, 2, "Initiating request");
61
- req->startedAt = ev_now(getLoop());
62
- req->bodyChannel.stop();
63
-
64
- initializeFlags(client, req, analysis);
65
- if (respondFromTurboCache(client, req)) {
66
- return;
67
- }
68
- initializePoolOptions(client, req, analysis);
69
- if (req->ended()) {
70
- return;
71
- }
72
- initializeUnionStation(client, req, analysis);
73
- if (req->ended()) {
74
- return;
75
- }
76
- setStickySessionId(client, req);
77
- }
42
+ /****************************
43
+ *
44
+ * Private methods
45
+ *
46
+ ****************************/
78
47
 
79
- if (!req->hasBody() || !req->requestBodyBuffering) {
80
- req->requestBodyBuffering = false;
81
- checkoutSession(client, req);
82
- } else {
83
- beginBufferingBody(client, req);
84
- }
85
- }
86
48
 
87
- virtual bool
88
- supportsUpgrade(Client *client, Request *req) {
89
- return true;
90
- }
49
+ struct Controller::RequestAnalysis {
50
+ const LString *flags;
51
+ ServerKit::HeaderTable::Cell *appGroupNameCell;
52
+ bool unionStationSupport;
53
+ };
91
54
 
92
- private:
93
55
 
94
56
  void
95
- initializeFlags(Client *client, Request *req, RequestAnalysis &analysis) {
57
+ Controller::initializeFlags(Client *client, Request *req, RequestAnalysis &analysis) {
96
58
  if (analysis.flags != NULL) {
97
59
  const LString::Part *part = analysis.flags->start;
98
60
  while (part != NULL) {
@@ -138,7 +100,7 @@ initializeFlags(Client *client, Request *req, RequestAnalysis &analysis) {
138
100
  }
139
101
 
140
102
  bool
141
- respondFromTurboCache(Client *client, Request *req) {
103
+ Controller::respondFromTurboCache(Client *client, Request *req) {
142
104
  if (!turboCaching.isEnabled() || !turboCaching.responseCache.prepareRequest(this, req)) {
143
105
  return false;
144
106
  }
@@ -171,7 +133,7 @@ respondFromTurboCache(Client *client, Request *req) {
171
133
  }
172
134
 
173
135
  void
174
- initializePoolOptions(Client *client, Request *req, RequestAnalysis &analysis) {
136
+ Controller::initializePoolOptions(Client *client, Request *req, RequestAnalysis &analysis) {
175
137
  boost::shared_ptr<Options> *options;
176
138
 
177
139
  if (singleAppMode) {
@@ -215,7 +177,7 @@ initializePoolOptions(Client *client, Request *req, RequestAnalysis &analysis) {
215
177
  }
216
178
 
217
179
  void
218
- fillPoolOptionsFromAgentsOptions(Options &options) {
180
+ Controller::fillPoolOptionsFromAgentsOptions(Options &options) {
219
181
  options.ruby = defaultRuby;
220
182
  if (agentsOptions->has("default_nodejs")) {
221
183
  options.nodejs = agentsOptions->get("default_nodejs");
@@ -242,6 +204,9 @@ fillPoolOptionsFromAgentsOptions(Options &options) {
242
204
  }
243
205
  options.minProcesses = agentsOptions->getInt("min_instances");
244
206
  options.maxPreloaderIdleTime = agentsOptions->getInt("max_preloader_idle_time");
207
+ options.maxRequestQueueSize = agentsOptions->getInt("max_request_queue_size");
208
+ options.abortWebsocketsOnProcessShutdown = agentsOptions->getBool("abort_websockets_on_process_shutdown");
209
+ options.forceMaxConcurrentRequestsPerProcess = agentsOptions->getInt("force_max_concurrent_requests_per_process");
245
210
  options.spawnMethod = agentsOptions->get("spawn_method");
246
211
  options.loadShellEnvvars = agentsOptions->getBool("load_shell_envvars");
247
212
  options.statThrottleRate = statThrottleRate;
@@ -249,8 +214,10 @@ fillPoolOptionsFromAgentsOptions(Options &options) {
249
214
  /******************************/
250
215
  }
251
216
 
252
- static void
253
- fillPoolOption(Request *req, StaticString &field, const HashedStaticString &name) {
217
+ void
218
+ Controller::fillPoolOption(Request *req, StaticString &field,
219
+ const HashedStaticString &name)
220
+ {
254
221
  const LString *value = req->secureHeaders.lookup(name);
255
222
  if (value != NULL && value->size > 0) {
256
223
  value = psg_lstr_make_contiguous(value, req->pool);
@@ -258,16 +225,31 @@ fillPoolOption(Request *req, StaticString &field, const HashedStaticString &name
258
225
  }
259
226
  }
260
227
 
261
- static void
262
- fillPoolOption(Request *req, bool &field, const HashedStaticString &name) {
228
+ void
229
+ Controller::fillPoolOption(Request *req, bool &field,
230
+ const HashedStaticString &name)
231
+ {
263
232
  const LString *value = req->secureHeaders.lookup(name);
264
233
  if (value != NULL && value->size > 0) {
265
234
  field = psg_lstr_first_byte(value) == 't';
266
235
  }
267
236
  }
268
237
 
269
- static void
270
- fillPoolOption(Request *req, unsigned int &field, const HashedStaticString &name) {
238
+ void
239
+ Controller::fillPoolOption(Request *req, int &field,
240
+ const HashedStaticString &name)
241
+ {
242
+ const LString *value = req->secureHeaders.lookup(name);
243
+ if (value != NULL && value->size > 0) {
244
+ value = psg_lstr_make_contiguous(value, req->pool);
245
+ field = stringToInt(StaticString(value->start->data, value->size));
246
+ }
247
+ }
248
+
249
+ void
250
+ Controller::fillPoolOption(Request *req, unsigned int &field,
251
+ const HashedStaticString &name)
252
+ {
271
253
  const LString *value = req->secureHeaders.lookup(name);
272
254
  if (value != NULL && value->size > 0) {
273
255
  value = psg_lstr_make_contiguous(value, req->pool);
@@ -275,8 +257,10 @@ fillPoolOption(Request *req, unsigned int &field, const HashedStaticString &name
275
257
  }
276
258
  }
277
259
 
278
- static void
279
- fillPoolOption(Request *req, unsigned long &field, const HashedStaticString &name) {
260
+ void
261
+ Controller::fillPoolOption(Request *req, unsigned long &field,
262
+ const HashedStaticString &name)
263
+ {
280
264
  const LString *value = req->secureHeaders.lookup(name);
281
265
  if (value != NULL && value->size > 0) {
282
266
  value = psg_lstr_make_contiguous(value, req->pool);
@@ -284,8 +268,10 @@ fillPoolOption(Request *req, unsigned long &field, const HashedStaticString &nam
284
268
  }
285
269
  }
286
270
 
287
- static void
288
- fillPoolOption(Request *req, long &field, const HashedStaticString &name) {
271
+ void
272
+ Controller::fillPoolOption(Request *req, long &field,
273
+ const HashedStaticString &name)
274
+ {
289
275
  const LString *value = req->secureHeaders.lookup(name);
290
276
  if (value != NULL && value->size > 0) {
291
277
  value = psg_lstr_make_contiguous(value, req->pool);
@@ -293,8 +279,10 @@ fillPoolOption(Request *req, long &field, const HashedStaticString &name) {
293
279
  }
294
280
  }
295
281
 
296
- static void
297
- fillPoolOptionSecToMsec(Request *req, unsigned int &field, const HashedStaticString &name) {
282
+ void
283
+ Controller::fillPoolOptionSecToMsec(Request *req, unsigned int &field,
284
+ const HashedStaticString &name)
285
+ {
298
286
  const LString *value = req->secureHeaders.lookup(name);
299
287
  if (value != NULL && value->size > 0) {
300
288
  value = psg_lstr_make_contiguous(value, req->pool);
@@ -303,7 +291,9 @@ fillPoolOptionSecToMsec(Request *req, unsigned int &field, const HashedStaticStr
303
291
  }
304
292
 
305
293
  void
306
- createNewPoolOptions(Client *client, Request *req, const HashedStaticString &appGroupName) {
294
+ Controller::createNewPoolOptions(Client *client, Request *req,
295
+ const HashedStaticString &appGroupName)
296
+ {
307
297
  ServerKit::HeaderTable &secureHeaders = req->secureHeaders;
308
298
  Options &options = req->options;
309
299
 
@@ -383,6 +373,8 @@ createNewPoolOptions(Client *client, Request *req, const HashedStaticString &app
383
373
  fillPoolOptionSecToMsec(req, options.startTimeout, "!~PASSENGER_START_TIMEOUT");
384
374
  fillPoolOption(req, options.maxPreloaderIdleTime, "!~PASSENGER_MAX_PRELOADER_IDLE_TIME");
385
375
  fillPoolOption(req, options.maxRequestQueueSize, "!~PASSENGER_MAX_REQUEST_QUEUE_SIZE");
376
+ fillPoolOption(req, options.abortWebsocketsOnProcessShutdown, "!~PASSENGER_ABORT_WEBSOCKETS_ON_PROCESS_SHUTDOWN");
377
+ fillPoolOption(req, options.forceMaxConcurrentRequestsPerProcess, "!~PASSENGER_FORCE_MAX_CONCURRENT_REQUESTS_PER_PROCESS");
386
378
  fillPoolOption(req, options.restartDir, "!~PASSENGER_RESTART_DIR");
387
379
  fillPoolOption(req, options.startupFile, "!~PASSENGER_STARTUP_FILE");
388
380
  fillPoolOption(req, options.loadShellEnvvars, "!~PASSENGER_LOAD_SHELL_ENVVARS");
@@ -397,7 +389,7 @@ createNewPoolOptions(Client *client, Request *req, const HashedStaticString &app
397
389
  }
398
390
 
399
391
  void
400
- initializeUnionStation(Client *client, Request *req, RequestAnalysis &analysis) {
392
+ Controller::initializeUnionStation(Client *client, Request *req, RequestAnalysis &analysis) {
401
393
  if (analysis.unionStationSupport) {
402
394
  Options &options = req->options;
403
395
  ServerKit::HeaderTable &headers = req->secureHeaders;
@@ -414,7 +406,7 @@ initializeUnionStation(Client *client, Request *req, RequestAnalysis &analysis)
414
406
  filters = psg_lstr_make_contiguous(filters, req->pool);
415
407
  }
416
408
 
417
- options.transaction = unionStationCore->newTransaction(
409
+ options.transaction = unionStationContext->newTransaction(
418
410
  options.getAppGroupName(), "requests",
419
411
  string(key->start->data, key->size),
420
412
  (filters != NULL)
@@ -432,7 +424,7 @@ initializeUnionStation(Client *client, Request *req, RequestAnalysis &analysis)
432
424
  }
433
425
 
434
426
  void
435
- setStickySessionId(Client *client, Request *req) {
427
+ Controller::setStickySessionId(Client *client, Request *req) {
436
428
  if (req->stickySession) {
437
429
  // TODO: This is not entirely correct. Clients MAY send multiple Cookie
438
430
  // headers, although this is in practice extremely rare.
@@ -456,7 +448,7 @@ setStickySessionId(Client *client, Request *req) {
456
448
  }
457
449
 
458
450
  const LString *
459
- getStickySessionCookieName(Request *req) {
451
+ Controller::getStickySessionCookieName(Request *req) {
460
452
  const LString *value = req->headers.lookup(PASSENGER_STICKY_SESSIONS_COOKIE_NAME);
461
453
  if (value == NULL || value->size == 0) {
462
454
  return psg_lstr_create(req->pool,
@@ -465,3 +457,65 @@ getStickySessionCookieName(Request *req) {
465
457
  return value;
466
458
  }
467
459
  }
460
+
461
+
462
+ /****************************
463
+ *
464
+ * Protected methods
465
+ *
466
+ ****************************/
467
+
468
+
469
+ void
470
+ Controller::onRequestBegin(Client *client, Request *req) {
471
+ ParentClass::onRequestBegin(client, req);
472
+
473
+ CC_BENCHMARK_POINT(client, req, BM_AFTER_ACCEPT);
474
+
475
+ {
476
+ // Perform hash table operations as close to header parsing as possible,
477
+ // and localize them as much as possible, for better CPU caching.
478
+ RequestAnalysis analysis;
479
+ analysis.flags = req->secureHeaders.lookup(FLAGS);
480
+ analysis.appGroupNameCell = singleAppMode
481
+ ? NULL
482
+ : req->secureHeaders.lookupCell(PASSENGER_APP_GROUP_NAME);
483
+ analysis.unionStationSupport = unionStationContext != NULL
484
+ && getBoolOption(req, UNION_STATION_SUPPORT, false);
485
+ req->stickySession = getBoolOption(req, PASSENGER_STICKY_SESSIONS,
486
+ this->stickySessions);
487
+ req->host = req->headers.lookup(HTTP_HOST);
488
+
489
+ /***************/
490
+ /***************/
491
+
492
+ SKC_TRACE(client, 2, "Initiating request");
493
+ req->startedAt = ev_now(getLoop());
494
+ req->bodyChannel.stop();
495
+
496
+ initializeFlags(client, req, analysis);
497
+ if (respondFromTurboCache(client, req)) {
498
+ return;
499
+ }
500
+ initializePoolOptions(client, req, analysis);
501
+ if (req->ended()) {
502
+ return;
503
+ }
504
+ initializeUnionStation(client, req, analysis);
505
+ if (req->ended()) {
506
+ return;
507
+ }
508
+ setStickySessionId(client, req);
509
+ }
510
+
511
+ if (!req->hasBody() || !req->requestBodyBuffering) {
512
+ req->requestBodyBuffering = false;
513
+ checkoutSession(client, req);
514
+ } else {
515
+ beginBufferingBody(client, req);
516
+ }
517
+ }
518
+
519
+
520
+ } // namespace Core
521
+ } // namespace Passenger