passenger 4.0.60 → 5.0.0.beta1

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 (1301) hide show
  1. checksums.yaml +8 -8
  2. checksums.yaml.gz.asc +7 -7
  3. data.tar.gz.asc +7 -7
  4. data/.editorconfig +5 -0
  5. data/.travis.yml +3 -2
  6. data/CHANGELOG +31 -53
  7. data/CONTRIBUTING.md +4 -4
  8. data/CONTRIBUTORS +0 -1
  9. data/Gemfile +18 -0
  10. data/Gemfile.lock +41 -0
  11. data/Rakefile +16 -0
  12. data/bin/passenger +2 -2
  13. data/bin/passenger-install-apache2-module +12 -12
  14. data/bin/passenger-install-nginx-module +9 -14
  15. data/bin/passenger-status +125 -87
  16. data/build/agents.rb +112 -140
  17. data/build/apache2.rb +4 -9
  18. data/build/basics.rb +5 -3
  19. data/build/common_library.rb +1 -0
  20. data/build/cxx_tests.rb +69 -47
  21. data/build/debian.rb +4 -2
  22. data/build/documentation.rb +1 -0
  23. data/build/integration_tests.rb +28 -43
  24. data/build/misc.rb +0 -18
  25. data/build/nginx.rb +2 -6
  26. data/build/packaging.rb +33 -22
  27. data/build/preprocessor.rb +2 -4
  28. data/build/ruby_tests.rb +7 -26
  29. data/build/test_basics.rb +24 -25
  30. data/debian.template/control.template +2 -2
  31. data/debian.template/locations.ini.template +2 -3
  32. data/debian.template/passenger.install.template +2 -2
  33. data/debian.template/rules.template +1 -1
  34. data/dev/ci/run_jenkins.sh +0 -1
  35. data/dev/ci/run_rpm_tests.sh +3 -0
  36. data/dev/ci/run_travis.sh +63 -17
  37. data/dev/copy_boost_headers +22 -6
  38. data/dev/ruby_server.rb +244 -0
  39. data/dev/vagrant/provision.sh +3 -1
  40. data/doc/DebuggingAndStressTesting.md +3 -3
  41. data/doc/Design and Architecture.txt +5 -6
  42. data/doc/Packaging.txt.md +35 -6
  43. data/doc/ServerOptimizationGuide.txt.md +339 -0
  44. data/doc/Users guide Apache.idmap.txt +177 -187
  45. data/doc/Users guide Apache.txt +143 -219
  46. data/doc/Users guide Nginx.idmap.txt +166 -166
  47. data/doc/Users guide Nginx.txt +265 -223
  48. data/doc/Users guide Standalone.txt +3 -3
  49. data/doc/templates/markdown.html.erb +37 -6
  50. data/doc/users_guide_snippets/environment_variables.txt +1 -1
  51. data/doc/users_guide_snippets/support_information.txt +1 -1
  52. data/doc/users_guide_snippets/tips.txt +2 -2
  53. data/ext/apache2/Configuration.cpp +23 -81
  54. data/ext/apache2/Configuration.hpp +18 -92
  55. data/ext/apache2/ConfigurationCommands.cpp +64 -15
  56. data/ext/apache2/ConfigurationCommands.cpp.erb +8 -4
  57. data/ext/apache2/ConfigurationFields.hpp +12 -0
  58. data/ext/apache2/ConfigurationSetters.cpp +73 -1
  59. data/ext/apache2/ConfigurationSetters.cpp.erb +3 -2
  60. data/ext/apache2/CreateDirConfig.cpp +6 -0
  61. data/ext/apache2/DirectoryMapper.h +11 -6
  62. data/ext/apache2/Hooks.cpp +291 -408
  63. data/ext/apache2/MergeDirConfig.cpp +42 -0
  64. data/ext/apache2/SetHeaders.cpp +61 -16
  65. data/ext/apache2/SetHeaders.cpp.erb +9 -7
  66. data/ext/boost/container/allocator_traits.hpp +400 -0
  67. data/ext/boost/container/deque.hpp +2012 -0
  68. data/ext/boost/container/detail/adaptive_node_pool_impl.hpp +874 -0
  69. data/ext/boost/container/detail/advanced_insert_int.hpp +369 -0
  70. data/ext/boost/container/detail/algorithms.hpp +84 -0
  71. data/ext/boost/container/detail/allocation_type.hpp +54 -0
  72. data/ext/boost/container/detail/allocator_version_traits.hpp +163 -0
  73. data/ext/boost/container/detail/config_begin.hpp +49 -0
  74. data/ext/boost/container/detail/config_end.hpp +17 -0
  75. data/ext/boost/container/detail/destroyers.hpp +365 -0
  76. data/ext/boost/container/detail/flat_tree.hpp +1055 -0
  77. data/ext/boost/container/detail/function_detector.hpp +88 -0
  78. data/ext/boost/container/detail/iterators.hpp +611 -0
  79. data/ext/boost/container/detail/math_functions.hpp +113 -0
  80. data/ext/boost/container/detail/memory_util.hpp +83 -0
  81. data/ext/boost/container/detail/mpl.hpp +160 -0
  82. data/ext/boost/container/detail/multiallocation_chain.hpp +286 -0
  83. data/ext/boost/container/detail/node_alloc_holder.hpp +386 -0
  84. data/ext/boost/container/detail/node_pool_impl.hpp +365 -0
  85. data/ext/boost/container/detail/pair.hpp +354 -0
  86. data/ext/boost/container/detail/pool_common.hpp +52 -0
  87. data/ext/boost/container/detail/preprocessor.hpp +232 -0
  88. data/ext/boost/container/detail/transform_iterator.hpp +176 -0
  89. data/ext/boost/container/detail/tree.hpp +1134 -0
  90. data/ext/boost/container/detail/type_traits.hpp +210 -0
  91. data/ext/boost/container/detail/utilities.hpp +1141 -0
  92. data/ext/boost/container/detail/value_init.hpp +45 -0
  93. data/ext/boost/container/detail/variadic_templates_tools.hpp +153 -0
  94. data/ext/boost/container/detail/version_type.hpp +92 -0
  95. data/ext/boost/container/detail/workaround.hpp +44 -0
  96. data/ext/boost/container/flat_map.hpp +1674 -0
  97. data/ext/boost/container/flat_set.hpp +1408 -0
  98. data/ext/boost/container/list.hpp +1475 -0
  99. data/ext/boost/container/map.hpp +1508 -0
  100. data/ext/boost/container/scoped_allocator.hpp +1503 -0
  101. data/ext/boost/container/scoped_allocator_fwd.hpp +83 -0
  102. data/ext/boost/container/set.hpp +1280 -0
  103. data/ext/boost/container/slist.hpp +1706 -0
  104. data/ext/boost/container/stable_vector.hpp +1869 -0
  105. data/ext/boost/container/static_vector.hpp +1053 -0
  106. data/ext/boost/container/string.hpp +2856 -0
  107. data/ext/boost/container/throw_exception.hpp +110 -0
  108. data/ext/boost/container/vector.hpp +2671 -0
  109. data/ext/boost/detail/is_xxx.hpp +61 -0
  110. data/ext/boost/intrusive/any_hook.hpp +344 -0
  111. data/ext/boost/intrusive/avl_set.hpp +2528 -0
  112. data/ext/boost/intrusive/avl_set_hook.hpp +297 -0
  113. data/ext/boost/intrusive/avltree.hpp +1786 -0
  114. data/ext/boost/intrusive/avltree_algorithms.hpp +968 -0
  115. data/ext/boost/intrusive/bs_set_hook.hpp +296 -0
  116. data/ext/boost/intrusive/circular_list_algorithms.hpp +413 -0
  117. data/ext/boost/intrusive/circular_slist_algorithms.hpp +404 -0
  118. data/ext/boost/intrusive/derivation_value_traits.hpp +70 -0
  119. data/ext/boost/intrusive/detail/any_node_and_algorithms.hpp +297 -0
  120. data/ext/boost/intrusive/detail/assert.hpp +41 -0
  121. data/ext/boost/intrusive/detail/avltree_node.hpp +197 -0
  122. data/ext/boost/intrusive/detail/clear_on_destructor_base.hpp +36 -0
  123. data/ext/boost/intrusive/detail/common_slist_algorithms.hpp +102 -0
  124. data/ext/boost/intrusive/detail/config_begin.hpp +52 -0
  125. data/ext/boost/intrusive/detail/config_end.hpp +15 -0
  126. data/ext/boost/intrusive/detail/ebo_functor_holder.hpp +95 -0
  127. data/ext/boost/intrusive/detail/function_detector.hpp +88 -0
  128. data/ext/boost/intrusive/detail/generic_hook.hpp +209 -0
  129. data/ext/boost/intrusive/detail/has_member_function_callable_with.hpp +357 -0
  130. data/ext/boost/intrusive/detail/hashtable_node.hpp +249 -0
  131. data/ext/boost/intrusive/detail/is_stateful_value_traits.hpp +77 -0
  132. data/ext/boost/intrusive/detail/list_node.hpp +196 -0
  133. data/ext/boost/intrusive/detail/memory_util.hpp +288 -0
  134. data/ext/boost/intrusive/detail/mpl.hpp +383 -0
  135. data/ext/boost/intrusive/detail/parent_from_member.hpp +97 -0
  136. data/ext/boost/intrusive/detail/preprocessor.hpp +52 -0
  137. data/ext/boost/intrusive/detail/rbtree_node.hpp +201 -0
  138. data/ext/boost/intrusive/detail/slist_node.hpp +166 -0
  139. data/ext/boost/intrusive/detail/transform_iterator.hpp +173 -0
  140. data/ext/boost/intrusive/detail/tree_algorithms.hpp +1742 -0
  141. data/ext/boost/intrusive/detail/tree_node.hpp +199 -0
  142. data/ext/boost/intrusive/detail/utilities.hpp +858 -0
  143. data/ext/boost/intrusive/detail/workaround.hpp +22 -0
  144. data/ext/boost/intrusive/hashtable.hpp +3110 -0
  145. data/ext/boost/intrusive/intrusive_fwd.hpp +542 -0
  146. data/ext/boost/intrusive/linear_slist_algorithms.hpp +327 -0
  147. data/ext/boost/intrusive/link_mode.hpp +46 -0
  148. data/ext/boost/intrusive/list.hpp +1525 -0
  149. data/ext/boost/intrusive/list_hook.hpp +290 -0
  150. data/ext/boost/intrusive/member_value_traits.hpp +70 -0
  151. data/ext/boost/intrusive/options.hpp +810 -0
  152. data/ext/boost/intrusive/parent_from_member.hpp +42 -0
  153. data/ext/boost/intrusive/pointer_plus_bits.hpp +86 -0
  154. data/ext/boost/intrusive/pointer_traits.hpp +265 -0
  155. data/ext/boost/intrusive/priority_compare.hpp +39 -0
  156. data/ext/boost/intrusive/rbtree.hpp +1785 -0
  157. data/ext/boost/intrusive/rbtree_algorithms.hpp +934 -0
  158. data/ext/boost/intrusive/set.hpp +2554 -0
  159. data/ext/boost/intrusive/set_hook.hpp +300 -0
  160. data/ext/boost/intrusive/sg_set.hpp +2601 -0
  161. data/ext/boost/intrusive/sgtree.hpp +2009 -0
  162. data/ext/boost/intrusive/sgtree_algorithms.hpp +807 -0
  163. data/ext/boost/intrusive/slist.hpp +2219 -0
  164. data/ext/boost/intrusive/slist_hook.hpp +294 -0
  165. data/ext/boost/intrusive/splay_set.hpp +2575 -0
  166. data/ext/boost/intrusive/splay_set_hook.hpp +292 -0
  167. data/ext/boost/intrusive/splaytree.hpp +1784 -0
  168. data/ext/boost/intrusive/splaytree_algorithms.hpp +1008 -0
  169. data/ext/boost/intrusive/treap.hpp +1882 -0
  170. data/ext/boost/intrusive/treap_algorithms.hpp +919 -0
  171. data/ext/boost/intrusive/treap_set.hpp +2751 -0
  172. data/ext/boost/intrusive/trivial_value_traits.hpp +46 -0
  173. data/ext/boost/intrusive/unordered_set.hpp +2115 -0
  174. data/ext/boost/intrusive/unordered_set_hook.hpp +434 -0
  175. data/ext/boost/intrusive_ptr.hpp +18 -0
  176. data/ext/boost/math/common_factor_ct.hpp +180 -0
  177. data/ext/boost/math_fwd.hpp +108 -0
  178. data/ext/boost/move/detail/move_helpers.hpp +175 -0
  179. data/ext/boost/parameter.hpp +21 -0
  180. data/ext/boost/parameter/aux_/arg_list.hpp +459 -0
  181. data/ext/boost/parameter/aux_/cast.hpp +143 -0
  182. data/ext/boost/parameter/aux_/default.hpp +69 -0
  183. data/ext/boost/parameter/aux_/is_maybe.hpp +26 -0
  184. data/ext/boost/parameter/aux_/maybe.hpp +120 -0
  185. data/ext/boost/parameter/aux_/overloads.hpp +88 -0
  186. data/ext/boost/parameter/aux_/parameter_requirements.hpp +25 -0
  187. data/ext/boost/parameter/aux_/parenthesized_type.hpp +119 -0
  188. data/ext/boost/parameter/aux_/preprocessor/flatten.hpp +115 -0
  189. data/ext/boost/parameter/aux_/preprocessor/for_each.hpp +103 -0
  190. data/ext/boost/parameter/aux_/python/invoker.hpp +132 -0
  191. data/ext/boost/parameter/aux_/python/invoker_iterate.hpp +93 -0
  192. data/ext/boost/parameter/aux_/result_of0.hpp +36 -0
  193. data/ext/boost/parameter/aux_/set.hpp +67 -0
  194. data/ext/boost/parameter/aux_/tag.hpp +38 -0
  195. data/ext/boost/parameter/aux_/tagged_argument.hpp +188 -0
  196. data/ext/boost/parameter/aux_/template_keyword.hpp +47 -0
  197. data/ext/boost/parameter/aux_/unwrap_cv_reference.hpp +97 -0
  198. data/ext/boost/parameter/aux_/void.hpp +29 -0
  199. data/ext/boost/parameter/aux_/yesno.hpp +26 -0
  200. data/ext/boost/parameter/binding.hpp +106 -0
  201. data/ext/boost/parameter/config.hpp +14 -0
  202. data/ext/boost/parameter/keyword.hpp +152 -0
  203. data/ext/boost/parameter/macros.hpp +99 -0
  204. data/ext/boost/parameter/match.hpp +55 -0
  205. data/ext/boost/parameter/name.hpp +156 -0
  206. data/ext/boost/parameter/parameters.hpp +931 -0
  207. data/ext/boost/parameter/preprocessor.hpp +1178 -0
  208. data/ext/boost/parameter/python.hpp +735 -0
  209. data/ext/boost/parameter/value_type.hpp +108 -0
  210. data/ext/boost/pool/detail/for.m4 +107 -0
  211. data/ext/boost/pool/detail/guard.hpp +69 -0
  212. data/ext/boost/pool/detail/mutex.hpp +42 -0
  213. data/ext/boost/pool/detail/pool_construct.bat +24 -0
  214. data/ext/boost/pool/detail/pool_construct.ipp +852 -0
  215. data/ext/boost/pool/detail/pool_construct.m4 +84 -0
  216. data/ext/boost/pool/detail/pool_construct.sh +12 -0
  217. data/ext/boost/pool/detail/pool_construct_simple.bat +25 -0
  218. data/ext/boost/pool/detail/pool_construct_simple.ipp +43 -0
  219. data/ext/boost/pool/detail/pool_construct_simple.m4 +72 -0
  220. data/ext/boost/pool/detail/pool_construct_simple.sh +12 -0
  221. data/ext/boost/pool/object_pool.hpp +287 -0
  222. data/ext/boost/pool/pool.hpp +1024 -0
  223. data/ext/boost/pool/pool_alloc.hpp +488 -0
  224. data/ext/boost/pool/poolfwd.hpp +82 -0
  225. data/ext/boost/pool/simple_segregated_storage.hpp +377 -0
  226. data/ext/boost/pool/singleton_pool.hpp +251 -0
  227. data/ext/boost/preprocessor/arithmetic.hpp +25 -0
  228. data/ext/boost/preprocessor/arithmetic/detail/div_base.hpp +61 -0
  229. data/ext/boost/preprocessor/arithmetic/div.hpp +39 -0
  230. data/ext/boost/preprocessor/arithmetic/mod.hpp +39 -0
  231. data/ext/boost/preprocessor/arithmetic/mul.hpp +53 -0
  232. data/ext/boost/preprocessor/array.hpp +32 -0
  233. data/ext/boost/preprocessor/array/enum.hpp +33 -0
  234. data/ext/boost/preprocessor/array/insert.hpp +55 -0
  235. data/ext/boost/preprocessor/array/pop_back.hpp +37 -0
  236. data/ext/boost/preprocessor/array/pop_front.hpp +38 -0
  237. data/ext/boost/preprocessor/array/push_back.hpp +33 -0
  238. data/ext/boost/preprocessor/array/push_front.hpp +33 -0
  239. data/ext/boost/preprocessor/array/remove.hpp +54 -0
  240. data/ext/boost/preprocessor/array/replace.hpp +49 -0
  241. data/ext/boost/preprocessor/array/reverse.hpp +29 -0
  242. data/ext/boost/preprocessor/array/to_list.hpp +33 -0
  243. data/ext/boost/preprocessor/array/to_seq.hpp +33 -0
  244. data/ext/boost/preprocessor/array/to_tuple.hpp +22 -0
  245. data/ext/boost/preprocessor/assert_msg.hpp +17 -0
  246. data/ext/boost/preprocessor/comma.hpp +17 -0
  247. data/ext/boost/preprocessor/comparison.hpp +24 -0
  248. data/ext/boost/preprocessor/comparison/equal.hpp +34 -0
  249. data/ext/boost/preprocessor/comparison/greater.hpp +38 -0
  250. data/ext/boost/preprocessor/comparison/greater_equal.hpp +38 -0
  251. data/ext/boost/preprocessor/comparison/less.hpp +46 -0
  252. data/ext/boost/preprocessor/comparison/less_equal.hpp +39 -0
  253. data/ext/boost/preprocessor/comparison/not_equal.hpp +814 -0
  254. data/ext/boost/preprocessor/config/limits.hpp +30 -0
  255. data/ext/boost/preprocessor/control.hpp +22 -0
  256. data/ext/boost/preprocessor/control/deduce_d.hpp +22 -0
  257. data/ext/boost/preprocessor/control/detail/dmc/while.hpp +536 -0
  258. data/ext/boost/preprocessor/control/detail/edg/while.hpp +534 -0
  259. data/ext/boost/preprocessor/control/detail/msvc/while.hpp +277 -0
  260. data/ext/boost/preprocessor/control/expr_if.hpp +30 -0
  261. data/ext/boost/preprocessor/debug.hpp +18 -0
  262. data/ext/boost/preprocessor/debug/assert.hpp +44 -0
  263. data/ext/boost/preprocessor/debug/line.hpp +35 -0
  264. data/ext/boost/preprocessor/detail/dmc/auto_rec.hpp +286 -0
  265. data/ext/boost/preprocessor/detail/is_nullary.hpp +30 -0
  266. data/ext/boost/preprocessor/detail/is_unary.hpp +30 -0
  267. data/ext/boost/preprocessor/detail/null.hpp +17 -0
  268. data/ext/boost/preprocessor/detail/split.hpp +35 -0
  269. data/ext/boost/preprocessor/enum_params_with_defaults.hpp +17 -0
  270. data/ext/boost/preprocessor/enum_shifted.hpp +17 -0
  271. data/ext/boost/preprocessor/expand.hpp +17 -0
  272. data/ext/boost/preprocessor/expr_if.hpp +17 -0
  273. data/ext/boost/preprocessor/facilities.hpp +23 -0
  274. data/ext/boost/preprocessor/facilities/apply.hpp +34 -0
  275. data/ext/boost/preprocessor/facilities/expand.hpp +28 -0
  276. data/ext/boost/preprocessor/facilities/is_1.hpp +23 -0
  277. data/ext/boost/preprocessor/facilities/is_empty.hpp +43 -0
  278. data/ext/boost/preprocessor/facilities/is_empty_or_1.hpp +30 -0
  279. data/ext/boost/preprocessor/for.hpp +17 -0
  280. data/ext/boost/preprocessor/if.hpp +17 -0
  281. data/ext/boost/preprocessor/iteration.hpp +19 -0
  282. data/ext/boost/preprocessor/iteration/detail/bounds/lower3.hpp +99 -0
  283. data/ext/boost/preprocessor/iteration/detail/bounds/lower4.hpp +99 -0
  284. data/ext/boost/preprocessor/iteration/detail/bounds/lower5.hpp +99 -0
  285. data/ext/boost/preprocessor/iteration/detail/bounds/upper3.hpp +99 -0
  286. data/ext/boost/preprocessor/iteration/detail/bounds/upper4.hpp +99 -0
  287. data/ext/boost/preprocessor/iteration/detail/bounds/upper5.hpp +99 -0
  288. data/ext/boost/preprocessor/iteration/detail/finish.hpp +99 -0
  289. data/ext/boost/preprocessor/iteration/detail/iter/forward3.hpp +1338 -0
  290. data/ext/boost/preprocessor/iteration/detail/iter/forward4.hpp +1338 -0
  291. data/ext/boost/preprocessor/iteration/detail/iter/forward5.hpp +1338 -0
  292. data/ext/boost/preprocessor/iteration/detail/iter/reverse2.hpp +1296 -0
  293. data/ext/boost/preprocessor/iteration/detail/iter/reverse3.hpp +1296 -0
  294. data/ext/boost/preprocessor/iteration/detail/iter/reverse4.hpp +1296 -0
  295. data/ext/boost/preprocessor/iteration/detail/iter/reverse5.hpp +1296 -0
  296. data/ext/boost/preprocessor/iteration/detail/local.hpp +812 -0
  297. data/ext/boost/preprocessor/iteration/detail/rlocal.hpp +782 -0
  298. data/ext/boost/preprocessor/iteration/detail/self.hpp +21 -0
  299. data/ext/boost/preprocessor/iteration/detail/start.hpp +99 -0
  300. data/ext/boost/preprocessor/iteration/local.hpp +26 -0
  301. data/ext/boost/preprocessor/iteration/self.hpp +19 -0
  302. data/ext/boost/preprocessor/library.hpp +36 -0
  303. data/ext/boost/preprocessor/limits.hpp +17 -0
  304. data/ext/boost/preprocessor/list.hpp +37 -0
  305. data/ext/boost/preprocessor/list/at.hpp +39 -0
  306. data/ext/boost/preprocessor/list/cat.hpp +42 -0
  307. data/ext/boost/preprocessor/list/detail/dmc/fold_left.hpp +279 -0
  308. data/ext/boost/preprocessor/list/detail/edg/fold_left.hpp +536 -0
  309. data/ext/boost/preprocessor/list/detail/edg/fold_right.hpp +794 -0
  310. data/ext/boost/preprocessor/list/enum.hpp +41 -0
  311. data/ext/boost/preprocessor/list/filter.hpp +54 -0
  312. data/ext/boost/preprocessor/list/first_n.hpp +58 -0
  313. data/ext/boost/preprocessor/list/for_each.hpp +49 -0
  314. data/ext/boost/preprocessor/list/for_each_product.hpp +141 -0
  315. data/ext/boost/preprocessor/list/rest_n.hpp +55 -0
  316. data/ext/boost/preprocessor/list/size.hpp +58 -0
  317. data/ext/boost/preprocessor/list/to_array.hpp +123 -0
  318. data/ext/boost/preprocessor/list/to_seq.hpp +32 -0
  319. data/ext/boost/preprocessor/list/to_tuple.hpp +38 -0
  320. data/ext/boost/preprocessor/logical.hpp +29 -0
  321. data/ext/boost/preprocessor/logical/bitnor.hpp +38 -0
  322. data/ext/boost/preprocessor/logical/bitor.hpp +38 -0
  323. data/ext/boost/preprocessor/logical/bitxor.hpp +38 -0
  324. data/ext/boost/preprocessor/logical/nor.hpp +30 -0
  325. data/ext/boost/preprocessor/logical/not.hpp +30 -0
  326. data/ext/boost/preprocessor/logical/or.hpp +30 -0
  327. data/ext/boost/preprocessor/logical/xor.hpp +30 -0
  328. data/ext/boost/preprocessor/max.hpp +17 -0
  329. data/ext/boost/preprocessor/min.hpp +17 -0
  330. data/ext/boost/preprocessor/punctuation.hpp +20 -0
  331. data/ext/boost/preprocessor/punctuation/paren_if.hpp +38 -0
  332. data/ext/boost/preprocessor/repeat_3rd.hpp +17 -0
  333. data/ext/boost/preprocessor/repeat_from_to.hpp +17 -0
  334. data/ext/boost/preprocessor/repeat_from_to_2nd.hpp +17 -0
  335. data/ext/boost/preprocessor/repeat_from_to_3rd.hpp +17 -0
  336. data/ext/boost/preprocessor/repetition.hpp +32 -0
  337. data/ext/boost/preprocessor/repetition/deduce_r.hpp +22 -0
  338. data/ext/boost/preprocessor/repetition/deduce_z.hpp +22 -0
  339. data/ext/boost/preprocessor/repetition/detail/dmc/for.hpp +536 -0
  340. data/ext/boost/preprocessor/repetition/detail/edg/for.hpp +534 -0
  341. data/ext/boost/preprocessor/repetition/detail/msvc/for.hpp +277 -0
  342. data/ext/boost/preprocessor/repetition/enum_params_with_defaults.hpp +24 -0
  343. data/ext/boost/preprocessor/repetition/enum_shifted.hpp +68 -0
  344. data/ext/boost/preprocessor/repetition/enum_shifted_binary_params.hpp +51 -0
  345. data/ext/boost/preprocessor/repetition/enum_trailing.hpp +63 -0
  346. data/ext/boost/preprocessor/repetition/enum_trailing_binary_params.hpp +53 -0
  347. data/ext/boost/preprocessor/selection.hpp +18 -0
  348. data/ext/boost/preprocessor/selection/max.hpp +39 -0
  349. data/ext/boost/preprocessor/selection/min.hpp +39 -0
  350. data/ext/boost/preprocessor/seq.hpp +43 -0
  351. data/ext/boost/preprocessor/seq/cat.hpp +49 -0
  352. data/ext/boost/preprocessor/seq/detail/binary_transform.hpp +40 -0
  353. data/ext/boost/preprocessor/seq/detail/split.hpp +284 -0
  354. data/ext/boost/preprocessor/seq/filter.hpp +54 -0
  355. data/ext/boost/preprocessor/seq/first_n.hpp +30 -0
  356. data/ext/boost/preprocessor/seq/fold_left.hpp +1070 -0
  357. data/ext/boost/preprocessor/seq/fold_right.hpp +288 -0
  358. data/ext/boost/preprocessor/seq/for_each.hpp +60 -0
  359. data/ext/boost/preprocessor/seq/for_each_product.hpp +126 -0
  360. data/ext/boost/preprocessor/seq/insert.hpp +28 -0
  361. data/ext/boost/preprocessor/seq/pop_back.hpp +29 -0
  362. data/ext/boost/preprocessor/seq/pop_front.hpp +27 -0
  363. data/ext/boost/preprocessor/seq/push_back.hpp +19 -0
  364. data/ext/boost/preprocessor/seq/push_front.hpp +19 -0
  365. data/ext/boost/preprocessor/seq/remove.hpp +29 -0
  366. data/ext/boost/preprocessor/seq/replace.hpp +29 -0
  367. data/ext/boost/preprocessor/seq/rest_n.hpp +30 -0
  368. data/ext/boost/preprocessor/seq/reverse.hpp +39 -0
  369. data/ext/boost/preprocessor/seq/subseq.hpp +28 -0
  370. data/ext/boost/preprocessor/seq/to_array.hpp +28 -0
  371. data/ext/boost/preprocessor/seq/to_list.hpp +29 -0
  372. data/ext/boost/preprocessor/seq/to_tuple.hpp +27 -0
  373. data/ext/boost/preprocessor/seq/transform.hpp +48 -0
  374. data/ext/boost/preprocessor/slot.hpp +17 -0
  375. data/ext/boost/preprocessor/slot/counter.hpp +25 -0
  376. data/ext/boost/preprocessor/slot/detail/counter.hpp +269 -0
  377. data/ext/boost/preprocessor/slot/detail/slot1.hpp +267 -0
  378. data/ext/boost/preprocessor/slot/detail/slot2.hpp +267 -0
  379. data/ext/boost/preprocessor/slot/detail/slot3.hpp +267 -0
  380. data/ext/boost/preprocessor/slot/detail/slot4.hpp +267 -0
  381. data/ext/boost/preprocessor/slot/detail/slot5.hpp +267 -0
  382. data/ext/boost/preprocessor/tuple.hpp +28 -0
  383. data/ext/boost/preprocessor/tuple/enum.hpp +22 -0
  384. data/ext/boost/preprocessor/tuple/reverse.hpp +114 -0
  385. data/ext/boost/preprocessor/tuple/size.hpp +28 -0
  386. data/ext/boost/preprocessor/tuple/to_array.hpp +37 -0
  387. data/ext/boost/preprocessor/tuple/to_seq.hpp +114 -0
  388. data/ext/boost/preprocessor/variadic.hpp +23 -0
  389. data/ext/boost/preprocessor/variadic/to_array.hpp +32 -0
  390. data/ext/boost/preprocessor/variadic/to_list.hpp +25 -0
  391. data/ext/boost/preprocessor/variadic/to_seq.hpp +25 -0
  392. data/ext/boost/preprocessor/variadic/to_tuple.hpp +24 -0
  393. data/ext/boost/preprocessor/while.hpp +17 -0
  394. data/ext/boost/preprocessor/wstringize.hpp +29 -0
  395. data/ext/boost/smart_ptr/intrusive_ptr.hpp +324 -0
  396. data/ext/common/AccountsDatabase.h +3 -4
  397. data/ext/common/AgentsStarter.cpp +12 -15
  398. data/ext/common/AgentsStarter.h +54 -120
  399. data/ext/common/ApplicationPool2/AppTypes.cpp +12 -5
  400. data/ext/common/ApplicationPool2/AppTypes.h +21 -14
  401. data/ext/common/ApplicationPool2/Common.h +36 -19
  402. data/ext/common/ApplicationPool2/DirectSpawner.h +15 -16
  403. data/ext/common/ApplicationPool2/DummySpawner.h +9 -8
  404. data/ext/common/ApplicationPool2/ErrorRenderer.h +1 -1
  405. data/ext/common/ApplicationPool2/Group.h +304 -171
  406. data/ext/common/ApplicationPool2/Implementation.cpp +234 -125
  407. data/ext/common/ApplicationPool2/Options.h +50 -62
  408. data/ext/common/ApplicationPool2/Pool.h +285 -189
  409. data/ext/common/ApplicationPool2/Process.h +126 -115
  410. data/ext/common/ApplicationPool2/Session.h +70 -30
  411. data/ext/common/ApplicationPool2/SmartSpawner.h +19 -18
  412. data/ext/common/ApplicationPool2/Socket.h +57 -43
  413. data/ext/common/ApplicationPool2/SpawnObject.h +83 -0
  414. data/ext/common/ApplicationPool2/Spawner.h +59 -38
  415. data/ext/common/ApplicationPool2/SpawnerFactory.h +8 -14
  416. data/ext/common/ApplicationPool2/SuperGroup.h +69 -40
  417. data/ext/common/BackgroundEventLoop.cpp +48 -1
  418. data/ext/common/BackgroundEventLoop.h +3 -1
  419. data/ext/common/Constants.h +30 -8
  420. data/ext/common/DataStructures/HashedStaticString.h +103 -0
  421. data/ext/common/DataStructures/LString.h +396 -0
  422. data/ext/common/DataStructures/StringKeyTable.h +588 -0
  423. data/ext/common/EventedMessageServer.h +1 -0
  424. data/ext/common/FileDescriptor.h +5 -0
  425. data/ext/common/InstanceDirectory.h +240 -0
  426. data/ext/common/Logging.cpp +38 -13
  427. data/ext/common/Logging.h +53 -22
  428. data/ext/common/MemoryKit/mbuf.cpp +413 -0
  429. data/ext/common/MemoryKit/mbuf.h +266 -0
  430. data/ext/common/MemoryKit/palloc.cpp +337 -0
  431. data/ext/common/MemoryKit/palloc.h +121 -0
  432. data/ext/common/ResourceLocator.h +62 -6
  433. data/ext/common/SafeLibev.h +4 -4
  434. data/ext/common/ServerKit/AcceptLoadBalancer.h +275 -0
  435. data/ext/common/ServerKit/Channel.h +747 -0
  436. data/ext/common/ServerKit/Client.h +166 -0
  437. data/ext/common/ServerKit/ClientRef.h +130 -0
  438. data/ext/common/ServerKit/Context.h +129 -0
  439. data/ext/common/ServerKit/Errors.h +103 -0
  440. data/ext/common/ServerKit/FdSinkChannel.h +206 -0
  441. data/ext/common/ServerKit/FdSourceChannel.h +230 -0
  442. data/ext/common/ServerKit/FileBufferedChannel.h +1399 -0
  443. data/ext/common/ServerKit/FileBufferedFdSinkChannel.h +228 -0
  444. data/ext/common/ServerKit/HeaderTable.h +472 -0
  445. data/ext/common/ServerKit/Hooks.h +79 -0
  446. data/ext/common/ServerKit/HttpChunkedBodyParser.h +289 -0
  447. data/ext/common/ServerKit/HttpChunkedBodyParserState.h +70 -0
  448. data/ext/common/ServerKit/HttpClient.h +94 -0
  449. data/ext/common/ServerKit/HttpHeaderParser.h +477 -0
  450. data/ext/common/ServerKit/HttpHeaderParserState.h +60 -0
  451. data/ext/common/ServerKit/HttpRequest.h +276 -0
  452. data/ext/common/ServerKit/HttpRequestRef.h +130 -0
  453. data/ext/common/ServerKit/HttpServer.h +1152 -0
  454. data/ext/common/ServerKit/Implementation.cpp +47 -0
  455. data/ext/common/ServerKit/Server.h +1040 -0
  456. data/ext/common/ServerKit/http_parser.cpp +2259 -0
  457. data/ext/common/ServerKit/http_parser.h +330 -0
  458. data/ext/common/StaticString.h +8 -0
  459. data/ext/common/Utils.cpp +14 -12
  460. data/ext/common/Utils.h +9 -103
  461. data/ext/common/Utils/BufferedIO.h +1 -0
  462. data/ext/common/Utils/CachedFileStat.hpp +1 -7
  463. data/ext/common/Utils/DateParsing.h +379 -0
  464. data/ext/common/Utils/FileChangeChecker.h +3 -9
  465. data/ext/common/Utils/Hasher.cpp +52 -0
  466. data/ext/common/Utils/Hasher.h +58 -0
  467. data/ext/common/Utils/IOUtils.cpp +62 -62
  468. data/ext/common/Utils/JsonUtils.h +21 -0
  469. data/ext/common/Utils/OptionParsing.h +75 -0
  470. data/ext/common/Utils/StrIntUtils.cpp +112 -19
  471. data/ext/common/Utils/StrIntUtils.h +52 -12
  472. data/ext/common/Utils/StrIntUtilsNoStrictAliasing.cpp +174 -0
  473. data/ext/common/Utils/VariantMap.h +18 -7
  474. data/ext/common/Utils/modp_b64.cpp +290 -0
  475. data/ext/common/Utils/modp_b64.h +241 -0
  476. data/ext/common/Utils/modp_b64_data.h +479 -0
  477. data/ext/common/Utils/sysqueue.h +811 -0
  478. data/ext/common/agents/Base.cpp +71 -98
  479. data/ext/common/agents/Base.h +11 -3
  480. data/ext/common/agents/HelperAgent/AdminServer.h +690 -0
  481. data/ext/common/agents/HelperAgent/Main.cpp +899 -487
  482. data/ext/common/agents/HelperAgent/OptionParser.h +311 -0
  483. data/ext/common/agents/HelperAgent/RequestHandler.h +315 -2548
  484. data/ext/common/agents/HelperAgent/RequestHandler/AppResponse.h +225 -0
  485. data/ext/common/agents/HelperAgent/RequestHandler/BufferBody.cpp +93 -0
  486. data/ext/common/agents/HelperAgent/RequestHandler/CheckoutSession.cpp +346 -0
  487. data/ext/common/agents/HelperAgent/RequestHandler/Client.h +54 -0
  488. data/ext/common/agents/HelperAgent/RequestHandler/ForwardResponse.cpp +846 -0
  489. data/ext/common/agents/HelperAgent/RequestHandler/Hooks.cpp +231 -0
  490. data/ext/common/agents/HelperAgent/RequestHandler/InitRequest.cpp +434 -0
  491. data/ext/common/agents/HelperAgent/RequestHandler/Request.h +149 -0
  492. data/ext/common/agents/HelperAgent/RequestHandler/SendRequest.cpp +887 -0
  493. data/ext/common/agents/HelperAgent/RequestHandler/TurboCaching.h +293 -0
  494. data/ext/common/agents/HelperAgent/RequestHandler/Utils.cpp +301 -0
  495. data/ext/common/agents/HelperAgent/ResponseCache.h +624 -0
  496. data/ext/common/agents/HelperAgent/SystemMetricsTool.cpp +21 -23
  497. data/ext/common/agents/LoggingAgent/AdminServer.h +369 -0
  498. data/ext/common/agents/LoggingAgent/LoggingServer.h +1 -0
  499. data/ext/common/agents/LoggingAgent/Main.cpp +422 -215
  500. data/ext/common/agents/LoggingAgent/OptionParser.h +167 -0
  501. data/ext/common/agents/LoggingAgent/RemoteSender.h +3 -3
  502. data/ext/common/agents/Main.cpp +107 -0
  503. data/ext/common/agents/SpawnPreparer/Main.cpp +207 -0
  504. data/ext/common/agents/TempDirToucher/Main.cpp +429 -0
  505. data/ext/common/agents/Watchdog/AdminServer.h +390 -0
  506. data/ext/common/agents/Watchdog/AgentWatcher.cpp +7 -5
  507. data/ext/common/agents/Watchdog/HelperAgentWatcher.cpp +18 -39
  508. data/ext/common/agents/Watchdog/InstanceDirToucher.cpp +116 -0
  509. data/ext/common/agents/Watchdog/LoggingAgentWatcher.cpp +13 -17
  510. data/ext/common/agents/Watchdog/Main.cpp +743 -202
  511. data/ext/libeio/eio.c +17 -0
  512. data/ext/libeio/eio.h +2 -0
  513. data/ext/nginx/CacheLocationConfig.c +177 -198
  514. data/ext/nginx/CacheLocationConfig.c.erb +35 -22
  515. data/ext/nginx/Configuration.c +402 -236
  516. data/ext/nginx/Configuration.h +12 -5
  517. data/ext/nginx/ConfigurationCommands.c +35 -15
  518. data/ext/nginx/ConfigurationCommands.c.erb +4 -4
  519. data/ext/nginx/ConfigurationFields.h +9 -5
  520. data/ext/nginx/ConfigurationFields.h.erb +3 -1
  521. data/ext/nginx/ContentHandler.c +393 -362
  522. data/ext/nginx/CreateLocationConfig.c +8 -4
  523. data/ext/nginx/CreateLocationConfig.c.erb +8 -3
  524. data/ext/nginx/MergeLocationConfig.c +36 -6
  525. data/ext/nginx/MergeLocationConfig.c.erb +42 -1
  526. data/ext/nginx/ngx_http_passenger_module.c +28 -15
  527. data/ext/oxt/detail/backtrace_disabled.hpp +2 -1
  528. data/ext/oxt/detail/backtrace_enabled.hpp +15 -2
  529. data/ext/oxt/implementation.cpp +92 -20
  530. data/ext/oxt/thread.hpp +5 -0
  531. data/ext/ruby/extconf.rb +3 -6
  532. data/ext/ruby/passenger_native_support.c +13 -40
  533. data/helper-scripts/download_binaries/extconf.rb +4 -4
  534. data/helper-scripts/meteor-loader.rb +12 -112
  535. data/helper-scripts/node-loader.js +3 -91
  536. data/helper-scripts/rack-loader.rb +13 -14
  537. data/helper-scripts/rack-preloader.rb +16 -17
  538. data/helper-scripts/wsgi-loader.py +11 -7
  539. data/lib/phusion_passenger.rb +100 -79
  540. data/lib/phusion_passenger/abstract_installer.rb +28 -3
  541. data/lib/phusion_passenger/admin_tools.rb +3 -3
  542. data/lib/phusion_passenger/admin_tools/instance.rb +207 -0
  543. data/lib/phusion_passenger/admin_tools/instance_registry.rb +98 -0
  544. data/lib/phusion_passenger/apache2/config_options.rb +72 -22
  545. data/lib/phusion_passenger/common_library.rb +79 -14
  546. data/lib/phusion_passenger/config/about_command.rb +17 -23
  547. data/lib/phusion_passenger/config/admin_command_command.rb +175 -0
  548. data/lib/phusion_passenger/config/agent_compiler.rb +170 -0
  549. data/lib/phusion_passenger/config/command.rb +1 -4
  550. data/lib/phusion_passenger/config/compile_agent_command.rb +102 -0
  551. data/lib/phusion_passenger/config/compile_nginx_engine_command.rb +112 -0
  552. data/lib/phusion_passenger/config/detach_process_command.rb +32 -10
  553. data/lib/phusion_passenger/config/download_agent_command.rb +285 -0
  554. data/lib/phusion_passenger/config/download_nginx_engine_command.rb +281 -0
  555. data/lib/phusion_passenger/config/install_agent_command.rb +174 -0
  556. data/lib/phusion_passenger/config/install_standalone_runtime_command.rb +231 -0
  557. data/lib/phusion_passenger/config/installation_utils.rb +241 -0
  558. data/lib/phusion_passenger/config/list_instances_command.rb +13 -25
  559. data/lib/phusion_passenger/config/main.rb +43 -14
  560. data/lib/phusion_passenger/config/nginx_engine_compiler.rb +337 -0
  561. data/lib/phusion_passenger/config/reopen_logs_command.rb +110 -0
  562. data/lib/phusion_passenger/config/restart_app_command.rb +61 -14
  563. data/lib/phusion_passenger/config/system_metrics_command.rb +2 -1
  564. data/lib/phusion_passenger/config/utils.rb +64 -39
  565. data/lib/phusion_passenger/config/validate_install_command.rb +2 -2
  566. data/lib/phusion_passenger/constants.rb +27 -6
  567. data/lib/phusion_passenger/debug_logging.rb +32 -15
  568. data/lib/phusion_passenger/loader_shared_helpers.rb +2 -5
  569. data/lib/phusion_passenger/message_client.rb +21 -22
  570. data/lib/phusion_passenger/native_support.rb +26 -31
  571. data/lib/phusion_passenger/nginx/config_options.rb +32 -19
  572. data/lib/phusion_passenger/packaging.rb +7 -3
  573. data/lib/phusion_passenger/platform_info/cxx_portability.rb +1 -2
  574. data/lib/phusion_passenger/platform_info/depcheck_specs/libs.rb +3 -4
  575. data/lib/phusion_passenger/platform_info/operating_system.rb +6 -6
  576. data/lib/phusion_passenger/preloader_shared_helpers.rb +2 -2
  577. data/lib/phusion_passenger/rack/out_of_band_gc.rb +2 -2
  578. data/lib/phusion_passenger/rack/thread_handler_extension.rb +168 -65
  579. data/lib/phusion_passenger/request_handler.rb +47 -82
  580. data/lib/phusion_passenger/request_handler/thread_handler.rb +46 -10
  581. data/lib/phusion_passenger/ruby_core_enhancements.rb +25 -77
  582. data/lib/phusion_passenger/ruby_core_io_enhancements.rb +108 -0
  583. data/lib/phusion_passenger/standalone/app_finder.rb +39 -59
  584. data/lib/phusion_passenger/standalone/command.rb +27 -275
  585. data/lib/phusion_passenger/standalone/command2.rb +292 -0
  586. data/lib/phusion_passenger/standalone/config_utils.rb +87 -0
  587. data/lib/phusion_passenger/standalone/control_utils.rb +88 -0
  588. data/lib/phusion_passenger/standalone/main.rb +69 -71
  589. data/lib/phusion_passenger/standalone/start2_command.rb +799 -0
  590. data/lib/phusion_passenger/standalone/start_command.rb +406 -467
  591. data/lib/phusion_passenger/standalone/start_command/builtin_engine.rb +167 -0
  592. data/lib/phusion_passenger/standalone/start_command/nginx_engine.rb +165 -0
  593. data/lib/phusion_passenger/standalone/status_command.rb +64 -23
  594. data/lib/phusion_passenger/standalone/stop_command.rb +69 -32
  595. data/lib/phusion_passenger/standalone/version_command.rb +1 -5
  596. data/lib/phusion_passenger/utils.rb +0 -4
  597. data/lib/phusion_passenger/utils/json.rb +70 -4
  598. data/lib/phusion_passenger/utils/progress_bar.rb +56 -0
  599. data/lib/phusion_passenger/utils/tee_input.rb +3 -3
  600. data/lib/phusion_passenger/utils/unseekable_socket.rb +30 -0
  601. data/packaging/rpm/nginx_spec/nginx.spec.template +4 -3
  602. data/packaging/rpm/passenger_spec/passenger.spec.template +6 -10
  603. data/packaging/rpm/setup-system +2 -1
  604. data/resources/oss-binaries.phusionpassenger.com.crt +208 -0
  605. data/resources/templates/config/agent_compiler/confirm_enable_optimizations.txt.erb +5 -0
  606. data/resources/templates/config/installation_utils/cannot_create_user_support_binaries_dir.txt.erb +15 -0
  607. data/resources/templates/config/installation_utils/download_tool_missing.txt.erb +7 -0
  608. data/resources/templates/config/installation_utils/passenger_not_installed_as_root.txt.erb +12 -0
  609. data/resources/templates/config/installation_utils/support_binaries_dir_not_writable_despite_running_as_root.txt.erb +13 -0
  610. data/resources/templates/config/installation_utils/unexpected_filesystem_problem.txt.erb +16 -0
  611. data/{packaging/debian/debian_specs/passenger/patches/series → resources/templates/config/installation_utils/user_support_binaries_dir_not_writable.txt.erb} +0 -0
  612. data/resources/templates/nginx/nginx_module_sources_not_available.txt.erb +2 -2
  613. data/resources/templates/standalone/config.erb +14 -16
  614. data/resources/templates/standalone/possible_solutions_for_download_and_extraction_problems.txt.erb +1 -1
  615. data/test/.rspec +1 -0
  616. data/test/cxx/ApplicationPool2/DirectSpawnerTest.cpp +20 -17
  617. data/test/cxx/ApplicationPool2/OptionsTest.cpp +0 -14
  618. data/test/cxx/ApplicationPool2/PoolTest.cpp +113 -90
  619. data/test/cxx/ApplicationPool2/ProcessTest.cpp +18 -27
  620. data/test/cxx/ApplicationPool2/SmartSpawnerTest.cpp +51 -53
  621. data/test/cxx/ApplicationPool2/SpawnerTestCases.cpp +55 -57
  622. data/test/cxx/BufferedIOTest.cpp +40 -40
  623. data/test/cxx/CxxTestMain.cpp +4 -22
  624. data/test/cxx/DataStructures/LStringTest.cpp +275 -0
  625. data/test/cxx/DataStructures/StringKeyTableTest.cpp +199 -0
  626. data/test/cxx/MemoryKit/MbufTest.cpp +213 -0
  627. data/test/cxx/MessageServerTest.cpp +62 -55
  628. data/test/cxx/RequestHandlerTest.cpp +26 -27
  629. data/test/cxx/ServerKit/ChannelTest.cpp +1467 -0
  630. data/test/cxx/ServerKit/FileBufferedChannelTest.cpp +817 -0
  631. data/test/cxx/ServerKit/HeaderTableTest.cpp +171 -0
  632. data/test/cxx/ServerKit/HttpServerTest.cpp +1503 -0
  633. data/test/cxx/ServerKit/ServerTest.cpp +408 -0
  634. data/test/cxx/TestSupport.cpp +51 -15
  635. data/test/cxx/TestSupport.h +31 -21
  636. data/test/cxx/UnionStationTest.cpp +121 -122
  637. data/test/cxx/UtilsTest.cpp +9 -33
  638. data/test/integration_tests/apache2_tests.rb +65 -27
  639. data/test/integration_tests/downloaded_binaries_tests.rb +30 -6
  640. data/test/integration_tests/native_packaging_spec.rb +32 -17
  641. data/test/integration_tests/nginx_tests.rb +28 -10
  642. data/test/integration_tests/shared/example_webapp_tests.rb +40 -27
  643. data/test/integration_tests/standalone_tests.rb +232 -169
  644. data/test/ruby/debug_logging_spec.rb +44 -40
  645. data/test/ruby/rails3.0/preloader_spec.rb +1 -1
  646. data/test/ruby/rails3.1/preloader_spec.rb +1 -1
  647. data/test/ruby/rails3.2/preloader_spec.rb +1 -1
  648. data/test/ruby/rails4.0/preloader_spec.rb +1 -1
  649. data/test/ruby/rails4.1/preloader_spec.rb +1 -1
  650. data/test/ruby/request_handler_spec.rb +62 -24
  651. data/test/ruby/shared/loader_sharedspec.rb +10 -9
  652. data/test/ruby/shared/rails/union_station_extensions_sharedspec.rb +23 -22
  653. data/test/ruby/spec_helper.rb +2 -11
  654. data/test/ruby/standalone/runtime_installer_spec.rb +15 -13
  655. data/test/ruby/union_station_spec.rb +45 -40
  656. data/test/ruby/utils/tee_input_spec.rb +5 -5
  657. data/test/ruby/utils_spec.rb +3 -39
  658. data/test/stub/apache2/httpd.conf.erb +5 -2
  659. data/test/stub/nginx/nginx.conf.erb +3 -1
  660. data/test/support/apache2_controller.rb +25 -25
  661. data/test/support/nginx_controller.rb +14 -14
  662. data/test/support/test_helper.rb +74 -75
  663. metadata +439 -643
  664. metadata.gz.asc +7 -7
  665. data/ext/common/MultiLibeio.cpp +0 -204
  666. data/ext/common/MultiLibeio.h +0 -67
  667. data/ext/common/ServerInstanceDir.h +0 -402
  668. data/ext/common/Utils/Base64.cpp +0 -143
  669. data/ext/common/Utils/Base64.h +0 -83
  670. data/ext/common/Utils/HttpHeaderBufferer.h +0 -184
  671. data/ext/common/Utils/PriorityQueue.h +0 -54
  672. data/ext/common/Utils/StreamBoyerMooreHorspool.h +0 -512
  673. data/ext/common/Utils/fib.c +0 -699
  674. data/ext/common/Utils/fib.h +0 -101
  675. data/ext/common/Utils/fibpriv.h +0 -67
  676. data/ext/common/agents/EnvPrinter.c +0 -16
  677. data/ext/common/agents/HelperAgent/AgentOptions.h +0 -109
  678. data/ext/common/agents/HelperAgent/FileBackedPipe.h +0 -732
  679. data/ext/common/agents/HelperAgent/RequestHandler.cpp +0 -294
  680. data/ext/common/agents/HelperAgent/ScgiRequestParser.h +0 -457
  681. data/ext/common/agents/LoggingAgent/AdminController.h +0 -96
  682. data/ext/common/agents/SpawnPreparer.cpp +0 -206
  683. data/ext/common/agents/TempDirToucher.c +0 -383
  684. data/ext/common/agents/Watchdog/ServerInstanceDirToucher.cpp +0 -116
  685. data/helper-scripts/classic-rails-loader.rb +0 -166
  686. data/helper-scripts/classic-rails-preloader.rb +0 -193
  687. data/lib/phusion_passenger/admin_tools/server_instance.rb +0 -339
  688. data/lib/phusion_passenger/classic_rails/cgi_fixed.rb +0 -68
  689. data/lib/phusion_passenger/classic_rails/thread_handler_extension.rb +0 -40
  690. data/lib/phusion_passenger/platform_info/openssl.rb +0 -61
  691. data/lib/phusion_passenger/standalone/config_file.rb +0 -119
  692. data/lib/phusion_passenger/standalone/help_command.rb +0 -57
  693. data/lib/phusion_passenger/standalone/runtime_installer.rb +0 -712
  694. data/lib/phusion_passenger/standalone/runtime_locator.rb +0 -170
  695. data/lib/phusion_passenger/standalone/utils.rb +0 -58
  696. data/lib/phusion_passenger/utils/tmpdir.rb +0 -69
  697. data/packaging/debian/LICENSE.md +0 -19
  698. data/packaging/debian/README.md +0 -320
  699. data/packaging/debian/Vagrantfile +0 -25
  700. data/packaging/debian/build +0 -210
  701. data/packaging/debian/debian_specs/nginx/changelog +0 -1989
  702. data/packaging/debian/debian_specs/nginx/compat.erb +0 -5
  703. data/packaging/debian/debian_specs/nginx/conf/fastcgi.conf +0 -25
  704. data/packaging/debian/debian_specs/nginx/conf/fastcgi_params +0 -24
  705. data/packaging/debian/debian_specs/nginx/conf/koi-utf +0 -109
  706. data/packaging/debian/debian_specs/nginx/conf/koi-win +0 -103
  707. data/packaging/debian/debian_specs/nginx/conf/mime.types +0 -89
  708. data/packaging/debian/debian_specs/nginx/conf/nginx.conf.erb +0 -97
  709. data/packaging/debian/debian_specs/nginx/conf/proxy_params +0 -4
  710. data/packaging/debian/debian_specs/nginx/conf/scgi_params +0 -16
  711. data/packaging/debian/debian_specs/nginx/conf/sites-available/default.erb +0 -93
  712. data/packaging/debian/debian_specs/nginx/conf/snippets/fastcgi-php.conf +0 -13
  713. data/packaging/debian/debian_specs/nginx/conf/snippets/snakeoil.conf +0 -5
  714. data/packaging/debian/debian_specs/nginx/conf/uwsgi_params +0 -16
  715. data/packaging/debian/debian_specs/nginx/conf/win-utf +0 -125
  716. data/packaging/debian/debian_specs/nginx/control.erb +0 -226
  717. data/packaging/debian/debian_specs/nginx/copyright +0 -196
  718. data/packaging/debian/debian_specs/nginx/debian-full.lintian-overrides +0 -1
  719. data/packaging/debian/debian_specs/nginx/gbp.conf +0 -2
  720. data/packaging/debian/debian_specs/nginx/help/docs/fcgiwrap +0 -14
  721. data/packaging/debian/debian_specs/nginx/help/docs/php +0 -119
  722. data/packaging/debian/debian_specs/nginx/help/docs/support-irc +0 -28
  723. data/packaging/debian/debian_specs/nginx/help/docs/upstream +0 -51
  724. data/packaging/debian/debian_specs/nginx/help/examples/drupal +0 -114
  725. data/packaging/debian/debian_specs/nginx/help/examples/http +0 -59
  726. data/packaging/debian/debian_specs/nginx/help/examples/mail +0 -30
  727. data/packaging/debian/debian_specs/nginx/help/examples/mailman +0 -59
  728. data/packaging/debian/debian_specs/nginx/help/examples/nginx.conf +0 -34
  729. data/packaging/debian/debian_specs/nginx/help/examples/nginx_modsite +0 -162
  730. data/packaging/debian/debian_specs/nginx/help/examples/virtual_hosts +0 -155
  731. data/packaging/debian/debian_specs/nginx/help/examples/wordpress +0 -74
  732. data/packaging/debian/debian_specs/nginx/helpers.rb +0 -41
  733. data/packaging/debian/debian_specs/nginx/index-debian.html.in +0 -32
  734. data/packaging/debian/debian_specs/nginx/index-ubuntu.html.in +0 -32
  735. data/packaging/debian/debian_specs/nginx/index.html.erb +0 -10
  736. data/packaging/debian/debian_specs/nginx/modules/README.Modules-versions +0 -65
  737. data/packaging/debian/debian_specs/nginx/modules/headers-more-nginx-module/README.markdown +0 -510
  738. data/packaging/debian/debian_specs/nginx/modules/headers-more-nginx-module/config +0 -5
  739. data/packaging/debian/debian_specs/nginx/modules/headers-more-nginx-module/doc/HttpHeadersMoreModule.wiki +0 -395
  740. data/packaging/debian/debian_specs/nginx/modules/headers-more-nginx-module/src/ddebug.h +0 -119
  741. data/packaging/debian/debian_specs/nginx/modules/headers-more-nginx-module/src/ngx_http_headers_more_filter_module.c +0 -348
  742. data/packaging/debian/debian_specs/nginx/modules/headers-more-nginx-module/src/ngx_http_headers_more_filter_module.h +0 -80
  743. data/packaging/debian/debian_specs/nginx/modules/headers-more-nginx-module/src/ngx_http_headers_more_headers_in.c +0 -826
  744. data/packaging/debian/debian_specs/nginx/modules/headers-more-nginx-module/src/ngx_http_headers_more_headers_in.h +0 -26
  745. data/packaging/debian/debian_specs/nginx/modules/headers-more-nginx-module/src/ngx_http_headers_more_headers_out.c +0 -716
  746. data/packaging/debian/debian_specs/nginx/modules/headers-more-nginx-module/src/ngx_http_headers_more_headers_out.h +0 -26
  747. data/packaging/debian/debian_specs/nginx/modules/headers-more-nginx-module/src/ngx_http_headers_more_util.c +0 -380
  748. data/packaging/debian/debian_specs/nginx/modules/headers-more-nginx-module/src/ngx_http_headers_more_util.h +0 -52
  749. data/packaging/debian/debian_specs/nginx/modules/headers-more-nginx-module/util/build.sh +0 -32
  750. data/packaging/debian/debian_specs/nginx/modules/headers-more-nginx-module/valgrind.suppress +0 -215
  751. data/packaging/debian/debian_specs/nginx/modules/nginx-auth-pam/ChangeLog +0 -35
  752. data/packaging/debian/debian_specs/nginx/modules/nginx-auth-pam/LICENSE +0 -25
  753. data/packaging/debian/debian_specs/nginx/modules/nginx-auth-pam/README.md +0 -93
  754. data/packaging/debian/debian_specs/nginx/modules/nginx-auth-pam/config +0 -4
  755. data/packaging/debian/debian_specs/nginx/modules/nginx-auth-pam/ngx_http_auth_pam_module.c +0 -462
  756. data/packaging/debian/debian_specs/nginx/modules/nginx-cache-purge/CHANGES +0 -66
  757. data/packaging/debian/debian_specs/nginx/modules/nginx-cache-purge/LICENSE +0 -26
  758. data/packaging/debian/debian_specs/nginx/modules/nginx-cache-purge/README.md +0 -171
  759. data/packaging/debian/debian_specs/nginx/modules/nginx-cache-purge/TODO.md +0 -7
  760. data/packaging/debian/debian_specs/nginx/modules/nginx-cache-purge/config +0 -21
  761. data/packaging/debian/debian_specs/nginx/modules/nginx-cache-purge/ngx_cache_purge_module.c +0 -1803
  762. data/packaging/debian/debian_specs/nginx/modules/nginx-dav-ext-module/README +0 -29
  763. data/packaging/debian/debian_specs/nginx/modules/nginx-dav-ext-module/config +0 -9
  764. data/packaging/debian/debian_specs/nginx/modules/nginx-dav-ext-module/ngx_http_dav_ext_module.c +0 -824
  765. data/packaging/debian/debian_specs/nginx/modules/nginx-development-kit/README +0 -139
  766. data/packaging/debian/debian_specs/nginx/modules/nginx-development-kit/README_AUTO_LIB +0 -395
  767. data/packaging/debian/debian_specs/nginx/modules/nginx-development-kit/TODO +0 -1
  768. data/packaging/debian/debian_specs/nginx/modules/nginx-development-kit/auto/actions/array +0 -10
  769. data/packaging/debian/debian_specs/nginx/modules/nginx-development-kit/auto/actions/palloc +0 -8
  770. data/packaging/debian/debian_specs/nginx/modules/nginx-development-kit/auto/build +0 -597
  771. data/packaging/debian/debian_specs/nginx/modules/nginx-development-kit/auto/data/action_replacements +0 -5
  772. data/packaging/debian/debian_specs/nginx/modules/nginx-development-kit/auto/data/action_types +0 -12
  773. data/packaging/debian/debian_specs/nginx/modules/nginx-development-kit/auto/data/conf_args +0 -22
  774. data/packaging/debian/debian_specs/nginx/modules/nginx-development-kit/auto/data/conf_locs +0 -25
  775. data/packaging/debian/debian_specs/nginx/modules/nginx-development-kit/auto/data/conf_macros +0 -35
  776. data/packaging/debian/debian_specs/nginx/modules/nginx-development-kit/auto/data/contexts +0 -22
  777. data/packaging/debian/debian_specs/nginx/modules/nginx-development-kit/auto/data/header_files +0 -3
  778. data/packaging/debian/debian_specs/nginx/modules/nginx-development-kit/auto/data/headers +0 -4
  779. data/packaging/debian/debian_specs/nginx/modules/nginx-development-kit/auto/data/module_dependencies +0 -5
  780. data/packaging/debian/debian_specs/nginx/modules/nginx-development-kit/auto/data/modules_optional +0 -15
  781. data/packaging/debian/debian_specs/nginx/modules/nginx-development-kit/auto/data/prefixes +0 -2
  782. data/packaging/debian/debian_specs/nginx/modules/nginx-development-kit/auto/src/array.h +0 -7
  783. data/packaging/debian/debian_specs/nginx/modules/nginx-development-kit/auto/src/conf_cmd_basic.h +0 -43
  784. data/packaging/debian/debian_specs/nginx/modules/nginx-development-kit/auto/src/conf_merge.h +0 -78
  785. data/packaging/debian/debian_specs/nginx/modules/nginx-development-kit/auto/src/palloc.h +0 -6
  786. data/packaging/debian/debian_specs/nginx/modules/nginx-development-kit/auto/text/autogen +0 -12
  787. data/packaging/debian/debian_specs/nginx/modules/nginx-development-kit/config +0 -49
  788. data/packaging/debian/debian_specs/nginx/modules/nginx-development-kit/docs/core/action_macros +0 -63
  789. data/packaging/debian/debian_specs/nginx/modules/nginx-development-kit/docs/core/conf_cmds +0 -62
  790. data/packaging/debian/debian_specs/nginx/modules/nginx-development-kit/docs/modules/set_var +0 -124
  791. data/packaging/debian/debian_specs/nginx/modules/nginx-development-kit/docs/patches/more_logging_info +0 -48
  792. data/packaging/debian/debian_specs/nginx/modules/nginx-development-kit/docs/upstream/list +0 -45
  793. data/packaging/debian/debian_specs/nginx/modules/nginx-development-kit/examples/README +0 -12
  794. data/packaging/debian/debian_specs/nginx/modules/nginx-development-kit/examples/http/set_var/config +0 -4
  795. data/packaging/debian/debian_specs/nginx/modules/nginx-development-kit/examples/http/set_var/ngx_http_set_var_examples_module.c +0 -136
  796. data/packaging/debian/debian_specs/nginx/modules/nginx-development-kit/ngx_auto_lib_core +0 -797
  797. data/packaging/debian/debian_specs/nginx/modules/nginx-development-kit/notes/CHANGES +0 -17
  798. data/packaging/debian/debian_specs/nginx/modules/nginx-development-kit/notes/LICENSE +0 -24
  799. data/packaging/debian/debian_specs/nginx/modules/nginx-development-kit/objs/ndk_array.h +0 -113
  800. data/packaging/debian/debian_specs/nginx/modules/nginx-development-kit/objs/ndk_conf_cmd_basic.h +0 -2203
  801. data/packaging/debian/debian_specs/nginx/modules/nginx-development-kit/objs/ndk_conf_cmd_extra.h +0 -5423
  802. data/packaging/debian/debian_specs/nginx/modules/nginx-development-kit/objs/ndk_conf_merge.h +0 -227
  803. data/packaging/debian/debian_specs/nginx/modules/nginx-development-kit/objs/ndk_config.c +0 -72
  804. data/packaging/debian/debian_specs/nginx/modules/nginx-development-kit/objs/ndk_config.h +0 -98
  805. data/packaging/debian/debian_specs/nginx/modules/nginx-development-kit/objs/ndk_includes.h +0 -66
  806. data/packaging/debian/debian_specs/nginx/modules/nginx-development-kit/objs/ndk_palloc.h +0 -112
  807. data/packaging/debian/debian_specs/nginx/modules/nginx-development-kit/patches/auto_config +0 -16
  808. data/packaging/debian/debian_specs/nginx/modules/nginx-development-kit/patches/expose_rewrite_functions +0 -291
  809. data/packaging/debian/debian_specs/nginx/modules/nginx-development-kit/patches/rewrite_phase_handler +0 -19
  810. data/packaging/debian/debian_specs/nginx/modules/nginx-development-kit/src/hash/md5.h +0 -117
  811. data/packaging/debian/debian_specs/nginx/modules/nginx-development-kit/src/hash/murmurhash2.c +0 -77
  812. data/packaging/debian/debian_specs/nginx/modules/nginx-development-kit/src/hash/sha.h +0 -200
  813. data/packaging/debian/debian_specs/nginx/modules/nginx-development-kit/src/ndk.c +0 -155
  814. data/packaging/debian/debian_specs/nginx/modules/nginx-development-kit/src/ndk.h +0 -58
  815. data/packaging/debian/debian_specs/nginx/modules/nginx-development-kit/src/ndk_buf.c +0 -43
  816. data/packaging/debian/debian_specs/nginx/modules/nginx-development-kit/src/ndk_buf.h +0 -5
  817. data/packaging/debian/debian_specs/nginx/modules/nginx-development-kit/src/ndk_complex_path.c +0 -129
  818. data/packaging/debian/debian_specs/nginx/modules/nginx-development-kit/src/ndk_complex_path.h +0 -30
  819. data/packaging/debian/debian_specs/nginx/modules/nginx-development-kit/src/ndk_complex_value.c +0 -192
  820. data/packaging/debian/debian_specs/nginx/modules/nginx-development-kit/src/ndk_complex_value.h +0 -21
  821. data/packaging/debian/debian_specs/nginx/modules/nginx-development-kit/src/ndk_conf_file.c +0 -396
  822. data/packaging/debian/debian_specs/nginx/modules/nginx-development-kit/src/ndk_conf_file.h +0 -44
  823. data/packaging/debian/debian_specs/nginx/modules/nginx-development-kit/src/ndk_debug.c +0 -72
  824. data/packaging/debian/debian_specs/nginx/modules/nginx-development-kit/src/ndk_debug.h +0 -171
  825. data/packaging/debian/debian_specs/nginx/modules/nginx-development-kit/src/ndk_encoding.c +0 -57
  826. data/packaging/debian/debian_specs/nginx/modules/nginx-development-kit/src/ndk_encoding.h +0 -12
  827. data/packaging/debian/debian_specs/nginx/modules/nginx-development-kit/src/ndk_hash.c +0 -82
  828. data/packaging/debian/debian_specs/nginx/modules/nginx-development-kit/src/ndk_hash.h +0 -45
  829. data/packaging/debian/debian_specs/nginx/modules/nginx-development-kit/src/ndk_http.c +0 -138
  830. data/packaging/debian/debian_specs/nginx/modules/nginx-development-kit/src/ndk_http.h +0 -3
  831. data/packaging/debian/debian_specs/nginx/modules/nginx-development-kit/src/ndk_http_headers.h +0 -35
  832. data/packaging/debian/debian_specs/nginx/modules/nginx-development-kit/src/ndk_log.c +0 -3
  833. data/packaging/debian/debian_specs/nginx/modules/nginx-development-kit/src/ndk_log.h +0 -165
  834. data/packaging/debian/debian_specs/nginx/modules/nginx-development-kit/src/ndk_parse.h +0 -67
  835. data/packaging/debian/debian_specs/nginx/modules/nginx-development-kit/src/ndk_path.c +0 -583
  836. data/packaging/debian/debian_specs/nginx/modules/nginx-development-kit/src/ndk_path.h +0 -22
  837. data/packaging/debian/debian_specs/nginx/modules/nginx-development-kit/src/ndk_process.c +0 -20
  838. data/packaging/debian/debian_specs/nginx/modules/nginx-development-kit/src/ndk_process.h +0 -12
  839. data/packaging/debian/debian_specs/nginx/modules/nginx-development-kit/src/ndk_regex.c +0 -215
  840. data/packaging/debian/debian_specs/nginx/modules/nginx-development-kit/src/ndk_regex.h +0 -7
  841. data/packaging/debian/debian_specs/nginx/modules/nginx-development-kit/src/ndk_rewrite.c +0 -103
  842. data/packaging/debian/debian_specs/nginx/modules/nginx-development-kit/src/ndk_rewrite.h +0 -26
  843. data/packaging/debian/debian_specs/nginx/modules/nginx-development-kit/src/ndk_set_var.c +0 -602
  844. data/packaging/debian/debian_specs/nginx/modules/nginx-development-kit/src/ndk_set_var.h +0 -44
  845. data/packaging/debian/debian_specs/nginx/modules/nginx-development-kit/src/ndk_string.c +0 -434
  846. data/packaging/debian/debian_specs/nginx/modules/nginx-development-kit/src/ndk_string.h +0 -37
  847. data/packaging/debian/debian_specs/nginx/modules/nginx-development-kit/src/ndk_string_util.h +0 -14
  848. data/packaging/debian/debian_specs/nginx/modules/nginx-development-kit/src/ndk_upstream_list.c +0 -205
  849. data/packaging/debian/debian_specs/nginx/modules/nginx-development-kit/src/ndk_upstream_list.h +0 -27
  850. data/packaging/debian/debian_specs/nginx/modules/nginx-development-kit/src/ndk_uri.c +0 -45
  851. data/packaging/debian/debian_specs/nginx/modules/nginx-development-kit/src/ndk_uri.h +0 -6
  852. data/packaging/debian/debian_specs/nginx/modules/nginx-echo/LICENSE +0 -25
  853. data/packaging/debian/debian_specs/nginx/modules/nginx-echo/README.markdown +0 -1850
  854. data/packaging/debian/debian_specs/nginx/modules/nginx-echo/config +0 -5
  855. data/packaging/debian/debian_specs/nginx/modules/nginx-echo/doc/HttpEchoModule.wiki +0 -1558
  856. data/packaging/debian/debian_specs/nginx/modules/nginx-echo/src/ddebug.h +0 -109
  857. data/packaging/debian/debian_specs/nginx/modules/nginx-echo/src/ngx_http_echo_echo.c +0 -344
  858. data/packaging/debian/debian_specs/nginx/modules/nginx-echo/src/ngx_http_echo_echo.h +0 -25
  859. data/packaging/debian/debian_specs/nginx/modules/nginx-echo/src/ngx_http_echo_filter.c +0 -282
  860. data/packaging/debian/debian_specs/nginx/modules/nginx-echo/src/ngx_http_echo_filter.h +0 -15
  861. data/packaging/debian/debian_specs/nginx/modules/nginx-echo/src/ngx_http_echo_foreach.c +0 -183
  862. data/packaging/debian/debian_specs/nginx/modules/nginx-echo/src/ngx_http_echo_foreach.h +0 -16
  863. data/packaging/debian/debian_specs/nginx/modules/nginx-echo/src/ngx_http_echo_handler.c +0 -429
  864. data/packaging/debian/debian_specs/nginx/modules/nginx-echo/src/ngx_http_echo_handler.h +0 -18
  865. data/packaging/debian/debian_specs/nginx/modules/nginx-echo/src/ngx_http_echo_location.c +0 -178
  866. data/packaging/debian/debian_specs/nginx/modules/nginx-echo/src/ngx_http_echo_location.h +0 -13
  867. data/packaging/debian/debian_specs/nginx/modules/nginx-echo/src/ngx_http_echo_module.c +0 -667
  868. data/packaging/debian/debian_specs/nginx/modules/nginx-echo/src/ngx_http_echo_module.h +0 -137
  869. data/packaging/debian/debian_specs/nginx/modules/nginx-echo/src/ngx_http_echo_request_info.c +0 -452
  870. data/packaging/debian/debian_specs/nginx/modules/nginx-echo/src/ngx_http_echo_request_info.h +0 -31
  871. data/packaging/debian/debian_specs/nginx/modules/nginx-echo/src/ngx_http_echo_sleep.c +0 -208
  872. data/packaging/debian/debian_specs/nginx/modules/nginx-echo/src/ngx_http_echo_sleep.h +0 -16
  873. data/packaging/debian/debian_specs/nginx/modules/nginx-echo/src/ngx_http_echo_subrequest.c +0 -788
  874. data/packaging/debian/debian_specs/nginx/modules/nginx-echo/src/ngx_http_echo_subrequest.h +0 -19
  875. data/packaging/debian/debian_specs/nginx/modules/nginx-echo/src/ngx_http_echo_timer.c +0 -96
  876. data/packaging/debian/debian_specs/nginx/modules/nginx-echo/src/ngx_http_echo_timer.h +0 -13
  877. data/packaging/debian/debian_specs/nginx/modules/nginx-echo/src/ngx_http_echo_util.c +0 -298
  878. data/packaging/debian/debian_specs/nginx/modules/nginx-echo/src/ngx_http_echo_util.h +0 -58
  879. data/packaging/debian/debian_specs/nginx/modules/nginx-echo/src/ngx_http_echo_var.c +0 -110
  880. data/packaging/debian/debian_specs/nginx/modules/nginx-echo/src/ngx_http_echo_var.h +0 -9
  881. data/packaging/debian/debian_specs/nginx/modules/nginx-echo/util/build.sh +0 -45
  882. data/packaging/debian/debian_specs/nginx/modules/nginx-echo/util/releng +0 -8
  883. data/packaging/debian/debian_specs/nginx/modules/nginx-echo/util/wiki2pod.pl +0 -131
  884. data/packaging/debian/debian_specs/nginx/modules/nginx-echo/valgrind.suppress +0 -38
  885. data/packaging/debian/debian_specs/nginx/modules/nginx-http-push/LICENCE +0 -24
  886. data/packaging/debian/debian_specs/nginx/modules/nginx-http-push/README +0 -206
  887. data/packaging/debian/debian_specs/nginx/modules/nginx-http-push/changelog.txt +0 -54
  888. data/packaging/debian/debian_specs/nginx/modules/nginx-http-push/config +0 -26
  889. data/packaging/debian/debian_specs/nginx/modules/nginx-http-push/protocol.txt +0 -191
  890. data/packaging/debian/debian_specs/nginx/modules/nginx-http-push/src/ngx_http_push_defs.c +0 -59
  891. data/packaging/debian/debian_specs/nginx/modules/nginx-http-push/src/ngx_http_push_defs.h +0 -73
  892. data/packaging/debian/debian_specs/nginx/modules/nginx-http-push/src/ngx_http_push_module.c +0 -783
  893. data/packaging/debian/debian_specs/nginx/modules/nginx-http-push/src/ngx_http_push_module.h +0 -31
  894. data/packaging/debian/debian_specs/nginx/modules/nginx-http-push/src/ngx_http_push_module_setup.c +0 -361
  895. data/packaging/debian/debian_specs/nginx/modules/nginx-http-push/src/ngx_http_push_types.h +0 -120
  896. data/packaging/debian/debian_specs/nginx/modules/nginx-http-push/src/store/memory/store.c +0 -1180
  897. data/packaging/debian/debian_specs/nginx/modules/nginx-http-push/src/store/memory/store.h +0 -1
  898. data/packaging/debian/debian_specs/nginx/modules/nginx-http-push/src/store/ngx_http_push_module_ipc.c +0 -146
  899. data/packaging/debian/debian_specs/nginx/modules/nginx-http-push/src/store/ngx_http_push_module_ipc.h +0 -5
  900. data/packaging/debian/debian_specs/nginx/modules/nginx-http-push/src/store/ngx_http_push_store.h +0 -51
  901. data/packaging/debian/debian_specs/nginx/modules/nginx-http-push/src/store/ngx_rwlock.c +0 -178
  902. data/packaging/debian/debian_specs/nginx/modules/nginx-http-push/src/store/ngx_rwlock.h +0 -5
  903. data/packaging/debian/debian_specs/nginx/modules/nginx-http-push/src/store/rbtree_util.c +0 -246
  904. data/packaging/debian/debian_specs/nginx/modules/nginx-http-push/src/store/rbtree_util.h +0 -9
  905. data/packaging/debian/debian_specs/nginx/modules/nginx-lua/Changes +0 -51
  906. data/packaging/debian/debian_specs/nginx/modules/nginx-lua/README.markdown +0 -6954
  907. data/packaging/debian/debian_specs/nginx/modules/nginx-lua/config +0 -363
  908. data/packaging/debian/debian_specs/nginx/modules/nginx-lua/doc/HttpLuaModule.wiki +0 -5898
  909. data/packaging/debian/debian_specs/nginx/modules/nginx-lua/dtrace/ngx_lua_provider.d +0 -61
  910. data/packaging/debian/debian_specs/nginx/modules/nginx-lua/misc/recv-until-pm/Makefile +0 -3
  911. data/packaging/debian/debian_specs/nginx/modules/nginx-lua/misc/recv-until-pm/lib/RecvUntil.pm +0 -138
  912. data/packaging/debian/debian_specs/nginx/modules/nginx-lua/misc/recv-until-pm/t/sanity.t +0 -140
  913. data/packaging/debian/debian_specs/nginx/modules/nginx-lua/src/api/ngx_http_lua_api.h +0 -52
  914. data/packaging/debian/debian_specs/nginx/modules/nginx-lua/src/ddebug.h +0 -82
  915. data/packaging/debian/debian_specs/nginx/modules/nginx-lua/src/ngx_http_lua_accessby.c +0 -377
  916. data/packaging/debian/debian_specs/nginx/modules/nginx-lua/src/ngx_http_lua_accessby.h +0 -22
  917. data/packaging/debian/debian_specs/nginx/modules/nginx-lua/src/ngx_http_lua_api.c +0 -77
  918. data/packaging/debian/debian_specs/nginx/modules/nginx-lua/src/ngx_http_lua_args.c +0 -537
  919. data/packaging/debian/debian_specs/nginx/modules/nginx-lua/src/ngx_http_lua_args.h +0 -20
  920. data/packaging/debian/debian_specs/nginx/modules/nginx-lua/src/ngx_http_lua_bodyfilterby.c +0 -632
  921. data/packaging/debian/debian_specs/nginx/modules/nginx-lua/src/ngx_http_lua_bodyfilterby.h +0 -31
  922. data/packaging/debian/debian_specs/nginx/modules/nginx-lua/src/ngx_http_lua_cache.c +0 -296
  923. data/packaging/debian/debian_specs/nginx/modules/nginx-lua/src/ngx_http_lua_cache.h +0 -24
  924. data/packaging/debian/debian_specs/nginx/modules/nginx-lua/src/ngx_http_lua_capturefilter.c +0 -175
  925. data/packaging/debian/debian_specs/nginx/modules/nginx-lua/src/ngx_http_lua_capturefilter.h +0 -20
  926. data/packaging/debian/debian_specs/nginx/modules/nginx-lua/src/ngx_http_lua_clfactory.c +0 -887
  927. data/packaging/debian/debian_specs/nginx/modules/nginx-lua/src/ngx_http_lua_clfactory.h +0 -22
  928. data/packaging/debian/debian_specs/nginx/modules/nginx-lua/src/ngx_http_lua_common.h +0 -478
  929. data/packaging/debian/debian_specs/nginx/modules/nginx-lua/src/ngx_http_lua_config.c +0 -67
  930. data/packaging/debian/debian_specs/nginx/modules/nginx-lua/src/ngx_http_lua_config.h +0 -19
  931. data/packaging/debian/debian_specs/nginx/modules/nginx-lua/src/ngx_http_lua_consts.c +0 -148
  932. data/packaging/debian/debian_specs/nginx/modules/nginx-lua/src/ngx_http_lua_consts.h +0 -20
  933. data/packaging/debian/debian_specs/nginx/modules/nginx-lua/src/ngx_http_lua_contentby.c +0 -369
  934. data/packaging/debian/debian_specs/nginx/modules/nginx-lua/src/ngx_http_lua_contentby.h +0 -26
  935. data/packaging/debian/debian_specs/nginx/modules/nginx-lua/src/ngx_http_lua_control.c +0 -483
  936. data/packaging/debian/debian_specs/nginx/modules/nginx-lua/src/ngx_http_lua_control.h +0 -20
  937. data/packaging/debian/debian_specs/nginx/modules/nginx-lua/src/ngx_http_lua_coroutine.c +0 -379
  938. data/packaging/debian/debian_specs/nginx/modules/nginx-lua/src/ngx_http_lua_coroutine.h +0 -23
  939. data/packaging/debian/debian_specs/nginx/modules/nginx-lua/src/ngx_http_lua_ctx.c +0 -216
  940. data/packaging/debian/debian_specs/nginx/modules/nginx-lua/src/ngx_http_lua_ctx.h +0 -23
  941. data/packaging/debian/debian_specs/nginx/modules/nginx-lua/src/ngx_http_lua_directive.c +0 -1081
  942. data/packaging/debian/debian_specs/nginx/modules/nginx-lua/src/ngx_http_lua_directive.h +0 -56
  943. data/packaging/debian/debian_specs/nginx/modules/nginx-lua/src/ngx_http_lua_exception.c +0 -58
  944. data/packaging/debian/debian_specs/nginx/modules/nginx-lua/src/ngx_http_lua_exception.h +0 -33
  945. data/packaging/debian/debian_specs/nginx/modules/nginx-lua/src/ngx_http_lua_headerfilterby.c +0 -302
  946. data/packaging/debian/debian_specs/nginx/modules/nginx-lua/src/ngx_http_lua_headerfilterby.h +0 -29
  947. data/packaging/debian/debian_specs/nginx/modules/nginx-lua/src/ngx_http_lua_headers.c +0 -1370
  948. data/packaging/debian/debian_specs/nginx/modules/nginx-lua/src/ngx_http_lua_headers.h +0 -22
  949. data/packaging/debian/debian_specs/nginx/modules/nginx-lua/src/ngx_http_lua_headers_in.c +0 -782
  950. data/packaging/debian/debian_specs/nginx/modules/nginx-lua/src/ngx_http_lua_headers_in.h +0 -22
  951. data/packaging/debian/debian_specs/nginx/modules/nginx-lua/src/ngx_http_lua_headers_out.c +0 -625
  952. data/packaging/debian/debian_specs/nginx/modules/nginx-lua/src/ngx_http_lua_headers_out.h +0 -23
  953. data/packaging/debian/debian_specs/nginx/modules/nginx-lua/src/ngx_http_lua_initby.c +0 -42
  954. data/packaging/debian/debian_specs/nginx/modules/nginx-lua/src/ngx_http_lua_initby.h +0 -23
  955. data/packaging/debian/debian_specs/nginx/modules/nginx-lua/src/ngx_http_lua_initworkerby.c +0 -320
  956. data/packaging/debian/debian_specs/nginx/modules/nginx-lua/src/ngx_http_lua_initworkerby.h +0 -25
  957. data/packaging/debian/debian_specs/nginx/modules/nginx-lua/src/ngx_http_lua_log.c +0 -300
  958. data/packaging/debian/debian_specs/nginx/modules/nginx-lua/src/ngx_http_lua_log.h +0 -20
  959. data/packaging/debian/debian_specs/nginx/modules/nginx-lua/src/ngx_http_lua_logby.c +0 -227
  960. data/packaging/debian/debian_specs/nginx/modules/nginx-lua/src/ngx_http_lua_logby.h +0 -22
  961. data/packaging/debian/debian_specs/nginx/modules/nginx-lua/src/ngx_http_lua_misc.c +0 -252
  962. data/packaging/debian/debian_specs/nginx/modules/nginx-lua/src/ngx_http_lua_misc.h +0 -20
  963. data/packaging/debian/debian_specs/nginx/modules/nginx-lua/src/ngx_http_lua_module.c +0 -924
  964. data/packaging/debian/debian_specs/nginx/modules/nginx-lua/src/ngx_http_lua_ndk.c +0 -184
  965. data/packaging/debian/debian_specs/nginx/modules/nginx-lua/src/ngx_http_lua_ndk.h +0 -21
  966. data/packaging/debian/debian_specs/nginx/modules/nginx-lua/src/ngx_http_lua_output.c +0 -794
  967. data/packaging/debian/debian_specs/nginx/modules/nginx-lua/src/ngx_http_lua_output.h +0 -28
  968. data/packaging/debian/debian_specs/nginx/modules/nginx-lua/src/ngx_http_lua_pcrefix.c +0 -106
  969. data/packaging/debian/debian_specs/nginx/modules/nginx-lua/src/ngx_http_lua_pcrefix.h +0 -23
  970. data/packaging/debian/debian_specs/nginx/modules/nginx-lua/src/ngx_http_lua_phase.c +0 -94
  971. data/packaging/debian/debian_specs/nginx/modules/nginx-lua/src/ngx_http_lua_phase.h +0 -13
  972. data/packaging/debian/debian_specs/nginx/modules/nginx-lua/src/ngx_http_lua_probe.h +0 -85
  973. data/packaging/debian/debian_specs/nginx/modules/nginx-lua/src/ngx_http_lua_regex.c +0 -2468
  974. data/packaging/debian/debian_specs/nginx/modules/nginx-lua/src/ngx_http_lua_regex.h +0 -22
  975. data/packaging/debian/debian_specs/nginx/modules/nginx-lua/src/ngx_http_lua_req_body.c +0 -1169
  976. data/packaging/debian/debian_specs/nginx/modules/nginx-lua/src/ngx_http_lua_req_body.h +0 -20
  977. data/packaging/debian/debian_specs/nginx/modules/nginx-lua/src/ngx_http_lua_req_method.c +0 -252
  978. data/packaging/debian/debian_specs/nginx/modules/nginx-lua/src/ngx_http_lua_req_method.h +0 -19
  979. data/packaging/debian/debian_specs/nginx/modules/nginx-lua/src/ngx_http_lua_rewriteby.c +0 -351
  980. data/packaging/debian/debian_specs/nginx/modules/nginx-lua/src/ngx_http_lua_rewriteby.h +0 -22
  981. data/packaging/debian/debian_specs/nginx/modules/nginx-lua/src/ngx_http_lua_script.c +0 -538
  982. data/packaging/debian/debian_specs/nginx/modules/nginx-lua/src/ngx_http_lua_script.h +0 -86
  983. data/packaging/debian/debian_specs/nginx/modules/nginx-lua/src/ngx_http_lua_setby.c +0 -216
  984. data/packaging/debian/debian_specs/nginx/modules/nginx-lua/src/ngx_http_lua_setby.h +0 -15
  985. data/packaging/debian/debian_specs/nginx/modules/nginx-lua/src/ngx_http_lua_shdict.c +0 -1844
  986. data/packaging/debian/debian_specs/nginx/modules/nginx-lua/src/ngx_http_lua_shdict.h +0 -52
  987. data/packaging/debian/debian_specs/nginx/modules/nginx-lua/src/ngx_http_lua_sleep.c +0 -191
  988. data/packaging/debian/debian_specs/nginx/modules/nginx-lua/src/ngx_http_lua_sleep.h +0 -20
  989. data/packaging/debian/debian_specs/nginx/modules/nginx-lua/src/ngx_http_lua_socket_tcp.c +0 -5314
  990. data/packaging/debian/debian_specs/nginx/modules/nginx-lua/src/ngx_http_lua_socket_tcp.h +0 -156
  991. data/packaging/debian/debian_specs/nginx/modules/nginx-lua/src/ngx_http_lua_socket_udp.c +0 -1624
  992. data/packaging/debian/debian_specs/nginx/modules/nginx-lua/src/ngx_http_lua_socket_udp.h +0 -56
  993. data/packaging/debian/debian_specs/nginx/modules/nginx-lua/src/ngx_http_lua_string.c +0 -704
  994. data/packaging/debian/debian_specs/nginx/modules/nginx-lua/src/ngx_http_lua_string.h +0 -20
  995. data/packaging/debian/debian_specs/nginx/modules/nginx-lua/src/ngx_http_lua_subrequest.c +0 -1741
  996. data/packaging/debian/debian_specs/nginx/modules/nginx-lua/src/ngx_http_lua_subrequest.h +0 -46
  997. data/packaging/debian/debian_specs/nginx/modules/nginx-lua/src/ngx_http_lua_time.c +0 -278
  998. data/packaging/debian/debian_specs/nginx/modules/nginx-lua/src/ngx_http_lua_time.h +0 -21
  999. data/packaging/debian/debian_specs/nginx/modules/nginx-lua/src/ngx_http_lua_timer.c +0 -661
  1000. data/packaging/debian/debian_specs/nginx/modules/nginx-lua/src/ngx_http_lua_timer.h +0 -20
  1001. data/packaging/debian/debian_specs/nginx/modules/nginx-lua/src/ngx_http_lua_uri.c +0 -110
  1002. data/packaging/debian/debian_specs/nginx/modules/nginx-lua/src/ngx_http_lua_uri.h +0 -20
  1003. data/packaging/debian/debian_specs/nginx/modules/nginx-lua/src/ngx_http_lua_uthread.c +0 -283
  1004. data/packaging/debian/debian_specs/nginx/modules/nginx-lua/src/ngx_http_lua_uthread.h +0 -36
  1005. data/packaging/debian/debian_specs/nginx/modules/nginx-lua/src/ngx_http_lua_util.c +0 -3972
  1006. data/packaging/debian/debian_specs/nginx/modules/nginx-lua/src/ngx_http_lua_util.h +0 -423
  1007. data/packaging/debian/debian_specs/nginx/modules/nginx-lua/src/ngx_http_lua_variable.c +0 -499
  1008. data/packaging/debian/debian_specs/nginx/modules/nginx-lua/src/ngx_http_lua_variable.h +0 -20
  1009. data/packaging/debian/debian_specs/nginx/modules/nginx-lua/src/ngx_http_lua_worker.c +0 -64
  1010. data/packaging/debian/debian_specs/nginx/modules/nginx-lua/src/ngx_http_lua_worker.h +0 -17
  1011. data/packaging/debian/debian_specs/nginx/modules/nginx-lua/tapset/ngx_lua.stp +0 -5
  1012. data/packaging/debian/debian_specs/nginx/modules/nginx-lua/util/build.sh +0 -39
  1013. data/packaging/debian/debian_specs/nginx/modules/nginx-lua/util/build2.sh +0 -55
  1014. data/packaging/debian/debian_specs/nginx/modules/nginx-lua/util/fix-comments +0 -27
  1015. data/packaging/debian/debian_specs/nginx/modules/nginx-lua/util/gdbinit +0 -415
  1016. data/packaging/debian/debian_specs/nginx/modules/nginx-lua/util/ngx-links +0 -62
  1017. data/packaging/debian/debian_specs/nginx/modules/nginx-lua/util/reindex +0 -64
  1018. data/packaging/debian/debian_specs/nginx/modules/nginx-lua/util/releng +0 -8
  1019. data/packaging/debian/debian_specs/nginx/modules/nginx-lua/util/retab +0 -8
  1020. data/packaging/debian/debian_specs/nginx/modules/nginx-lua/util/revim +0 -102
  1021. data/packaging/debian/debian_specs/nginx/modules/nginx-lua/util/run_test.sh +0 -10
  1022. data/packaging/debian/debian_specs/nginx/modules/nginx-lua/util/update-readme.sh +0 -4
  1023. data/packaging/debian/debian_specs/nginx/modules/nginx-lua/valgrind.suppress +0 -144
  1024. data/packaging/debian/debian_specs/nginx/modules/nginx-upload-progress/CHANGES +0 -107
  1025. data/packaging/debian/debian_specs/nginx/modules/nginx-upload-progress/LICENSE +0 -25
  1026. data/packaging/debian/debian_specs/nginx/modules/nginx-upload-progress/Makefile +0 -8
  1027. data/packaging/debian/debian_specs/nginx/modules/nginx-upload-progress/README +0 -329
  1028. data/packaging/debian/debian_specs/nginx/modules/nginx-upload-progress/config +0 -3
  1029. data/packaging/debian/debian_specs/nginx/modules/nginx-upload-progress/ngx_http_uploadprogress_module.c +0 -1774
  1030. data/packaging/debian/debian_specs/nginx/modules/nginx-upstream-fair/README +0 -53
  1031. data/packaging/debian/debian_specs/nginx/modules/nginx-upstream-fair/config +0 -3
  1032. data/packaging/debian/debian_specs/nginx/modules/nginx-upstream-fair/ngx_http_upstream_fair_module.c +0 -1356
  1033. data/packaging/debian/debian_specs/nginx/modules/ngx-fancyindex/CHANGELOG.md +0 -37
  1034. data/packaging/debian/debian_specs/nginx/modules/ngx-fancyindex/HACKING.md +0 -24
  1035. data/packaging/debian/debian_specs/nginx/modules/ngx-fancyindex/LICENSE +0 -20
  1036. data/packaging/debian/debian_specs/nginx/modules/ngx-fancyindex/README.rst +0 -182
  1037. data/packaging/debian/debian_specs/nginx/modules/ngx-fancyindex/config +0 -8
  1038. data/packaging/debian/debian_specs/nginx/modules/ngx-fancyindex/nginx-0.6-support.patch +0 -23
  1039. data/packaging/debian/debian_specs/nginx/modules/ngx-fancyindex/ngx_http_fancyindex_module.c +0 -1305
  1040. data/packaging/debian/debian_specs/nginx/modules/ngx-fancyindex/template.awk +0 -52
  1041. data/packaging/debian/debian_specs/nginx/modules/ngx-fancyindex/template.h +0 -103
  1042. data/packaging/debian/debian_specs/nginx/modules/ngx-fancyindex/template.html +0 -102
  1043. data/packaging/debian/debian_specs/nginx/modules/ngx_http_substitutions_filter_module/CHANGES +0 -37
  1044. data/packaging/debian/debian_specs/nginx/modules/ngx_http_substitutions_filter_module/README +0 -141
  1045. data/packaging/debian/debian_specs/nginx/modules/ngx_http_substitutions_filter_module/config +0 -3
  1046. data/packaging/debian/debian_specs/nginx/modules/ngx_http_substitutions_filter_module/doc/README.google_code_home_page.wiki +0 -120
  1047. data/packaging/debian/debian_specs/nginx/modules/ngx_http_substitutions_filter_module/doc/README.html +0 -199
  1048. data/packaging/debian/debian_specs/nginx/modules/ngx_http_substitutions_filter_module/doc/README.wiki +0 -123
  1049. data/packaging/debian/debian_specs/nginx/modules/ngx_http_substitutions_filter_module/ngx_http_subs_filter_module.c +0 -1298
  1050. data/packaging/debian/debian_specs/nginx/modules/ngx_http_substitutions_filter_module/test/README +0 -275
  1051. data/packaging/debian/debian_specs/nginx/modules/ngx_http_substitutions_filter_module/test/inc/Module/AutoInstall.pm +0 -820
  1052. data/packaging/debian/debian_specs/nginx/modules/ngx_http_substitutions_filter_module/test/inc/Module/Install.pm +0 -470
  1053. data/packaging/debian/debian_specs/nginx/modules/ngx_http_substitutions_filter_module/test/inc/Module/Install/AutoInstall.pm +0 -82
  1054. data/packaging/debian/debian_specs/nginx/modules/ngx_http_substitutions_filter_module/test/inc/Module/Install/Base.pm +0 -83
  1055. data/packaging/debian/debian_specs/nginx/modules/ngx_http_substitutions_filter_module/test/inc/Module/Install/Can.pm +0 -81
  1056. data/packaging/debian/debian_specs/nginx/modules/ngx_http_substitutions_filter_module/test/inc/Module/Install/Fetch.pm +0 -93
  1057. data/packaging/debian/debian_specs/nginx/modules/ngx_http_substitutions_filter_module/test/inc/Module/Install/Include.pm +0 -34
  1058. data/packaging/debian/debian_specs/nginx/modules/ngx_http_substitutions_filter_module/test/inc/Module/Install/Makefile.pm +0 -415
  1059. data/packaging/debian/debian_specs/nginx/modules/ngx_http_substitutions_filter_module/test/inc/Module/Install/Metadata.pm +0 -716
  1060. data/packaging/debian/debian_specs/nginx/modules/ngx_http_substitutions_filter_module/test/inc/Module/Install/TestBase.pm +0 -29
  1061. data/packaging/debian/debian_specs/nginx/modules/ngx_http_substitutions_filter_module/test/inc/Module/Install/Win32.pm +0 -64
  1062. data/packaging/debian/debian_specs/nginx/modules/ngx_http_substitutions_filter_module/test/inc/Module/Install/WriteAll.pm +0 -63
  1063. data/packaging/debian/debian_specs/nginx/modules/ngx_http_substitutions_filter_module/test/inc/Spiffy.pm +0 -539
  1064. data/packaging/debian/debian_specs/nginx/modules/ngx_http_substitutions_filter_module/test/inc/Test/Base.pm +0 -682
  1065. data/packaging/debian/debian_specs/nginx/modules/ngx_http_substitutions_filter_module/test/inc/Test/Base/Filter.pm +0 -341
  1066. data/packaging/debian/debian_specs/nginx/modules/ngx_http_substitutions_filter_module/test/inc/Test/Builder.pm +0 -1413
  1067. data/packaging/debian/debian_specs/nginx/modules/ngx_http_substitutions_filter_module/test/inc/Test/Builder/Module.pm +0 -81
  1068. data/packaging/debian/debian_specs/nginx/modules/ngx_http_substitutions_filter_module/test/inc/Test/More.pm +0 -735
  1069. data/packaging/debian/debian_specs/nginx/modules/ngx_http_substitutions_filter_module/test/lib/Test/Nginx.pm +0 -315
  1070. data/packaging/debian/debian_specs/nginx/modules/ngx_http_substitutions_filter_module/test/lib/Test/Nginx/LWP.pm +0 -524
  1071. data/packaging/debian/debian_specs/nginx/modules/ngx_http_substitutions_filter_module/test/lib/Test/Nginx/Socket.pm +0 -1749
  1072. data/packaging/debian/debian_specs/nginx/modules/ngx_http_substitutions_filter_module/test/lib/Test/Nginx/Util.pm +0 -874
  1073. data/packaging/debian/debian_specs/nginx/modules/ngx_http_substitutions_filter_module/test/t/subs.t +0 -136
  1074. data/packaging/debian/debian_specs/nginx/modules/ngx_http_substitutions_filter_module/test/t/subs_capture.t +0 -32
  1075. data/packaging/debian/debian_specs/nginx/modules/ngx_http_substitutions_filter_module/test/t/subs_fix_string.t +0 -32
  1076. data/packaging/debian/debian_specs/nginx/modules/ngx_http_substitutions_filter_module/test/t/subs_regex.t +0 -108
  1077. data/packaging/debian/debian_specs/nginx/modules/ngx_http_substitutions_filter_module/test/t/subs_types.t +0 -59
  1078. data/packaging/debian/debian_specs/nginx/modules/ngx_http_substitutions_filter_module/test/test.sh +0 -5
  1079. data/packaging/debian/debian_specs/nginx/modules/ngx_http_substitutions_filter_module/util/update-readme.sh +0 -7
  1080. data/packaging/debian/debian_specs/nginx/modules/ngx_http_substitutions_filter_module/util/wiki2google_code_homepage.pl +0 -29
  1081. data/packaging/debian/debian_specs/nginx/modules/ngx_http_substitutions_filter_module/util/wiki2pod.pl +0 -129
  1082. data/packaging/debian/debian_specs/nginx/nginx-common.NEWS +0 -135
  1083. data/packaging/debian/debian_specs/nginx/nginx-common.README.Debian +0 -45
  1084. data/packaging/debian/debian_specs/nginx/nginx-common.dirs.erb +0 -32
  1085. data/packaging/debian/debian_specs/nginx/nginx-common.install +0 -3
  1086. data/packaging/debian/debian_specs/nginx/nginx-common.lintian-overrides +0 -2
  1087. data/packaging/debian/debian_specs/nginx/nginx-common.manpages +0 -1
  1088. data/packaging/debian/debian_specs/nginx/nginx-common.nginx.default +0 -10
  1089. data/packaging/debian/debian_specs/nginx/nginx-common.nginx.init.erb +0 -214
  1090. data/packaging/debian/debian_specs/nginx/nginx-common.nginx.logrotate +0 -18
  1091. data/packaging/debian/debian_specs/nginx/nginx-common.nginx.service.erb +0 -37
  1092. data/packaging/debian/debian_specs/nginx/nginx-common.postinst.erb +0 -66
  1093. data/packaging/debian/debian_specs/nginx/nginx-common.postrm.erb +0 -46
  1094. data/packaging/debian/debian_specs/nginx/nginx-common.preinst +0 -47
  1095. data/packaging/debian/debian_specs/nginx/nginx-common.prerm.erb +0 -28
  1096. data/packaging/debian/debian_specs/nginx/nginx-doc.docs +0 -2
  1097. data/packaging/debian/debian_specs/nginx/nginx-doc.examples +0 -1
  1098. data/packaging/debian/debian_specs/nginx/nginx-extras.install.erb +0 -17
  1099. data/packaging/debian/debian_specs/nginx/nginx-extras.lintian-overrides +0 -1
  1100. data/packaging/debian/debian_specs/nginx/nginx-extras.postinst.erb +0 -44
  1101. data/packaging/debian/debian_specs/nginx/nginx-extras.prerm +0 -22
  1102. data/packaging/debian/debian_specs/nginx/nginx.1 +0 -47
  1103. data/packaging/debian/debian_specs/nginx/patches/perl-use-dpkg-buildflags.patch +0 -23
  1104. data/packaging/debian/debian_specs/nginx/patches/series +0 -1
  1105. data/packaging/debian/debian_specs/nginx/rules.erb +0 -185
  1106. data/packaging/debian/debian_specs/nginx/source/format +0 -1
  1107. data/packaging/debian/debian_specs/nginx/tests/control +0 -4
  1108. data/packaging/debian/debian_specs/nginx/ufw/nginx +0 -14
  1109. data/packaging/debian/debian_specs/nginx/upstream/signing-key.asc +0 -34
  1110. data/packaging/debian/debian_specs/nginx/watch +0 -3
  1111. data/packaging/debian/debian_specs/passenger/README.Debian +0 -12
  1112. data/packaging/debian/debian_specs/passenger/changelog +0 -316
  1113. data/packaging/debian/debian_specs/passenger/compat +0 -1
  1114. data/packaging/debian/debian_specs/passenger/control.erb +0 -123
  1115. data/packaging/debian/debian_specs/passenger/copyright +0 -385
  1116. data/packaging/debian/debian_specs/passenger/helpers.rb +0 -24
  1117. data/packaging/debian/debian_specs/passenger/libapache2-mod-passenger.install +0 -3
  1118. data/packaging/debian/debian_specs/passenger/libapache2-mod-passenger.postinst +0 -36
  1119. data/packaging/debian/debian_specs/passenger/libapache2-mod-passenger.prerm +0 -15
  1120. data/packaging/debian/debian_specs/passenger/locations.ini.erb +0 -14
  1121. data/packaging/debian/debian_specs/passenger/passenger-dev.install.erb +0 -3
  1122. data/packaging/debian/debian_specs/passenger/passenger-doc.install.erb +0 -2
  1123. data/packaging/debian/debian_specs/passenger/passenger.conf +0 -6
  1124. data/packaging/debian/debian_specs/passenger/passenger.docs +0 -4
  1125. data/packaging/debian/debian_specs/passenger/passenger.install.erb +0 -16
  1126. data/packaging/debian/debian_specs/passenger/passenger.load +0 -3
  1127. data/packaging/debian/debian_specs/passenger/passenger.manpages +0 -3
  1128. data/packaging/debian/debian_specs/passenger/passenger_free_ruby.c +0 -29
  1129. data/packaging/debian/debian_specs/passenger/passenger_ruby_utils.c +0 -54
  1130. data/packaging/debian/debian_specs/passenger/passenger_system_ruby.c.erb +0 -37
  1131. data/packaging/debian/debian_specs/passenger/rules.erb +0 -84
  1132. data/packaging/debian/debian_specs/passenger/source/format +0 -1
  1133. data/packaging/debian/debian_specs/passenger_enterprise/README.Debian +0 -12
  1134. data/packaging/debian/debian_specs/passenger_enterprise/changelog +0 -316
  1135. data/packaging/debian/debian_specs/passenger_enterprise/compat +0 -1
  1136. data/packaging/debian/debian_specs/passenger_enterprise/control.erb +0 -123
  1137. data/packaging/debian/debian_specs/passenger_enterprise/copyright +0 -385
  1138. data/packaging/debian/debian_specs/passenger_enterprise/helpers.rb +0 -2
  1139. data/packaging/debian/debian_specs/passenger_enterprise/libapache2-mod-passenger-enterprise.install +0 -3
  1140. data/packaging/debian/debian_specs/passenger_enterprise/libapache2-mod-passenger-enterprise.postinst +0 -36
  1141. data/packaging/debian/debian_specs/passenger_enterprise/libapache2-mod-passenger-enterprise.prerm +0 -15
  1142. data/packaging/debian/debian_specs/passenger_enterprise/locations.ini.erb +0 -14
  1143. data/packaging/debian/debian_specs/passenger_enterprise/passenger-enterprise-dev.install.erb +0 -3
  1144. data/packaging/debian/debian_specs/passenger_enterprise/passenger-enterprise-doc.install.erb +0 -2
  1145. data/packaging/debian/debian_specs/passenger_enterprise/passenger-enterprise.docs +0 -4
  1146. data/packaging/debian/debian_specs/passenger_enterprise/passenger-enterprise.install.erb +0 -14
  1147. data/packaging/debian/debian_specs/passenger_enterprise/passenger-enterprise.manpages +0 -3
  1148. data/packaging/debian/debian_specs/passenger_enterprise/passenger.conf +0 -6
  1149. data/packaging/debian/debian_specs/passenger_enterprise/passenger.load +0 -3
  1150. data/packaging/debian/debian_specs/passenger_enterprise/passenger_free_ruby.c.erb +0 -1
  1151. data/packaging/debian/debian_specs/passenger_enterprise/passenger_ruby_utils.c.erb +0 -1
  1152. data/packaging/debian/debian_specs/passenger_enterprise/passenger_system_ruby.c.erb +0 -1
  1153. data/packaging/debian/debian_specs/passenger_enterprise/patches/series +0 -0
  1154. data/packaging/debian/debian_specs/passenger_enterprise/rules.erb +0 -84
  1155. data/packaging/debian/debian_specs/passenger_enterprise/source/format +0 -1
  1156. data/packaging/debian/docker_images/Makefile +0 -38
  1157. data/packaging/debian/docker_images/buildbox/CONTAINER_VERSION.txt +0 -0
  1158. data/packaging/debian/docker_images/buildbox/Dockerfile +0 -3
  1159. data/packaging/debian/docker_images/buildbox/Gemfile +0 -9
  1160. data/packaging/debian/docker_images/buildbox/Gemfile.lock +0 -42
  1161. data/packaging/debian/docker_images/buildbox/install.sh +0 -85
  1162. data/packaging/debian/docker_images/buildbox/pbuilderrc +0 -4
  1163. data/packaging/debian/docker_images/buildbox/sudoers.conf +0 -6
  1164. data/packaging/debian/docker_images/setup-buildbox-docker-image +0 -7
  1165. data/packaging/debian/docker_images/setup-testbox-docker-image-debian-6 +0 -7
  1166. data/packaging/debian/docker_images/setup-testbox-docker-image-debian-7 +0 -7
  1167. data/packaging/debian/docker_images/setup-testbox-docker-image-debian-8 +0 -7
  1168. data/packaging/debian/docker_images/setup-testbox-docker-image-ubuntu-12.04 +0 -7
  1169. data/packaging/debian/docker_images/setup-testbox-docker-image-ubuntu-14.04 +0 -7
  1170. data/packaging/debian/docker_images/setup-testbox-docker-image-ubuntu-15.04 +0 -7
  1171. data/packaging/debian/docker_images/setup-testbox-docker-image-ubuntu-15.10 +0 -7
  1172. data/packaging/debian/docker_images/testbox-debian-6/Dockerfile +0 -3
  1173. data/packaging/debian/docker_images/testbox-debian-6/Gemfile +0 -2
  1174. data/packaging/debian/docker_images/testbox-debian-6/Gemfile.lock +0 -23
  1175. data/packaging/debian/docker_images/testbox-debian-6/argparse.py +0 -2374
  1176. data/packaging/debian/docker_images/testbox-debian-6/install.sh +0 -78
  1177. data/packaging/debian/docker_images/testbox-debian-7/Dockerfile +0 -3
  1178. data/packaging/debian/docker_images/testbox-debian-7/Gemfile +0 -2
  1179. data/packaging/debian/docker_images/testbox-debian-7/Gemfile.lock +0 -23
  1180. data/packaging/debian/docker_images/testbox-debian-7/install.sh +0 -71
  1181. data/packaging/debian/docker_images/testbox-debian-8/Dockerfile +0 -3
  1182. data/packaging/debian/docker_images/testbox-debian-8/Gemfile +0 -2
  1183. data/packaging/debian/docker_images/testbox-debian-8/Gemfile.lock +0 -23
  1184. data/packaging/debian/docker_images/testbox-debian-8/install.sh +0 -70
  1185. data/packaging/debian/docker_images/testbox-ubuntu-12.04/Dockerfile +0 -3
  1186. data/packaging/debian/docker_images/testbox-ubuntu-12.04/Gemfile +0 -2
  1187. data/packaging/debian/docker_images/testbox-ubuntu-12.04/Gemfile.lock +0 -23
  1188. data/packaging/debian/docker_images/testbox-ubuntu-12.04/install.sh +0 -69
  1189. data/packaging/debian/docker_images/testbox-ubuntu-14.04/Dockerfile +0 -3
  1190. data/packaging/debian/docker_images/testbox-ubuntu-14.04/Gemfile +0 -2
  1191. data/packaging/debian/docker_images/testbox-ubuntu-14.04/Gemfile.lock +0 -23
  1192. data/packaging/debian/docker_images/testbox-ubuntu-14.04/install.sh +0 -69
  1193. data/packaging/debian/docker_images/testbox-ubuntu-15.04/Dockerfile +0 -3
  1194. data/packaging/debian/docker_images/testbox-ubuntu-15.04/Gemfile +0 -2
  1195. data/packaging/debian/docker_images/testbox-ubuntu-15.04/Gemfile.lock +0 -23
  1196. data/packaging/debian/docker_images/testbox-ubuntu-15.04/install.sh +0 -69
  1197. data/packaging/debian/docker_images/testbox-ubuntu-15.10/Dockerfile +0 -3
  1198. data/packaging/debian/docker_images/testbox-ubuntu-15.10/Gemfile +0 -2
  1199. data/packaging/debian/docker_images/testbox-ubuntu-15.10/Gemfile.lock +0 -23
  1200. data/packaging/debian/docker_images/testbox-ubuntu-15.10/install.sh +0 -69
  1201. data/packaging/debian/internal/build/Rakefile +0 -235
  1202. data/packaging/debian/internal/build/build-passenger-orig-tarball.sh +0 -76
  1203. data/packaging/debian/internal/build/build-source-package.rb +0 -121
  1204. data/packaging/debian/internal/build/download-nginx-orig-tarball.sh +0 -17
  1205. data/packaging/debian/internal/build/rakefile_support.rb +0 -96
  1206. data/packaging/debian/internal/build/setup-environment-essentials.sh +0 -15
  1207. data/packaging/debian/internal/build/setup-environment.sh +0 -29
  1208. data/packaging/debian/internal/lib/distro_info.rb +0 -82
  1209. data/packaging/debian/internal/lib/distro_info.sh +0 -303
  1210. data/packaging/debian/internal/lib/distro_info.sh.erb +0 -65
  1211. data/packaging/debian/internal/lib/library.sh +0 -83
  1212. data/packaging/debian/internal/lib/preprocessor.rb +0 -173
  1213. data/packaging/debian/internal/lib/tracking.rb +0 -95
  1214. data/packaging/debian/internal/lib/tracking_category.rb +0 -45
  1215. data/packaging/debian/internal/lib/tracking_database.rb +0 -132
  1216. data/packaging/debian/internal/lib/tracking_task.rb +0 -148
  1217. data/packaging/debian/internal/lib/utils.rb +0 -78
  1218. data/packaging/debian/internal/publish/Rakefile +0 -97
  1219. data/packaging/debian/internal/publish/oss-binaries.phusionpassenger.com-fingerprint.txt +0 -1
  1220. data/packaging/debian/internal/publish/packagecloud_fingerprint.txt +0 -1
  1221. data/packaging/debian/internal/publish/passenger_website_fingerprint.txt +0 -1
  1222. data/packaging/debian/internal/publish/preinit.sh +0 -7
  1223. data/packaging/debian/internal/publish/rakefile_support.rb +0 -183
  1224. data/packaging/debian/internal/scripts/gpg_noninteractive/gpg +0 -11
  1225. data/packaging/debian/internal/scripts/initccache.sh +0 -35
  1226. data/packaging/debian/internal/scripts/inituidgid.sh +0 -19
  1227. data/packaging/debian/internal/scripts/my_init +0 -340
  1228. data/packaging/debian/internal/scripts/pin_certificates +0 -34
  1229. data/packaging/debian/internal/scripts/regen_distro_info_script.sh +0 -3
  1230. data/packaging/debian/internal/scripts/setup-vagrant.sh +0 -12
  1231. data/packaging/debian/internal/scripts/setuser +0 -31
  1232. data/packaging/debian/internal/shell/initpbuilder.sh +0 -3
  1233. data/packaging/debian/internal/shell/preinit.sh +0 -28
  1234. data/packaging/debian/internal/shell/sudoers.conf +0 -1
  1235. data/packaging/debian/internal/test/apache/apache-24.conf +0 -5
  1236. data/packaging/debian/internal/test/apache/apache-pre-24.conf +0 -4
  1237. data/packaging/debian/internal/test/apache/vhost.conf +0 -17
  1238. data/packaging/debian/internal/test/misc/config.json +0 -15
  1239. data/packaging/debian/internal/test/misc/hosts.conf +0 -4
  1240. data/packaging/debian/internal/test/misc/init.sh +0 -25
  1241. data/packaging/debian/internal/test/misc/nodejs_test_app.js +0 -6
  1242. data/packaging/debian/internal/test/misc/python_test_app.py +0 -3
  1243. data/packaging/debian/internal/test/misc/ruby_test_app.rb +0 -5
  1244. data/packaging/debian/internal/test/misc/test_support.rb +0 -61
  1245. data/packaging/debian/internal/test/nginx/vhost.conf +0 -23
  1246. data/packaging/debian/internal/test/system_web_server_test.rb +0 -126
  1247. data/packaging/debian/internal/test/test.sh +0 -141
  1248. data/packaging/debian/jenkins/publish/clear_caches.rb +0 -48
  1249. data/packaging/debian/jenkins/publish/publish.sh +0 -69
  1250. data/packaging/debian/jenkins/test/test.sh +0 -63
  1251. data/packaging/debian/passenger_apt_automation.sublime-project +0 -14
  1252. data/packaging/debian/publish +0 -172
  1253. data/packaging/debian/shell +0 -116
  1254. data/packaging/debian/test +0 -142
  1255. data/packaging/rpm/passenger_spec/rubygem-passenger-4.0.18-gcc47-include-sys_types.patch +0 -45
  1256. data/test/cxx/Base64Test.cpp +0 -50
  1257. data/test/cxx/FileBackedPipeTest.cpp +0 -626
  1258. data/test/cxx/HttpHeaderBuffererTest.cpp +0 -257
  1259. data/test/cxx/ScgiRequestParserTest.cpp +0 -423
  1260. data/test/cxx/ServerInstanceDirTest.cpp +0 -175
  1261. data/test/ruby/admin_tools_spec.rb +0 -360
  1262. data/test/ruby/classic_rails/loader_spec.rb +0 -46
  1263. data/test/ruby/classic_rails/preloader_spec.rb +0 -52
  1264. data/test/ruby/standalone/runtime_locator_spec.rb +0 -214
  1265. data/test/stub/rails2.3/Rakefile +0 -10
  1266. data/test/stub/rails2.3/app/controllers/application_controller.rb +0 -10
  1267. data/test/stub/rails2.3/app/controllers/bar_controller_1.rb +0 -5
  1268. data/test/stub/rails2.3/app/controllers/bar_controller_2.rb +0 -5
  1269. data/test/stub/rails2.3/app/controllers/foo_controller.rb +0 -21
  1270. data/test/stub/rails2.3/app/helpers/application_helper.rb +0 -3
  1271. data/test/stub/rails2.3/app/helpers/bar_helper.rb +0 -2
  1272. data/test/stub/rails2.3/app/helpers/foo_helper.rb +0 -2
  1273. data/test/stub/rails2.3/config/boot.rb +0 -110
  1274. data/test/stub/rails2.3/config/database.yml +0 -19
  1275. data/test/stub/rails2.3/config/environment.rb +0 -62
  1276. data/test/stub/rails2.3/config/environments/development.rb +0 -17
  1277. data/test/stub/rails2.3/config/environments/production.rb +0 -18
  1278. data/test/stub/rails2.3/config/environments/staging.rb +0 -18
  1279. data/test/stub/rails2.3/config/initializers/inflections.rb +0 -10
  1280. data/test/stub/rails2.3/config/initializers/mime_types.rb +0 -5
  1281. data/test/stub/rails2.3/config/routes.rb +0 -35
  1282. data/test/stub/rails2.3/log/.gitignore +0 -1
  1283. data/test/stub/rails2.3/public/.gitignore +0 -1
  1284. data/test/stub/rails2.3/script/about +0 -3
  1285. data/test/stub/rails2.3/script/console +0 -3
  1286. data/test/stub/rails2.3/script/dbconsole +0 -3
  1287. data/test/stub/rails2.3/script/destroy +0 -3
  1288. data/test/stub/rails2.3/script/generate +0 -3
  1289. data/test/stub/rails2.3/script/performance/benchmarker +0 -3
  1290. data/test/stub/rails2.3/script/performance/profiler +0 -3
  1291. data/test/stub/rails2.3/script/performance/request +0 -3
  1292. data/test/stub/rails2.3/script/plugin +0 -3
  1293. data/test/stub/rails2.3/script/process/inspector +0 -3
  1294. data/test/stub/rails2.3/script/process/reaper +0 -3
  1295. data/test/stub/rails2.3/script/process/spawner +0 -3
  1296. data/test/stub/rails2.3/script/runner +0 -3
  1297. data/test/stub/rails2.3/script/server +0 -3
  1298. data/test/stub/rails2.3/tmp/cache/.gitignore +0 -1
  1299. data/test/stub/rails2.3/tmp/pids/.gitignore +0 -1
  1300. data/test/stub/rails2.3/tmp/sessions/.gitignore +0 -1
  1301. data/test/stub/rails2.3/tmp/sockets/.gitignore +0 -1
@@ -0,0 +1,311 @@
1
+ /*
2
+ * Phusion Passenger - https://www.phusionpassenger.com/
3
+ * Copyright (c) 2010-2014 Phusion
4
+ *
5
+ * "Phusion Passenger" is a trademark of Hongli Lai & Ninh Bui.
6
+ *
7
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
8
+ * of this software and associated documentation files (the "Software"), to deal
9
+ * in the Software without restriction, including without limitation the rights
10
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11
+ * copies of the Software, and to permit persons to whom the Software is
12
+ * furnished to do so, subject to the following conditions:
13
+ *
14
+ * The above copyright notice and this permission notice shall be included in
15
+ * all copies or substantial portions of the Software.
16
+ *
17
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23
+ * THE SOFTWARE.
24
+ */
25
+ #ifndef _PASSENGER_SERVER_OPTION_PARSER_H_
26
+ #define _PASSENGER_SERVER_OPTION_PARSER_H_
27
+
28
+ #include <boost/thread.hpp>
29
+ #include <cstdio>
30
+ #include <cstdlib>
31
+ #include <Constants.h>
32
+ #include <Utils.h>
33
+ #include <Utils/VariantMap.h>
34
+ #include <Utils/OptionParsing.h>
35
+ #include <Utils/StrIntUtils.h>
36
+
37
+ namespace Passenger {
38
+
39
+ using namespace std;
40
+
41
+
42
+ inline void
43
+ serverUsage() {
44
+ printf("Usage: " AGENT_EXE " server <OPTIONS...> [APP DIRECTORY]\n");
45
+ printf("Runs the " PROGRAM_NAME " standalone HTTP server agent.\n");
46
+ printf("\n");
47
+ printf("The server starts in single-app mode, unless --multi-app is specified. When\n");
48
+ printf("in single-app mode, it serves the app at the current working directory, or the\n");
49
+ printf("app specified by APP DIRECTORY.\n");
50
+ printf("\n");
51
+ printf("Required options:\n");
52
+ printf(" --passenger-root PATH The location to the " PROGRAM_NAME " source\n");
53
+ printf(" directory\n");
54
+ printf("\n");
55
+ printf("Socket options (optional):\n");
56
+ printf(" -l, --listen ADDRESS Listen on the given address. The address must be\n");
57
+ printf(" formatted as tcp://IP:PORT for TCP sockets, or\n");
58
+ printf(" unix:PATH for Unix domain sockets. You can specify\n");
59
+ printf(" this option multiple times (up to %u times) to\n",
60
+ SERVER_KIT_MAX_SERVER_ENDPOINTS);
61
+ printf(" listen on multiple addresses. Default:\n");
62
+ printf(" " DEFAULT_HTTP_SERVER_LISTEN_ADDRESS "\n");
63
+ printf(" --admin-listen ADDRESS\n");
64
+ printf(" Listen on the given address for admin commands.\n");
65
+ printf(" The same syntax and limitations as with --listen\n");
66
+ printf(" are applicable\n");
67
+ printf("\n");
68
+ printf("Daemon options (optional):\n");
69
+ printf(" --pid-file PATH Store the server's PID in the given file. The file\n");
70
+ printf(" is deleted on exit\n");
71
+ printf("\n");
72
+ printf("Security options (optional):\n");
73
+ printf(" --multi-app-password-file PATH\n");
74
+ printf(" Password-protect access to the HTTP server\n");
75
+ printf(" (multi-app mode only)\n");
76
+ printf(" --authorize [LEVEL]:USERNAME:PASSWORDFILE\n");
77
+ printf(" Enables authentication on the admin server, through\n");
78
+ printf(" the given admin account. LEVEL indicates the\n");
79
+ printf(" privilege level (see below). PASSWORDFILE must\n");
80
+ printf(" point to a file containing the password\n");
81
+ printf("\n");
82
+ printf("Application serving options (optional):\n");
83
+ printf(" -e, --environment NAME Default framework environment name to use.\n");
84
+ printf(" Default: " DEFAULT_APP_ENV "\n");
85
+ printf(" --app-type TYPE The type of application you want to serve\n");
86
+ printf(" (single-app mode only)\n");
87
+ printf(" --startup-file PATH The path of the app's startup file, relative to\n");
88
+ printf(" the app root directory (single-app mode only)\n");
89
+ printf(" --spawn-method NAME Spawn method to use. Can either be 'smart' or\n");
90
+ printf(" 'direct'. Default: %s\n", DEFAULT_SPAWN_METHOD);
91
+ printf(" --load-shell-envvars Load shell startup files before loading application\n");
92
+ printf(" --concurrency-model The concurrency model to use for the app, either\n");
93
+ printf(" 'process' or 'thread' (Enterprise only).\n");
94
+ printf(" Default: " DEFAULT_CONCURRENCY_MODEL "\n");
95
+ printf(" --app-thread-count The number of application threads to use when using\n");
96
+ printf(" the 'thread' concurrency model (Enterprise only).\n");
97
+ printf(" Default: %d\n", DEFAULT_APP_THREAD_COUNT);
98
+ printf("\n");
99
+ printf(" --multi-app Enable multi-app mode\n");
100
+ printf("\n");
101
+ printf(" --force-friendly-error-pages\n");
102
+ printf(" Force friendly error pages to be always on\n");
103
+ printf(" --disable-friendly-error-pages\n");
104
+ printf(" Force friendly error pages to be always off\n");
105
+ printf(" --disable-turbocaching\n");
106
+ printf(" Disable turbocaching\n");
107
+ printf("\n");
108
+ printf(" --ruby PATH Default Ruby interpreter to use.\n");
109
+ printf("\n");
110
+ printf(" --rolling-restarts Enable rolling restarts (Enterprise only)\n");
111
+ printf("\n");
112
+ printf("Process management options (optional):\n");
113
+ printf(" --max-pool-size N Maximum number of application processes.\n");
114
+ printf(" Default: %d\n", DEFAULT_MAX_POOL_SIZE);
115
+ printf(" --pool-idle-time SECS\n");
116
+ printf(" Maximum number of seconds an application process\n");
117
+ printf(" may be idle. Default: %d\n", DEFAULT_POOL_IDLE_TIME);
118
+ printf(" --min-instances N Minimum number of application processes. Default: 1\n");
119
+ printf("\n");
120
+ printf("Other options (optional):\n");
121
+ printf(" --log-file PATH Log to the given file.\n");
122
+ printf(" --log-level LEVEL Logging level. Default: %d\n", DEFAULT_LOG_LEVEL);
123
+ printf(" --stat-throttle-rate SECONDS\n");
124
+ printf(" Throttle filesystem restart.txt checks to at most\n");
125
+ printf(" once per given seconds. Default: %d\n", DEFAULT_STAT_THROTTLE_RATE);
126
+ printf(" --no-show-version-in-header\n");
127
+ printf(" Do not show " PROGRAM_NAME " version number in\n");
128
+ printf(" HTTP headers.\n");
129
+ printf(" --data-buffer-dir PATH\n");
130
+ printf(" Directory to store data buffers in. Default:\n");
131
+ printf(" %s\n", getSystemTempDir());
132
+ printf(" --no-graceful-exit When exiting, exit immediately instead of waiting\n");
133
+ printf(" for all connections to terminate\n");
134
+ printf(" --benchmark MODE Enable benchmark mode. Available modes:\n");
135
+ printf(" after_accept,before_checkout,after_checkout,\n");
136
+ printf(" response_begin\n");
137
+ printf(" --disable-selfchecks Disable various self-checks. This improves\n");
138
+ printf(" performance, but might delay finding bugs in\n");
139
+ printf(" " PROGRAM_NAME "\n");
140
+ printf(" --threads NUMBER Number of threads to use for request handling.\n");
141
+ printf(" Default: number of CPU cores (%d)\n",
142
+ boost::thread::hardware_concurrency());
143
+ printf(" --cpu-affine Enable per-thread CPU affinity (Linux only)\n");
144
+ printf(" -h, --help Show this help\n");
145
+ printf("\n");
146
+ printf("Admin account privilege levels (ordered from most to least privileges):\n");
147
+ printf(" readonly Read-only access\n");
148
+ printf(" full Full access (default)\n");
149
+ }
150
+
151
+ inline bool
152
+ parseServerOption(int argc, const char *argv[], int &i, VariantMap &options) {
153
+ OptionParser p(serverUsage);
154
+
155
+ if (p.isValueFlag(argc, i, argv[i], '\0', "--passenger-root")) {
156
+ options.set("passenger_root", argv[i + 1]);
157
+ i += 2;
158
+ } else if (p.isValueFlag(argc, i, argv[i], 'l', "--listen")) {
159
+ if (getSocketAddressType(argv[i + 1]) != SAT_UNKNOWN) {
160
+ vector<string> addresses = options.getStrSet("server_addresses", false);
161
+ if (addresses.size() == SERVER_KIT_MAX_SERVER_ENDPOINTS) {
162
+ fprintf(stderr, "ERROR: you may specify up to %u --listen addresses.\n",
163
+ SERVER_KIT_MAX_SERVER_ENDPOINTS);
164
+ exit(1);
165
+ }
166
+ addresses.push_back(argv[i + 1]);
167
+ options.setStrSet("server_addresses", addresses);
168
+ i += 2;
169
+ } else {
170
+ fprintf(stderr, "ERROR: invalid address format for --listen. The address "
171
+ "must be formatted as tcp://IP:PORT for TCP sockets, or unix:PATH "
172
+ "for Unix domain sockets.\n");
173
+ exit(1);
174
+ }
175
+ } else if (p.isValueFlag(argc, i, argv[i], '\0', "--admin-listen")) {
176
+ if (getSocketAddressType(argv[i + 1]) != SAT_UNKNOWN) {
177
+ vector<string> addresses = options.getStrSet("server_admin_addresses",
178
+ false);
179
+ if (addresses.size() == SERVER_KIT_MAX_SERVER_ENDPOINTS) {
180
+ fprintf(stderr, "ERROR: you may specify up to %u --admin-listen addresses.\n",
181
+ SERVER_KIT_MAX_SERVER_ENDPOINTS);
182
+ exit(1);
183
+ }
184
+ addresses.push_back(argv[i + 1]);
185
+ options.setStrSet("server_admin_addresses", addresses);
186
+ i += 2;
187
+ } else {
188
+ fprintf(stderr, "ERROR: invalid address format for --admin-listen. The address "
189
+ "must be formatted as tcp://IP:PORT for TCP sockets, or unix:PATH "
190
+ "for Unix domain sockets.\n");
191
+ exit(1);
192
+ }
193
+ } else if (p.isValueFlag(argc, i, argv[i], '\0', "--pid-file")) {
194
+ options.set("server_pid_file", argv[i + 1]);
195
+ i += 2;
196
+ } else if (p.isValueFlag(argc, i, argv[i], '\0', "--authorize")) {
197
+ vector<string> args;
198
+ vector<string> authorizations = options.getStrSet("server_authorizations",
199
+ false);
200
+
201
+ split(argv[i + 1], ':', args);
202
+ if (args.size() < 2 || args.size() > 3) {
203
+ fprintf(stderr, "ERROR: invalid format for --authorize. The syntax "
204
+ "is \"[LEVEL:]USERNAME:PASSWORDFILE\".\n");
205
+ exit(1);
206
+ }
207
+
208
+ authorizations.push_back(argv[i + 1]);
209
+ options.setStrSet("server_authorizations", authorizations);
210
+ i += 2;
211
+ } else if (p.isValueFlag(argc, i, argv[i], '\0', "--max-pool-size")) {
212
+ options.setInt("max_pool_size", atoi(argv[i + 1]));
213
+ i += 2;
214
+ } else if (p.isValueFlag(argc, i, argv[i], '\0', "--pool-idle-time")) {
215
+ options.setInt("pool_idle_time", atoi(argv[i + 1]));
216
+ i += 2;
217
+ } else if (p.isValueFlag(argc, i, argv[i], '\0', "--min-instances")) {
218
+ options.setInt("min_instances", atoi(argv[i + 1]));
219
+ i += 2;
220
+ } else if (p.isValueFlag(argc, i, argv[i], 'e', "--environment")) {
221
+ options.set("environment", argv[i + 1]);
222
+ i += 2;
223
+ } else if (p.isValueFlag(argc, i, argv[i], '\0', "--app-type")) {
224
+ options.set("app_type", argv[i + 1]);
225
+ i += 2;
226
+ } else if (p.isValueFlag(argc, i, argv[i], '\0', "--startup-file")) {
227
+ options.set("startup_file", argv[i + 1]);
228
+ i += 2;
229
+ } else if (p.isValueFlag(argc, i, argv[i], '\0', "--spawn-method")) {
230
+ options.set("spawn_method", argv[i + 1]);
231
+ i += 2;
232
+ } else if (p.isFlag(argv[i], '\0', "--load-shell-envvars")) {
233
+ options.setBool("load_shell_envvars", true);
234
+ i++;
235
+ } else if (p.isValueFlag(argc, i, argv[i], '\0', "--concurrency-model")) {
236
+ options.set("concurrency_model", argv[i + 1]);
237
+ i += 2;
238
+ } else if (p.isValueFlag(argc, i, argv[i], '\0', "--app-thread-count")) {
239
+ options.setInt("app_thread_count", atoi(argv[i + 1]));
240
+ i += 2;
241
+ } else if (p.isFlag(argv[i], '\0', "--multi-app")) {
242
+ options.setBool("multi_app", true);
243
+ i++;
244
+ } else if (p.isFlag(argv[i], '\0', "--force-friendly-error-pages")) {
245
+ options.set("friendly_error_pages", "true");
246
+ i++;
247
+ } else if (p.isFlag(argv[i], '\0', "--disable-friendly-error-pages")) {
248
+ options.set("friendly_error_pages", "false");
249
+ i++;
250
+ } else if (p.isFlag(argv[i], '\0', "--disable-turbocaching")) {
251
+ options.setBool("turbocaching", false);
252
+ i++;
253
+ } else if (p.isValueFlag(argc, i, argv[i], '\0', "--ruby")) {
254
+ options.set("default_ruby", argv[i + 1]);
255
+ i += 2;
256
+ } else if (p.isFlag(argv[i], '\0', "--rolling-restarts")) {
257
+ options.setBool("rolling_restarts", true);
258
+ i++;
259
+ } else if (p.isValueFlag(argc, i, argv[i], '\0', "--log-level")) {
260
+ // We do not set log_level because, when this function is called from
261
+ // the Watchdog, we don't want to affect the Watchdog's own log level.
262
+ options.setInt("server_log_level", atoi(argv[i + 1]));
263
+ i += 2;
264
+ } else if (p.isValueFlag(argc, i, argv[i], '\0', "--log-file")) {
265
+ // We do not set debug_log_file because, when this function is called from
266
+ // the Watchdog, we don't want to affect the Watchdog's own log file.
267
+ options.set("server_log_file", argv[i + 1]);
268
+ i += 2;
269
+ } else if (p.isValueFlag(argc, i, argv[i], '\0', "--stat-throttle-rate")) {
270
+ options.setInt("stat_throttle_rate", atoi(argv[i + 1]));
271
+ i += 2;
272
+ } else if (p.isFlag(argv[i], '\0', "--no-show-version-in-header")) {
273
+ options.setBool("show_version_in_header", false);
274
+ i++;
275
+ } else if (p.isValueFlag(argc, i, argv[i], '\0', "--data-buffer-dir")) {
276
+ options.setInt("data_buffer_dir", atoi(argv[i + 1]));
277
+ i += 2;
278
+ } else if (p.isFlag(argv[i], '\0', "--no-graceful-exit")) {
279
+ options.setBool("server_graceful_exit", false);
280
+ i++;
281
+ } else if (p.isValueFlag(argc, i, argv[i], '\0', "--benchmark")) {
282
+ options.set("benchmark_mode", argv[i + 1]);
283
+ i += 2;
284
+ } else if (p.isFlag(argv[i], '\0', "--disable-selfchecks")) {
285
+ options.setBool("selfchecks", false);
286
+ i++;
287
+ } else if (p.isValueFlag(argc, i, argv[i], '\0', "--threads")) {
288
+ options.setInt("server_threads", atoi(argv[i + 1]));
289
+ i += 2;
290
+ } else if (p.isFlag(argv[i], '\0', "--cpu-affine")) {
291
+ options.setBool("server_cpu_affine", true);
292
+ i++;
293
+ } else if (!startsWith(argv[i], "-")) {
294
+ if (!options.has("app_root")) {
295
+ options.set("app_root", argv[i]);
296
+ i++;
297
+ } else {
298
+ fprintf(stderr, "ERROR: you may not pass multiple application directories. "
299
+ "Please type '%s server --help' for usage.\n", argv[0]);
300
+ exit(1);
301
+ }
302
+ } else {
303
+ return false;
304
+ }
305
+ return true;
306
+ }
307
+
308
+
309
+ } // namespace Passenger
310
+
311
+ #endif /* _PASSENGER_SERVER_OPTION_PARSER_H_ */
@@ -109,12 +109,14 @@
109
109
  #ifndef _PASSENGER_REQUEST_HANDLER_H_
110
110
  #define _PASSENGER_REQUEST_HANDLER_H_
111
111
 
112
+ //#define DEBUG_RH_EVENT_LOOP_BLOCKING
113
+
112
114
  #include <boost/shared_ptr.hpp>
113
- #include <boost/weak_ptr.hpp>
114
115
  #include <boost/make_shared.hpp>
115
- #include <boost/regex.hpp>
116
116
  #include <boost/cstdint.hpp>
117
+ #include <oxt/macros.hpp>
117
118
  #include <ev++.h>
119
+ #include <ostream>
118
120
 
119
121
  #if defined(__GLIBCXX__) || defined(__APPLE__)
120
122
  #include <cxxabi.h>
@@ -122,32 +124,34 @@
122
124
  #endif
123
125
 
124
126
  #include <sys/types.h>
125
- #include <arpa/inet.h>
126
- #include <sys/un.h>
127
+ #include <sys/uio.h>
127
128
  #include <utility>
128
129
  #include <typeinfo>
130
+ #include <cstdio>
129
131
  #include <cassert>
130
132
  #include <cctype>
131
133
 
132
134
  #include <Logging.h>
133
- #include <EventedBufferedInput.h>
134
135
  #include <MessageReadersWriters.h>
135
136
  #include <Constants.h>
136
- #include <UnionStation/Core.h>
137
- #include <UnionStation/Transaction.h>
138
- #include <UnionStation/ScopeLog.h>
139
- #include <ApplicationPool2/Pool.h>
137
+ #include <ServerKit/Errors.h>
138
+ #include <ServerKit/HttpServer.h>
139
+ #include <ServerKit/HttpHeaderParser.h>
140
+ #include <MemoryKit/palloc.h>
141
+ #include <DataStructures/LString.h>
142
+ #include <DataStructures/StringKeyTable.h>
140
143
  #include <ApplicationPool2/ErrorRenderer.h>
144
+ #include <StaticString.h>
145
+ #include <Utils.h>
141
146
  #include <Utils/StrIntUtils.h>
142
147
  #include <Utils/IOUtils.h>
143
- #include <Utils/HttpHeaderBufferer.h>
148
+ #include <Utils/JsonUtils.h>
144
149
  #include <Utils/HttpConstants.h>
145
- #include <Utils/Template.h>
150
+ #include <Utils/VariantMap.h>
146
151
  #include <Utils/Timer.h>
147
- #include <Utils/Dechunker.h>
148
- #include <agents/HelperAgent/AgentOptions.h>
149
- #include <agents/HelperAgent/FileBackedPipe.h>
150
- #include <agents/HelperAgent/ScgiRequestParser.h>
152
+ #include <agents/HelperAgent/RequestHandler/Client.h>
153
+ #include <agents/HelperAgent/RequestHandler/AppResponse.h>
154
+ #include <agents/HelperAgent/RequestHandler/TurboCaching.h>
151
155
 
152
156
  namespace Passenger {
153
157
 
@@ -156,2595 +160,358 @@ using namespace boost;
156
160
  using namespace oxt;
157
161
  using namespace ApplicationPool2;
158
162
 
159
- class RequestHandler;
160
-
161
- #define MAX_STATUS_HEADER_SIZE 64
162
-
163
- #define RH_ERROR(client, x) P_ERROR("[Client " << client->name() << "] " << x)
164
- #define RH_WARN(client, x) P_WARN("[Client " << client->name() << "] " << x)
165
- #define RH_DEBUG(client, x) P_DEBUG("[Client " << client->name() << "] " << x)
166
- #define RH_TRACE(client, level, x) P_TRACE(level, "[Client " << client->name() << "] " << x)
167
-
168
- #define RH_LOG_EVENT(client, eventName) \
169
- char _clientName[7 + 8]; \
170
- snprintf(_clientName, sizeof(_clientName), "Client %d", client->fdnum); \
171
- TRACE_POINT_WITH_DATA(_clientName); \
172
- RH_TRACE(client, 3, "Event: " eventName)
173
-
174
-
175
- class Client: public boost::enable_shared_from_this<Client> {
176
- private:
177
- struct ev_loop *getLoop() const;
178
- const SafeLibevPtr &getSafeLibev() const;
179
- unsigned int getConnectPasswordTimeout(const RequestHandler *handler) const;
180
-
181
- static size_t onClientInputData(const EventedBufferedInputPtr &source, const StaticString &data);
182
- static void onClientInputError(const EventedBufferedInputPtr &source, const char *message, int errnoCode);
183
-
184
- static void onClientBodyBufferData(const FileBackedPipePtr &source,
185
- const char *data, size_t size,
186
- const FileBackedPipe::ConsumeCallback &callback);
187
- static void onClientBodyBufferEnd(const FileBackedPipePtr &source);
188
- static void onClientBodyBufferError(const FileBackedPipePtr &source, int errorCode);
189
- static void onClientBodyBufferCommit(const FileBackedPipePtr &source);
190
-
191
- static void onClientOutputPipeData(const FileBackedPipePtr &source,
192
- const char *data, size_t size,
193
- const FileBackedPipe::ConsumeCallback &callback);
194
- static void onClientOutputPipeEnd(const FileBackedPipePtr &source);
195
- static void onClientOutputPipeError(const FileBackedPipePtr &source, int errorCode);
196
- static void onClientOutputPipeCommit(const FileBackedPipePtr &source);
197
-
198
- void onClientOutputWritable(ev::io &io, int revents);
199
-
200
- static size_t onAppInputData(const EventedBufferedInputPtr &source, const StaticString &data);
201
- static void onAppInputChunk(const char *data, size_t size, void *userData);
202
- static void onAppInputChunkEnd(void *userData);
203
- static void onAppInputError(const EventedBufferedInputPtr &source, const char *message, int errnoCode);
204
-
205
- void onAppOutputWritable(ev::io &io, int revents);
206
-
207
- void onTimeout(ev::timer &timer, int revents);
208
-
209
-
210
- static const char *boolStr(bool val) {
211
- static const char *strs[] = { "false", "true" };
212
- return strs[val];
213
- }
214
-
215
- void resetPrimitiveFields() {
216
- requestHandler = NULL;
217
- state = DISCONNECTED;
218
- backgroundOperations = 0;
219
- requestBodyIsBuffered = false;
220
- requestIsChunked = false;
221
- freeBufferedConnectPassword();
222
- connectedAt = 0;
223
- requestBodyLength = 0;
224
- requestBodyAlreadyRead = 0;
225
- checkoutSessionAfterCommit = false;
226
- stickySession = false;
227
- sessionCheckedOut = false;
228
- sessionCheckoutTry = 0;
229
- responseHeaderSeen = false;
230
- chunkedResponse = false;
231
- responseContentLength = -1;
232
- responseBodyAlreadyRead = 0;
233
- appRoot.clear();
234
- }
235
-
236
- void freeScopeLogs() {
237
- endScopeLog(&scopeLogs.requestProxying, false);
238
- endScopeLog(&scopeLogs.getFromPool, false);
239
- endScopeLog(&scopeLogs.bufferingRequestBody, false);
240
- endScopeLog(&scopeLogs.requestProcessing, false);
241
- }
242
-
243
- public:
244
- /** Back reference to the RequestHandler that this Client is associated with.
245
- * NULL when this Client is not in the pool or is disconnected. */
246
- RequestHandler *requestHandler;
247
- /** File descriptor of the client socket. Is empty when this Client is not
248
- * in the pool or is disconnected. */
249
- FileDescriptor fd;
250
- /** The last associated file descriptor number is stored here. It is not
251
- * cleared after disassociating. Its only purpose is to make logging calls
252
- * like RH_DEBUG() print the correct client name after disconnect() is called.
253
- * Do not use this value for anything else as it may not refer to a valid
254
- * file descriptor. */
255
- int fdnum;
256
-
257
-
258
- /***** Client <-> RequestHandler I/O channels, pipes and watchers *****/
259
-
260
- /** Client input channel. */
261
- EventedBufferedInputPtr clientInput;
262
- /** If request body buffering is turned on, it will be buffered into this FileBackedPipe. */
263
- FileBackedPipePtr clientBodyBuffer;
264
- /** Client output pipe. */
265
- FileBackedPipePtr clientOutputPipe;
266
- /** Client output channel watcher. */
267
- ev::io clientOutputWatcher;
268
-
269
-
270
- /***** RequestHandler <-> Application I/O channels, pipes and watchers *****/
271
-
272
- /** Application input channel. */
273
- EventedBufferedInputPtr appInput;
274
- string appOutputBuffer;
275
- /** Application output channel watcher. */
276
- ev::io appOutputWatcher;
277
-
278
-
279
- /***** State variables *****/
280
-
281
- enum {
282
- BEGIN_READING_CONNECT_PASSWORD,
283
- STILL_READING_CONNECT_PASSWORD,
284
- READING_HEADER,
285
- BUFFERING_REQUEST_BODY,
286
- CHECKING_OUT_SESSION,
287
- SENDING_HEADER_TO_APP,
288
- FORWARDING_BODY_TO_APP,
289
-
290
- // Special states
291
- WRITING_SIMPLE_RESPONSE,
292
- DISCONNECTED
293
- } state;
294
-
295
- /* How many background operations are currently in progress, e.g.
296
- * an asyncGet() or bodyBuffer.add(). If the client is disconnected
297
- * while this flag is true, then the Client object is not reassociateable
298
- * in order to give the completion callbacks a chance to cancel properly.
299
- */
300
- unsigned int backgroundOperations;
301
-
302
- struct {
303
- char *data;
304
- unsigned int alreadyRead;
305
- } bufferedConnectPassword;
306
-
307
- // Used for enforcing the connection timeout.
308
- ev::timer timeoutTimer;
309
-
310
- ev_tstamp connectedAt;
311
- /** The size of the request body. The request body is the part that comes
312
- * after the request headers, which may be the HTTP request message body,
313
- * but may also be any other arbitrary data that is sent over the request
314
- * socket (e.g. WebSocket data).
315
- *
316
- * Possible values:
317
- *
318
- * -1: infinite. Should keep forwarding client body until end of stream.
319
- * 0: no client body. Should stop after sending headers to application.
320
- * >0: Should forward exactly this many bytes of the client body.
321
- */
322
- long long requestBodyLength;
323
- unsigned long long requestBodyAlreadyRead;
324
- Options options;
325
- ScgiRequestParser scgiParser;
326
- SessionPtr session;
327
- string appRoot;
328
- struct {
329
- UnionStation::ScopeLog
330
- *requestProcessing,
331
- *bufferingRequestBody,
332
- *getFromPool,
333
- *requestProxying;
334
- } scopeLogs;
335
- unsigned int sessionCheckoutTry;
336
- bool requestBodyIsBuffered;
337
- bool requestIsChunked;
338
- bool sessionCheckedOut;
339
- bool checkoutSessionAfterCommit;
340
- bool stickySession;
341
-
342
- bool responseHeaderSeen;
343
- bool chunkedResponse;
344
- /** The size of the response body, set based on the values of
345
- * the Content-Length and Transfer-Encoding response headers.
346
- * Possible values:
347
- *
348
- * -1: infinite. Should keep forwarding response body until end of stream.
349
- * This is the case for WebSockets or for responses without Content-Length.
350
- * Responses with "Transfer-Encoding: chunked" also fall under this
351
- * category, though in this case encountering the zero-length chunk is
352
- * treated the same as end of stream.
353
- * 0 : no client body. Should immediately close connection after forwarding
354
- * headers.
355
- * >0: Should forward exactly this many bytes of the response body.
356
- */
357
- long long responseContentLength;
358
- unsigned long long responseBodyAlreadyRead;
359
- HttpHeaderBufferer responseHeaderBufferer;
360
- Dechunker responseDechunker;
361
-
362
-
363
- Client() {
364
- fdnum = -1;
365
-
366
- clientInput = boost::make_shared< EventedBufferedInput<> >();
367
- clientInput->onData = onClientInputData;
368
- clientInput->onError = onClientInputError;
369
- clientInput->userData = this;
370
-
371
- clientBodyBuffer = boost::make_shared<FileBackedPipe>("/tmp");
372
- clientBodyBuffer->userData = this;
373
- clientBodyBuffer->onData = onClientBodyBufferData;
374
- clientBodyBuffer->onEnd = onClientBodyBufferEnd;
375
- clientBodyBuffer->onError = onClientBodyBufferError;
376
- clientBodyBuffer->onCommit = onClientBodyBufferCommit;
377
-
378
- clientOutputPipe = boost::make_shared<FileBackedPipe>("/tmp");
379
- clientOutputPipe->userData = this;
380
- clientOutputPipe->onData = onClientOutputPipeData;
381
- clientOutputPipe->onEnd = onClientOutputPipeEnd;
382
- clientOutputPipe->onError = onClientOutputPipeError;
383
- clientOutputPipe->onCommit = onClientOutputPipeCommit;
384
-
385
- clientOutputWatcher.set<Client, &Client::onClientOutputWritable>(this);
386
-
387
-
388
- appInput = boost::make_shared< EventedBufferedInput<> >();
389
- appInput->onData = onAppInputData;
390
- appInput->onError = onAppInputError;
391
- appInput->userData = this;
392
-
393
- appOutputWatcher.set<Client, &Client::onAppOutputWritable>(this);
394
-
395
-
396
- timeoutTimer.set<Client, &Client::onTimeout>(this);
397
-
398
-
399
- responseDechunker.onData = onAppInputChunk;
400
- responseDechunker.onEnd = onAppInputChunkEnd;
401
- responseDechunker.userData = this;
402
-
403
-
404
- bufferedConnectPassword.data = NULL;
405
- bufferedConnectPassword.alreadyRead = 0;
406
- memset(&scopeLogs, 0, sizeof(scopeLogs));
407
- resetPrimitiveFields();
408
- }
409
-
410
- ~Client() {
411
- if (requestHandler != NULL) {
412
- discard();
413
- }
414
- clientInput->userData = NULL;
415
- clientBodyBuffer->userData = NULL;
416
- clientOutputPipe->userData = NULL;
417
- appInput->userData = NULL;
418
- freeBufferedConnectPassword();
419
- freeScopeLogs();
420
- }
421
-
422
- void associate(RequestHandler *handler, const FileDescriptor &_fd) {
423
- assert(requestHandler == NULL);
424
- requestHandler = handler;
425
- fd = _fd;
426
- fdnum = _fd;
427
- state = BEGIN_READING_CONNECT_PASSWORD;
428
- connectedAt = ev_time();
429
-
430
- clientInput->reset(getSafeLibev().get(), _fd);
431
- clientInput->start();
432
- clientBodyBuffer->reset(getSafeLibev());
433
- clientOutputPipe->reset(getSafeLibev());
434
- clientOutputPipe->start();
435
- clientOutputWatcher.set(getLoop());
436
- clientOutputWatcher.set(_fd, ev::WRITE);
437
-
438
- // appOutputWatcher is initialized in initiateSession.
439
-
440
- timeoutTimer.set(getLoop());
441
- timeoutTimer.start(getConnectPasswordTimeout(handler) / 1000.0, 0.0);
442
- }
443
-
444
- void disassociate() {
445
- assert(requestHandler != NULL);
446
- resetPrimitiveFields();
447
- fd = FileDescriptor();
448
-
449
- clientInput->reset(NULL, FileDescriptor());
450
- clientBodyBuffer->reset();
451
- clientOutputPipe->reset();
452
- clientOutputWatcher.stop();
453
-
454
- appInput->reset(NULL, FileDescriptor());
455
- appOutputBuffer.resize(0);
456
- appOutputWatcher.stop();
457
-
458
- timeoutTimer.stop();
459
- scgiParser.reset();
460
- session.reset();
461
- responseHeaderBufferer.reset();
462
- responseDechunker.reset();
463
- freeScopeLogs();
464
- }
465
-
466
- void discard() {
467
- assert(requestHandler != NULL);
468
- resetPrimitiveFields();
469
- fd = FileDescriptor();
470
-
471
- clientInput->stop();
472
- clientBodyBuffer->reset();
473
- clientOutputPipe->reset();
474
- clientOutputWatcher.stop();
475
-
476
- appInput->stop();
477
- appOutputWatcher.stop();
478
-
479
- timeoutTimer.stop();
480
-
481
- freeScopeLogs();
482
-
483
- requestHandler = NULL;
484
- }
485
-
486
- bool reassociateable() const {
487
- return requestHandler == NULL
488
- && backgroundOperations == 0
489
- && clientInput->resetable()
490
- && clientBodyBuffer->resetable()
491
- && clientOutputPipe->resetable()
492
- && appInput->resetable();
493
- }
494
-
495
- string name() const {
496
- if (fdnum == -1) {
497
- return "(null)";
498
- } else {
499
- return toString(fdnum);
500
- }
501
- }
502
-
503
- bool connected() const {
504
- return requestHandler != NULL;
505
- }
506
-
507
- const char *getStateName() const {
508
- switch (state) {
509
- case BEGIN_READING_CONNECT_PASSWORD:
510
- return "BEGIN_READING_CONNECT_PASSWORD";
511
- case STILL_READING_CONNECT_PASSWORD:
512
- return "STILL_READING_CONNECT_PASSWORD";
513
- case READING_HEADER:
514
- return "READING_HEADER";
515
- case BUFFERING_REQUEST_BODY:
516
- return "BUFFERING_REQUEST_BODY";
517
- case CHECKING_OUT_SESSION:
518
- return "CHECKING_OUT_SESSION";
519
- case SENDING_HEADER_TO_APP:
520
- return "SENDING_HEADER_TO_APP";
521
- case FORWARDING_BODY_TO_APP:
522
- return "FORWARDING_BODY_TO_APP";
523
- case WRITING_SIMPLE_RESPONSE:
524
- return "WRITING_SIMPLE_RESPONSE";
525
- case DISCONNECTED:
526
- return "DISCONNECTED";
527
- default:
528
- return "UNKNOWN";
529
- }
530
- }
531
-
532
- void freeBufferedConnectPassword() {
533
- if (bufferedConnectPassword.data != NULL) {
534
- free(bufferedConnectPassword.data);
535
- bufferedConnectPassword.data = NULL;
536
- bufferedConnectPassword.alreadyRead = 0;
537
- }
538
- }
539
-
540
- /**
541
- * Checks whether we should half-close the application socket after forwarding
542
- * the request. HTTP does not formally support half-closing, and Node.js treats a
543
- * half-close as a full close, so we only half-close session sockets, not
544
- * HTTP sockets.
545
- */
546
- bool shouldHalfCloseWrite() const {
547
- return session->getProtocol() == "session";
548
- }
549
-
550
- bool useUnionStation() const {
551
- return options.transaction != NULL;
552
- }
553
-
554
- UnionStation::TransactionPtr getUnionStationTransaction() const {
555
- return options.transaction;
556
- }
557
-
558
- void beginScopeLog(UnionStation::ScopeLog **scopeLog, const char *name) {
559
- if (options.transaction != NULL) {
560
- *scopeLog = new UnionStation::ScopeLog(options.transaction, name);
561
- }
562
- }
563
-
564
- void endScopeLog(UnionStation::ScopeLog **scopeLog, bool success = true) {
565
- if (success && *scopeLog != NULL) {
566
- (*scopeLog)->success();
567
- }
568
- delete *scopeLog;
569
- *scopeLog = NULL;
570
- }
571
-
572
- void logMessage(const StaticString &message) {
573
- options.transaction->message(message);
574
- }
575
-
576
- void verifyInvariants() const {
577
- assert((requestHandler == NULL) == (fd == -1));
578
- assert((requestHandler == NULL) == (state == DISCONNECTED));
579
- }
580
-
581
- template<typename Stream>
582
- void inspect(Stream &stream) const {
583
- const char *indent = " ";
584
- time_t the_time;
585
- struct tm the_tm;
586
- char timestr[60];
587
-
588
- the_time = (time_t) connectedAt;
589
- localtime_r(&the_time, &the_tm);
590
- strftime(timestr, sizeof(timestr) - 1, "%F %H:%M:%S", &the_tm);
591
-
592
- stream << indent << "host = " << (scgiParser.getHeader("HTTP_HOST").empty() ? "(empty)" : scgiParser.getHeader("HTTP_HOST")) << "\n";
593
- stream << indent << "uri = " << (scgiParser.getHeader("REQUEST_URI").empty() ? "(empty)" : scgiParser.getHeader("REQUEST_URI")) << "\n";
594
- stream << indent << "connected at = " << timestr << " (" << (unsigned long long) (ev_time() - connectedAt) << " sec ago)\n";
595
- stream << indent << "state = " << getStateName() << "\n";
596
- if (session == NULL) {
597
- stream << indent << "session = NULL\n";
598
- } else {
599
- stream << indent << "session pid = " << session->getPid() << " (" <<
600
- session->getGroup()->name << ")\n";
601
- stream << indent << "session gupid = " << session->getGupid() << "\n";
602
- stream << indent << "session initiated = " << boolStr(session->initiated()) << "\n";
603
- }
604
- stream
605
- << indent << "requestBodyIsBuffered = " << boolStr(requestBodyIsBuffered) << "\n"
606
- << indent << "requestIsChunked = " << boolStr(requestIsChunked) << "\n"
607
- << indent << "requestBodyLength = " << requestBodyLength << "\n"
608
- << indent << "requestBodyAlreadyRead = " << requestBodyAlreadyRead << "\n"
609
- << indent << "responseContentLength = " << responseContentLength << "\n"
610
- << indent << "responseBodyAlreadyRead = " << responseBodyAlreadyRead << "\n"
611
- << indent << "clientInput = " << clientInput.get() << " " << clientInput->inspect() << "\n"
612
- << indent << "clientInput started = " << boolStr(clientInput->isStarted()) << "\n"
613
- << indent << "clientBodyBuffer started = " << boolStr(clientBodyBuffer->isStarted()) << "\n"
614
- << indent << "clientBodyBuffer reachedEnd = " << boolStr(clientBodyBuffer->reachedEnd()) << "\n"
615
- << indent << "clientOutputPipe started = " << boolStr(clientOutputPipe->isStarted()) << "\n"
616
- << indent << "clientOutputPipe reachedEnd = " << boolStr(clientOutputPipe->reachedEnd()) << "\n"
617
- << indent << "clientOutputWatcher active = " << boolStr(clientOutputWatcher.is_active()) << "\n"
618
- << indent << "appInput = " << appInput.get() << " " << appInput->inspect() << "\n"
619
- << indent << "appInput started = " << boolStr(appInput->isStarted()) << "\n"
620
- << indent << "appInput reachedEnd = " << boolStr(appInput->endReached()) << "\n"
621
- << indent << "responseHeaderSeen = " << boolStr(responseHeaderSeen) << "\n"
622
- << indent << "useUnionStation = " << boolStr(useUnionStation()) << "\n"
623
- ;
624
- }
625
- };
626
-
627
- typedef boost::shared_ptr<Client> ClientPtr;
628
163
 
629
-
630
- class RequestHandler {
164
+ class RequestHandler: public ServerKit::HttpServer<RequestHandler, Client> {
631
165
  public:
632
- enum BenchmarkPoint {
633
- BP_NONE,
634
- BP_AFTER_ACCEPT,
635
- BP_AFTER_CHECK_CONNECT_PASSWORD,
636
- BP_AFTER_PARSING_HEADER,
637
- BP_BEFORE_CHECKOUT_SESSION
166
+ enum BenchmarkMode {
167
+ BM_NONE,
168
+ BM_AFTER_ACCEPT,
169
+ BM_BEFORE_CHECKOUT,
170
+ BM_AFTER_CHECKOUT,
171
+ BM_RESPONSE_BEGIN,
172
+ BM_UNKNOWN
638
173
  };
639
174
 
640
175
  private:
641
- friend class Client;
176
+ typedef ServerKit::HttpServer<RequestHandler, Client> ParentClass;
177
+ typedef ServerKit::Channel Channel;
178
+ typedef ServerKit::FdSinkChannel FdSinkChannel;
179
+ typedef ServerKit::FdSourceChannel FdSourceChannel;
180
+ typedef ServerKit::FileBufferedChannel FileBufferedChannel;
181
+ typedef ServerKit::FileBufferedFdSinkChannel FileBufferedFdSinkChannel;
182
+
183
+ static const unsigned int MAX_SESSION_CHECKOUT_TRY = 10;
184
+
185
+ unsigned int statThrottleRate;
186
+ BenchmarkMode benchmarkMode: 3;
187
+ bool singleAppMode: 1;
188
+ bool showVersionInHeader: 1;
189
+ bool gracefulExit: 1;
190
+
191
+ const VariantMap *agentsOptions;
192
+ psg_pool_t *stringPool;
193
+ StringKeyTable< boost::shared_ptr<Options> > poolOptionsCache;
194
+
195
+ StaticString defaultRuby;
196
+ StaticString loggingAgentAddress;
197
+ StaticString loggingAgentPassword;
198
+ StaticString defaultUser;
199
+ StaticString defaultGroup;
200
+ StaticString defaultServerName;
201
+ StaticString defaultServerPort;
202
+ StaticString serverSoftware;
203
+
204
+ HashedStaticString PASSENGER_APP_GROUP_NAME;
205
+ HashedStaticString PASSENGER_MAX_REQUESTS;
206
+ HashedStaticString PASSENGER_STICKY_SESSIONS;
207
+ HashedStaticString PASSENGER_STICKY_SESSIONS_COOKIE_NAME;
208
+ HashedStaticString PASSENGER_REQUEST_OOB_WORK;
209
+ HashedStaticString UNION_STATION_SUPPORT;
210
+ HashedStaticString REMOTE_ADDR;
211
+ HashedStaticString REMOTE_PORT;
212
+ HashedStaticString REMOTE_USER;
213
+ HashedStaticString FLAGS;
214
+ HashedStaticString HTTP_COOKIE;
215
+ HashedStaticString HTTP_DATE;
216
+ HashedStaticString HTTP_HOST;
217
+ HashedStaticString HTTP_CONTENT_LENGTH;
218
+ HashedStaticString HTTP_CONTENT_TYPE;
219
+ HashedStaticString HTTP_EXPECT;
220
+ HashedStaticString HTTP_CONNECTION;
221
+ HashedStaticString HTTP_STATUS;
222
+ HashedStaticString HTTP_TRANSFER_ENCODING;
223
+
224
+ unsigned int threadNumber;
225
+ StaticString serverLogName;
226
+
227
+ friend class TurboCaching<Request>;
228
+ struct ev_check checkWatcher;
229
+ TurboCaching<Request> turboCaching;
230
+
231
+ #ifdef DEBUG_RH_EVENT_LOOP_BLOCKING
232
+ struct ev_prepare prepareWatcher;
233
+ ev_tstamp timeBeforeBlocking;
234
+ #endif
642
235
 
643
- const SafeLibevPtr libev;
644
- FileDescriptor requestSocket;
645
- PoolPtr pool;
646
- const AgentOptions &options;
647
- const ResourceLocator resourceLocator;
236
+ public:
237
+ ResourceLocator *resourceLocator;
238
+ PoolPtr appPool;
648
239
  UnionStation::CorePtr unionStationCore;
649
- ev::io requestSocketWatcher;
650
- ev::timer resumeSocketWatcherTimer;
651
- HashMap<int, ClientPtr> clients;
652
- Timer inactivityTimer;
653
- bool accept4Available;
654
- boost::regex upgradeHeaderRegex;
655
-
656
-
657
- void disconnect(const ClientPtr &client) {
658
- // Prevent Client object from being destroyed until we're done.
659
- ClientPtr reference = client;
660
-
661
- clients.erase(client->fd);
662
- client->discard();
663
- client->verifyInvariants();
664
- RH_DEBUG(client, "Disconnected; new client count = " << clients.size());
665
-
666
- if (clients.empty()) {
667
- inactivityTimer.start();
668
- }
669
- }
670
-
671
- void disconnectWithError(const ClientPtr &client, const StaticString &message) {
672
- RH_WARN(client, "Disconnecting with error: " << message);
673
- if (client->useUnionStation()) {
674
- client->logMessage("Disconnecting with error: " + message);
675
- }
676
- disconnect(client);
677
- }
678
-
679
- void disconnectWithClientSocketWriteError(const ClientPtr &client, int e) {
680
- stringstream message;
681
- message << "client socket write error: ";
682
- message << strerror(e);
683
- message << " (errno=" << e << ")";
684
- disconnectWithError(client, message.str());
685
- }
686
-
687
- void disconnectWithAppSocketWriteError(const ClientPtr &client, int e) {
688
- stringstream message;
689
- message << "app socket write error: ";
690
- message << strerror(e);
691
- message << " (errno=" << e << ")";
692
- disconnectWithError(client, message.str());
693
- }
694
-
695
- void disconnectWithWarning(const ClientPtr &client, const StaticString &message) {
696
- P_DEBUG("Disconnected client " << client->name() << " with warning: " << message);
697
- disconnect(client);
698
- }
699
-
700
- template<typename Number>
701
- static Number clamp(Number n, Number min, Number max) {
702
- if (n < min) {
703
- return min;
704
- } else if (n > max) {
705
- return max;
706
- } else {
707
- return n;
708
- }
709
- }
710
-
711
- // GDB helper function, implemented in .cpp file to prevent inlining.
712
- Client *getClientPointer(const ClientPtr &client);
713
-
714
- void doResetInactivityTime() {
715
- inactivityTimer.reset();
716
- }
717
-
718
- void getInactivityTime(unsigned long long *result) const {
719
- *result = inactivityTimer.elapsed();
720
- }
721
-
722
- static bool getBoolOption(const ClientPtr &client, const StaticString &name, bool defaultValue = false) {
723
- ScgiRequestParser::const_iterator it = client->scgiParser.getHeaderIterator(name);
724
- if (it != client->scgiParser.end()) {
725
- return it->second == "true";
726
- } else {
727
- return defaultValue;
728
- }
729
- }
730
-
731
- static long long getULongLongOption(const ClientPtr &client, const StaticString &name, long long defaultValue = -1) {
732
- ScgiRequestParser::const_iterator it = client->scgiParser.getHeaderIterator(name);
733
- if (it != client->scgiParser.end()) {
734
- long long result = stringToULL(it->second);
735
- // The client may send a malicious integer, so check for this.
736
- if (result < 0) {
737
- return defaultValue;
738
- } else {
739
- return result;
740
- }
741
- } else {
742
- return defaultValue;
743
- }
744
- }
745
-
746
- bool friendlyErrorPagesEnabled(const ClientPtr &client) const {
747
- bool defaultValue = client->options.environment != "staging"
748
- && client->options.environment != "production";
749
- return getBoolOption(client, "PASSENGER_FRIENDLY_ERROR_PAGES", defaultValue);
750
- }
751
-
752
- void writeSimpleResponse(const ClientPtr &client, const StaticString &data, int code = 200) {
753
- char header[256], statusBuffer[50];
754
- char *pos = header;
755
- const char *end = header + sizeof(header) - 1;
756
- const char *status;
757
-
758
- status = getStatusCodeAndReasonPhrase(code);
759
- if (status == NULL) {
760
- snprintf(statusBuffer, sizeof(statusBuffer), "%d Unknown Reason-Phrase", code);
761
- status = statusBuffer;
762
- }
763
-
764
- if (getBoolOption(client, "PASSENGER_STATUS_LINE", true)) {
765
- pos += snprintf(pos, end - pos, "HTTP/1.1 %s\r\n",
766
- status);
767
- }
768
- pos += snprintf(pos, end - pos,
769
- "Status: %s\r\n"
770
- "Content-Length: %lu\r\n"
771
- "Content-Type: text/html; charset=UTF-8\r\n"
772
- "Cache-Control: no-cache, no-store, must-revalidate\r\n"
773
- "\r\n",
774
- status, (unsigned long) data.size());
775
-
776
- client->clientOutputPipe->write(header, pos - header);
777
- if (!client->connected()) {
778
- return;
779
- }
780
- client->clientOutputPipe->write(data.data(), data.size());
781
- if (!client->connected()) {
782
- return;
783
- }
784
- client->clientOutputPipe->end();
785
- if (!client->connected()) {
786
- return;
787
- }
788
-
789
- if (client->useUnionStation()) {
790
- snprintf(header, end - header, "Status: %d %s",
791
- code, status);
792
- client->logMessage(header);
793
- }
794
- }
795
-
796
- void writeErrorResponse(const ClientPtr &client, const StaticString &message, const SpawnException *e = NULL) {
797
- assert(client->state < Client::FORWARDING_BODY_TO_APP);
798
- client->state = Client::WRITING_SIMPLE_RESPONSE;
799
-
800
- ErrorRenderer renderer(resourceLocator);
801
- string data;
802
-
803
- if (friendlyErrorPagesEnabled(client)) {
804
- try {
805
- data = renderer.renderWithDetails(message, client->options, e);
806
- } catch (const SystemException &e2) {
807
- P_ERROR("Cannot render an error page: " << e2.what() << "\n" <<
808
- e2.backtrace());
809
- data = message;
810
- }
811
- } else {
812
- try {
813
- data = renderer.renderWithoutDetails();
814
- } catch (const SystemException &e2) {
815
- P_ERROR("Cannot render an error page: " << e2.what() << "\n" <<
816
- e2.backtrace());
817
- data = "Internal Server Error";
818
- }
819
- }
820
-
821
- stringstream str;
822
- if (getBoolOption(client, "PASSENGER_STATUS_LINE", true)) {
823
- str << "HTTP/1.1 500 Internal Server Error\r\n";
824
- }
825
- str << "Status: 500 Internal Server Error\r\n";
826
- str << "Content-Length: " << data.size() << "\r\n";
827
- str << "Content-Type: text/html; charset=UTF-8\r\n";
828
- str << "Cache-Control: no-cache, no-store, must-revalidate\r\n";
829
- str << "\r\n";
830
-
831
- const string header = str.str();
832
- client->clientOutputPipe->write(header.data(), header.size());
833
- if (!client->connected()) {
834
- return;
835
- }
836
- client->clientOutputPipe->write(data.data(), data.size());
837
- if (!client->connected()) {
838
- return;
839
- }
840
- client->clientOutputPipe->end();
841
- if (!client->connected()) {
842
- return;
843
- }
844
-
845
- if (client->useUnionStation()) {
846
- client->logMessage("Status: 500 Internal Server Error");
847
- // TODO: record error message
848
- }
849
- }
850
-
851
- static BenchmarkPoint getDefaultBenchmarkPoint() {
852
- const char *val = getenv("PASSENGER_REQUEST_HANDLER_BENCHMARK_POINT");
853
- if (val == NULL || *val == '\0') {
854
- return BP_NONE;
855
- } else if (strcmp(val, "after_accept") == 0) {
856
- return BP_AFTER_ACCEPT;
857
- } else if (strcmp(val, "after_check_connect_password") == 0) {
858
- return BP_AFTER_CHECK_CONNECT_PASSWORD;
859
- } else if (strcmp(val, "after_parsing_header") == 0) {
860
- return BP_AFTER_PARSING_HEADER;
861
- } else if (strcmp(val, "before_checkout_session") == 0) {
862
- return BP_BEFORE_CHECKOUT_SESSION;
863
- } else {
864
- P_WARN("Invalid RequestHandler benchmark point requested: " << val);
865
- return BP_NONE;
866
- }
867
- }
868
-
869
-
870
- /*****************************************************
871
- * COMPONENT: appInput -> clientOutputPipe plumbing
872
- *
873
- * The following code receives data from appInput,
874
- * possibly modifies it, and forwards it to
875
- * clientOutputPipe.
876
- *****************************************************/
877
-
878
- struct Header {
879
- StaticString key;
880
- StaticString value;
881
-
882
- Header() { }
883
-
884
- Header(const StaticString &_key, const StaticString &_value)
885
- : key(_key),
886
- value(_value)
887
- { }
888
-
889
- bool empty() const {
890
- return key.empty();
891
- }
892
-
893
- const char *begin() const {
894
- return key.data();
895
- }
896
-
897
- const char *end() const {
898
- return value.data() + value.size() + sizeof("\r\n") - 1;
899
- }
900
-
901
- size_t size() const {
902
- return end() - begin();
903
- }
904
- };
905
-
906
- /** Given a substring containing the start of the header value,
907
- * extracts the substring that contains a single header value.
908
- *
909
- * const char *data =
910
- * "Status: 200 OK\r\n"
911
- * "Foo: bar\r\n";
912
- * extractHeaderValue(data + strlen("Status:"), strlen(data) - strlen("Status:"));
913
- * // "200 OK"
914
- */
915
- static StaticString extractHeaderValue(const char *data, size_t size) {
916
- const char *start = data;
917
- const char *end = data + size;
918
- const char *terminator;
919
-
920
- while (start < end && *start == ' ') {
921
- start++;
922
- }
923
-
924
- terminator = (const char *) memchr(start, '\r', end - start);
925
- if (terminator == NULL) {
926
- return StaticString();
927
- } else {
928
- return StaticString(start, terminator - start);
929
- }
930
- }
931
240
 
932
- static Header lookupHeader(const StaticString &headerData, const StaticString &name) {
933
- string::size_type searchStart = 0;
934
- while (searchStart < headerData.size()) {
935
- string::size_type pos = headerData.find(name, searchStart);
936
- if (OXT_UNLIKELY(pos == string::npos)) {
937
- return Header();
938
- } else if ((pos == 0 || headerData[pos - 1] == '\n')
939
- && headerData.size() > pos + name.size()
940
- && headerData[pos + name.size()] == ':')
941
- {
942
- StaticString value = extractHeaderValue(
943
- headerData.data() + pos + name.size() + 1,
944
- headerData.size() - pos - name.size() - 1);
945
- return Header(headerData.substr(pos, name.size()), value);
946
- } else {
947
- searchStart = pos + name.size() + 1;
948
- }
949
- }
950
- return Header();
951
- }
241
+ protected:
242
+ #include <agents/HelperAgent/RequestHandler/Utils.cpp>
243
+ #include <agents/HelperAgent/RequestHandler/Hooks.cpp>
244
+ #include <agents/HelperAgent/RequestHandler/InitRequest.cpp>
245
+ #include <agents/HelperAgent/RequestHandler/BufferBody.cpp>
246
+ #include <agents/HelperAgent/RequestHandler/CheckoutSession.cpp>
247
+ #include <agents/HelperAgent/RequestHandler/SendRequest.cpp>
248
+ #include <agents/HelperAgent/RequestHandler/ForwardResponse.cpp>
952
249
 
953
- static Header lookupHeader(const StaticString &headerData, const StaticString &name,
954
- const StaticString &name2)
250
+ public:
251
+ RequestHandler(ServerKit::Context *context, const VariantMap *_agentsOptions,
252
+ unsigned int _threadNumber = 1)
253
+ : ParentClass(context),
254
+
255
+ statThrottleRate(_agentsOptions->getInt("stat_throttle_rate")),
256
+ benchmarkMode(parseBenchmarkMode(_agentsOptions->get("benchmark_mode", false))),
257
+ singleAppMode(false),
258
+ showVersionInHeader(_agentsOptions->getBool("show_version_in_header")),
259
+ gracefulExit(_agentsOptions->getBool("server_graceful_exit")),
260
+
261
+ agentsOptions(_agentsOptions),
262
+ stringPool(psg_create_pool(1024 * 4)),
263
+ poolOptionsCache(4),
264
+
265
+ PASSENGER_APP_GROUP_NAME("!~PASSENGER_APP_GROUP_NAME"),
266
+ PASSENGER_MAX_REQUESTS("!~PASSENGER_MAX_REQUESTS"),
267
+ PASSENGER_STICKY_SESSIONS("!~PASSENGER_STICKY_SESSIONS"),
268
+ PASSENGER_STICKY_SESSIONS_COOKIE_NAME("!~PASSENGER_STICKY_SESSIONS_COOKIE_NAME"),
269
+ PASSENGER_REQUEST_OOB_WORK("!~Request-OOB-Work"),
270
+ UNION_STATION_SUPPORT("!~UNION_STATION_SUPPORT"),
271
+ REMOTE_ADDR("!~REMOTE_ADDR"),
272
+ REMOTE_PORT("!~REMOTE_PORT"),
273
+ REMOTE_USER("!~REMOTE_USER"),
274
+ FLAGS("!~FLAGS"),
275
+ HTTP_COOKIE("cookie"),
276
+ HTTP_DATE("date"),
277
+ HTTP_HOST("host"),
278
+ HTTP_CONTENT_LENGTH("content-length"),
279
+ HTTP_CONTENT_TYPE("content-type"),
280
+ HTTP_EXPECT("expect"),
281
+ HTTP_CONNECTION("connection"),
282
+ HTTP_STATUS("status"),
283
+ HTTP_TRANSFER_ENCODING("transfer-encoding"),
284
+
285
+ threadNumber(_threadNumber),
286
+ turboCaching(getTurboCachingInitialState(_agentsOptions))
955
287
  {
956
- Header header = lookupHeader(headerData, name);
957
- if (header.empty()) {
958
- header = lookupHeader(headerData, name2);
959
- }
960
- return header;
961
- }
962
-
963
- bool addStatusHeaderFromStatusLine(const ClientPtr &client, string &headerData) {
964
- string::size_type begin, end;
965
-
966
- begin = headerData.find(' ');
967
- if (begin != string::npos) {
968
- end = headerData.find("\r\n", begin + 1);
969
- } else {
970
- end = string::npos;
971
- }
972
- if (begin != string::npos && end != string::npos) {
973
- StaticString statusValue(headerData.data() + begin + 1, end - begin);
974
- if (statusValue.size() <= MAX_STATUS_HEADER_SIZE) {
975
- char header[MAX_STATUS_HEADER_SIZE + sizeof("Status: \r\n")];
976
- char *pos = header;
977
- const char *end = header + sizeof(header);
978
-
979
- pos = appendData(pos, end, "Status: ");
980
- pos = appendData(pos, end, statusValue);
981
- pos = appendData(pos, end, "\r\n");
982
- headerData.append(StaticString(header, pos - header));
983
- return true;
984
- } else {
985
- disconnectWithError(client, "application sent malformed response: the Status header's (" +
986
- statusValue + ") exceeds the allowed limit of " +
987
- toString(MAX_STATUS_HEADER_SIZE) + " bytes.");
988
- return false;
989
- }
990
- } else {
991
- disconnectWithError(client, "application sent malformed response: the HTTP status line is invalid.");
992
- return false;
993
- }
288
+ defaultRuby = psg_pstrdup(stringPool,
289
+ agentsOptions->get("default_ruby"));
290
+ loggingAgentAddress = psg_pstrdup(stringPool,
291
+ agentsOptions->get("logging_agent_address", false));
292
+ loggingAgentPassword = psg_pstrdup(stringPool,
293
+ agentsOptions->get("logging_agent_password", false));
294
+ defaultUser = psg_pstrdup(stringPool,
295
+ agentsOptions->get("default_user", false));
296
+ defaultGroup = psg_pstrdup(stringPool,
297
+ agentsOptions->get("default_group", false));
298
+ defaultServerName = psg_pstrdup(stringPool,
299
+ agentsOptions->get("default_server_name"));
300
+ defaultServerPort = psg_pstrdup(stringPool,
301
+ agentsOptions->get("default_server_port"));
302
+ serverSoftware = psg_pstrdup(stringPool,
303
+ agentsOptions->get("server_software"));
304
+
305
+ generateServerLogName(_threadNumber);
306
+
307
+ if (!agentsOptions->getBool("multi_app")) {
308
+ boost::shared_ptr<Options> options = boost::make_shared<Options>();
309
+
310
+ singleAppMode = true;
311
+ fillPoolOptionsFromAgentsOptions(*options);
312
+
313
+ options->appRoot = psg_pstrdup(stringPool,
314
+ agentsOptions->get("app_root"));
315
+ options->environment = psg_pstrdup(stringPool,
316
+ agentsOptions->get("environment"));
317
+ options->appType = psg_pstrdup(stringPool,
318
+ agentsOptions->get("app_type"));
319
+ options->startupFile = psg_pstrdup(stringPool,
320
+ agentsOptions->get("startup_file"));
321
+ poolOptionsCache.insert(options->getAppGroupName(), options);
322
+ }
323
+
324
+ ev_check_init(&checkWatcher, onEventLoopCheck);
325
+ ev_set_priority(&checkWatcher, EV_MAXPRI);
326
+ ev_check_start(getLoop(), &checkWatcher);
327
+ checkWatcher.data = this;
328
+
329
+ #ifdef DEBUG_RH_EVENT_LOOP_BLOCKING
330
+ ev_prepare_init(&prepareWatcher, onEventLoopPrepare);
331
+ ev_prepare_start(getLoop(), &prepareWatcher);
332
+ prepareWatcher.data = this;
333
+
334
+ timeBeforeBlocking = 0;
335
+ #endif
994
336
  }
995
337
 
996
- static bool addReasonPhrase(string &headerData, const Header &status) {
997
- if (status.value.find(' ') == string::npos) {
998
- int statusCode = stringToInt(status.value);
999
- const char *statusCodeAndReasonPhrase = getStatusCodeAndReasonPhrase(statusCode);
1000
- char newStatus[100];
1001
- char *pos = newStatus;
1002
- const char *end = newStatus + sizeof(newStatus);
1003
-
1004
- pos = appendData(pos, end, "Status: ");
1005
- if (statusCodeAndReasonPhrase == NULL) {
1006
- pos = appendData(pos, end, toString(statusCode));
1007
- pos = appendData(pos, end, " Unknown Reason-Phrase\r\n");
1008
- } else {
1009
- pos = appendData(pos, end, statusCodeAndReasonPhrase);
1010
- pos = appendData(pos, end, "\r\n");
1011
- }
1012
-
1013
- headerData.replace(status.begin() - headerData.data(), status.size(),
1014
- newStatus, pos - newStatus);
1015
- return true;
1016
- } else {
1017
- return false;
1018
- }
338
+ ~RequestHandler() {
339
+ psg_destroy_pool(stringPool);
1019
340
  }
1020
341
 
1021
- bool removeStatusLine(const ClientPtr &client, string &headerData) {
1022
- string::size_type end = headerData.find("\r\n");
1023
- if (end != string::npos) {
1024
- headerData.erase(0, end + 2);
1025
- return true;
342
+ static BenchmarkMode parseBenchmarkMode(const StaticString mode) {
343
+ if (mode.empty()) {
344
+ return BM_NONE;
345
+ } else if (mode == "after_accept") {
346
+ return BM_AFTER_ACCEPT;
347
+ } else if (mode == "before_checkout") {
348
+ return BM_BEFORE_CHECKOUT;
349
+ } else if (mode == "after_checkout") {
350
+ return BM_AFTER_CHECKOUT;
351
+ } else if (mode == "response_begin") {
352
+ return BM_RESPONSE_BEGIN;
1026
353
  } else {
1027
- disconnectWithError(client, "application sent malformed response: the HTTP status line is invalid.");
1028
- return false;
354
+ return BM_UNKNOWN;
1029
355
  }
1030
356
  }
1031
357
 
1032
- static void addStatusLineFromStatusHeader(string &headerData, const Header &status) {
1033
- char statusLine[100];
1034
- char *pos = statusLine;
1035
- const char *end = statusLine + sizeof(statusLine);
1036
-
1037
- pos = appendData(pos, end, "HTTP/1.1 ");
1038
- pos = appendData(pos, end, status.value);
1039
- pos = appendData(pos, end, "\r\n");
1040
-
1041
- headerData.insert(0, statusLine, pos - statusLine);
1042
- }
1043
-
1044
- static void removeHeader(string &headerData, const Header &header) {
1045
- headerData.erase(header.begin() - headerData.data(), header.size());
1046
- }
1047
-
1048
- /*
1049
- * Given a full header, possibly modify the header and send it to the clientOutputPipe.
1050
- */
1051
- bool processResponseHeader(const ClientPtr &client,
1052
- const StaticString &origHeaderData)
1053
- {
1054
- string headerData;
1055
- headerData.reserve(origHeaderData.size() + 150);
1056
- // Strip trailing CRLF.
1057
- headerData.append(origHeaderData.data(), origHeaderData.size() - 2);
1058
-
1059
- if (startsWith(headerData, "HTTP/1.")) {
1060
- Header status = lookupHeader(headerData, "Status", "status");
1061
- if (status.empty()) {
1062
- // Add status header if necessary.
1063
- if (!addStatusHeaderFromStatusLine(client, headerData)) {
1064
- return false;
1065
- }
1066
- } else {
1067
- // Add reason phrase to existing status header if necessary.
1068
- addReasonPhrase(headerData, status);
1069
- }
1070
- // Remove status line if necesary.
1071
- if (!getBoolOption(client, "PASSENGER_STATUS_LINE", true)) {
1072
- if (!removeStatusLine(client, headerData)) {
1073
- return false;
1074
- }
1075
- }
1076
- } else {
1077
- Header status = lookupHeader(headerData, "Status", "status");
1078
- if (!status.empty()) {
1079
- // Add reason phrase to status header if necessary.
1080
- if (addReasonPhrase(headerData, status)) {
1081
- status = lookupHeader(headerData, "Status", "status");
1082
- }
1083
- // Add status line if necessary.
1084
- if (getBoolOption(client, "PASSENGER_STATUS_LINE", true)) {
1085
- addStatusLineFromStatusHeader(headerData, status);
1086
- }
1087
- } else {
1088
- disconnectWithError(client, "application sent malformed response: it didn't send an HTTP status line or a Status header.");
1089
- return false;
1090
- }
1091
- }
1092
-
1093
- if (client->useUnionStation()) {
1094
- Header status = lookupHeader(headerData, "Status", "status");
1095
- string message = "Status: ";
1096
- message.append(status.value);
1097
- client->logMessage(message);
358
+ void initialize() {
359
+ TRACE_POINT();
360
+ if (resourceLocator == NULL) {
361
+ throw RuntimeException("ResourceLocator not initialized");
1098
362
  }
1099
-
1100
- // Process chunked transfer encoding.
1101
- Header transferEncoding = lookupHeader(headerData, "Transfer-Encoding", "transfer-encoding");
1102
- if (!transferEncoding.empty() && transferEncoding.value == "chunked") {
1103
- RH_TRACE(client, 3, "Response with chunked transfer encoding detected.");
1104
- client->chunkedResponse = true;
1105
- removeHeader(headerData, transferEncoding);
1106
- } else {
1107
- Header contentLength = lookupHeader(headerData, "Content-Length", "content-length");
1108
- if (!contentLength.empty()) {
1109
- client->responseContentLength = stringToLL(contentLength.value);
1110
- }
363
+ if (appPool == NULL) {
364
+ throw RuntimeException("AppPool not initialized");
1111
365
  }
1112
-
1113
- Header connection = lookupHeader(headerData, "Connection", "connection");
1114
- if (!connection.empty() && (connection.value == "keep-alive"
1115
- || connection.value == "Keep-Alive"))
1116
- {
1117
- RH_TRACE(client, 3, "Keep-alive response detected. Changing to non-keep alive.");
1118
- removeHeader(headerData, connection);
1119
- headerData.append("Connection: close\r\n");
366
+ if (unionStationCore == NULL) {
367
+ unionStationCore = appPool->getUnionStationCore();
1120
368
  }
369
+ }
1121
370
 
1122
- // Add X-Powered-By.
1123
- if (getBoolOption(client, "PASSENGER_SHOW_VERSION_IN_HEADER", true)) {
1124
- headerData.append("X-Powered-By: Phusion Passenger " PASSENGER_VERSION "\r\n");
1125
- } else {
1126
- headerData.append("X-Powered-By: Phusion Passenger\r\n");
1127
- }
371
+ void disconnectLongRunningConnections(const StaticString &gupid) {
372
+ vector<Client *> clients;
373
+ vector<Client *>::iterator v_it, v_end;
374
+ Client *client;
1128
375
 
1129
- // Add sticky session ID.
1130
- if (client->stickySession && client->session != NULL) {
1131
- StaticString baseURI = client->scgiParser.getHeader("SCRIPT_NAME");
1132
- if (baseURI.empty()) {
1133
- baseURI = StaticString("/", 1);
1134
- }
376
+ // We collect all clients in a vector so that we don't have to worry about
377
+ // `activeClients` being mutated while we work.
378
+ TAILQ_FOREACH (client, &activeClients, nextClient.activeOrDisconnectedClient) {
379
+ P_ASSERT_EQ(client->getConnState(), Client::ACTIVE);
380
+ if (client->currentRequest != NULL) {
381
+ Request *req = client->currentRequest;
382
+ if (req->httpState >= Request::COMPLETE
383
+ && req->upgraded()
384
+ && req->session != NULL
385
+ && req->session->getGupid() == gupid)
386
+ {
387
+ if (getLogLevel() >= LVL_INFO) {
388
+ char clientName[32];
389
+ unsigned int size;
390
+ const LString *host;
391
+ StaticString hostStr;
1135
392
 
1136
- StaticString cookieName = getStickySessionCookieName(client);
1137
- // Note that we do NOT set HttpOnly. If we set that flag then Chrome
1138
- // doesn't send cookies over WebSocket handshakes. Confirmed on Chrome 25.
1139
- headerData.append("Set-Cookie: ");
1140
- headerData.append(cookieName.data(), cookieName.size());
1141
- headerData.append("=");
1142
- headerData.append(toString(client->session->getStickySessionId()));
1143
- headerData.append("; Path=");
1144
- headerData.append(baseURI.data(), baseURI.size());
1145
- headerData.append("\r\n");
1146
-
1147
- // Invalidate all cookies with a different route.
1148
- //
1149
- // TODO: This is not entirely correct. Clients MAY send multiple Cookie
1150
- // headers, although this is in practice extremely rare.
1151
- // http://stackoverflow.com/questions/16305814/are-multiple-cookie-headers-allowed-in-an-http-request
1152
- StaticString cookieHeader = client->scgiParser.getHeader("HTTP_COOKIE");
1153
- vector< pair<StaticString, StaticString> > cookies;
1154
- pair<StaticString, StaticString> cookie;
1155
-
1156
- parseCookieHeader(cookieHeader, cookies);
1157
-
1158
- foreach (cookie, cookies) {
1159
- if (cookie.first == cookieName) {
1160
- unsigned int stickySessionId = stringToUint(cookie.second);
1161
- if (stickySessionId != client->session->getStickySessionId()) {
1162
- headerData.append("Set-Cookie: ");
1163
- headerData.append(cookie.first.data(), cookie.first.size());
1164
- headerData.append("=");
1165
- headerData.append(cookie.second.data(), cookie.second.size());
1166
- headerData.append("; Path=");
1167
- headerData.append(baseURI.data(), baseURI.size());
1168
- headerData.append("; Expires=Thu, 01 Jan 1970 00:00:00 GMT\r\n");
393
+ size = getClientName(client, clientName, sizeof(clientName));
394
+ if (req->host != NULL) {
395
+ host = psg_lstr_make_contiguous(req->host, req->pool);
396
+ hostStr = StaticString(host->start->data, host->size);
397
+ }
398
+ P_INFO("[" << getServerName() << "] Disconnecting client " <<
399
+ StaticString(clientName, size) << ": " <<
400
+ hostStr << StaticString(req->path.start->data, req->path.size));
1169
401
  }
402
+ refClient(client, __FILE__, __LINE__);
403
+ clients.push_back(client);
1170
404
  }
1171
405
  }
1172
406
  }
1173
407
 
1174
- // Add Date header. https://code.google.com/p/phusion-passenger/issues/detail?id=485
1175
- if (lookupHeader(headerData, "Date", "date").empty()) {
1176
- char dateStr[60];
1177
- char *pos = dateStr;
1178
- const char *end = dateStr + sizeof(dateStr) - 1;
1179
- time_t the_time = time(NULL);
1180
- struct tm the_tm;
1181
-
1182
- pos = appendData(pos, end, "Date: ");
1183
- gmtime_r(&the_time, &the_tm);
1184
- pos += strftime(pos, end - pos, "%a, %d %b %Y %H:%M:%S %Z", &the_tm);
1185
- pos = appendData(pos, end, "\r\n");
1186
- headerData.append(dateStr, pos - dateStr);
1187
- }
1188
-
1189
- // Detect out of band work request
1190
- Header oobw = lookupHeader(headerData, "X-Passenger-Request-OOB-Work", "x-passenger-request-oob-work");
1191
- if (!oobw.empty()) {
1192
- P_TRACE(3, "Response with oobw detected.");
1193
- if (client->session != NULL) {
1194
- client->session->requestOOBW();
1195
- }
1196
- removeHeader(headerData, oobw);
408
+ // Disconnect each eligible client.
409
+ v_end = clients.end();
410
+ for (v_it = clients.begin(); v_it != v_end; v_it++) {
411
+ client = *v_it;
412
+ Client *c = client;
413
+ disconnect(&client);
414
+ unrefClient(c, __FILE__, __LINE__);
1197
415
  }
1198
-
1199
- P_TRACE(2, "Fowarding response header from app client: " << headerData);
1200
- headerData.append("\r\n");
1201
- writeToClientOutputPipe(client, headerData);
1202
- return true;
1203
416
  }
1204
417
 
1205
- void writeToClientOutputPipe(const ClientPtr &client, const StaticString &data) {
1206
- bool wasCommittingToDisk = client->clientOutputPipe->isCommittingToDisk();
1207
- bool nowCommittingToDisk = !client->clientOutputPipe->write(data.data(), data.size());
1208
- if (!client->connected()) {
1209
- // EPIPE/ECONNRESET detected.
1210
- return;
1211
- }
1212
- if (!wasCommittingToDisk && nowCommittingToDisk) {
1213
- RH_TRACE(client, 3, "Buffering response data to disk; temporarily stopping application socket.");
1214
- client->backgroundOperations++;
1215
- // If the data comes from writeErrorResponse(), then appInput is not available.
1216
- if (client->session != NULL && client->session->initiated()) {
1217
- client->appInput->stop();
1218
- }
1219
- }
418
+ virtual Json::Value getConfigAsJson() const {
419
+ Json::Value doc = ParentClass::getConfigAsJson();
420
+ doc["single_app_mode"] = singleAppMode;
421
+ doc["stat_throttle_rate"] = statThrottleRate;
422
+ doc["show_version_in_header"] = showVersionInHeader;
423
+ doc["data_buffer_dir"] = getContext()->defaultFileBufferedChannelConfig.bufferDir;
424
+ return doc;
1220
425
  }
1221
426
 
1222
- size_t onAppInputData(const ClientPtr &client, const StaticString &data) {
1223
- RH_LOG_EVENT(client, "onAppInputData");
1224
- if (!client->connected()) {
1225
- return 0;
427
+ virtual void configure(const Json::Value &doc) {
428
+ ParentClass::configure(doc);
429
+ if (doc.isMember("show_version_in_header")) {
430
+ showVersionInHeader = doc["show_version_in_header"].asBool();
1226
431
  }
1227
-
1228
- if (!data.empty()) {
1229
- RH_TRACE(client, 3, "Application sent data: \"" << cEscapeString(data) << "\"");
1230
-
1231
- // Buffer the application response until we've encountered the end of the header.
1232
- if (!client->responseHeaderSeen) {
1233
- size_t consumed = client->responseHeaderBufferer.feed(data.data(), data.size());
1234
- if (!client->responseHeaderBufferer.acceptingInput()) {
1235
- if (client->responseHeaderBufferer.hasError()) {
1236
- disconnectWithError(client, "application response format error (invalid header)");
1237
- } else {
1238
- // Now that we have a full header, do something with it.
1239
- RH_TRACE(client, 3, "Response header fully buffered");
1240
- client->responseHeaderSeen = true;
1241
- StaticString header = client->responseHeaderBufferer.getData();
1242
- if (processResponseHeader(client, header)) {
1243
- if (client->responseContentLength == 0) {
1244
- RH_TRACE(client, 3, "Disconnecting client because response Content-Length = 0");
1245
- onAppInputEof(client);
1246
- }
1247
- return consumed;
1248
- } else {
1249
- assert(!client->connected());
1250
- }
1251
- }
1252
- }
1253
- // The header has already been processed so forward it
1254
- // directly to clientOutputPipe, possibly through a
1255
- // dechunker first.
1256
- } else if (client->chunkedResponse) {
1257
- client->responseDechunker.feed(data.data(), data.size());
1258
- } else {
1259
- onAppInputChunk(client, data);
1260
- }
1261
- return data.size();
1262
-
1263
- } else {
1264
- onAppInputEof(client);
1265
- return 0;
432
+ if (doc.isMember("data_buffer_dir")) {
433
+ getContext()->defaultFileBufferedChannelConfig.bufferDir =
434
+ doc["data_buffer_dir"].asString();
1266
435
  }
1267
436
  }
1268
437
 
1269
- void onAppInputChunk(const ClientPtr &client, const StaticString &data) {
1270
- RH_LOG_EVENT(client, "onAppInputChunk");
1271
- StaticString data2;
1272
-
1273
- if (client->responseContentLength == -1) {
1274
- data2 = data;
1275
- } else {
1276
- size_t rest = client->responseContentLength -
1277
- client->responseBodyAlreadyRead;
1278
- data2 = StaticString(data.data(), std::min<size_t>(
1279
- rest, data.size()));
1280
- }
1281
-
1282
- client->responseBodyAlreadyRead += data2.size();
1283
- assert(client->responseContentLength == -1 || client->responseBodyAlreadyRead <=
1284
- (unsigned long long) client->responseContentLength);
1285
- if (data2.empty()) {
1286
- // Client sent more data than was advertised through
1287
- // Content-Length. Ignore them.
1288
- return;
1289
- }
1290
-
1291
- writeToClientOutputPipe(client, data2);
1292
-
1293
- if (client->responseContentLength > 0) {
1294
- RH_TRACE(client, 3, client->responseBodyAlreadyRead << "/" <<
1295
- client->responseContentLength <<
1296
- " bytes of application data forwarded so far.");
1297
-
1298
- if (client->connected() && (unsigned long long) client->responseContentLength
1299
- == client->responseBodyAlreadyRead)
1300
- {
1301
- RH_TRACE(client, 3, "Disconnecting client because application data has been fully forwarded.");
1302
- onAppInputEof(client);
1303
- }
438
+ virtual Json::Value inspectStateAsJson() const {
439
+ Json::Value doc = ParentClass::inspectStateAsJson();
440
+ if (turboCaching.isEnabled()) {
441
+ Json::Value subdoc;
442
+ subdoc["fetches"] = turboCaching.responseCache.getFetches();
443
+ subdoc["hits"] = turboCaching.responseCache.getHits();
444
+ subdoc["hit_ratio"] = turboCaching.responseCache.getHitRatio();
445
+ subdoc["stores"] = turboCaching.responseCache.getStores();
446
+ subdoc["store_successes"] = turboCaching.responseCache.getStoreSuccesses();
447
+ subdoc["store_success_ratio"] = turboCaching.responseCache.getStoreSuccessRatio();
448
+ doc["turbocaching"] = subdoc;
1304
449
  }
450
+ return doc;
1305
451
  }
1306
452
 
1307
- void onAppInputChunkEnd(const ClientPtr &client) {
1308
- RH_LOG_EVENT(client, "onAppInputChunkEnd");
1309
- onAppInputEof(client);
453
+ virtual Json::Value inspectClientStateAsJson(const Client *client) const {
454
+ Json::Value doc = ParentClass::inspectClientStateAsJson(client);
455
+ doc["connected_at"] = timeToJson(client->connectedAt * 1000000.0);
456
+ return doc;
1310
457
  }
1311
458
 
1312
- void onAppInputEof(const ClientPtr &client) {
1313
- RH_LOG_EVENT(client, "onAppInputEof");
1314
- // Check for session == NULL in order to avoid executing the code twice on
1315
- // responses with chunked encoding.
1316
- // This also ensures that when onAppInputEof() is called twice (e.g. because
1317
- // additional data was received after onAppInputChunk has already called onAppInputEof()),
1318
- // we don't do things twice.
1319
- if (!client->connected() || client->session == NULL) {
1320
- return;
1321
- }
1322
-
1323
- RH_DEBUG(client, "Application sent EOF");
1324
- client->appInput->stop();
1325
- client->session.reset();
1326
- client->endScopeLog(&client->scopeLogs.requestProxying);
1327
- client->clientOutputPipe->end();
1328
- }
459
+ virtual Json::Value inspectRequestStateAsJson(const Request *req) const {
460
+ Json::Value doc = ParentClass::inspectRequestStateAsJson(req);
461
+ Json::Value flags;
1329
462
 
1330
- void onAppInputError(const ClientPtr &client, const char *message, int errorCode) {
1331
- RH_LOG_EVENT(client, "onAppInputError");
1332
- if (!client->connected()) {
1333
- return;
463
+ if (req->startedAt != 0) {
464
+ doc["started_at"] = timeToJson(req->startedAt * 1000000.0);
1334
465
  }
1335
-
1336
- if (errorCode == ECONNRESET) {
1337
- // We might as well treat ECONNRESET like an EOF.
1338
- // http://stackoverflow.com/questions/2974021/what-does-econnreset-mean-in-the-context-of-an-af-local-socket
1339
- onAppInputEof(client);
1340
- } else {
1341
- stringstream message;
1342
- message << "application socket read error: ";
1343
- message << strerror(errorCode);
1344
- message << " (fd=" << client->appInput->getFd();
1345
- message << ", errno=" << errorCode << ")";
1346
- disconnectWithError(client, message.str());
466
+ doc["state"] = req->getStateString();
467
+ if (req->stickySession) {
468
+ doc["sticky_session_id"] = req->options.stickySessionId;
1347
469
  }
1348
- }
470
+ doc["sticky_session"] = req->stickySession;
471
+ doc["session_checkout_try"] = req->sessionCheckoutTry;
1349
472
 
1350
- void onClientOutputPipeCommit(const ClientPtr &client) {
1351
- RH_LOG_EVENT(client, "onClientOutputPipeCommit");
1352
- if (!client->connected()) {
1353
- return;
1354
- }
473
+ flags["dechunk_response"] = req->dechunkResponse;
474
+ flags["request_body_buffering"] = req->requestBodyBuffering;
475
+ flags["https"] = req->https;
476
+ doc["flags"] = flags;
1355
477
 
1356
- RH_TRACE(client, 3, "Done buffering response data to disk; resuming application socket.");
1357
- client->backgroundOperations--;
1358
- // If the data comes from writeErrorResponse(), then appInput is not available.
1359
- if (client->session != NULL && client->session->initiated()) {
1360
- client->appInput->start();
478
+ if (req->requestBodyBuffering) {
479
+ doc["body_bytes_buffered"] = (Json::Value::UInt64) req->bodyBytesBuffered;
1361
480
  }
1362
- }
1363
-
1364
481
 
1365
- /*****************************************************
1366
- * COMPONENT: clientOutputPipe -> client fd plumbing
1367
- *
1368
- * The following code handles forwarding data from
1369
- * clientOutputPipe to the client socket.
1370
- *****************************************************/
482
+ if (req->session != NULL) {
483
+ Json::Value &sessionDoc = doc["session"] = Json::Value(Json::objectValue);
484
+ const Session *session = req->session.get();
485
+ const AppResponse *resp = &req->appResponse;
1371
486
 
1372
- void onClientOutputPipeData(const ClientPtr &client, const char *data,
1373
- size_t size, const FileBackedPipe::ConsumeCallback &consumed)
1374
- {
1375
- RH_LOG_EVENT(client, "onClientOutputPipeData");
1376
- if (!client->connected()) {
1377
- return;
1378
- }
1379
-
1380
- RH_TRACE(client, 3, "Forwarding " << size << " bytes of application data to client.");
1381
- ssize_t ret = syscalls::write(client->fd, data, size);
1382
- if (ret == -1) {
1383
- int e = errno;
1384
- RH_TRACE(client, 3, "Could not write to client socket: " << strerror(e) << " (errno=" << e << ")");
1385
- if (e == EAGAIN) {
1386
- RH_TRACE(client, 3, "Waiting until the client socket is writable again.");
1387
- client->clientOutputWatcher.start();
1388
- consumed(0, true);
1389
- } else if (e == EPIPE || e == ECONNRESET) {
1390
- // If the client closed the connection then disconnect quietly.
1391
- RH_TRACE(client, 3, "Client stopped reading prematurely");
1392
- if (client->useUnionStation()) {
1393
- client->logMessage("Disconnecting: client stopped reading prematurely");
487
+ if (req->session->isClosed()) {
488
+ sessionDoc["closed"] = true;
489
+ } else {
490
+ sessionDoc["pid"] = session->getPid();
491
+ sessionDoc["gupid"] = session->getGupid().toString();
492
+ }
493
+
494
+ doc["app_response_http_state"] = resp->getHttpStateString();
495
+ doc["app_response_http_major"] = resp->httpMajor;
496
+ doc["app_response_http_minor"] = resp->httpMinor;
497
+ doc["app_response_want_keep_alive"] = resp->wantKeepAlive;
498
+ doc["app_response_body_type"] = resp->getBodyTypeString();
499
+ doc["app_response_body_fully_read"] = resp->bodyFullyRead();
500
+ doc["app_response_body_already_read"] = (Json::Value::UInt64)
501
+ resp->bodyAlreadyRead;
502
+ if (resp->httpState != AppResponse::ERROR) {
503
+ if (resp->bodyType == AppResponse::RBT_CONTENT_LENGTH) {
504
+ doc["app_response_content_length"] = (Json::Value::UInt64)
505
+ resp->aux.bodyInfo.contentLength;
506
+ } else if (resp->bodyType == AppResponse::RBT_CHUNKED) {
507
+ doc["app_response_end_chunk_reached"] = resp->aux.bodyInfo.endChunkReached;
1394
508
  }
1395
- disconnect(client);
1396
509
  } else {
1397
- disconnectWithClientSocketWriteError(client, e);
510
+ doc["parse_error"] = ServerKit::getErrorDesc(resp->aux.parseError);
1398
511
  }
1399
- } else {
1400
- RH_TRACE(client, 3, "Managed to forward " << ret << " bytes.");
1401
- consumed(ret, false);
1402
- }
1403
- }
1404
-
1405
- void onClientOutputPipeEnd(const ClientPtr &client) {
1406
- RH_LOG_EVENT(client, "onClientOutputPipeEnd");
1407
- if (!client->connected()) {
1408
- return;
1409
- }
1410
-
1411
- RH_TRACE(client, 2, "Client output pipe ended; disconnecting client");
1412
- client->endScopeLog(&client->scopeLogs.requestProcessing);
1413
- disconnect(client);
1414
- }
1415
-
1416
- void onClientOutputPipeError(const ClientPtr &client, int errorCode) {
1417
- RH_LOG_EVENT(client, "onClientOutputPipeError");
1418
- if (!client->connected()) {
1419
- return;
1420
512
  }
1421
513
 
1422
- stringstream message;
1423
- message << "client output pipe error: ";
1424
- message << strerror(errorCode);
1425
- message << " (errno=" << errorCode << ")";
1426
- disconnectWithError(client, message.str());
1427
- }
1428
-
1429
- void onClientOutputWritable(const ClientPtr &client) {
1430
- RH_LOG_EVENT(client, "onClientOutputWritable");
1431
- if (!client->connected()) {
1432
- return;
1433
- }
1434
-
1435
- // Continue forwarding output data to the client.
1436
- RH_TRACE(client, 3, "Client socket became writable again.");
1437
- client->clientOutputWatcher.stop();
1438
- assert(!client->clientOutputPipe->isStarted());
1439
- client->clientOutputPipe->start();
1440
- }
1441
-
1442
-
1443
- /*****************************************************
1444
- * COMPONENT: client acceptor
1445
- *
1446
- * The following code accepts new client connections
1447
- * and forwards events to the appropriate functions
1448
- * depending on the client state.
1449
- *****************************************************/
1450
-
1451
- FileDescriptor acceptNonBlockingSocket(int sock) {
1452
- union {
1453
- struct sockaddr_in inaddr;
1454
- struct sockaddr_un unaddr;
1455
- } u;
1456
- socklen_t addrlen = sizeof(u);
1457
-
1458
- if (accept4Available) {
1459
- FileDescriptor fd(callAccept4(requestSocket,
1460
- (struct sockaddr *) &u, &addrlen, O_NONBLOCK));
1461
- // FreeBSD returns EINVAL if accept4() is called with invalid flags.
1462
- if (fd == -1 && (errno == ENOSYS || errno == EINVAL)) {
1463
- accept4Available = false;
1464
- return acceptNonBlockingSocket(sock);
1465
- } else {
1466
- return fd;
1467
- }
1468
- } else {
1469
- FileDescriptor fd(syscalls::accept(requestSocket,
1470
- (struct sockaddr *) &u, &addrlen));
1471
- if (fd != -1) {
1472
- int e = errno;
1473
- setNonBlocking(fd);
1474
- errno = e;
1475
- }
1476
- return fd;
1477
- }
1478
- }
1479
-
1480
-
1481
- void onResumeSocketWatcher(ev::timer &timer, int revents) {
1482
- P_INFO("Resuming listening on server socket.");
1483
- resumeSocketWatcherTimer.stop();
1484
- requestSocketWatcher.start();
1485
- }
1486
-
1487
- void onAcceptable(ev::io &io, int revents) {
1488
- bool endReached = false;
1489
- unsigned int count = 0;
1490
- unsigned int maxAcceptTries = clamp<unsigned int>(clients.size(), 1, 10);
1491
- ClientPtr acceptedClients[10];
1492
-
1493
- while (!endReached && count < maxAcceptTries) {
1494
- FileDescriptor fd = acceptNonBlockingSocket(requestSocket);
1495
- if (fd == -1) {
1496
- if (errno == EAGAIN || errno == EWOULDBLOCK) {
1497
- endReached = true;
1498
- } else {
1499
- int e = errno;
1500
- P_ERROR("Cannot accept client: " << strerror(e) <<
1501
- " (errno=" << e << "). " <<
1502
- "Pausing listening on server socket for 3 seconds. " <<
1503
- "Current client count: " << clients.size());
1504
- requestSocketWatcher.stop();
1505
- resumeSocketWatcherTimer.start();
1506
- endReached = true;
1507
- }
1508
- } else if (benchmarkPoint == BP_AFTER_ACCEPT) {
1509
- writeExact(fd,
1510
- "HTTP/1.1 200 OK\r\n"
1511
- "Status: 200 OK\r\n"
1512
- "Content-Type: text/html\r\n"
1513
- "Connection: close\r\n"
1514
- "\r\n"
1515
- "Benchmark point: after_accept\n");
1516
- } else {
1517
- ClientPtr client = boost::make_shared<Client>();
1518
- client->associate(this, fd);
1519
- clients.insert(make_pair((int) fd, client));
1520
- acceptedClients[count] = client;
1521
- count++;
1522
- RH_DEBUG(client, "New client accepted; new client count = " << clients.size());
1523
- }
1524
- }
1525
-
1526
- for (unsigned int i = 0; i < count; i++) {
1527
- acceptedClients[i]->clientInput->readNow();
1528
- }
1529
-
1530
- if (OXT_LIKELY(!clients.empty())) {
1531
- inactivityTimer.stop();
1532
- }
1533
- }
1534
-
1535
-
1536
- size_t onClientInputData(const ClientPtr &client, const StaticString &data) {
1537
- RH_LOG_EVENT(client, "onClientInputData");
1538
- if (!client->connected()) {
1539
- return 0;
1540
- }
1541
-
1542
- if (data.empty()) {
1543
- onClientEof(client);
1544
- return 0;
1545
- } else {
1546
- return onClientRealData(client, data.data(), data.size());
1547
- }
1548
- }
1549
-
1550
- size_t onClientRealData(const ClientPtr &client, const char *buf, size_t size) {
1551
- size_t consumed = 0;
1552
-
1553
- while (consumed < size && client->connected() && client->clientInput->isStarted()) {
1554
- const char *data = buf + consumed;
1555
- size_t len = size - consumed;
1556
- size_t locallyConsumed;
1557
-
1558
- RH_TRACE(client, 3, "Processing client data: \"" << cEscapeString(StaticString(data, len)) << "\"");
1559
- switch (client->state) {
1560
- case Client::BEGIN_READING_CONNECT_PASSWORD:
1561
- locallyConsumed = state_beginReadingConnectPassword_onClientData(client, data, len);
1562
- break;
1563
- case Client::STILL_READING_CONNECT_PASSWORD:
1564
- locallyConsumed = state_stillReadingConnectPassword_onClientData(client, data, len);
1565
- break;
1566
- case Client::READING_HEADER:
1567
- locallyConsumed = state_readingHeader_onClientData(client, data, len);
1568
- break;
1569
- case Client::BUFFERING_REQUEST_BODY:
1570
- locallyConsumed = state_bufferingRequestBody_onClientData(client, data, len);
1571
- break;
1572
- case Client::FORWARDING_BODY_TO_APP:
1573
- locallyConsumed = state_forwardingBodyToApp_onClientData(client, data, len);
1574
- break;
1575
- default:
1576
- abort();
1577
- }
1578
-
1579
- consumed += locallyConsumed;
1580
- RH_TRACE(client, 3, "Processed client data: consumed " << locallyConsumed << " bytes");
1581
- assert(consumed <= size);
1582
- }
1583
-
1584
- return consumed;
1585
- }
1586
-
1587
- void onClientEof(const ClientPtr &client) {
1588
- RH_LOG_EVENT(client, "onClientEof; client sent EOF");
1589
- switch (client->state) {
1590
- case Client::BUFFERING_REQUEST_BODY:
1591
- state_bufferingRequestBody_onClientEof(client);
1592
- break;
1593
- case Client::FORWARDING_BODY_TO_APP:
1594
- state_forwardingBodyToApp_onClientEof(client);
1595
- break;
1596
- default:
1597
- disconnect(client);
1598
- break;
1599
- }
1600
- }
1601
-
1602
- void onClientInputError(const ClientPtr &client, const char *message, int errnoCode) {
1603
- RH_LOG_EVENT(client, "onClientInputError");
1604
- if (!client->connected()) {
1605
- return;
1606
- }
1607
-
1608
- if (errnoCode == ECONNRESET) {
1609
- // We might as well treat ECONNRESET like an EOF.
1610
- // http://stackoverflow.com/questions/2974021/what-does-econnreset-mean-in-the-context-of-an-af-local-socket
1611
- RH_TRACE(client, 3, "Client socket ECONNRESET error; treating it as EOF");
1612
- onClientEof(client);
1613
- } else {
1614
- stringstream message;
1615
- message << "client socket read error: ";
1616
- message << strerror(errnoCode);
1617
- message << " (errno=" << errnoCode << ")";
1618
- disconnectWithError(client, message.str());
1619
- }
1620
- }
1621
-
1622
-
1623
- void onClientBodyBufferData(const ClientPtr &client, const char *data, size_t size, const FileBackedPipe::ConsumeCallback &consumed) {
1624
- RH_LOG_EVENT(client, "onClientBodyBufferData");
1625
- if (!client->connected()) {
1626
- return;
1627
- }
1628
-
1629
- switch (client->state) {
1630
- case Client::FORWARDING_BODY_TO_APP:
1631
- state_forwardingBodyToApp_onClientBodyBufferData(client, data, size, consumed);
1632
- break;
1633
- default:
1634
- abort();
1635
- }
1636
- }
1637
-
1638
- void onClientBodyBufferError(const ClientPtr &client, int errorCode) {
1639
- RH_LOG_EVENT(client, "onClientBodyBufferError");
1640
- if (!client->connected()) {
1641
- return;
1642
- }
1643
-
1644
- stringstream message;
1645
- message << "client body buffer error: ";
1646
- message << strerror(errorCode);
1647
- message << " (errno=" << errorCode << ")";
1648
- disconnectWithError(client, message.str());
1649
- }
1650
-
1651
- void onClientBodyBufferEnd(const ClientPtr &client) {
1652
- RH_LOG_EVENT(client, "onClientBodyBufferEnd");
1653
- if (!client->connected()) {
1654
- return;
1655
- }
1656
-
1657
- switch (client->state) {
1658
- case Client::FORWARDING_BODY_TO_APP:
1659
- state_forwardingBodyToApp_onClientBodyBufferEnd(client);
1660
- break;
1661
- default:
1662
- abort();
1663
- }
1664
- }
1665
-
1666
- void onClientBodyBufferCommit(const ClientPtr &client) {
1667
- RH_LOG_EVENT(client, "onClientBodyBufferCommit");
1668
- if (!client->connected()) {
1669
- return;
1670
- }
1671
-
1672
- switch (client->state) {
1673
- case Client::BUFFERING_REQUEST_BODY:
1674
- state_bufferingRequestBody_onClientBodyBufferCommit(client);
1675
- break;
1676
- default:
1677
- abort();
1678
- }
1679
- }
1680
-
1681
- void onAppOutputWritable(const ClientPtr &client) {
1682
- RH_LOG_EVENT(client, "onAppOutputWritable");
1683
- if (!client->connected()) {
1684
- return;
1685
- }
1686
-
1687
- switch (client->state) {
1688
- case Client::SENDING_HEADER_TO_APP:
1689
- state_sendingHeaderToApp_onAppOutputWritable(client);
1690
- break;
1691
- case Client::FORWARDING_BODY_TO_APP:
1692
- state_forwardingBodyToApp_onAppOutputWritable(client);
1693
- break;
1694
- default:
1695
- abort();
1696
- }
1697
- }
1698
-
1699
-
1700
- void onTimeout(const ClientPtr &client) {
1701
- RH_LOG_EVENT(client, "onTimeout");
1702
- if (!client->connected()) {
1703
- return;
1704
- }
1705
-
1706
- switch (client->state) {
1707
- case Client::BEGIN_READING_CONNECT_PASSWORD:
1708
- case Client::STILL_READING_CONNECT_PASSWORD:
1709
- disconnectWithError(client, "no connect password received within timeout");
1710
- break;
1711
- default:
1712
- disconnectWithError(client, "timeout");
1713
- break;
1714
- }
1715
- }
1716
-
1717
-
1718
- /*****************************************************
1719
- * COMPONENT: client -> application plumbing
1720
- *
1721
- * The following code implements forwarding data from
1722
- * the client to the application. Code is seperated
1723
- * by client state.
1724
- *****************************************************/
1725
-
1726
-
1727
- /******* State: BEGIN_READING_CONNECT_PASSWORD *******/
1728
-
1729
- void checkConnectPassword(const ClientPtr &client, const char *data, unsigned int len) {
1730
- RH_TRACE(client, 3, "Given connect password: \"" << cEscapeString(StaticString(data, len)) << "\"");
1731
- if (constantTimeCompare(StaticString(data, len), options.requestSocketPassword)) {
1732
- RH_TRACE(client, 3, "Connect password is correct; reading header");
1733
- client->state = Client::READING_HEADER;
1734
- client->freeBufferedConnectPassword();
1735
- client->timeoutTimer.stop();
1736
-
1737
- if (benchmarkPoint == BP_AFTER_CHECK_CONNECT_PASSWORD) {
1738
- writeSimpleResponse(client, "Benchmark point: after_check_connect_password\n");
1739
- }
1740
- } else {
1741
- disconnectWithError(client, "wrong connect password");
1742
- }
1743
- }
1744
-
1745
- size_t state_beginReadingConnectPassword_onClientData(const ClientPtr &client, const char *data, size_t size) {
1746
- if (size >= options.requestSocketPassword.size()) {
1747
- checkConnectPassword(client, data, options.requestSocketPassword.size());
1748
- return options.requestSocketPassword.size();
1749
- } else {
1750
- client->bufferedConnectPassword.data = (char *) malloc(options.requestSocketPassword.size());
1751
- client->bufferedConnectPassword.alreadyRead = size;
1752
- memcpy(client->bufferedConnectPassword.data, data, size);
1753
- client->state = Client::STILL_READING_CONNECT_PASSWORD;
1754
- return size;
1755
- }
1756
- }
1757
-
1758
-
1759
- /******* State: STILL_READING_CONNECT_PASSWORD *******/
1760
-
1761
- size_t state_stillReadingConnectPassword_onClientData(const ClientPtr &client, const char *data, size_t size) {
1762
- size_t consumed = std::min<size_t>(size,
1763
- options.requestSocketPassword.size() -
1764
- client->bufferedConnectPassword.alreadyRead);
1765
- memcpy(client->bufferedConnectPassword.data + client->bufferedConnectPassword.alreadyRead,
1766
- data, consumed);
1767
- client->bufferedConnectPassword.alreadyRead += consumed;
1768
- if (client->bufferedConnectPassword.alreadyRead == options.requestSocketPassword.size()) {
1769
- checkConnectPassword(client, client->bufferedConnectPassword.data,
1770
- options.requestSocketPassword.size());
1771
- }
1772
- return consumed;
1773
- }
1774
-
1775
-
1776
- /******* State: READING_HEADER *******/
1777
-
1778
- bool modifyClientHeaders(const ClientPtr &client) {
1779
- ScgiRequestParser &parser = client->scgiParser;
1780
- ScgiRequestParser::HeaderMap &map = parser.getMap();
1781
- ScgiRequestParser::iterator it, end = map.end();
1782
- bool modified = false;
1783
-
1784
- /* The Rack spec specifies that HTTP_CONTENT_LENGTH and HTTP_CONTENT_TYPE must
1785
- * not exist and that their respective non-HTTP_ versions should exist instead.
1786
- */
1787
-
1788
- if ((it = map.find("HTTP_CONTENT_LENGTH")) != end) {
1789
- if (map.find("CONTENT_LENGTH") == end) {
1790
- map["CONTENT_LENGTH"] = it->second;
1791
- map.erase("HTTP_CONTENT_LENGTH");
1792
- } else {
1793
- map.erase(it);
1794
- }
1795
- modified = true;
1796
- }
1797
-
1798
- if ((it = map.find("HTTP_CONTENT_TYPE")) != end) {
1799
- if (map.find("CONTENT_TYPE") == end) {
1800
- map["CONTENT_TYPE"] = it->second;
1801
- map.erase("HTTP_CONTENT_TYPE");
1802
- } else {
1803
- map.erase(it);
1804
- }
1805
- modified = true;
1806
- }
1807
-
1808
- return modified;
1809
- }
1810
-
1811
- void reportBadRequestAndDisconnect(const ClientPtr &client, const char *message) {
1812
- writeSimpleResponse(client, message, 400);
1813
- if (client->connected()) {
1814
- disconnectWithError(client, message);
1815
- }
1816
- }
1817
-
1818
- void checkAndInternalizeRequestHeaders(const ClientPtr &client) {
1819
- ScgiRequestParser &parser = client->scgiParser;
1820
- StaticString requestMethod = parser.getHeader("REQUEST_METHOD");
1821
-
1822
- if (requestMethod.empty()) {
1823
- reportBadRequestAndDisconnect(client, "Bad request (no request method given)");
1824
- return;
1825
- }
1826
-
1827
- // Check Content-Length and Transfer-Encoding.
1828
- long long contentLength = getULongLongOption(client, "CONTENT_LENGTH");
1829
- StaticString transferEncoding = parser.getHeader("HTTP_TRANSFER_ENCODING");
1830
- if (contentLength != -1 && !transferEncoding.empty()) {
1831
- reportBadRequestAndDisconnect(client, "Bad request (request may not contain both Content-Length and Transfer-Encoding)");
1832
- return;
1833
- }
1834
- if (!transferEncoding.empty() && transferEncoding != "chunked") {
1835
- reportBadRequestAndDisconnect(client, "Bad request (only Transfer-Encoding chunked is supported)");
1836
- return;
1837
- }
1838
- // According to the HTTP/1.1 spec, Content-Length may not be 0.
1839
- // We could reject the request, but some important HTTP clients are broken
1840
- // (*cough* Ruby Net::HTTP *cough*) and fixing them is too much of
1841
- // a pain, so we choose support it.
1842
- if (contentLength == 0) {
1843
- contentLength = -1;
1844
- assert(transferEncoding.empty());
1845
- }
1846
-
1847
- StaticString upgrade = parser.getHeader("HTTP_UPGRADE");
1848
- const bool requestIsGetOrHead = requestMethod == "GET" || requestMethod == "HEAD";
1849
- const bool requestBodyOffered = contentLength != -1 || !transferEncoding.empty();
1850
-
1851
- // Reject requests that have a request body and an Upgrade header.
1852
- if (!requestIsGetOrHead && !upgrade.empty()) {
1853
- reportBadRequestAndDisconnect(client, "Bad request (Upgrade header is only allowed for non-GET and non-HEAD requests)");
1854
- return;
1855
- }
1856
-
1857
- if (!requestBodyOffered) {
1858
- if (upgrade.empty()) {
1859
- client->requestBodyLength = 0;
1860
- } else {
1861
- client->requestBodyLength = -1;
1862
- }
1863
- } else {
1864
- client->requestBodyLength = contentLength;
1865
- client->requestIsChunked = !transferEncoding.empty();
1866
- }
1867
- }
1868
-
1869
- static void fillPoolOption(const ClientPtr &client, StaticString &field, const StaticString &name) {
1870
- ScgiRequestParser::const_iterator it = client->scgiParser.getHeaderIterator(name);
1871
- if (it != client->scgiParser.end()) {
1872
- field = it->second;
1873
- }
1874
- }
1875
-
1876
- static void fillPoolOption(const ClientPtr &client, bool &field, const StaticString &name) {
1877
- ScgiRequestParser::const_iterator it = client->scgiParser.getHeaderIterator(name);
1878
- if (it != client->scgiParser.end()) {
1879
- field = it->second == "true";
1880
- }
1881
- }
1882
-
1883
- static void fillPoolOption(const ClientPtr &client, unsigned int &field, const StaticString &name) {
1884
- ScgiRequestParser::const_iterator it = client->scgiParser.getHeaderIterator(name);
1885
- if (it != client->scgiParser.end()) {
1886
- field = stringToUint(it->second);
1887
- }
1888
- }
1889
-
1890
- static void fillPoolOption(const ClientPtr &client, unsigned long &field, const StaticString &name) {
1891
- ScgiRequestParser::const_iterator it = client->scgiParser.getHeaderIterator(name);
1892
- if (it != client->scgiParser.end()) {
1893
- field = stringToUint(it->second);
1894
- }
1895
- }
1896
-
1897
- static void fillPoolOption(const ClientPtr &client, long &field, const StaticString &name) {
1898
- ScgiRequestParser::const_iterator it = client->scgiParser.getHeaderIterator(name);
1899
- if (it != client->scgiParser.end()) {
1900
- field = stringToInt(it->second);
1901
- }
1902
- }
1903
-
1904
- static void fillPoolOptionSecToMsec(const ClientPtr &client, unsigned int &field, const StaticString &name) {
1905
- ScgiRequestParser::const_iterator it = client->scgiParser.getHeaderIterator(name);
1906
- if (it != client->scgiParser.end()) {
1907
- field = stringToUint(it->second) * 1000;
1908
- }
1909
- }
1910
-
1911
- void fillPoolOptions(const ClientPtr &client) {
1912
- Options &options = client->options;
1913
- ScgiRequestParser &parser = client->scgiParser;
1914
- ScgiRequestParser::const_iterator it, end = client->scgiParser.end();
1915
-
1916
- options = Options();
1917
-
1918
- StaticString scriptName = parser.getHeader("SCRIPT_NAME");
1919
- StaticString appRoot = parser.getHeader("PASSENGER_APP_ROOT");
1920
- if (scriptName.empty()) {
1921
- if (appRoot.empty()) {
1922
- StaticString documentRoot = parser.getHeader("DOCUMENT_ROOT");
1923
- if (documentRoot.empty()) {
1924
- disconnectWithError(client, "no PASSENGER_APP_ROOT or DOCUMENT_ROOT headers set.");
1925
- return;
1926
- }
1927
- client->appRoot = extractDirName(documentRoot);
1928
- options.appRoot = client->appRoot;
1929
- } else {
1930
- options.appRoot = appRoot;
1931
- }
1932
- } else {
1933
- if (appRoot.empty()) {
1934
- client->appRoot = extractDirName(resolveSymlink(parser.getHeader("DOCUMENT_ROOT")));
1935
- options.appRoot = client->appRoot;
1936
- } else {
1937
- options.appRoot = appRoot;
1938
- }
1939
- options.baseURI = scriptName;
1940
- }
1941
-
1942
- options.ruby = this->options.defaultRubyCommand;
1943
- options.logLevel = getLogLevel();
1944
- options.loggingAgentAddress = this->options.loggingAgentAddress;
1945
- options.loggingAgentUsername = "logging";
1946
- options.loggingAgentPassword = this->options.loggingAgentPassword;
1947
- options.defaultUser = this->options.defaultUser;
1948
- options.defaultGroup = this->options.defaultGroup;
1949
- fillPoolOption(client, options.appGroupName, "PASSENGER_APP_GROUP_NAME");
1950
- fillPoolOption(client, options.appType, "PASSENGER_APP_TYPE");
1951
- fillPoolOption(client, options.environment, "PASSENGER_APP_ENV");
1952
- fillPoolOption(client, options.ruby, "PASSENGER_RUBY");
1953
- fillPoolOption(client, options.python, "PASSENGER_PYTHON");
1954
- fillPoolOption(client, options.nodejs, "PASSENGER_NODEJS");
1955
- fillPoolOption(client, options.user, "PASSENGER_USER");
1956
- fillPoolOption(client, options.group, "PASSENGER_GROUP");
1957
- fillPoolOption(client, options.minProcesses, "PASSENGER_MIN_PROCESSES");
1958
- fillPoolOption(client, options.maxProcesses, "PASSENGER_MAX_PROCESSES");
1959
- fillPoolOption(client, options.maxRequests, "PASSENGER_MAX_REQUESTS");
1960
- fillPoolOption(client, options.spawnMethod, "PASSENGER_SPAWN_METHOD");
1961
- fillPoolOption(client, options.startCommand, "PASSENGER_START_COMMAND");
1962
- fillPoolOptionSecToMsec(client, options.startTimeout, "PASSENGER_START_TIMEOUT");
1963
- fillPoolOption(client, options.maxPreloaderIdleTime, "PASSENGER_MAX_PRELOADER_IDLE_TIME");
1964
- fillPoolOption(client, options.maxRequestQueueSize, "PASSENGER_MAX_REQUEST_QUEUE_SIZE");
1965
- fillPoolOption(client, options.statThrottleRate, "PASSENGER_STAT_THROTTLE_RATE");
1966
- fillPoolOption(client, options.restartDir, "PASSENGER_RESTART_DIR");
1967
- fillPoolOption(client, options.startupFile, "PASSENGER_STARTUP_FILE");
1968
- fillPoolOption(client, options.loadShellEnvvars, "PASSENGER_LOAD_SHELL_ENVVARS");
1969
- fillPoolOption(client, options.debugger, "PASSENGER_DEBUGGER");
1970
- fillPoolOption(client, options.raiseInternalError, "PASSENGER_RAISE_INTERNAL_ERROR");
1971
- setStickySessionId(client);
1972
- /******************/
1973
-
1974
- for (it = client->scgiParser.begin(); it != end; it++) {
1975
- if (!startsWith(it->first, "PASSENGER_")
1976
- && !startsWith(it->first, "HTTP_")
1977
- && it->first != "PATH_INFO"
1978
- && it->first != "SCRIPT_NAME"
1979
- && it->first != "CONTENT_LENGTH"
1980
- && it->first != "CONTENT_TYPE")
1981
- {
1982
- options.environmentVariables.push_back(*it);
1983
- }
1984
- }
1985
- }
1986
-
1987
- void initializeUnionStation(const ClientPtr &client) {
1988
- if (getBoolOption(client, "UNION_STATION_SUPPORT", false)) {
1989
- Options &options = client->options;
1990
- ScgiRequestParser &parser = client->scgiParser;
1991
-
1992
- StaticString key = parser.getHeader("UNION_STATION_KEY");
1993
- StaticString filters = parser.getHeader("UNION_STATION_FILTERS");
1994
- if (key.empty()) {
1995
- disconnectWithError(client, "header UNION_STATION_KEY must be set.");
1996
- return;
1997
- }
1998
-
1999
- client->options.transaction = unionStationCore->newTransaction(
2000
- options.getAppGroupName(), "requests", key, filters);
2001
- if (!client->options.transaction->isNull()) {
2002
- client->options.analytics = true;
2003
- client->options.unionStationKey = key;
2004
- }
2005
-
2006
- client->beginScopeLog(&client->scopeLogs.requestProcessing, "request processing");
2007
-
2008
- StaticString staticRequestMethod = parser.getHeader("REQUEST_METHOD");
2009
- client->logMessage("Request method: " + staticRequestMethod);
2010
-
2011
- StaticString staticRequestURI = parser.getHeader("REQUEST_URI");
2012
- if (!staticRequestURI.empty()) {
2013
- client->logMessage("URI: " + staticRequestURI);
2014
- } else {
2015
- string requestURI = parser.getHeader("SCRIPT_NAME");
2016
- requestURI.append(parser.getHeader("PATH_INFO"));
2017
- StaticString queryString = parser.getHeader("QUERY_STRING");
2018
- if (!queryString.empty()) {
2019
- requestURI.append("?");
2020
- requestURI.append(queryString);
2021
- }
2022
- client->logMessage("URI: " + requestURI);
2023
- }
2024
- }
2025
- }
2026
-
2027
- void parseCookieHeader(const StaticString &header,
2028
- vector< pair<StaticString, StaticString> > &cookies) const
2029
- {
2030
- // See http://stackoverflow.com/questions/6108207/definite-guide-to-valid-cookie-values
2031
- // for syntax grammar.
2032
- vector<StaticString> parts;
2033
- vector<StaticString>::const_iterator it, it_end;
2034
-
2035
- split(header, ';', parts);
2036
- cookies.reserve(parts.size());
2037
- it_end = parts.end();
2038
-
2039
- for (it = parts.begin(); it != it_end; it++) {
2040
- const char *begin = it->data();
2041
- const char *end = it->data() + it->size();
2042
- const char *sep;
2043
-
2044
- skipLeadingWhitespaces(&begin, end);
2045
- skipTrailingWhitespaces(begin, &end);
2046
-
2047
- // Find the separator ('=').
2048
- sep = (const char *) memchr(begin, '=', end - begin);
2049
- if (sep != NULL) {
2050
- // Valid cookie. Otherwise, ignore it.
2051
- const char *nameEnd = sep;
2052
- const char *valueBegin = sep + 1;
2053
-
2054
- skipTrailingWhitespaces(begin, &nameEnd);
2055
- skipLeadingWhitespaces(&valueBegin, end);
2056
-
2057
- cookies.push_back(make_pair(
2058
- StaticString(begin, nameEnd - begin),
2059
- StaticString(valueBegin, end - valueBegin)
2060
- ));
2061
- }
2062
- }
2063
- }
2064
-
2065
- void setStickySessionId(const ClientPtr &client) {
2066
- ScgiRequestParser &parser = client->scgiParser;
2067
- if (parser.getHeader("PASSENGER_STICKY_SESSIONS") == "true") {
2068
- // TODO: This is not entirely correct. Clients MAY send multiple Cookie
2069
- // headers, although this is in practice extremely rare.
2070
- // http://stackoverflow.com/questions/16305814/are-multiple-cookie-headers-allowed-in-an-http-request
2071
- StaticString cookieHeader = parser.getHeader("HTTP_COOKIE");
2072
- StaticString cookieName = getStickySessionCookieName(client);
2073
- vector< pair<StaticString, StaticString> > cookies;
2074
- pair<StaticString, StaticString> cookie;
2075
-
2076
- client->stickySession = true;
2077
- parseCookieHeader(cookieHeader, cookies);
2078
- foreach (cookie, cookies) {
2079
- if (cookie.first == cookieName) {
2080
- // This cookie matches the one we're looking for.
2081
- client->options.stickySessionId = stringToUint(cookie.second);
2082
- return;
2083
- }
2084
- }
2085
- }
2086
- }
2087
-
2088
- StaticString getStickySessionCookieName(const ClientPtr &client) const {
2089
- StaticString value = client->scgiParser.getHeader("PASSENGER_STICKY_SESSIONS_COOKIE_NAME");
2090
- if (value.empty()) {
2091
- return StaticString(DEFAULT_STICKY_SESSIONS_COOKIE_NAME,
2092
- sizeof(DEFAULT_STICKY_SESSIONS_COOKIE_NAME) - 1);
2093
- } else {
2094
- return value;
2095
- }
2096
- }
2097
-
2098
- size_t state_readingHeader_onClientData(const ClientPtr &client, const char *data, size_t size) {
2099
- ScgiRequestParser &parser = client->scgiParser;
2100
- size_t consumed = parser.feed(data, size);
2101
- if (!parser.acceptingInput()) {
2102
- if (parser.getState() == ScgiRequestParser::ERROR) {
2103
- if (parser.getErrorReason() == ScgiRequestParser::LIMIT_REACHED) {
2104
- disconnectWithError(client, "SCGI header too large");
2105
- } else {
2106
- disconnectWithError(client, "invalid SCGI header");
2107
- }
2108
- return consumed;
2109
- }
2110
-
2111
- if (benchmarkPoint == BP_AFTER_PARSING_HEADER) {
2112
- writeSimpleResponse(client, "Benchmark point: after_parsing_header\n");
2113
- return consumed;
2114
- }
2115
-
2116
- bool modified = modifyClientHeaders(client);
2117
- /* TODO: in case the headers are not modified, we only need to rebuild the header data
2118
- * right now because the scgiParser buffer is invalidated as soon as onClientData exits.
2119
- * We should figure out a way to not copy anything if we can do everything before
2120
- * onClientData exits.
2121
- */
2122
- parser.rebuildData(modified);
2123
-
2124
- checkAndInternalizeRequestHeaders(client);
2125
- if (!client->connected()) {
2126
- return consumed;
2127
- }
2128
- fillPoolOptions(client);
2129
- if (!client->connected()) {
2130
- return consumed;
2131
- }
2132
- initializeUnionStation(client);
2133
- if (!client->connected()) {
2134
- return consumed;
2135
- }
2136
-
2137
- if (getBoolOption(client, "PASSENGER_BUFFERING")) {
2138
- RH_TRACE(client, 3, "Valid SCGI header; buffering request body");
2139
- client->state = Client::BUFFERING_REQUEST_BODY;
2140
- client->requestBodyIsBuffered = true;
2141
- client->beginScopeLog(&client->scopeLogs.bufferingRequestBody, "buffering request body");
2142
- if (client->requestBodyLength == 0) {
2143
- client->clientInput->stop();
2144
- state_bufferingRequestBody_onClientEof(client);
2145
- return 0;
2146
- }
2147
- } else {
2148
- RH_TRACE(client, 3, "Valid SCGI header; not buffering request body; checking out session");
2149
- client->clientInput->stop();
2150
- checkoutSession(client);
2151
- }
2152
- }
2153
- return consumed;
2154
- }
2155
-
2156
-
2157
- /******* State: BUFFERING_REQUEST_BODY *******/
2158
-
2159
- void state_bufferingRequestBody_verifyInvariants(const ClientPtr &client) const {
2160
- assert(client->requestBodyIsBuffered);
2161
- assert(!client->clientBodyBuffer->isStarted());
2162
- }
2163
-
2164
- size_t state_bufferingRequestBody_onClientData(const ClientPtr &client, const char *data, size_t size) {
2165
- state_bufferingRequestBody_verifyInvariants(client);
2166
- assert(!client->clientBodyBuffer->isCommittingToDisk());
2167
-
2168
- if (client->requestBodyLength >= 0) {
2169
- size = std::min<unsigned long long>(
2170
- size,
2171
- (unsigned long long) client->requestBodyLength - client->requestBodyAlreadyRead
2172
- );
2173
- }
2174
-
2175
- if (!client->clientBodyBuffer->write(data, size)) {
2176
- // The pipe cannot write the data to disk quickly enough, so
2177
- // suspend reading from the client until the pipe is done.
2178
- client->backgroundOperations++; // TODO: figure out whether this is necessary
2179
- client->clientInput->stop();
2180
- }
2181
- client->requestBodyAlreadyRead += size;
2182
-
2183
- RH_TRACE(client, 3, "Buffered " << size << " bytes of client body data; total=" <<
2184
- client->requestBodyAlreadyRead << ", content-length=" << client->requestBodyLength);
2185
- assert(client->requestBodyLength == -1 || client->requestBodyAlreadyRead <= (unsigned long long) client->requestBodyLength);
2186
-
2187
- if (client->requestBodyLength >= 0 && client->requestBodyAlreadyRead == (unsigned long long) client->requestBodyLength) {
2188
- if (client->clientBodyBuffer->isCommittingToDisk()) {
2189
- RH_TRACE(client, 3, "Done buffering request body, but clientBodyBuffer not yet done committing data to disk; waiting until it's done");
2190
- client->checkoutSessionAfterCommit = true;
2191
- } else {
2192
- client->clientInput->stop();
2193
- state_bufferingRequestBody_onClientEof(client);
2194
- }
2195
- }
2196
-
2197
- return size;
2198
- }
2199
-
2200
- void state_bufferingRequestBody_onClientEof(const ClientPtr &client) {
2201
- state_bufferingRequestBody_verifyInvariants(client);
2202
-
2203
- RH_TRACE(client, 3, "Done buffering request body; checking out session");
2204
- client->clientBodyBuffer->end();
2205
- client->endScopeLog(&client->scopeLogs.bufferingRequestBody);
2206
- checkoutSession(client);
2207
- }
2208
-
2209
- void state_bufferingRequestBody_onClientBodyBufferCommit(const ClientPtr &client) {
2210
- // Now that the pipe has committed the data to disk
2211
- // resume reading from the client socket.
2212
- state_bufferingRequestBody_verifyInvariants(client);
2213
- assert(!client->clientInput->isStarted());
2214
- client->backgroundOperations--;
2215
- if (client->checkoutSessionAfterCommit) {
2216
- RH_TRACE(client, 3, "Done committing request body to disk");
2217
- state_bufferingRequestBody_onClientEof(client);
2218
- } else {
2219
- client->clientInput->start();
2220
- }
2221
- }
2222
-
2223
-
2224
- /******* State: CHECKING_OUT_SESSION *******/
2225
-
2226
- void state_checkingOutSession_verifyInvariants(const ClientPtr &client) {
2227
- assert(!client->clientInput->isStarted());
2228
- assert(!client->clientBodyBuffer->isStarted());
2229
- }
2230
-
2231
- void checkoutSession(const ClientPtr &client) {
2232
- if (benchmarkPoint != BP_BEFORE_CHECKOUT_SESSION) {
2233
- RH_TRACE(client, 2, "Checking out session: appRoot=" << client->options.appRoot);
2234
- client->state = Client::CHECKING_OUT_SESSION;
2235
- client->beginScopeLog(&client->scopeLogs.getFromPool, "get from pool");
2236
- pool->asyncGet(client->options, boost::bind(&RequestHandler::sessionCheckedOut,
2237
- this, client, _1, _2));
2238
- if (!client->sessionCheckedOut) {
2239
- client->backgroundOperations++;
2240
- }
2241
- } else {
2242
- writeSimpleResponse(client, "Benchmark point: before_checkout_session\n");
2243
- }
2244
- }
2245
-
2246
- void sessionCheckedOut(ClientPtr client, const SessionPtr &session, const ExceptionPtr &e) {
2247
- if (!pthread_equal(pthread_self(), libev->getCurrentThread())) {
2248
- libev->runLater(boost::bind(&RequestHandler::sessionCheckedOut_real, this,
2249
- client, session, e));
2250
- } else {
2251
- sessionCheckedOut_real(client, session, e);
2252
- }
2253
- }
2254
-
2255
- void sessionCheckedOut_real(ClientPtr client, const SessionPtr &session, const ExceptionPtr &e) {
2256
- RH_LOG_EVENT(client, "sessionCheckedOut");
2257
- if (!client->connected()) {
2258
- return;
2259
- }
2260
-
2261
- state_checkingOutSession_verifyInvariants(client);
2262
- client->backgroundOperations--;
2263
- client->sessionCheckedOut = true;
2264
-
2265
- if (e != NULL) {
2266
- client->endScopeLog(&client->scopeLogs.getFromPool, false);
2267
- {
2268
- boost::shared_ptr<RequestQueueFullException> e2 = dynamic_pointer_cast<RequestQueueFullException>(e);
2269
- if (e2 != NULL) {
2270
- writeRequestQueueFullExceptionErrorResponse(client);
2271
- return;
2272
- }
2273
- }
2274
- {
2275
- boost::shared_ptr<SpawnException> e2 = dynamic_pointer_cast<SpawnException>(e);
2276
- if (e2 != NULL) {
2277
- writeSpawnExceptionErrorResponse(client, e2);
2278
- return;
2279
- }
2280
- }
2281
- writeOtherExceptionErrorResponse(client, e);
2282
- } else {
2283
- RH_DEBUG(client, "Session checked out: pid=" << session->getPid() <<
2284
- ", gupid=" << session->getGupid());
2285
- client->session = session;
2286
- initiateSession(client);
2287
- }
2288
- }
2289
-
2290
- void writeRequestQueueFullExceptionErrorResponse(const ClientPtr &client) {
2291
- StaticString value = client->scgiParser.getHeader("PASSENGER_REQUEST_QUEUE_OVERFLOW_STATUS_CODE");
2292
- int requestQueueOverflowStatusCode = 503;
2293
- if (!value.empty()) {
2294
- requestQueueOverflowStatusCode = atoi(value.data());
2295
- }
2296
- writeSimpleResponse(client,
2297
- "<h1>This website is under heavy load</h1>"
2298
- "<p>We're sorry, too many people are accessing this website at the same "
2299
- "time. We're working on this problem. Please try again later.</p>",
2300
- requestQueueOverflowStatusCode);
2301
- }
2302
-
2303
- void writeSpawnExceptionErrorResponse(const ClientPtr &client, const boost::shared_ptr<SpawnException> &e) {
2304
- RH_ERROR(client, "Cannot checkout session because a spawning error occurred. " <<
2305
- "The identifier of the error is " << e->get("error_id") << ". Please see earlier logs for " <<
2306
- "details about the error.");
2307
- writeErrorResponse(client, e->getErrorPage(), e.get());
2308
- }
2309
-
2310
- void writeOtherExceptionErrorResponse(const ClientPtr &client, const ExceptionPtr &e) {
2311
- string typeName;
2312
- #ifdef CXX_ABI_API_AVAILABLE
2313
- int status;
2314
- char *tmp = abi::__cxa_demangle(typeid(*e).name(), 0, 0, &status);
2315
- if (tmp != NULL) {
2316
- typeName = tmp;
2317
- free(tmp);
2318
- } else {
2319
- typeName = typeid(*e).name();
2320
- }
2321
- #else
2322
- typeName = typeid(*e).name();
2323
- #endif
2324
-
2325
- RH_WARN(client, "Cannot checkout session (exception type " <<
2326
- typeName << "): " << e->what());
2327
-
2328
- string response = "An internal error occurred while trying to spawn the application.\n";
2329
- response.append("Exception type: ");
2330
- response.append(typeName);
2331
- response.append("\nError message: ");
2332
- response.append(e->what());
2333
- boost::shared_ptr<tracable_exception> e3 = dynamic_pointer_cast<tracable_exception>(e);
2334
- if (e3 != NULL) {
2335
- response.append("\nBacktrace:\n");
2336
- response.append(e3->backtrace());
2337
- }
2338
-
2339
- writeErrorResponse(client, response);
2340
- }
2341
-
2342
- void initiateSession(const ClientPtr &client) {
2343
- assert(client->state == Client::CHECKING_OUT_SESSION);
2344
- client->sessionCheckoutTry++;
2345
- try {
2346
- client->session->initiate();
2347
- } catch (const SystemException &e2) {
2348
- if (client->sessionCheckoutTry < 10) {
2349
- RH_DEBUG(client, "Error checking out session (" << e2.what() <<
2350
- "); retrying (attempt " << client->sessionCheckoutTry << ")");
2351
- client->sessionCheckedOut = false;
2352
- pool->asyncGet(client->options,
2353
- boost::bind(&RequestHandler::sessionCheckedOut,
2354
- this, client, _1, _2));
2355
- if (!client->sessionCheckedOut) {
2356
- client->backgroundOperations++;
2357
- }
2358
- } else {
2359
- string message = "could not initiate a session (";
2360
- message.append(e2.what());
2361
- message.append(")");
2362
- disconnectWithError(client, message);
2363
- }
2364
- return;
2365
- }
2366
-
2367
- if (client->useUnionStation()) {
2368
- client->endScopeLog(&client->scopeLogs.getFromPool);
2369
- client->logMessage("Application PID: " +
2370
- toString(client->session->getPid()) +
2371
- " (GUPID: " + client->session->getGupid() + ")");
2372
- client->beginScopeLog(&client->scopeLogs.requestProxying, "request proxying");
2373
- }
2374
-
2375
- RH_DEBUG(client, "Session initiated: fd=" << client->session->fd());
2376
- setNonBlocking(client->session->fd());
2377
- client->appInput->reset(libev.get(), client->session->fd());
2378
- client->appInput->start();
2379
- client->appOutputWatcher.set(libev->getLoop());
2380
- client->appOutputWatcher.set(client->session->fd(), ev::WRITE);
2381
- sendHeaderToApp(client);
2382
- }
2383
-
2384
-
2385
- /******* State: SENDING_HEADER_TO_APP *******/
2386
-
2387
- void state_sendingHeaderToApp_verifyInvariants(const ClientPtr &client) {
2388
- assert(!client->clientInput->isStarted());
2389
- assert(!client->clientBodyBuffer->isStarted());
2390
- }
2391
-
2392
- void sendHeaderToApp(const ClientPtr &client) {
2393
- assert(!client->clientInput->isStarted());
2394
- assert(!client->clientBodyBuffer->isStarted());
2395
-
2396
- RH_TRACE(client, 2, "Sending headers to application");
2397
-
2398
- if (client->session == NULL) {
2399
- disconnectWithError(client,
2400
- "Application sent EOF before we were able to send headers to it");
2401
- } else if (client->session->getProtocol() == "session") {
2402
- char sizeField[sizeof(boost::uint32_t)];
2403
- SmallVector<StaticString, 10> data;
2404
-
2405
- data.push_back(StaticString(sizeField, sizeof(boost::uint32_t)));
2406
- data.push_back(client->scgiParser.getHeaderData());
2407
-
2408
- data.push_back(makeStaticStringWithNull("PASSENGER_CONNECT_PASSWORD"));
2409
- data.push_back(makeStaticStringWithNull(client->session->getConnectPassword()));
2410
-
2411
- if (client->options.analytics) {
2412
- data.push_back(makeStaticStringWithNull("PASSENGER_TXN_ID"));
2413
- data.push_back(makeStaticStringWithNull(client->options.transaction->getTxnId()));
2414
- }
2415
-
2416
- boost::uint32_t dataSize = 0;
2417
- for (unsigned int i = 1; i < data.size(); i++) {
2418
- dataSize += (boost::uint32_t) data[i].size();
2419
- }
2420
- Uint32Message::generate(sizeField, dataSize);
2421
-
2422
- ssize_t ret = gatheredWrite(client->session->fd(), &data[0],
2423
- data.size(), client->appOutputBuffer);
2424
- if (ret == -1 && errno != EAGAIN) {
2425
- disconnectWithAppSocketWriteError(client, errno);
2426
- } else if (!client->appOutputBuffer.empty()) {
2427
- client->state = Client::SENDING_HEADER_TO_APP;
2428
- client->appOutputWatcher.start();
2429
- } else {
2430
- sendBodyToApp(client);
2431
- }
2432
- } else {
2433
- assert(client->session->getProtocol() == "http_session");
2434
- const ScgiRequestParser &parser = client->scgiParser;
2435
- ScgiRequestParser::const_iterator it, end = parser.end();
2436
- string data;
2437
-
2438
- data.reserve(parser.getHeaderData().size() + 128);
2439
- data.append(parser.getHeader("REQUEST_METHOD"));
2440
- data.append(" ");
2441
- data.append(parser.getHeader("REQUEST_URI"));
2442
- data.append(" HTTP/1.1\r\n");
2443
-
2444
- for (it = parser.begin(); it != end; it++) {
2445
- if (startsWith(it->first, "HTTP_") && it->first != "HTTP_CONNECTION") {
2446
- string subheader = it->first.substr(sizeof("HTTP_") - 1);
2447
- string::size_type i;
2448
- for (i = 0; i < subheader.size(); i++) {
2449
- if (subheader[i] == '_') {
2450
- subheader[i] = '-';
2451
- } else if (i > 0 && subheader[i - 1] != '-') {
2452
- subheader[i] = tolower(subheader[i]);
2453
- }
2454
- }
2455
-
2456
- data.append(subheader);
2457
- data.append(": ");
2458
- data.append(it->second);
2459
- data.append("\r\n");
2460
- }
2461
- }
2462
-
2463
- StaticString connection = parser.getHeader("HTTP_CONNECTION");
2464
- if (regex_match(connection.data(), connection.data() + connection.size(),
2465
- upgradeHeaderRegex))
2466
- {
2467
- data.append("Connection: ");
2468
- data.append(connection.data(), connection.size());
2469
- data.append("\r\n");
2470
- } else {
2471
- data.append("Connection: close\r\n");
2472
- }
2473
-
2474
- StaticString header = parser.getHeader("CONTENT_LENGTH");
2475
- if (!header.empty()) {
2476
- data.append("Content-Length: ");
2477
- data.append(header);
2478
- data.append("\r\n");
2479
- }
2480
-
2481
- header = parser.getHeader("CONTENT_TYPE");
2482
- if (!header.empty()) {
2483
- data.append("Content-Type: ");
2484
- data.append(header);
2485
- data.append("\r\n");
2486
- }
2487
-
2488
- header = parser.getHeader("HTTPS");
2489
- if (!header.empty()) {
2490
- data.append("X-Forwarded-Proto: https\r\n");
2491
- }
2492
-
2493
- header = parser.getHeader("REMOTE_ADDR");
2494
- if (!header.empty()) {
2495
- data.append("X-Forwarded-For: ");
2496
- data.append(header);
2497
- data.append("\r\n");
2498
- }
2499
-
2500
- if (client->options.analytics) {
2501
- data.append("Passenger-Txn-Id: ");
2502
- data.append(client->options.transaction->getTxnId());
2503
- data.append("\r\n");
2504
- }
2505
-
2506
- P_TRACE(3, "Sending headers to application: " << data);
2507
- data.append("\r\n");
2508
-
2509
- StaticString datas[] = { data };
2510
- ssize_t ret = gatheredWrite(client->session->fd(), datas,
2511
- 1, client->appOutputBuffer);
2512
- if (ret == -1 && errno != EAGAIN) {
2513
- disconnectWithAppSocketWriteError(client, errno);
2514
- // TODO: what about other errors?
2515
- } else if (!client->appOutputBuffer.empty()) {
2516
- client->state = Client::SENDING_HEADER_TO_APP;
2517
- client->appOutputWatcher.start();
2518
- } else {
2519
- sendBodyToApp(client);
2520
- }
2521
- }
2522
- }
2523
-
2524
- void state_sendingHeaderToApp_onAppOutputWritable(const ClientPtr &client) {
2525
- state_sendingHeaderToApp_verifyInvariants(client);
2526
-
2527
- if (client->session == NULL) {
2528
- disconnectWithError(client,
2529
- "Application sent EOF before we were able to send headers to it");
2530
- } else {
2531
- ssize_t ret = gatheredWrite(client->session->fd(), NULL, 0, client->appOutputBuffer);
2532
- if (ret == -1) {
2533
- if (errno != EAGAIN && errno != EPIPE && errno != ECONNRESET) {
2534
- disconnectWithAppSocketWriteError(client, errno);
2535
- }
2536
- // TODO: what about other errors?
2537
- } else if (client->appOutputBuffer.empty()) {
2538
- client->appOutputWatcher.stop();
2539
- sendBodyToApp(client);
2540
- }
2541
- }
2542
- }
2543
-
2544
-
2545
- /******* State: FORWARDING_BODY_TO_APP *******/
2546
-
2547
- void state_forwardingBodyToApp_verifyInvariants(const ClientPtr &client) const {
2548
- assert(client->state == Client::FORWARDING_BODY_TO_APP);
2549
- }
2550
-
2551
- void sendBodyToApp(const ClientPtr &client) {
2552
- assert(client->appOutputBuffer.empty());
2553
- assert(!client->clientBodyBuffer->isStarted());
2554
- assert(!client->clientInput->isStarted());
2555
- assert(!client->appOutputWatcher.is_active());
2556
-
2557
- RH_TRACE(client, 2, "Begin sending body to application");
2558
-
2559
- client->state = Client::FORWARDING_BODY_TO_APP;
2560
- if (client->requestBodyIsBuffered) {
2561
- client->clientBodyBuffer->start();
2562
- } else if (client->requestBodyLength == 0) {
2563
- state_forwardingBodyToApp_onClientEof(client);
2564
- } else {
2565
- client->clientInput->start();
2566
- }
2567
- }
2568
-
2569
-
2570
- size_t state_forwardingBodyToApp_onClientData(const ClientPtr &client,
2571
- const char *data, size_t size)
2572
- {
2573
- state_forwardingBodyToApp_verifyInvariants(client);
2574
- assert(!client->requestBodyIsBuffered);
2575
-
2576
- if (client->requestBodyLength >= 0) {
2577
- size = std::min<unsigned long long>(
2578
- size,
2579
- (unsigned long long) client->requestBodyLength - client->requestBodyAlreadyRead
2580
- );
2581
- }
2582
-
2583
- RH_TRACE(client, 3, "Forwarding " << size << " bytes of client body data to application.");
2584
-
2585
- if (client->session == NULL) {
2586
- RH_TRACE(client, 2, "Application had already sent EOF. Stop reading client input.");
2587
- client->clientInput->stop();
2588
- syscalls::shutdown(client->fd, SHUT_RD);
2589
- return 0;
2590
- }
2591
-
2592
- ssize_t ret = syscalls::write(client->session->fd(), data, size);
2593
- int e = errno;
2594
- if (ret == -1) {
2595
- RH_TRACE(client, 3, "Could not write to application socket: " << strerror(e) << " (errno=" << e << ")");
2596
- if (e == EAGAIN) {
2597
- RH_TRACE(client, 3, "Waiting until the application socket is writable again.");
2598
- client->clientInput->stop();
2599
- client->appOutputWatcher.start();
2600
- } else if (e == EPIPE || e == ECONNRESET) {
2601
- // Client will be disconnected after response forwarding is done.
2602
- client->clientInput->stop();
2603
- syscalls::shutdown(client->fd, SHUT_RD);
2604
- } else {
2605
- disconnectWithAppSocketWriteError(client, e);
2606
- }
2607
- return 0;
2608
- } else {
2609
- client->requestBodyAlreadyRead += ret;
2610
-
2611
- RH_TRACE(client, 3, "Managed to forward " << ret << " bytes; total=" <<
2612
- client->requestBodyAlreadyRead << ", content-length=" << client->requestBodyLength);
2613
- assert(client->requestBodyLength == -1 || client->requestBodyAlreadyRead <= (unsigned long long) client->requestBodyLength);
2614
- if (client->requestBodyLength >= 0 && client->requestBodyAlreadyRead == (unsigned long long) client->requestBodyLength) {
2615
- client->clientInput->stop();
2616
- state_forwardingBodyToApp_onClientEof(client);
2617
- }
2618
-
2619
- return ret;
2620
- }
2621
- }
2622
-
2623
- void state_forwardingBodyToApp_onClientEof(const ClientPtr &client) {
2624
- state_forwardingBodyToApp_verifyInvariants(client);
2625
- assert(!client->requestBodyIsBuffered);
2626
-
2627
- RH_TRACE(client, 2, "End of (unbuffered) client body reached; done sending data to application");
2628
- client->clientInput->stop();
2629
- if (client->session != NULL && client->shouldHalfCloseWrite()) {
2630
- syscalls::shutdown(client->session->fd(), SHUT_WR);
2631
- }
2632
- }
2633
-
2634
- void state_forwardingBodyToApp_onAppOutputWritable(const ClientPtr &client) {
2635
- state_forwardingBodyToApp_verifyInvariants(client);
2636
-
2637
- RH_TRACE(client, 3, "Application socket became writable again.");
2638
- client->appOutputWatcher.stop();
2639
- if (client->requestBodyIsBuffered) {
2640
- assert(!client->clientBodyBuffer->isStarted());
2641
- client->clientBodyBuffer->start();
2642
- } else {
2643
- assert(!client->clientInput->isStarted());
2644
- client->clientInput->start();
2645
- }
2646
- }
2647
-
2648
-
2649
- void state_forwardingBodyToApp_onClientBodyBufferData(const ClientPtr &client,
2650
- const char *data, size_t size, const FileBackedPipe::ConsumeCallback &consumed)
2651
- {
2652
- state_forwardingBodyToApp_verifyInvariants(client);
2653
- assert(client->requestBodyIsBuffered);
2654
-
2655
- RH_TRACE(client, 3, "Forwarding " << size << " bytes of buffered client body data to application.");
2656
-
2657
- if (client->session == NULL) {
2658
- RH_TRACE(client, 2, "Application had already sent EOF. Stop reading client input.");
2659
- syscalls::shutdown(client->fd, SHUT_RD);
2660
- consumed(0, true);
2661
- return;
2662
- }
2663
-
2664
- ssize_t ret = syscalls::write(client->session->fd(), data, size);
2665
- if (ret == -1) {
2666
- int e = errno;
2667
- RH_TRACE(client, 3, "Could not write to application socket: " << strerror(e) << " (errno=" << e << ")");
2668
- if (e == EAGAIN) {
2669
- RH_TRACE(client, 3, "Waiting until the application socket is writable again.");
2670
- client->appOutputWatcher.start();
2671
- consumed(0, true);
2672
- } else if (e == EPIPE || e == ECONNRESET) {
2673
- // Client will be disconnected after response forwarding is done.
2674
- syscalls::shutdown(client->fd, SHUT_RD);
2675
- consumed(0, true);
2676
- } else {
2677
- disconnectWithAppSocketWriteError(client, e);
2678
- }
2679
- } else {
2680
- RH_TRACE(client, 3, "Managed to forward " << ret << " bytes.");
2681
- consumed(ret, false);
2682
- }
2683
- }
2684
-
2685
- void state_forwardingBodyToApp_onClientBodyBufferEnd(const ClientPtr &client) {
2686
- state_forwardingBodyToApp_verifyInvariants(client);
2687
- assert(client->requestBodyIsBuffered);
2688
-
2689
- RH_TRACE(client, 2, "End of (buffered) client body reached; done sending data to application");
2690
- if (client->session != NULL && client->shouldHalfCloseWrite()) {
2691
- syscalls::shutdown(client->session->fd(), SHUT_WR);
2692
- }
2693
- }
2694
-
2695
-
2696
- public:
2697
- // For unit testing purposes.
2698
- unsigned int connectPasswordTimeout; // milliseconds
2699
-
2700
- BenchmarkPoint benchmarkPoint;
2701
-
2702
- RequestHandler(const SafeLibevPtr &_libev,
2703
- const FileDescriptor &_requestSocket,
2704
- const PoolPtr &_pool,
2705
- const AgentOptions &_options)
2706
- : libev(_libev),
2707
- requestSocket(_requestSocket),
2708
- pool(_pool),
2709
- options(_options),
2710
- resourceLocator(_options.passengerRoot),
2711
- upgradeHeaderRegex("(keep-alive, *)?upgrade(, *keep-alive)?",
2712
- boost::regex::perl | boost::regex::icase),
2713
- benchmarkPoint(getDefaultBenchmarkPoint())
2714
- {
2715
- accept4Available = true;
2716
- connectPasswordTimeout = 15000;
2717
- unionStationCore = pool->getUnionStationCore();
2718
-
2719
- requestSocketWatcher.set(_requestSocket, ev::READ);
2720
- requestSocketWatcher.set(_libev->getLoop());
2721
- requestSocketWatcher.set<RequestHandler, &RequestHandler::onAcceptable>(this);
2722
- requestSocketWatcher.start();
2723
-
2724
- resumeSocketWatcherTimer.set<RequestHandler, &RequestHandler::onResumeSocketWatcher>(this);
2725
- resumeSocketWatcherTimer.set(_libev->getLoop());
2726
- resumeSocketWatcherTimer.set(3, 3);
2727
- }
2728
-
2729
- template<typename Stream>
2730
- void inspect(Stream &stream) const {
2731
- stream << clients.size() << " clients:\n";
2732
- HashMap<int, ClientPtr>::const_iterator it;
2733
- for (it = clients.begin(); it != clients.end(); it++) {
2734
- const ClientPtr &client = it->second;
2735
- stream << " Client " << client->fd << ":\n";
2736
- client->inspect(stream);
2737
- }
2738
- }
2739
-
2740
- void resetInactivityTime() {
2741
- libev->run(boost::bind(&RequestHandler::doResetInactivityTime, this));
2742
- }
2743
-
2744
- unsigned long long inactivityTime() const {
2745
- unsigned long long result;
2746
- libev->run(boost::bind(&RequestHandler::getInactivityTime, this, &result));
2747
- return result;
514
+ return doc;
2748
515
  }
2749
516
  };
2750
517