passenger 5.3.4 → 6.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (283) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +69 -0
  3. data/CONTRIBUTORS +1 -0
  4. data/README.md +2 -1
  5. data/Rakefile +0 -5
  6. data/build/agent.rb +6 -3
  7. data/build/cxx_tests.rb +28 -19
  8. data/build/integration_tests.rb +6 -2
  9. data/build/misc.rb +2 -1
  10. data/build/packaging.rb +2 -0
  11. data/build/support/cplusplus.rb +2 -2
  12. data/build/support/cxx_dependency_map.rb +2651 -2189
  13. data/dev/colorize-logs +272 -0
  14. data/dev/show-latest-crashlog-dir +27 -0
  15. data/resources/templates/standalone/http.erb +2 -0
  16. data/resources/templates/standalone/server.erb +1 -0
  17. data/src/agent/AgentMain.cpp +4 -0
  18. data/src/agent/Core/AdminPanelConnector.h +6 -6
  19. data/src/agent/Core/ApiServer.h +4 -4
  20. data/src/agent/Core/ApplicationPool/BasicProcessInfo.h +2 -2
  21. data/src/agent/Core/ApplicationPool/Context.h +5 -1
  22. data/src/agent/Core/ApplicationPool/Group/InternalUtils.cpp +2 -2
  23. data/src/agent/Core/ApplicationPool/Group/LifetimeAndBasics.cpp +5 -0
  24. data/src/agent/Core/ApplicationPool/Group/Miscellaneous.cpp +2 -1
  25. data/src/agent/Core/ApplicationPool/Group/OutOfBandWork.cpp +3 -3
  26. data/src/agent/Core/ApplicationPool/Group/ProcessListManagement.cpp +1 -1
  27. data/src/agent/Core/ApplicationPool/Group/StateInspection.cpp +13 -20
  28. data/src/agent/Core/ApplicationPool/Group.h +4 -2
  29. data/src/agent/Core/ApplicationPool/Implementation.cpp +5 -5
  30. data/src/agent/Core/ApplicationPool/Options.h +42 -38
  31. data/src/agent/Core/ApplicationPool/Pool/GroupUtils.cpp +2 -1
  32. data/src/agent/Core/ApplicationPool/Pool.h +4 -4
  33. data/src/agent/Core/ApplicationPool/Process.h +13 -15
  34. data/src/agent/Core/ApplicationPool/Socket.h +5 -5
  35. data/src/agent/Core/ApplicationPool/TestSession.h +3 -3
  36. data/src/agent/Core/Config.h +50 -10
  37. data/src/agent/Core/ConfigChange.cpp +13 -1
  38. data/src/agent/Core/Controller/Config.h +41 -17
  39. data/src/agent/Core/Controller/ForwardResponse.cpp +4 -0
  40. data/src/agent/Core/Controller/InitRequest.cpp +14 -8
  41. data/src/agent/Core/Controller/InitializationAndShutdown.cpp +5 -0
  42. data/src/agent/Core/Controller/SendRequest.cpp +9 -9
  43. data/src/agent/Core/Controller/TurboCaching.h +2 -2
  44. data/src/agent/Core/Controller.h +7 -5
  45. data/src/agent/Core/CoreMain.cpp +204 -60
  46. data/src/agent/Core/OptionParser.h +20 -3
  47. data/src/agent/Core/ResponseCache.h +3 -3
  48. data/src/agent/Core/SecurityUpdateChecker.h +4 -2
  49. data/src/agent/Core/SpawningKit/Config/AutoGeneratedCode.h +1 -1
  50. data/src/agent/Core/SpawningKit/Config.h +3 -2
  51. data/src/agent/Core/SpawningKit/Context.h +8 -2
  52. data/src/agent/Core/SpawningKit/DirectSpawner.h +4 -4
  53. data/src/agent/Core/SpawningKit/DummySpawner.h +3 -3
  54. data/src/agent/Core/SpawningKit/ErrorRenderer.h +1 -1
  55. data/src/agent/Core/SpawningKit/Exceptions.h +21 -14
  56. data/src/agent/Core/SpawningKit/Factory.h +1 -1
  57. data/src/agent/Core/SpawningKit/Handshake/BackgroundIOCapturer.h +1 -1
  58. data/src/agent/Core/SpawningKit/Handshake/Perform.h +14 -2
  59. data/src/agent/Core/SpawningKit/Handshake/Prepare.h +3 -3
  60. data/src/agent/Core/SpawningKit/Handshake/WorkDir.h +1 -1
  61. data/src/agent/Core/SpawningKit/Journey.h +4 -5
  62. data/src/agent/Core/SpawningKit/PipeWatcher.h +1 -1
  63. data/src/agent/Core/SpawningKit/README.md +34 -17
  64. data/src/agent/Core/SpawningKit/Result/AutoGeneratedCode.h +1 -1
  65. data/src/agent/Core/SpawningKit/Result.h +20 -8
  66. data/src/agent/Core/SpawningKit/SmartSpawner.h +7 -7
  67. data/src/agent/Core/SpawningKit/Spawner.h +25 -8
  68. data/src/agent/Core/SpawningKit/UserSwitchingRules.h +17 -7
  69. data/src/agent/Core/TelemetryCollector.h +681 -0
  70. data/src/agent/ExecHelper/ExecHelperMain.cpp +1 -1
  71. data/src/agent/FileReadHelper/FileReadHelperMain.cpp +198 -0
  72. data/src/agent/README.md +1 -1
  73. data/src/agent/Shared/ApiAccountUtils.h +1 -1
  74. data/src/agent/Shared/ApiServerUtils.h +3 -3
  75. data/src/agent/Shared/ApplicationPoolApiKey.h +2 -2
  76. data/src/agent/Shared/Fundamentals/AbortHandler.cpp +324 -98
  77. data/src/agent/Shared/Fundamentals/AbortHandler.h +31 -4
  78. data/src/agent/Shared/Fundamentals/Initialization.cpp +4 -5
  79. data/src/agent/Shared/Fundamentals/Initialization.h +9 -1
  80. data/src/agent/SpawnEnvSetupper/SpawnEnvSetupperMain.cpp +1 -1
  81. data/src/agent/SystemMetrics/SystemMetricsMain.cpp +4 -3
  82. data/src/agent/TempDirToucher/TempDirToucherMain.cpp +3 -3
  83. data/src/agent/Watchdog/ApiServer.h +3 -3
  84. data/src/agent/Watchdog/Config.h +24 -5
  85. data/src/agent/Watchdog/CoreWatcher.cpp +2 -2
  86. data/src/agent/Watchdog/WatchdogMain.cpp +97 -28
  87. data/src/apache2_module/Config.cpp +14 -14
  88. data/src/apache2_module/Config.h +8 -16
  89. data/src/apache2_module/ConfigGeneral/AutoGeneratedDefinitions.cpp +510 -481
  90. data/src/apache2_module/ConfigGeneral/AutoGeneratedDefinitions.cpp.cxxcodebuilder +39 -17
  91. data/src/apache2_module/ConfigGeneral/AutoGeneratedManifestDefaultsInitialization.cpp +5 -0
  92. data/src/apache2_module/ConfigGeneral/AutoGeneratedSetterFuncs.cpp +69 -1
  93. data/src/apache2_module/ConfigGeneral/AutoGeneratedSetterFuncs.cpp.cxxcodebuilder +31 -1
  94. data/src/apache2_module/ConfigGeneral/Common.h +45 -0
  95. data/src/apache2_module/DirConfig/AutoGeneratedCreateFunction.cpp +17 -1
  96. data/src/apache2_module/DirConfig/AutoGeneratedCreateFunction.cpp.cxxcodebuilder +16 -1
  97. data/src/apache2_module/DirConfig/AutoGeneratedHeaderSerialization.cpp +19 -5
  98. data/src/apache2_module/DirConfig/AutoGeneratedHeaderSerialization.cpp.cxxcodebuilder +26 -9
  99. data/src/apache2_module/DirConfig/AutoGeneratedManifestGeneration.cpp +19 -1
  100. data/src/apache2_module/DirConfig/AutoGeneratedManifestGeneration.cpp.cxxcodebuilder +10 -1
  101. data/src/apache2_module/DirConfig/AutoGeneratedMergeFunction.cpp +14 -1
  102. data/src/apache2_module/DirConfig/AutoGeneratedMergeFunction.cpp.cxxcodebuilder +11 -1
  103. data/src/apache2_module/DirConfig/AutoGeneratedStruct.h +36 -1
  104. data/src/apache2_module/DirConfig/AutoGeneratedStruct.h.cxxcodebuilder +34 -1
  105. data/src/apache2_module/DirectoryMapper.h +36 -37
  106. data/src/apache2_module/Hooks.cpp +27 -8
  107. data/src/apache2_module/ServerConfig/AutoGeneratedManifestGeneration.cpp +20 -0
  108. data/src/apache2_module/ServerConfig/AutoGeneratedStruct.h +48 -1
  109. data/src/apache2_module/ServerConfig/AutoGeneratedStruct.h.cxxcodebuilder +36 -1
  110. data/src/cxx_supportlib/{Utils → Algorithms}/Hasher.cpp +2 -2
  111. data/src/cxx_supportlib/{Utils → Algorithms}/Hasher.h +4 -4
  112. data/src/cxx_supportlib/AppLocalConfigFileUtils.h +148 -0
  113. data/src/cxx_supportlib/AppTypeDetector/CBindings.cpp +147 -0
  114. data/src/cxx_supportlib/AppTypeDetector/CBindings.h +75 -0
  115. data/src/cxx_supportlib/{AppTypes.h → AppTypeDetector/Detector.h} +92 -131
  116. data/src/cxx_supportlib/ConfigKit/README.md +90 -2
  117. data/src/cxx_supportlib/ConfigKit/Schema.h +60 -15
  118. data/src/cxx_supportlib/ConfigKit/Store.h +129 -5
  119. data/src/cxx_supportlib/Constants.h +1 -1
  120. data/src/cxx_supportlib/{Utils → DataStructures}/HashMap.h +4 -4
  121. data/src/cxx_supportlib/DataStructures/HashedStaticString.h +5 -5
  122. data/src/cxx_supportlib/DataStructures/LString.h +3 -3
  123. data/src/cxx_supportlib/{Utils → DataStructures}/StringMap.h +36 -36
  124. data/src/cxx_supportlib/FileTools/FileManip.cpp +1 -1
  125. data/src/cxx_supportlib/FileTools/PathManip.cpp +2 -2
  126. data/src/cxx_supportlib/FileTools/PathSecurityCheck.cpp +1 -1
  127. data/src/cxx_supportlib/Hooks.h +2 -2
  128. data/src/cxx_supportlib/{Utils → IOTools}/BufferedIO.h +5 -5
  129. data/src/cxx_supportlib/{Utils → IOTools}/IOUtils.cpp +4 -3
  130. data/src/cxx_supportlib/{Utils → IOTools}/IOUtils.h +3 -3
  131. data/src/cxx_supportlib/{Utils → IOTools}/MessageIO.h +7 -7
  132. data/src/cxx_supportlib/{MessageReadersWriters.h → IOTools/MessageSerialization.h} +5 -5
  133. data/src/cxx_supportlib/InstanceDirectory.h +4 -4
  134. data/src/cxx_supportlib/Integrations/LibevJsonUtils.h +3 -3
  135. data/src/cxx_supportlib/{Utils → JsonTools}/JsonUtils.h +5 -5
  136. data/src/cxx_supportlib/LoggingKit/Context.h +2 -2
  137. data/src/cxx_supportlib/LoggingKit/Implementation.cpp +3 -3
  138. data/src/cxx_supportlib/MemoryKit/mbuf.cpp +2 -2
  139. data/src/cxx_supportlib/ProcessManagement/Ruby.cpp +3 -3
  140. data/src/cxx_supportlib/ProcessManagement/Ruby.h +7 -2
  141. data/src/cxx_supportlib/ProcessManagement/Spawn.cpp +19 -12
  142. data/src/cxx_supportlib/ProcessManagement/Spawn.h +21 -2
  143. data/src/cxx_supportlib/ProcessManagement/Utils.h +10 -0
  144. data/src/cxx_supportlib/RandomGenerator.h +2 -2
  145. data/src/cxx_supportlib/ResourceLocator.h +1 -1
  146. data/src/cxx_supportlib/{Crypto.cpp → SecurityKit/Crypto.cpp} +4 -4
  147. data/src/cxx_supportlib/{Crypto.h → SecurityKit/Crypto.h} +4 -4
  148. data/src/cxx_supportlib/{Utils → SecurityKit}/MemZeroGuard.h +0 -0
  149. data/src/cxx_supportlib/ServerKit/AcceptLoadBalancer.h +2 -2
  150. data/src/cxx_supportlib/ServerKit/Channel.h +1 -1
  151. data/src/cxx_supportlib/ServerKit/ClientRef.h +17 -7
  152. data/src/cxx_supportlib/ServerKit/Context.h +2 -2
  153. data/src/cxx_supportlib/ServerKit/FileBufferedChannel.h +1 -1
  154. data/src/cxx_supportlib/ServerKit/HttpHeaderParser.h +3 -3
  155. data/src/cxx_supportlib/ServerKit/HttpHeaderParserState.h +2 -2
  156. data/src/cxx_supportlib/ServerKit/HttpRequestRef.h +17 -7
  157. data/src/cxx_supportlib/ServerKit/HttpServer.h +16 -10
  158. data/src/cxx_supportlib/ServerKit/Server.h +3 -4
  159. data/src/cxx_supportlib/{Utils → StrIntTools}/DateParsing.h +5 -5
  160. data/src/cxx_supportlib/{Utils → StrIntTools}/StrIntUtils.cpp +3 -3
  161. data/src/cxx_supportlib/{Utils → StrIntTools}/StrIntUtils.h +0 -0
  162. data/src/cxx_supportlib/{Utils → StrIntTools}/StrIntUtilsNoStrictAliasing.cpp +12 -12
  163. data/src/cxx_supportlib/{Utils → StrIntTools}/StringScanning.h +5 -5
  164. data/src/cxx_supportlib/{Utils → StrIntTools}/Template.h +30 -5
  165. data/src/cxx_supportlib/SystemTools/ContainerHelpers.h +88 -0
  166. data/src/cxx_supportlib/{Utils → SystemTools}/ProcessMetricsCollector.h +15 -12
  167. data/src/cxx_supportlib/{Utils → SystemTools}/SystemMetricsCollector.h +3 -3
  168. data/src/cxx_supportlib/{Utils → SystemTools}/SystemTime.cpp +1 -1
  169. data/src/cxx_supportlib/{Utils → SystemTools}/SystemTime.h +0 -0
  170. data/src/cxx_supportlib/SystemTools/UserDatabase.h +1 -1
  171. data/src/cxx_supportlib/Utils/CachedFileStat.hpp +3 -3
  172. data/src/cxx_supportlib/Utils/Curl.h +2 -2
  173. data/src/cxx_supportlib/Utils/FileChangeChecker.h +2 -2
  174. data/src/cxx_supportlib/Utils/MessagePassing.h +1 -1
  175. data/src/cxx_supportlib/Utils/SpeedMeter.h +2 -2
  176. data/src/cxx_supportlib/Utils/Timer.h +2 -2
  177. data/src/cxx_supportlib/Utils/VariantMap.h +3 -3
  178. data/src/cxx_supportlib/Utils.cpp +2 -2
  179. data/src/cxx_supportlib/WatchdogLauncher.h +3 -3
  180. data/src/cxx_supportlib/WebSocketCommandReverseServer.h +1 -1
  181. data/src/cxx_supportlib/WrapperRegistry/CBindings.cpp +85 -0
  182. data/src/cxx_supportlib/{Utils/MemoryBarrier.h → WrapperRegistry/CBindings.h} +30 -27
  183. data/src/cxx_supportlib/WrapperRegistry/Entry.h +112 -0
  184. data/src/cxx_supportlib/WrapperRegistry/README.md +37 -0
  185. data/src/cxx_supportlib/WrapperRegistry/Registry.h +309 -0
  186. data/src/cxx_supportlib/vendor-modified/psg_sysqueue.h +3 -0
  187. data/src/helper-scripts/download_binaries/extconf.rb +6 -2
  188. data/src/nginx_module/ConfigGeneral/AutoGeneratedDefinitions.c +32 -0
  189. data/src/nginx_module/ConfigGeneral/AutoGeneratedManifestDefaultsInitialization.c +12 -0
  190. data/src/nginx_module/ConfigGeneral/AutoGeneratedSetterFuncs.c +36 -0
  191. data/src/nginx_module/Configuration.c +23 -3
  192. data/src/nginx_module/ContentHandler.c +331 -32
  193. data/src/nginx_module/ContentHandler.h +8 -3
  194. data/src/nginx_module/LocationConfig/AutoGeneratedCreateFunction.c +10 -0
  195. data/src/nginx_module/LocationConfig/AutoGeneratedManifestGeneration.c +27 -0
  196. data/src/nginx_module/LocationConfig/AutoGeneratedMergeFunction.c +3 -0
  197. data/src/nginx_module/LocationConfig/AutoGeneratedStruct.h +7 -0
  198. data/src/nginx_module/MainConfig/AutoGeneratedCreateFunction.c +11 -0
  199. data/src/nginx_module/MainConfig/AutoGeneratedManifestGeneration.c +23 -0
  200. data/src/nginx_module/MainConfig/AutoGeneratedStruct.h +8 -0
  201. data/src/nginx_module/config +2 -1
  202. data/src/nginx_module/ngx_http_passenger_module.c +9 -3
  203. data/src/nginx_module/ngx_http_passenger_module.h +10 -3
  204. data/src/ruby_supportlib/phusion_passenger/apache2/config_options.rb +19 -0
  205. data/src/ruby_supportlib/phusion_passenger/common_library.rb +19 -16
  206. data/src/ruby_supportlib/phusion_passenger/config/agent_compiler.rb +4 -4
  207. data/src/ruby_supportlib/phusion_passenger/config/download_agent_command.rb +6 -2
  208. data/src/ruby_supportlib/phusion_passenger/config/download_nginx_engine_command.rb +6 -2
  209. data/src/ruby_supportlib/phusion_passenger/config/nginx_engine_compiler.rb +1 -1
  210. data/src/ruby_supportlib/phusion_passenger/message_channel.rb +2 -2
  211. data/src/ruby_supportlib/phusion_passenger/native_support.rb +7 -3
  212. data/src/ruby_supportlib/phusion_passenger/nginx/config_options.rb +29 -0
  213. data/src/ruby_supportlib/phusion_passenger/packaging.rb +20 -19
  214. data/src/ruby_supportlib/phusion_passenger/platform_info/apache.rb +22 -4
  215. data/src/ruby_supportlib/phusion_passenger/platform_info/ruby.rb +33 -13
  216. data/src/ruby_supportlib/phusion_passenger/standalone/app_finder.rb +1 -0
  217. data/src/ruby_supportlib/phusion_passenger/standalone/config_options_list.rb +22 -2
  218. data/src/ruby_supportlib/phusion_passenger/standalone/start_command/builtin_engine.rb +4 -1
  219. data/src/ruby_supportlib/phusion_passenger.rb +7 -5
  220. data/src/schema_printer/SchemaPrinterMain.cpp +2 -0
  221. metadata +40 -89
  222. data/.editorconfig +0 -134
  223. data/CODE_OF_CONDUCT.md +0 -52
  224. data/dev/boost-patches/0001-Patch-boost-thread-so-that-oxt-thread-can-use-it.patch +0 -48
  225. data/dev/boost-patches/0002-Make-boost-thread_interrupted-derive-from-oxt-tracab.patch +0 -33
  226. data/dev/boost-patches/0003-Disable-a-Clang-pragma-to-prevent-warnings-on-OS-X.patch +0 -25
  227. data/dev/ci/README.md +0 -134
  228. data/dev/ci/lib/functions.sh +0 -129
  229. data/dev/ci/lib/set-container-envvars.sh +0 -53
  230. data/dev/ci/lib/setup-container.sh +0 -46
  231. data/dev/ci/run-tests-natively +0 -24
  232. data/dev/ci/run-tests-with-docker +0 -42
  233. data/dev/ci/scripts/debug-console-wrapper.sh +0 -29
  234. data/dev/ci/scripts/docker-entrypoint-stage2.sh +0 -17
  235. data/dev/ci/scripts/docker-entrypoint.sh +0 -17
  236. data/dev/ci/scripts/inituidgid +0 -17
  237. data/dev/ci/scripts/run-tests-natively-stage2.sh +0 -17
  238. data/dev/ci/scripts/setup-host-natively.sh +0 -11
  239. data/dev/ci/setup-host +0 -56
  240. data/dev/ci/tests/apache2/run +0 -6
  241. data/dev/ci/tests/apache2/setup +0 -4
  242. data/dev/ci/tests/binaries/Jenkinsfile +0 -105
  243. data/dev/ci/tests/binaries/build-linux +0 -38
  244. data/dev/ci/tests/binaries/build-macos +0 -40
  245. data/dev/ci/tests/binaries/prepare-macos +0 -38
  246. data/dev/ci/tests/binaries/test-linux +0 -45
  247. data/dev/ci/tests/binaries/test-macos +0 -38
  248. data/dev/ci/tests/cxx/run +0 -9
  249. data/dev/ci/tests/cxx/setup +0 -4
  250. data/dev/ci/tests/debian/Jenkinsfile +0 -89
  251. data/dev/ci/tests/debian/run +0 -60
  252. data/dev/ci/tests/nginx/run +0 -5
  253. data/dev/ci/tests/nginx/setup +0 -4
  254. data/dev/ci/tests/nginx-dynamic/run +0 -20
  255. data/dev/ci/tests/nginx-dynamic/setup +0 -4
  256. data/dev/ci/tests/nodejs/run +0 -4
  257. data/dev/ci/tests/nodejs/setup +0 -4
  258. data/dev/ci/tests/rpm/Jenkinsfile +0 -68
  259. data/dev/ci/tests/rpm/run +0 -63
  260. data/dev/ci/tests/ruby/run +0 -4
  261. data/dev/ci/tests/ruby/setup +0 -4
  262. data/dev/ci/tests/source-packaging/run +0 -4
  263. data/dev/ci/tests/source-packaging/setup +0 -4
  264. data/dev/ci/tests/standalone/run +0 -4
  265. data/dev/ci/tests/standalone/setup +0 -4
  266. data/dev/configkit-schemas/index.json +0 -1748
  267. data/dev/configkit-schemas/update_schema_inline_comments.rb +0 -118
  268. data/dev/rack.test/config.ru +0 -5
  269. data/dev/rack.test/public/asset.txt +0 -1
  270. data/dev/vagrant/apache_default_site.conf +0 -35
  271. data/dev/vagrant/apache_passenger.conf +0 -5
  272. data/dev/vagrant/apache_passenger.load +0 -1
  273. data/dev/vagrant/apache_ports.conf +0 -24
  274. data/dev/vagrant/apache_rack_test.conf +0 -9
  275. data/dev/vagrant/bashrc +0 -23
  276. data/dev/vagrant/nginx.conf +0 -39
  277. data/dev/vagrant/nginx_rakefile +0 -33
  278. data/dev/vagrant/nginx_start +0 -32
  279. data/dev/vagrant/provision.sh +0 -117
  280. data/dev/vagrant/sudoers.conf +0 -5
  281. data/resources/templates/error_renderer/.editorconfig +0 -19
  282. data/src/cxx_supportlib/AppTypes.cpp +0 -109
  283. data/src/cxx_supportlib/vendor-modified/SmallVector.h +0 -653
@@ -1,7 +1,7 @@
1
1
  /*
2
2
  * Copyright (C) Igor Sysoev
3
3
  * Copyright (C) 2007 Manlio Perillo (manlio.perillo@gmail.com)
4
- * Copyright (c) 2010-2017 Phusion Holding B.V.
4
+ * Copyright (c) 2010-2018 Phusion Holding B.V.
5
5
  *
6
6
  * Redistribution and use in source and binary forms, with or without
7
7
  * modification, are permitted provided that the following conditions
@@ -169,6 +169,11 @@ map_uri_to_page_cache_file(ngx_http_request_t *r, ngx_str_t *public_dir,
169
169
  }
170
170
  }
171
171
 
172
+ static void
173
+ cleanup_detector_result(void *data) {
174
+ psg_app_type_detector_result_deinit((PsgAppTypeDetectorResult *) data);
175
+ }
176
+
172
177
  static int
173
178
  find_base_uri(ngx_http_request_t *r, const passenger_loc_conf_t *loc,
174
179
  ngx_str_t *found_base_uri)
@@ -326,6 +331,179 @@ header_is_transfer_encoding(ngx_str_t *key)
326
331
  ngx_strncasecmp(key->data + 1, (u_char *) "ransfer-encodin", sizeof("ransfer-encodin") - 1) == 0;
327
332
  }
328
333
 
334
+ /* Given an ngx_chain_t head and tail position, appends a new chain element at the end,
335
+ * updates the head (if necessary) and returns the new element.
336
+ *
337
+ * - The element is allocated from a freelist.
338
+ * - Ensures that the element contains a buffer of at least `size` bytes.
339
+ * - Sets the given tag on the buffer in the chain element.
340
+ *
341
+ * On error, returns NULL without modifying the given chain.
342
+ */
343
+ static ngx_chain_t *
344
+ append_ngx_chain_element(ngx_pool_t *p, ngx_chain_t **head,
345
+ ngx_chain_t *tail, ngx_chain_t **freelist, ngx_buf_tag_t tag, size_t size)
346
+ {
347
+ ngx_chain_t *elem;
348
+ ngx_buf_t *buf;
349
+
350
+ elem = ngx_chain_get_free_buf(p, freelist);
351
+ if (elem == NULL) {
352
+ return NULL;
353
+ }
354
+
355
+ buf = elem->buf;
356
+ buf->tag = tag;
357
+
358
+ if (size > 0 && (buf->pos == NULL || buf->last == NULL
359
+ || (size_t) ngx_buf_size(buf) < size))
360
+ {
361
+ ngx_memzero(buf, sizeof(ngx_buf_t));
362
+
363
+ buf->start = ngx_palloc(p, size);
364
+ if (buf->start == NULL) {
365
+ return NULL;
366
+ }
367
+
368
+ /*
369
+ * set by ngx_memzero():
370
+ *
371
+ * b->file_pos = 0;
372
+ * b->file_last = 0;
373
+ * b->file = NULL;
374
+ * b->shadow = NULL;
375
+ * b->tag = 0;
376
+ * and flags
377
+ */
378
+
379
+ buf->pos = buf->start;
380
+ buf->last = buf->start;
381
+ buf->end = buf->last + size;
382
+ buf->temporary = 1;
383
+ }
384
+
385
+ if (*head == NULL) {
386
+ *head = elem;
387
+ } else {
388
+ tail->next = elem;
389
+ }
390
+ return elem;
391
+ }
392
+
393
+ /* Given a chain of buffers containing client body data,
394
+ * this filter wraps all that data into chunked encoding
395
+ * headers and footers.
396
+ */
397
+ static ngx_int_t
398
+ body_rechunk_output_filter(void *data, ngx_chain_t *input)
399
+ {
400
+ ngx_http_request_t *r = data;
401
+ ngx_chain_t *output_head = NULL, *output_tail = NULL;
402
+ ngx_int_t body_eof_reached = 0;
403
+ ngx_int_t rc;
404
+ passenger_context_t *ctx;
405
+
406
+ ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
407
+ PROGRAM_NAME " rechunk output filter");
408
+
409
+ ctx = ngx_http_get_module_ctx(r, ngx_http_passenger_module);
410
+
411
+ if (input == NULL) {
412
+ goto out;
413
+ }
414
+
415
+ if (!ctx->header_sent) {
416
+ /* The first buffer contains the request header, so pass it unmodified. */
417
+ ctx->header_sent = 1;
418
+
419
+ while (input != NULL) {
420
+ output_tail = append_ngx_chain_element(r->pool,
421
+ &output_head, output_tail, &ctx->free,
422
+ (ngx_buf_tag_t) &body_rechunk_output_filter,
423
+ 0);
424
+ if (output_tail == NULL) {
425
+ return NGX_ERROR;
426
+ }
427
+
428
+ ngx_memcpy(output_tail->buf, input->buf, sizeof(ngx_buf_t));
429
+
430
+ body_eof_reached = input->buf->last_buf;
431
+ input = input->next;
432
+ }
433
+ } else {
434
+ while (input != NULL) {
435
+ /* Append chunked encoding size header */
436
+ output_tail = append_ngx_chain_element(r->pool,
437
+ &output_head, output_tail, &ctx->free,
438
+ (ngx_buf_tag_t) &body_rechunk_output_filter,
439
+ 32);
440
+ if (output_tail == NULL) {
441
+ return NGX_ERROR;
442
+ }
443
+
444
+ output_tail->buf->last = ngx_sprintf(output_tail->buf->last, "%xO\r\n",
445
+ ngx_buf_size(input->buf));
446
+
447
+
448
+ /* Append chunked encoding payload */
449
+ output_tail = append_ngx_chain_element(r->pool,
450
+ &output_head, output_tail, &ctx->free,
451
+ (ngx_buf_tag_t) &body_rechunk_output_filter,
452
+ 0);
453
+ if (output_tail == NULL) {
454
+ return NGX_ERROR;
455
+ }
456
+
457
+ ngx_memcpy(output_tail->buf, input->buf, sizeof(ngx_buf_t));
458
+
459
+
460
+ /* Append chunked encoding footer */
461
+ output_tail = append_ngx_chain_element(r->pool,
462
+ &output_head, output_tail, &ctx->free,
463
+ (ngx_buf_tag_t) &body_rechunk_output_filter,
464
+ 2);
465
+ if (output_tail == NULL) {
466
+ return NGX_ERROR;
467
+ }
468
+
469
+ output_tail->buf->last = ngx_copy(output_tail->buf->last, "\r\n", 2);
470
+
471
+
472
+ body_eof_reached = input->buf->last_buf;
473
+ input = input->next;
474
+ }
475
+ }
476
+
477
+ if (body_eof_reached) {
478
+ /* Append final termination chunk. */
479
+ output_tail = append_ngx_chain_element(r->pool,
480
+ &output_head, output_tail, &ctx->free,
481
+ (ngx_buf_tag_t) &body_rechunk_output_filter,
482
+ 5);
483
+ if (output_tail == NULL) {
484
+ return NGX_ERROR;
485
+ }
486
+
487
+ output_tail->buf->last = ngx_copy(output_tail->buf->last,
488
+ "0\r\n\r\n", 5);
489
+ }
490
+
491
+ out:
492
+
493
+ rc = ngx_chain_writer(&r->upstream->writer, output_head);
494
+
495
+ /*
496
+ * The previous ngx_chain_writer() call consumed some buffers.
497
+ * Find such consumped (empty) buffers in the output buffer list,
498
+ * and either free them or add them to the freelist depending on
499
+ * whether the buffer's tag matches ours.
500
+ */
501
+ ngx_chain_update_chains(r->pool, &ctx->free, &ctx->busy, &output_head,
502
+ (ngx_buf_tag_t) &body_rechunk_output_filter);
503
+
504
+ return rc;
505
+ }
506
+
329
507
  #define SET_NGX_STR(str, the_data) \
330
508
  do { \
331
509
  (str)->data = (u_char *) the_data; \
@@ -341,15 +519,25 @@ header_is_transfer_encoding(ngx_str_t *key)
341
519
  typedef struct {
342
520
  ngx_str_t method; /* Includes trailing space */
343
521
  ngx_str_t app_type;
522
+ ngx_str_t app_start_command;
344
523
  ngx_str_t escaped_uri;
345
- ngx_str_t content_length;
524
+ ngx_str_t content_length; /* Only used if !r->request_body_no_buffering */
346
525
  ngx_str_t core_password;
347
526
  ngx_str_t remote_port;
348
527
  } buffer_construction_state;
349
528
 
529
+ /* prepare_request_buffer_construction() and construct_request_buffer() are
530
+ * used to create an HTTP request header buffer to be sent to the Core Controller.
531
+ *
532
+ * construct_request_buffer() is actually called twice: the first time in "no-op" mode to
533
+ * calculate how many bytes it must allocate, and the second time to actually create the
534
+ * buffer. For efficiency reasons, as much preparation work as possible is split into
535
+ * the prepare_request_buffer_construction() function so that the two construct_request_buffer()
536
+ * calls don't have to perform that work twice.
537
+ */
350
538
  static ngx_int_t
351
- prepare_request_buffer_construction(ngx_http_request_t *r, passenger_context_t *context,
352
- buffer_construction_state *state)
539
+ prepare_request_buffer_construction(ngx_http_request_t *r, passenger_loc_conf_t *slcf,
540
+ passenger_context_t *context, buffer_construction_state *state)
353
541
  {
354
542
  unsigned int len;
355
543
  ngx_uint_t port;
@@ -357,7 +545,9 @@ prepare_request_buffer_construction(ngx_http_request_t *r, passenger_context_t *
357
545
  #if (NGX_HAVE_INET6)
358
546
  struct sockaddr_in6 *sin6;
359
547
  #endif
548
+ const PsgWrapperRegistryEntry *wrapper_registry_entry;
360
549
 
550
+ /* Construct HTTP method string, including trailing space. */
361
551
  switch (r->method) {
362
552
  case NGX_HTTP_GET:
363
553
  SET_NGX_STR(&state->method, "GET ");
@@ -409,9 +599,28 @@ prepare_request_buffer_construction(ngx_http_request_t *r, passenger_context_t *
409
599
  break;
410
600
  }
411
601
 
412
- state->app_type.data = (u_char *) pp_get_app_type_name(context->app_type);
413
- /* Include null terminator */
414
- state->app_type.len = strlen((const char *) state->app_type.data);
602
+ if (slcf->autogenerated.app_start_command.data != NULL) {
603
+ /* The config specified that this is either a generic app or a Kuria app. */
604
+ state->app_type.data = NULL;
605
+ state->app_type.len = 0;
606
+ state->app_start_command = slcf->autogenerated.app_start_command;
607
+ } else {
608
+ wrapper_registry_entry = psg_app_type_detector_result_get_wrapper_registry_entry(
609
+ context->detector_result);
610
+ if (wrapper_registry_entry != NULL) {
611
+ /* This is an auto-supported app. */
612
+ state->app_type.data = (u_char *) psg_wrapper_registry_entry_get_language(wrapper_registry_entry,
613
+ &state->app_type.len);
614
+ state->app_start_command.data = NULL;
615
+ state->app_start_command.len = 0;
616
+ } else {
617
+ /* This has been autodetected to be a generic app or a Kuria app. */
618
+ state->app_type.data = NULL;
619
+ state->app_type.len = 0;
620
+ state->app_start_command.data = (u_char *) psg_app_type_detector_result_get_app_start_command(
621
+ context->detector_result, &state->app_start_command.len);
622
+ }
623
+ }
415
624
 
416
625
  /*
417
626
  * Nginx unescapes URI's before passing them to Phusion Passenger,
@@ -439,7 +648,7 @@ prepare_request_buffer_construction(ngx_http_request_t *r, passenger_context_t *
439
648
  NGX_ESCAPE_URI);
440
649
  }
441
650
 
442
- if (r->headers_in.chunked) {
651
+ if (r->headers_in.chunked && !r->request_body_no_buffering) {
443
652
  /* If the request body is chunked, then Nginx sets r->headers_in.content_length_n
444
653
  * but does not set r->headers_in.headers, so we add this header ourselves.
445
654
  */
@@ -488,6 +697,7 @@ prepare_request_buffer_construction(ngx_http_request_t *r, passenger_context_t *
488
697
  return NGX_OK;
489
698
  }
490
699
 
700
+ /* See comment for prepare_request_buffer_construction() */
491
701
  static ngx_uint_t
492
702
  construct_request_buffer(ngx_http_request_t *r, passenger_loc_conf_t *slcf,
493
703
  passenger_context_t *context, buffer_construction_state *state, ngx_buf_t *b)
@@ -547,7 +757,7 @@ construct_request_buffer(ngx_http_request_t *r, passenger_loc_conf_t *slcf,
547
757
 
548
758
  if (ngx_hash_find(&slcf->headers_set_hash, header[i].hash,
549
759
  header[i].lowcase_key, header[i].key.len)
550
- || header_is_transfer_encoding(&header[i].key))
760
+ || (!r->request_body_no_buffering && header_is_transfer_encoding(&header[i].key)))
551
761
  {
552
762
  continue;
553
763
  }
@@ -561,7 +771,7 @@ construct_request_buffer(ngx_http_request_t *r, passenger_loc_conf_t *slcf,
561
771
  total_size += header[i].key.len + header[i].value.len + 4;
562
772
  }
563
773
 
564
- if (r->headers_in.chunked) {
774
+ if (r->headers_in.chunked && !r->request_body_no_buffering) {
565
775
  PUSH_STATIC_STR("Content-Length: ");
566
776
  if (b != NULL) {
567
777
  b->last = ngx_copy(b->last, state->content_length.data,
@@ -749,13 +959,23 @@ construct_request_buffer(ngx_http_request_t *r, passenger_loc_conf_t *slcf,
749
959
  PUSH_STATIC_STR("\r\n");
750
960
  }
751
961
 
752
- PUSH_STATIC_STR("!~PASSENGER_APP_TYPE: ");
753
- if (b != NULL) {
754
- b->last = ngx_copy(b->last, state->app_type.data,
755
- state->app_type.len);
962
+ if (state->app_type.len > 0) {
963
+ PUSH_STATIC_STR("!~PASSENGER_APP_TYPE: ");
964
+ if (b != NULL) {
965
+ b->last = ngx_copy(b->last, state->app_type.data,
966
+ state->app_type.len);
967
+ }
968
+ total_size += state->app_type.len;
969
+ PUSH_STATIC_STR("\r\n");
970
+ } else {
971
+ PUSH_STATIC_STR("!~PASSENGER_APP_START_COMMAND: ");
972
+ if (b != NULL) {
973
+ b->last = ngx_copy(b->last, state->app_start_command.data,
974
+ state->app_start_command.len);
975
+ }
976
+ total_size += state->app_start_command.len;
977
+ PUSH_STATIC_STR("\r\n");
756
978
  }
757
- total_size += state->app_type.len;
758
- PUSH_STATIC_STR("\r\n");
759
979
 
760
980
  if (b != NULL) {
761
981
  b->last = ngx_copy(b->last, slcf->options_cache.data, slcf->options_cache.len);
@@ -809,7 +1029,7 @@ create_request(ngx_http_request_t *r)
809
1029
 
810
1030
  /* Construct and pass request headers */
811
1031
 
812
- if (prepare_request_buffer_construction(r, context, &state) != NGX_OK) {
1032
+ if (prepare_request_buffer_construction(r, slcf, context, &state) != NGX_OK) {
813
1033
  return NGX_ERROR;
814
1034
  }
815
1035
  request_size = construct_request_buffer(r, slcf, context, &state, NULL);
@@ -818,20 +1038,45 @@ create_request(ngx_http_request_t *r)
818
1038
  if (b == NULL) {
819
1039
  return NGX_ERROR;
820
1040
  }
1041
+ construct_request_buffer(r, slcf, context, &state, b);
1042
+
821
1043
  cl = ngx_alloc_chain_link(r->pool);
822
1044
  if (cl == NULL) {
823
1045
  return NGX_ERROR;
824
1046
  }
825
1047
  cl->buf = b;
826
1048
 
827
- construct_request_buffer(r, slcf, context, &state, b);
828
1049
 
829
- /* Pass request body */
1050
+ /* Pass already received request body buffers. Make sure they come
1051
+ * after the request header buffer we just constructed.
1052
+ */
830
1053
 
831
1054
  body = r->upstream->request_bufs;
832
1055
  r->upstream->request_bufs = cl;
833
1056
 
834
1057
  while (body) {
1058
+ if (r->headers_in.chunked && r->request_body_no_buffering) {
1059
+ /* If Transfer-Encoding is chunked, then Nginx dechunks the body.
1060
+ * If at the same time request body buffering is disabled, then
1061
+ * we pass the Transfer-Encoding header to the Passenger Core,
1062
+ * and thus we also need to ensure we rechunk the body.
1063
+ */
1064
+ b = ngx_create_temp_buf(r->pool, 32);
1065
+ if (b == NULL) {
1066
+ return NGX_ERROR;
1067
+ }
1068
+
1069
+ b->last = ngx_sprintf(b->last, "%xO\r\n",
1070
+ ngx_buf_size(body->buf));
1071
+ cl->next = ngx_alloc_chain_link(r->pool);
1072
+ if (cl->next == NULL) {
1073
+ return NGX_ERROR;
1074
+ }
1075
+
1076
+ cl = cl->next;
1077
+ cl->buf = b;
1078
+ }
1079
+
835
1080
  b = ngx_alloc_buf(r->pool);
836
1081
  if (b == NULL) {
837
1082
  return NGX_ERROR;
@@ -843,15 +1088,41 @@ create_request(ngx_http_request_t *r)
843
1088
  if (cl->next == NULL) {
844
1089
  return NGX_ERROR;
845
1090
  }
846
-
847
1091
  cl = cl->next;
848
1092
  cl->buf = b;
849
1093
 
850
1094
  body = body->next;
1095
+
1096
+ if (r->headers_in.chunked && r->request_body_no_buffering) {
1097
+ b = ngx_create_temp_buf(r->pool, 2);
1098
+ if (b == NULL) {
1099
+ return NGX_ERROR;
1100
+ }
1101
+
1102
+ b->last = ngx_copy(b->last, "\r\n", 2);
1103
+ cl->next = ngx_alloc_chain_link(r->pool);
1104
+ if (cl->next == NULL) {
1105
+ return NGX_ERROR;
1106
+ }
1107
+
1108
+ cl = cl->next;
1109
+ cl->buf = b;
1110
+ }
851
1111
  }
1112
+
852
1113
  b->flush = 1;
853
1114
  cl->next = NULL;
854
1115
 
1116
+ /* Again, if Transfer-Encoding is chunked, then Nginx dechunks the body.
1117
+ * Here we install an output filter to make sure that the request body parts
1118
+ * that will be received in the future, will also be rechunked when passed
1119
+ * to the Passenger Core.
1120
+ */
1121
+ if (r->headers_in.chunked && r->request_body_no_buffering) {
1122
+ r->upstream->output.output_filter = body_rechunk_output_filter;
1123
+ r->upstream->output.filter_ctx = r;
1124
+ }
1125
+
855
1126
  return NGX_OK;
856
1127
  }
857
1128
 
@@ -1362,7 +1633,10 @@ passenger_content_handler(ngx_http_request_t *r)
1362
1633
  u_char page_cache_file_str[NGX_MAX_PATH + 1];
1363
1634
  ngx_str_t page_cache_file;
1364
1635
  passenger_context_t *context;
1636
+ void *detector_result_mem;
1637
+ ngx_pool_cleanup_t *detector_result_cleanup;
1365
1638
  PP_Error error;
1639
+ const PsgWrapperRegistryEntry *wrapper_registry_entry;
1366
1640
 
1367
1641
  if (passenger_main_conf.autogenerated.root_dir.len == 0) {
1368
1642
  return NGX_DECLINED;
@@ -1450,24 +1724,39 @@ passenger_content_handler(ngx_http_request_t *r)
1450
1724
  return passenger_static_content_handler(r, &page_cache_file);
1451
1725
  }
1452
1726
 
1453
- if (slcf->autogenerated.app_type.data == NULL) {
1727
+ detector_result_mem = ngx_palloc(r->pool,
1728
+ psg_app_type_detector_result_get_object_size());
1729
+ context->detector_result = psg_app_type_detector_result_init(detector_result_mem);
1730
+ detector_result_cleanup = ngx_pool_cleanup_add(r->pool, 0);
1731
+ detector_result_cleanup->handler = cleanup_detector_result;
1732
+ detector_result_cleanup->data = context->detector_result;
1733
+
1734
+ /* If `app_start_command` is set, then it means the config specified that it is
1735
+ * either a generic app or a Kuria app.
1736
+ */
1737
+ if (slcf->autogenerated.app_start_command.data == NULL
1738
+ && slcf->autogenerated.app_type.data == NULL)
1739
+ {
1740
+ /* If neither `app_start_command` nor `app_type` are set, then
1741
+ * autodetect what kind of app this is.
1742
+ */
1454
1743
  pp_error_init(&error);
1455
1744
  if (slcf->autogenerated.app_root.data == NULL) {
1456
- context->app_type = pp_app_type_detector_check_document_root(
1457
- pp_app_type_detector,
1745
+ psg_app_type_detector_check_document_root(
1746
+ psg_app_type_detector, context->detector_result,
1458
1747
  (const char *) context->public_dir.data, context->public_dir.len,
1459
1748
  context->base_uri.len != 0,
1460
1749
  &error);
1461
1750
  } else {
1462
- context->app_type = pp_app_type_detector_check_app_root(
1463
- pp_app_type_detector,
1751
+ psg_app_type_detector_check_app_root(
1752
+ psg_app_type_detector, context->detector_result,
1464
1753
  (const char *) slcf->autogenerated.app_root.data, slcf->autogenerated.app_root.len,
1465
1754
  &error);
1466
1755
  }
1467
- if (context->app_type == PAT_NONE) {
1468
- return NGX_DECLINED;
1469
- } else if (context->app_type == PAT_ERROR) {
1470
- if (error.errnoCode == EACCES) {
1756
+ if (psg_app_type_detector_result_is_null(context->detector_result)) {
1757
+ if (error.message == NULL) {
1758
+ return NGX_DECLINED;
1759
+ } else if (error.errnoCode == EACCES) {
1471
1760
  ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
1472
1761
  "%s; This error means that the Nginx worker process (PID %d, "
1473
1762
  "running as UID %d) does not have permission to access this file. "
@@ -1485,11 +1774,19 @@ passenger_content_handler(ngx_http_request_t *r)
1485
1774
  pp_error_destroy(&error);
1486
1775
  return NGX_HTTP_INTERNAL_SERVER_ERROR;
1487
1776
  }
1488
- } else {
1489
- context->app_type = pp_get_app_type2((const char *) slcf->autogenerated.app_type.data,
1777
+ } else if (slcf->autogenerated.app_start_command.data == NULL) {
1778
+ /* If `app_start_command` is not set but `app_type` is, then
1779
+ * verify whether the given `app_type` value is supported
1780
+ * and resolve aliases.
1781
+ */
1782
+ wrapper_registry_entry = psg_wrapper_registry_lookup(psg_wrapper_registry,
1783
+ (const char *) slcf->autogenerated.app_type.data,
1490
1784
  slcf->autogenerated.app_type.len);
1491
- if (context->app_type == PAT_NONE) {
1785
+ if (psg_wrapper_registry_entry_is_null(wrapper_registry_entry)) {
1492
1786
  return NGX_DECLINED;
1787
+ } else {
1788
+ psg_app_type_detector_result_set_wrapper_registry_entry(
1789
+ context->detector_result, wrapper_registry_entry);
1493
1790
  }
1494
1791
  }
1495
1792
 
@@ -1526,6 +1823,8 @@ passenger_content_handler(ngx_http_request_t *r)
1526
1823
  u->pipe->input_filter = ngx_event_pipe_copy_input_filter;
1527
1824
  u->pipe->input_ctx = r;
1528
1825
 
1826
+ r->request_body_no_buffering = !slcf->upstream_config.request_buffering;
1827
+
1529
1828
  rc = ngx_http_read_client_request_body(r, ngx_http_upstream_init);
1530
1829
 
1531
1830
  fix_peer_address(r);
@@ -30,7 +30,7 @@
30
30
 
31
31
  #include <ngx_core.h>
32
32
  #include <ngx_http.h>
33
- #include "cxx_supportlib/AppTypes.h"
33
+ #include "cxx_supportlib/AppTypeDetector/CBindings.h"
34
34
 
35
35
 
36
36
  typedef struct {
@@ -40,14 +40,19 @@ typedef struct {
40
40
  u_char *status_start;
41
41
  u_char *status_end;
42
42
 
43
+ /* body_rechunk_output_filter state. */
44
+ ngx_chain_t *free;
45
+ ngx_chain_t *busy;
46
+ unsigned header_sent: 1;
47
+
43
48
  /** The application's 'public' directory. */
44
49
  ngx_str_t public_dir;
45
50
 
46
51
  /** The application's base URI. Points to an empty string if none. */
47
52
  ngx_str_t base_uri;
48
53
 
49
- /** The application's type. */
50
- PassengerAppType app_type;
54
+ /** Detected information about the app. */
55
+ PsgAppTypeDetectorResult *detector_result;
51
56
  } passenger_context_t;
52
57
 
53
58
 
@@ -75,6 +75,8 @@ passenger_create_autogenerated_loc_conf(passenger_autogenerated_loc_conf_t *con
75
75
  conf->app_type.len = 0;
76
76
  conf->startup_file.data = NULL;
77
77
  conf->startup_file.len = 0;
78
+ conf->app_start_command.data = NULL;
79
+ conf->app_start_command.len = 0;
78
80
  conf->restart_dir.data = NULL;
79
81
  conf->restart_dir.len = 0;
80
82
  conf->abort_websockets_on_process_shutdown = NGX_CONF_UNSET;
@@ -183,6 +185,10 @@ passenger_create_autogenerated_loc_conf(passenger_autogenerated_loc_conf_t *con
183
185
  conf->startup_file_source_file.len = 0;
184
186
  conf->startup_file_source_line = 0;
185
187
  conf->startup_file_explicitly_set = 0;
188
+ conf->app_start_command_source_file.data = NULL;
189
+ conf->app_start_command_source_file.len = 0;
190
+ conf->app_start_command_source_line = 0;
191
+ conf->app_start_command_explicitly_set = 0;
186
192
  conf->restart_dir_source_file.data = NULL;
187
193
  conf->restart_dir_source_file.len = 0;
188
194
  conf->restart_dir_source_line = 0;
@@ -255,6 +261,10 @@ passenger_create_autogenerated_loc_conf(passenger_autogenerated_loc_conf_t *con
255
261
  conf->upstream_config_busy_buffers_size_conf_source_file.len = 0;
256
262
  conf->upstream_config_busy_buffers_size_conf_source_line = 0;
257
263
  conf->upstream_config_busy_buffers_size_conf_explicitly_set = 0;
264
+ conf->upstream_config_request_buffering_source_file.data = NULL;
265
+ conf->upstream_config_request_buffering_source_file.len = 0;
266
+ conf->upstream_config_request_buffering_source_line = 0;
267
+ conf->upstream_config_request_buffering_explicitly_set = 0;
258
268
  conf->upstream_config_intercept_errors_source_file.data = NULL;
259
269
  conf->upstream_config_intercept_errors_source_file.len = 0;
260
270
  conf->upstream_config_intercept_errors_source_line = 0;
@@ -345,6 +345,20 @@ generate_config_manifest_for_autogenerated_loc_conf(manifest_gen_ctx_t *ctx, pas
345
345
  (const char *) plcf->autogenerated.startup_file.data,
346
346
  plcf->autogenerated.startup_file.len);
347
347
  }
348
+ if (plcf->autogenerated.app_start_command_explicitly_set) {
349
+ find_or_create_manifest_app_and_loc_options_containers(ctx,
350
+ plcf, cscf, clcf, &app_options_container, &loc_options_container);
351
+ option_container = find_or_create_manifest_option_container(ctx,
352
+ app_options_container,
353
+ "passenger_app_start_command",
354
+ sizeof("passenger_app_start_command") - 1);
355
+ hierarchy_member = add_manifest_option_container_hierarchy_member(option_container,
356
+ &plcf->autogenerated.app_start_command_source_file,
357
+ plcf->autogenerated.app_start_command_source_line);
358
+ psg_json_value_set_str(hierarchy_member, "value",
359
+ (const char *) plcf->autogenerated.app_start_command.data,
360
+ plcf->autogenerated.app_start_command.len);
361
+ }
348
362
  if (plcf->autogenerated.restart_dir_explicitly_set) {
349
363
  find_or_create_manifest_app_and_loc_options_containers(ctx,
350
364
  plcf, cscf, clcf, &app_options_container, &loc_options_container);
@@ -529,6 +543,19 @@ generate_config_manifest_for_autogenerated_loc_conf(manifest_gen_ctx_t *ctx, pas
529
543
  psg_json_value_set_bool(hierarchy_member, "value",
530
544
  plcf->upstream_config.buffering);
531
545
  }
546
+ if (plcf->autogenerated.upstream_config_request_buffering_explicitly_set) {
547
+ find_or_create_manifest_app_and_loc_options_containers(ctx,
548
+ plcf, cscf, clcf, &app_options_container, &loc_options_container);
549
+ option_container = find_or_create_manifest_option_container(ctx,
550
+ loc_options_container,
551
+ "passenger_request_buffering",
552
+ sizeof("passenger_request_buffering") - 1);
553
+ hierarchy_member = add_manifest_option_container_hierarchy_member(option_container,
554
+ &plcf->autogenerated.upstream_config_request_buffering_source_file,
555
+ plcf->autogenerated.upstream_config_request_buffering_source_line);
556
+ psg_json_value_set_bool(hierarchy_member, "value",
557
+ plcf->upstream_config.request_buffering);
558
+ }
532
559
  if (plcf->autogenerated.upstream_config_intercept_errors_explicitly_set) {
533
560
  find_or_create_manifest_app_and_loc_options_containers(ctx,
534
561
  plcf, cscf, clcf, &app_options_container, &loc_options_container);
@@ -113,6 +113,9 @@ passenger_merge_autogenerated_loc_conf(passenger_autogenerated_loc_conf_t *conf,
113
113
  ngx_conf_merge_str_value(conf->startup_file,
114
114
  prev->startup_file,
115
115
  NULL);
116
+ ngx_conf_merge_str_value(conf->app_start_command,
117
+ prev->app_start_command,
118
+ NULL);
116
119
  ngx_conf_merge_str_value(conf->restart_dir,
117
120
  prev->restart_dir,
118
121
  "tmp");