passenger 2.1.3 → 2.2.0

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 (398) hide show
  1. data/DEVELOPERS.TXT +2 -0
  2. data/INSTALL +3 -1
  3. data/LICENSE +19 -355
  4. data/NEWS +3 -0
  5. data/README +11 -4
  6. data/Rakefile +435 -236
  7. data/bin/passenger-config +20 -14
  8. data/bin/passenger-install-apache2-module +67 -201
  9. data/bin/passenger-install-nginx-module +477 -0
  10. data/bin/passenger-make-enterprisey +17 -12
  11. data/bin/passenger-memory-stats +33 -23
  12. data/bin/passenger-spawn-server +17 -12
  13. data/bin/passenger-status +18 -13
  14. data/bin/passenger-stress-test +17 -12
  15. data/doc/{Users guide.html → Users guide Apache.html } +79 -61
  16. data/doc/{Users guide.txt → Users guide Apache.txt } +43 -939
  17. data/doc/Users guide Nginx.html +2276 -0
  18. data/doc/Users guide Nginx.txt +776 -0
  19. data/doc/cxxapi/ApplicationPoolServer_8h-source.html +9 -4
  20. data/doc/cxxapi/ApplicationPool_8h-source.html +9 -4
  21. data/doc/cxxapi/Application_8h-source.html +26 -21
  22. data/doc/cxxapi/Bucket_8h-source.html +54 -44
  23. data/doc/cxxapi/CachedFileStat_8h-source.html +9 -4
  24. data/doc/cxxapi/Configuration_8h-source.html +357 -339
  25. data/doc/cxxapi/DirectoryMapper_8h-source.html +294 -280
  26. data/doc/cxxapi/DummySpawnManager_8h-source.html +9 -4
  27. data/doc/cxxapi/Exceptions_8h-source.html +9 -4
  28. data/doc/cxxapi/FileChecker_8h-source.html +9 -4
  29. data/doc/cxxapi/Hooks_8h-source.html +50 -40
  30. data/doc/cxxapi/Logging_8h-source.html +9 -4
  31. data/doc/cxxapi/MessageChannel_8h-source.html +20 -15
  32. data/doc/cxxapi/PoolOptions_8h-source.html +10 -5
  33. data/doc/cxxapi/SpawnManager_8h-source.html +9 -4
  34. data/doc/cxxapi/StandardApplicationPool_8h-source.html +10 -5
  35. data/doc/cxxapi/SystemTime_8h-source.html +9 -4
  36. data/doc/cxxapi/Utils_8h-source.html +242 -214
  37. data/doc/cxxapi/annotated.html +4 -28
  38. data/doc/cxxapi/classClient-members.html +4 -4
  39. data/doc/cxxapi/classClient.html +14 -11
  40. data/doc/cxxapi/classHooks-members.html +4 -5
  41. data/doc/cxxapi/classHooks.html +26 -24
  42. data/doc/cxxapi/classPassenger_1_1Application-members.html +4 -4
  43. data/doc/cxxapi/classPassenger_1_1Application.html +40 -37
  44. data/doc/cxxapi/classPassenger_1_1ApplicationPool-members.html +4 -4
  45. data/doc/cxxapi/classPassenger_1_1ApplicationPool.html +95 -92
  46. data/doc/cxxapi/classPassenger_1_1ApplicationPoolServer-members.html +4 -4
  47. data/doc/cxxapi/classPassenger_1_1ApplicationPoolServer.html +26 -23
  48. data/doc/cxxapi/classPassenger_1_1ApplicationPool__inherit__graph.map +1 -1
  49. data/doc/cxxapi/classPassenger_1_1ApplicationPool__inherit__graph.md5 +1 -1
  50. data/doc/cxxapi/classPassenger_1_1ApplicationPool__inherit__graph.png +0 -0
  51. data/doc/cxxapi/classPassenger_1_1Application_1_1Session-members.html +17 -17
  52. data/doc/cxxapi/classPassenger_1_1Application_1_1Session.html +139 -136
  53. data/doc/cxxapi/classPassenger_1_1BufferedUpload-members.html +4 -4
  54. data/doc/cxxapi/classPassenger_1_1BufferedUpload.html +13 -10
  55. data/doc/cxxapi/classPassenger_1_1BusyException-members.html +4 -4
  56. data/doc/cxxapi/classPassenger_1_1BusyException.html +11 -8
  57. data/doc/cxxapi/classPassenger_1_1ConfigurationException-members.html +4 -4
  58. data/doc/cxxapi/classPassenger_1_1ConfigurationException.html +11 -8
  59. data/doc/cxxapi/classPassenger_1_1DirectoryMapper-members.html +4 -5
  60. data/doc/cxxapi/classPassenger_1_1DirectoryMapper.html +45 -43
  61. data/doc/cxxapi/classPassenger_1_1DummySpawnManager-members.html +4 -4
  62. data/doc/cxxapi/classPassenger_1_1DummySpawnManager.html +13 -10
  63. data/doc/cxxapi/classPassenger_1_1FileChecker-members.html +4 -4
  64. data/doc/cxxapi/classPassenger_1_1FileChecker.html +22 -19
  65. data/doc/cxxapi/classPassenger_1_1FileNotFoundException-members.html +4 -4
  66. data/doc/cxxapi/classPassenger_1_1FileNotFoundException.html +12 -9
  67. data/doc/cxxapi/classPassenger_1_1FileNotFoundException__inherit__graph.map +1 -1
  68. data/doc/cxxapi/classPassenger_1_1FileNotFoundException__inherit__graph.md5 +1 -1
  69. data/doc/cxxapi/classPassenger_1_1FileNotFoundException__inherit__graph.png +0 -0
  70. data/doc/cxxapi/classPassenger_1_1FileSystemException-members.html +4 -4
  71. data/doc/cxxapi/classPassenger_1_1FileSystemException.html +14 -11
  72. data/doc/cxxapi/classPassenger_1_1FileSystemException__inherit__graph.map +1 -1
  73. data/doc/cxxapi/classPassenger_1_1FileSystemException__inherit__graph.md5 +1 -1
  74. data/doc/cxxapi/classPassenger_1_1FileSystemException__inherit__graph.png +0 -0
  75. data/doc/cxxapi/classPassenger_1_1IOException-members.html +4 -4
  76. data/doc/cxxapi/classPassenger_1_1IOException.html +12 -9
  77. data/doc/cxxapi/classPassenger_1_1IOException__inherit__graph.map +1 -1
  78. data/doc/cxxapi/classPassenger_1_1IOException__inherit__graph.md5 +1 -1
  79. data/doc/cxxapi/classPassenger_1_1IOException__inherit__graph.png +0 -0
  80. data/doc/cxxapi/classPassenger_1_1MessageChannel-members.html +4 -4
  81. data/doc/cxxapi/classPassenger_1_1MessageChannel.html +228 -225
  82. data/doc/cxxapi/classPassenger_1_1RuntimeException-members.html +4 -4
  83. data/doc/cxxapi/classPassenger_1_1RuntimeException.html +11 -8
  84. data/doc/cxxapi/classPassenger_1_1SpawnException-members.html +4 -4
  85. data/doc/cxxapi/classPassenger_1_1SpawnException.html +14 -11
  86. data/doc/cxxapi/classPassenger_1_1SpawnManager-members.html +4 -4
  87. data/doc/cxxapi/classPassenger_1_1SpawnManager.html +50 -47
  88. data/doc/cxxapi/classPassenger_1_1StandardApplicationPool-members.html +4 -4
  89. data/doc/cxxapi/classPassenger_1_1StandardApplicationPool.html +73 -70
  90. data/doc/cxxapi/classPassenger_1_1StandardApplicationPool__inherit__graph.map +1 -1
  91. data/doc/cxxapi/classPassenger_1_1StandardApplicationPool__inherit__graph.md5 +1 -1
  92. data/doc/cxxapi/classPassenger_1_1StandardApplicationPool__inherit__graph.png +0 -0
  93. data/doc/cxxapi/classPassenger_1_1SystemException-members.html +4 -4
  94. data/doc/cxxapi/classPassenger_1_1SystemException.html +17 -14
  95. data/doc/cxxapi/classPassenger_1_1SystemException__inherit__graph.map +1 -1
  96. data/doc/cxxapi/classPassenger_1_1SystemException__inherit__graph.md5 +1 -1
  97. data/doc/cxxapi/classPassenger_1_1SystemException__inherit__graph.png +0 -0
  98. data/doc/cxxapi/classPassenger_1_1SystemTime-members.html +4 -4
  99. data/doc/cxxapi/classPassenger_1_1SystemTime.html +14 -11
  100. data/doc/cxxapi/classes.html +35 -0
  101. data/doc/cxxapi/definitions_8h-source.html +9 -4
  102. data/doc/cxxapi/doxygen.css +311 -303
  103. data/doc/cxxapi/files.html +9 -18
  104. data/doc/cxxapi/functions.html +5 -224
  105. data/doc/cxxapi/functions_func.html +5 -185
  106. data/doc/cxxapi/functions_type.html +4 -4
  107. data/doc/cxxapi/functions_vars.html +4 -4
  108. data/doc/cxxapi/graph_legend.dot +19 -19
  109. data/doc/cxxapi/graph_legend.html +5 -5
  110. data/doc/cxxapi/graph_legend.png +0 -0
  111. data/doc/cxxapi/group__Configuration.html +11 -13
  112. data/doc/cxxapi/group__Configuration.png +0 -0
  113. data/doc/cxxapi/group__Core.html +10 -12
  114. data/doc/cxxapi/group__Core.png +0 -0
  115. data/doc/cxxapi/group__Exceptions.html +5 -7
  116. data/doc/cxxapi/group__Hooks.html +5 -7
  117. data/doc/cxxapi/group__Hooks.png +0 -0
  118. data/doc/cxxapi/group__Support.html +5 -624
  119. data/doc/cxxapi/hierarchy.html +6 -6
  120. data/doc/cxxapi/inherit__graph__0.map +1 -1
  121. data/doc/cxxapi/inherit__graph__0.md5 +1 -1
  122. data/doc/cxxapi/inherit__graph__0.png +0 -0
  123. data/doc/cxxapi/inherit__graph__1.map +1 -1
  124. data/doc/cxxapi/inherit__graph__1.md5 +1 -1
  125. data/doc/cxxapi/inherit__graph__1.png +0 -0
  126. data/doc/cxxapi/inherit__graph__10.map +1 -1
  127. data/doc/cxxapi/inherit__graph__10.md5 +1 -1
  128. data/doc/cxxapi/inherit__graph__10.png +0 -0
  129. data/doc/cxxapi/inherit__graph__11.map +1 -1
  130. data/doc/cxxapi/inherit__graph__11.md5 +1 -1
  131. data/doc/cxxapi/inherit__graph__11.png +0 -0
  132. data/doc/cxxapi/inherit__graph__12.map +1 -1
  133. data/doc/cxxapi/inherit__graph__12.md5 +1 -1
  134. data/doc/cxxapi/inherit__graph__12.png +0 -0
  135. data/doc/cxxapi/inherit__graph__13.map +1 -2
  136. data/doc/cxxapi/inherit__graph__13.md5 +1 -1
  137. data/doc/cxxapi/inherit__graph__13.png +0 -0
  138. data/doc/cxxapi/inherit__graph__14.map +2 -1
  139. data/doc/cxxapi/inherit__graph__14.md5 +1 -1
  140. data/doc/cxxapi/inherit__graph__14.png +0 -0
  141. data/doc/cxxapi/inherit__graph__15.map +1 -1
  142. data/doc/cxxapi/inherit__graph__15.md5 +1 -1
  143. data/doc/cxxapi/inherit__graph__15.png +0 -0
  144. data/doc/cxxapi/inherit__graph__16.map +1 -1
  145. data/doc/cxxapi/inherit__graph__16.md5 +1 -1
  146. data/doc/cxxapi/inherit__graph__16.png +0 -0
  147. data/doc/cxxapi/inherit__graph__17.map +1 -1
  148. data/doc/cxxapi/inherit__graph__17.md5 +1 -1
  149. data/doc/cxxapi/inherit__graph__17.png +0 -0
  150. data/doc/cxxapi/inherit__graph__18.map +1 -1
  151. data/doc/cxxapi/inherit__graph__18.md5 +1 -1
  152. data/doc/cxxapi/inherit__graph__18.png +0 -0
  153. data/doc/cxxapi/inherit__graph__19.map +1 -1
  154. data/doc/cxxapi/inherit__graph__19.md5 +1 -1
  155. data/doc/cxxapi/inherit__graph__19.png +0 -0
  156. data/doc/cxxapi/inherit__graph__2.map +1 -1
  157. data/doc/cxxapi/inherit__graph__2.md5 +1 -1
  158. data/doc/cxxapi/inherit__graph__2.png +0 -0
  159. data/doc/cxxapi/inherit__graph__20.map +2 -2
  160. data/doc/cxxapi/inherit__graph__20.md5 +1 -1
  161. data/doc/cxxapi/inherit__graph__20.png +0 -0
  162. data/doc/cxxapi/inherit__graph__21.map +1 -1
  163. data/doc/cxxapi/inherit__graph__21.md5 +1 -1
  164. data/doc/cxxapi/inherit__graph__21.png +0 -0
  165. data/doc/cxxapi/inherit__graph__3.map +1 -1
  166. data/doc/cxxapi/inherit__graph__3.md5 +1 -1
  167. data/doc/cxxapi/inherit__graph__3.png +0 -0
  168. data/doc/cxxapi/inherit__graph__4.map +1 -1
  169. data/doc/cxxapi/inherit__graph__4.md5 +1 -1
  170. data/doc/cxxapi/inherit__graph__4.png +0 -0
  171. data/doc/cxxapi/inherit__graph__5.map +1 -2
  172. data/doc/cxxapi/inherit__graph__5.md5 +1 -1
  173. data/doc/cxxapi/inherit__graph__5.png +0 -0
  174. data/doc/cxxapi/inherit__graph__6.map +2 -1
  175. data/doc/cxxapi/inherit__graph__6.md5 +1 -1
  176. data/doc/cxxapi/inherit__graph__6.png +0 -0
  177. data/doc/cxxapi/inherit__graph__7.map +1 -1
  178. data/doc/cxxapi/inherit__graph__7.md5 +1 -1
  179. data/doc/cxxapi/inherit__graph__7.png +0 -0
  180. data/doc/cxxapi/inherit__graph__8.map +1 -1
  181. data/doc/cxxapi/inherit__graph__8.md5 +1 -1
  182. data/doc/cxxapi/inherit__graph__8.png +0 -0
  183. data/doc/cxxapi/inherit__graph__9.map +1 -1
  184. data/doc/cxxapi/inherit__graph__9.md5 +1 -1
  185. data/doc/cxxapi/inherit__graph__9.png +0 -0
  186. data/doc/cxxapi/inherits.html +41 -41
  187. data/doc/cxxapi/main.html +4 -4
  188. data/doc/cxxapi/modules.html +4 -5
  189. data/doc/cxxapi/structPassenger_1_1AnythingToString-members.html +4 -4
  190. data/doc/cxxapi/structPassenger_1_1AnythingToString.html +13 -10
  191. data/doc/cxxapi/structPassenger_1_1AnythingToString_3_01vector_3_01string_01_4_01_4-members.html +5 -5
  192. data/doc/cxxapi/structPassenger_1_1AnythingToString_3_01vector_3_01string_01_4_01_4.html +16 -13
  193. data/doc/cxxapi/structPassenger_1_1PoolOptions-members.html +4 -4
  194. data/doc/cxxapi/structPassenger_1_1PoolOptions.html +63 -60
  195. data/doc/cxxapi/tabs.css +5 -2
  196. data/doc/cxxapi/tree.html +7 -81
  197. data/doc/rdoc/classes/ConditionVariable.html +59 -59
  198. data/doc/rdoc/classes/Exception.html +11 -11
  199. data/doc/rdoc/classes/GC.html +4 -4
  200. data/doc/rdoc/classes/IO.html +14 -14
  201. data/doc/rdoc/classes/PhusionPassenger.html +75 -20
  202. data/doc/rdoc/classes/PhusionPassenger/AbstractInstaller.html +153 -0
  203. data/doc/rdoc/classes/PhusionPassenger/AbstractRequestHandler.html +125 -130
  204. data/doc/rdoc/classes/PhusionPassenger/AbstractServer.html +236 -236
  205. data/doc/rdoc/classes/PhusionPassenger/AbstractServerCollection.html +213 -213
  206. data/doc/rdoc/classes/PhusionPassenger/AdminTools.html +28 -28
  207. data/doc/rdoc/classes/PhusionPassenger/AdminTools/ControlProcess.html +91 -75
  208. data/doc/rdoc/classes/PhusionPassenger/AppInitError.html +10 -10
  209. data/doc/rdoc/classes/PhusionPassenger/Application.html +64 -64
  210. data/doc/rdoc/classes/PhusionPassenger/ConsoleTextTemplate.html +34 -34
  211. data/doc/rdoc/classes/PhusionPassenger/FrameworkInitError.html +13 -13
  212. data/doc/rdoc/classes/PhusionPassenger/HTMLTemplate.html +30 -30
  213. data/doc/rdoc/classes/PhusionPassenger/InitializationError.html +10 -10
  214. data/doc/rdoc/classes/PhusionPassenger/MessageChannel.html +136 -136
  215. data/doc/rdoc/classes/PhusionPassenger/NativeSupport.html +24 -24
  216. data/doc/rdoc/classes/PhusionPassenger/Rack/ApplicationSpawner.html +42 -42
  217. data/doc/rdoc/classes/PhusionPassenger/Rack/RequestHandler.html +55 -53
  218. data/doc/rdoc/classes/PhusionPassenger/Railz.html +1 -1
  219. data/doc/rdoc/classes/PhusionPassenger/Railz/ApplicationSpawner.html +25 -30
  220. data/doc/rdoc/classes/PhusionPassenger/Railz/CGIFixed.html +23 -23
  221. data/doc/rdoc/classes/PhusionPassenger/Railz/FrameworkSpawner.html +116 -117
  222. data/doc/rdoc/classes/PhusionPassenger/Railz/RequestHandler.html +22 -22
  223. data/doc/rdoc/classes/PhusionPassenger/SpawnManager.html +118 -124
  224. data/doc/rdoc/classes/PhusionPassenger/UnknownError.html +10 -10
  225. data/doc/rdoc/classes/PhusionPassenger/Utils.html +354 -354
  226. data/doc/rdoc/classes/PhusionPassenger/VersionNotFound.html +9 -9
  227. data/doc/rdoc/classes/PhusionPassenger/WSGI/ApplicationSpawner.html +37 -37
  228. data/doc/rdoc/classes/PlatformInfo.html +282 -261
  229. data/doc/rdoc/classes/RakeExtensions.html +7 -7
  230. data/doc/rdoc/classes/Signal.html +26 -26
  231. data/doc/rdoc/created.rid +1 -1
  232. data/doc/rdoc/files/DEVELOPERS_TXT.html +6 -1
  233. data/doc/rdoc/files/README.html +15 -6
  234. data/doc/rdoc/files/ext/phusion_passenger/native_support_c.html +1 -1
  235. data/doc/rdoc/files/lib/phusion_passenger/abstract_installer_rb.html +129 -0
  236. data/doc/rdoc/files/lib/phusion_passenger/abstract_request_handler_rb.html +20 -13
  237. data/doc/rdoc/files/lib/phusion_passenger/abstract_server_collection_rb.html +19 -13
  238. data/doc/rdoc/files/lib/phusion_passenger/abstract_server_rb.html +19 -13
  239. data/doc/rdoc/files/lib/phusion_passenger/admin_tools/control_process_rb.html +31 -1
  240. data/doc/rdoc/files/lib/phusion_passenger/admin_tools_rb.html +31 -1
  241. data/doc/rdoc/files/lib/phusion_passenger/application_rb.html +19 -13
  242. data/doc/rdoc/files/lib/phusion_passenger/console_text_template_rb.html +19 -13
  243. data/doc/rdoc/files/lib/phusion_passenger/constants_rb.html +21 -12
  244. data/doc/rdoc/files/lib/phusion_passenger/dependencies_rb.html +19 -13
  245. data/doc/rdoc/files/lib/phusion_passenger/events_rb.html +19 -13
  246. data/doc/rdoc/files/lib/phusion_passenger/exceptions_rb.html +19 -13
  247. data/doc/rdoc/files/lib/phusion_passenger/html_template_rb.html +19 -13
  248. data/doc/rdoc/files/lib/phusion_passenger/message_channel_rb.html +19 -13
  249. data/doc/rdoc/files/lib/phusion_passenger/packaging_rb.html +122 -0
  250. data/doc/rdoc/files/lib/phusion_passenger/platform_info_rb.html +19 -13
  251. data/doc/rdoc/files/lib/phusion_passenger/rack/application_spawner_rb.html +22 -12
  252. data/doc/rdoc/files/lib/phusion_passenger/rack/request_handler_rb.html +21 -12
  253. data/doc/rdoc/files/lib/phusion_passenger/railz/application_spawner_rb.html +19 -13
  254. data/doc/rdoc/files/lib/phusion_passenger/railz/cgi_fixed_rb.html +1 -1
  255. data/doc/rdoc/files/lib/phusion_passenger/railz/framework_spawner_rb.html +19 -13
  256. data/doc/rdoc/files/lib/phusion_passenger/railz/request_handler_rb.html +21 -12
  257. data/doc/rdoc/files/lib/phusion_passenger/simple_benchmarking_rb.html +19 -13
  258. data/doc/rdoc/files/lib/phusion_passenger/spawn_manager_rb.html +19 -13
  259. data/doc/rdoc/files/lib/phusion_passenger/utils_rb.html +27 -21
  260. data/doc/rdoc/files/lib/phusion_passenger/wsgi/application_spawner_rb.html +21 -12
  261. data/doc/rdoc/files/misc/rake/extensions_rb.html +21 -12
  262. data/doc/rdoc/fr_class_index.html +1 -0
  263. data/doc/rdoc/fr_file_index.html +2 -0
  264. data/doc/rdoc/fr_method_index.html +116 -112
  265. data/doc/users_guide_snippets/analysis_and_system_maintenance_tools.txt +144 -0
  266. data/doc/users_guide_snippets/appendix_a_about.txt +13 -0
  267. data/doc/users_guide_snippets/appendix_b_terminology.txt +63 -0
  268. data/doc/users_guide_snippets/appendix_c_spawning_methods.txt +304 -0
  269. data/doc/users_guide_snippets/global_queueing_explained.txt +78 -0
  270. data/doc/users_guide_snippets/rackup_specifications.txt +75 -0
  271. data/doc/users_guide_snippets/rails_spawn_method.txt +48 -0
  272. data/doc/users_guide_snippets/tips.txt +173 -0
  273. data/ext/apache2/Bucket.cpp +17 -12
  274. data/ext/apache2/Bucket.h +17 -12
  275. data/ext/apache2/Configuration.cpp +17 -12
  276. data/ext/apache2/Configuration.h +27 -14
  277. data/ext/apache2/DirectoryMapper.h +21 -12
  278. data/ext/apache2/Hooks.cpp +67 -21
  279. data/ext/apache2/Hooks.h +17 -12
  280. data/ext/apache2/mod_passenger.c +17 -12
  281. data/ext/{apache2 → common}/Application.h +19 -14
  282. data/ext/{apache2 → common}/ApplicationPool.h +17 -12
  283. data/ext/{apache2 → common}/ApplicationPoolServer.h +18 -72
  284. data/ext/{apache2 → common}/ApplicationPoolServerExecutable.cpp +45 -104
  285. data/ext/common/ApplicationPoolStatusReporter.h +212 -0
  286. data/ext/{apache2 → common}/CachedFileStat.cpp +17 -12
  287. data/ext/{apache2 → common}/CachedFileStat.h +17 -12
  288. data/ext/{apache2 → common}/DummySpawnManager.h +17 -12
  289. data/ext/{apache2 → common}/Exceptions.h +17 -12
  290. data/ext/{apache2 → common}/FileChecker.h +17 -12
  291. data/ext/common/Logging.cpp +65 -0
  292. data/ext/{apache2 → common}/Logging.h +17 -12
  293. data/ext/{apache2 → common}/MessageChannel.h +17 -12
  294. data/ext/{apache2 → common}/PoolOptions.h +17 -12
  295. data/ext/{apache2 → common}/SpawnManager.h +17 -12
  296. data/ext/{apache2 → common}/StandardApplicationPool.h +17 -12
  297. data/ext/common/StaticString.h +147 -0
  298. data/ext/common/SystemTime.cpp +33 -0
  299. data/ext/{apache2 → common}/SystemTime.h +17 -12
  300. data/ext/{apache2 → common}/Utils.cpp +69 -12
  301. data/ext/{apache2 → common}/Utils.h +41 -12
  302. data/ext/nginx/Configuration.c +1091 -0
  303. data/ext/nginx/Configuration.h +71 -0
  304. data/ext/nginx/ContentHandler.c +1154 -0
  305. data/ext/nginx/ContentHandler.h +64 -0
  306. data/ext/nginx/HelperServer.cpp +857 -0
  307. data/ext/nginx/HttpStatusExtractor.h +161 -0
  308. data/ext/nginx/ScgiRequestParser.h +317 -0
  309. data/ext/nginx/StaticContentHandler.c +222 -0
  310. data/ext/nginx/StaticContentHandler.h +37 -0
  311. data/ext/nginx/config +41 -0
  312. data/ext/nginx/ngx_http_passenger_module.c +572 -0
  313. data/ext/nginx/ngx_http_passenger_module.h +72 -0
  314. data/ext/oxt/backtrace.cpp +8 -1
  315. data/ext/oxt/system_calls.cpp +40 -0
  316. data/ext/oxt/system_calls.hpp +14 -7
  317. data/ext/phusion_passenger/extconf.rb +17 -12
  318. data/ext/phusion_passenger/native_support.c +19 -12
  319. data/lib/phusion_passenger/abstract_installer.rb +196 -0
  320. data/lib/phusion_passenger/abstract_request_handler.rb +19 -24
  321. data/lib/phusion_passenger/abstract_server.rb +17 -12
  322. data/lib/phusion_passenger/abstract_server_collection.rb +17 -12
  323. data/lib/phusion_passenger/admin_tools.rb +23 -0
  324. data/lib/phusion_passenger/admin_tools/control_process.rb +39 -13
  325. data/lib/phusion_passenger/application.rb +17 -12
  326. data/lib/phusion_passenger/console_text_template.rb +17 -12
  327. data/lib/phusion_passenger/constants.rb +22 -11
  328. data/lib/phusion_passenger/dependencies.rb +47 -12
  329. data/lib/phusion_passenger/events.rb +17 -12
  330. data/lib/phusion_passenger/exceptions.rb +17 -12
  331. data/lib/phusion_passenger/html_template.rb +17 -12
  332. data/lib/phusion_passenger/message_channel.rb +17 -12
  333. data/lib/phusion_passenger/packaging.rb +39 -0
  334. data/lib/phusion_passenger/platform_info.rb +48 -22
  335. data/lib/phusion_passenger/rack/application_spawner.rb +22 -11
  336. data/lib/phusion_passenger/rack/request_handler.rb +21 -12
  337. data/lib/phusion_passenger/railz/application_spawner.rb +23 -23
  338. data/lib/phusion_passenger/railz/framework_spawner.rb +18 -14
  339. data/lib/phusion_passenger/railz/request_handler.rb +18 -11
  340. data/lib/phusion_passenger/simple_benchmarking.rb +17 -12
  341. data/lib/phusion_passenger/spawn_manager.rb +17 -20
  342. data/lib/phusion_passenger/templates/{apache_must_be_compiled_with_compatible_mpm.txt.erb → apache2/apache_must_be_compiled_with_compatible_mpm.txt.erb} +0 -0
  343. data/lib/phusion_passenger/templates/{apache2_config_snippets.txt.erb → apache2/config_snippets.txt.erb} +0 -0
  344. data/lib/phusion_passenger/templates/{deployment_example.txt.erb → apache2/deployment_example.txt.erb} +0 -0
  345. data/lib/phusion_passenger/templates/{no_write_permission_to_passenger_root.txt.erb → apache2/no_write_permission_to_passenger_root.txt.erb} +0 -0
  346. data/lib/phusion_passenger/templates/{possible_solutions_for_compilation_and_installation_problems.txt.erb → apache2/possible_solutions_for_compilation_and_installation_problems.txt.erb} +0 -0
  347. data/lib/phusion_passenger/templates/{run_installer_as_root.txt.erb → apache2/run_installer_as_root.txt.erb} +0 -0
  348. data/lib/phusion_passenger/templates/{welcome.txt.erb → apache2/welcome.txt.erb} +0 -0
  349. data/lib/phusion_passenger/templates/nginx/ask_for_extra_configure_flags.txt.erb +8 -0
  350. data/lib/phusion_passenger/templates/nginx/cannot_write_to_dir.txt.erb +11 -0
  351. data/lib/phusion_passenger/templates/nginx/config_snippets.txt.erb +17 -0
  352. data/lib/phusion_passenger/templates/nginx/config_snippets_inserted.txt.erb +20 -0
  353. data/lib/phusion_passenger/templates/nginx/confirm_extra_configure_flags.txt.erb +5 -0
  354. data/lib/phusion_passenger/templates/nginx/deployment_example.txt.erb +22 -0
  355. data/lib/phusion_passenger/templates/nginx/pcre_could_not_be_downloaded.txt.erb +11 -0
  356. data/lib/phusion_passenger/templates/nginx/pcre_could_not_be_extracted.txt.erb +11 -0
  357. data/lib/phusion_passenger/templates/nginx/possible_solutions_for_compilation_and_installation_problems.txt.erb +11 -0
  358. data/lib/phusion_passenger/templates/nginx/possible_solutions_for_download_and_extraction_problems.txt.erb +20 -0
  359. data/lib/phusion_passenger/templates/nginx/query_download_and_install.txt.erb +21 -0
  360. data/lib/phusion_passenger/templates/nginx/run_installer_as_root.txt.erb +8 -0
  361. data/lib/phusion_passenger/templates/nginx/welcome.txt.erb +15 -0
  362. data/lib/phusion_passenger/utils.rb +20 -15
  363. data/lib/phusion_passenger/wsgi/application_spawner.rb +18 -11
  364. data/lib/phusion_passenger/wsgi/request_handler.py +23 -0
  365. data/misc/copy_boost_headers.rb +23 -0
  366. data/misc/find_owner_pipe_leaks.rb +18 -11
  367. data/misc/rake/cplusplus.rb +18 -11
  368. data/misc/rake/extensions.rb +21 -14
  369. data/misc/render_error_pages.rb +18 -11
  370. data/test/ApplicationPoolServerTest.cpp +1 -3
  371. data/test/ApplicationPoolServer_ApplicationPoolTest.cpp +1 -1
  372. data/test/CxxTestMain.cpp +19 -3
  373. data/test/HttpStatusExtractorTest.cpp +181 -0
  374. data/test/ScgiRequestParserTest.cpp +337 -0
  375. data/test/StaticStringTest.cpp +51 -0
  376. data/test/UtilsTest.cpp +32 -0
  377. data/test/config.yml.example +5 -0
  378. data/test/{integration_tests.rb → integration_tests/apache2_tests.rb} +7 -299
  379. data/test/integration_tests/hello_world_rack_spec.rb +36 -0
  380. data/test/integration_tests/hello_world_wsgi_spec.rb +41 -0
  381. data/test/integration_tests/mycook_spec.rb +192 -0
  382. data/test/integration_tests/nginx_tests.rb +98 -0
  383. data/test/ruby/rack/application_spawner_spec.rb +40 -0
  384. data/test/stub/nginx/koi-utf +109 -0
  385. data/test/stub/nginx/koi-win +103 -0
  386. data/test/stub/nginx/mime.types +70 -0
  387. data/test/stub/nginx/nginx.conf.erb +57 -0
  388. data/test/stub/nginx/win-utf +126 -0
  389. data/test/stub/rails_apps/mycook/app/controllers/uploads_controller.rb +4 -0
  390. data/test/stub/rails_apps/mycook/config/routes.rb +1 -1
  391. data/test/stub/wsgi/passenger_wsgi.pyc +0 -0
  392. data/test/support/Support.h +40 -0
  393. data/test/support/nginx_controller.rb +98 -0
  394. data/test/support/test_helper.rb +79 -0
  395. metadata +1091 -1028
  396. data/benchmark/DummyRequestHandler.cpp +0 -101
  397. data/ext/apache2/Logging.cpp +0 -60
  398. data/ext/apache2/SystemTime.cpp +0 -28
@@ -0,0 +1,71 @@
1
+ /*
2
+ * Copyright (C) Igor Sysoev
3
+ * Copyright (C) 2007 Manlio Perillo (manlio.perillo@gmail.com)
4
+ * Copyright (C) 2008, 2009 Phusion
5
+ *
6
+ * Redistribution and use in source and binary forms, with or without
7
+ * modification, are permitted provided that the following conditions
8
+ * are met:
9
+ * 1. Redistributions of source code must retain the above copyright
10
+ * notice, this list of conditions and the following disclaimer.
11
+ * 2. Redistributions in binary form must reproduce the above copyright
12
+ * notice, this list of conditions and the following disclaimer in the
13
+ * documentation and/or other materials provided with the distribution.
14
+ *
15
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18
+ * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
19
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25
+ * SUCH DAMAGE.
26
+ */
27
+
28
+ #ifndef _PASSENGER_NGINX_CONFIGURATION_H_
29
+ #define _PASSENGER_NGINX_CONFIGURATION_H_
30
+
31
+ #include <ngx_config.h>
32
+ #include <ngx_http.h>
33
+
34
+ typedef struct {
35
+ ngx_http_upstream_conf_t upstream;
36
+ ngx_str_t index;
37
+ ngx_array_t *flushes;
38
+ ngx_array_t *vars_len;
39
+ ngx_array_t *vars;
40
+ ngx_array_t *vars_source;
41
+
42
+ ngx_flag_t enabled;
43
+ ngx_flag_t use_global_queue;
44
+ ngx_str_t environment;
45
+ ngx_str_t spawn_method;
46
+ int framework_spawner_idle_time;
47
+ int app_spawner_idle_time;
48
+ ngx_array_t *base_uris;
49
+ } passenger_loc_conf_t;
50
+
51
+ typedef struct {
52
+ ngx_str_t root_dir;
53
+ ngx_str_t ruby;
54
+ ngx_uint_t log_level;
55
+ ngx_uint_t max_pool_size;
56
+ ngx_uint_t max_instances_per_app;
57
+ ngx_uint_t pool_idle_time;
58
+ ngx_flag_t user_switching;
59
+ ngx_str_t default_user;
60
+ } passenger_main_conf_t;
61
+
62
+ extern const ngx_command_t passenger_commands[];
63
+ extern passenger_main_conf_t passenger_main_conf;
64
+
65
+ void *passenger_create_main_conf(ngx_conf_t *cf);
66
+ char *passenger_init_main_conf(ngx_conf_t *cf, void *conf_pointer);
67
+ void *passenger_create_loc_conf(ngx_conf_t *cf);
68
+ char *passenger_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child);
69
+
70
+ #endif /* _PASSENGER_NGINX_CONFIGURATION_H_ */
71
+
@@ -0,0 +1,1154 @@
1
+ /*
2
+ * Copyright (C) Igor Sysoev
3
+ * Copyright (C) 2007 Manlio Perillo (manlio.perillo@gmail.com)
4
+ * Copyright (C) 2008, 2009 Phusion
5
+ *
6
+ * Redistribution and use in source and binary forms, with or without
7
+ * modification, are permitted provided that the following conditions
8
+ * are met:
9
+ * 1. Redistributions of source code must retain the above copyright
10
+ * notice, this list of conditions and the following disclaimer.
11
+ * 2. Redistributions in binary form must reproduce the above copyright
12
+ * notice, this list of conditions and the following disclaimer in the
13
+ * documentation and/or other materials provided with the distribution.
14
+ *
15
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18
+ * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
19
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25
+ * SUCH DAMAGE.
26
+ */
27
+
28
+ #include <nginx.h>
29
+ #include "ngx_http_passenger_module.h"
30
+ #include "ContentHandler.h"
31
+ #include "StaticContentHandler.h"
32
+ #include "Configuration.h"
33
+
34
+
35
+ #define NGX_HTTP_SCGI_PARSE_NO_HEADER 20
36
+
37
+ typedef enum {
38
+ FT_ERROR,
39
+ FT_FILE,
40
+ FT_DIRECTORY,
41
+ FT_OTHER
42
+ } FileType;
43
+
44
+
45
+ static ngx_int_t reinit_request(ngx_http_request_t *r);
46
+ static ngx_int_t process_status_line(ngx_http_request_t *r);
47
+ static ngx_int_t parse_status_line(ngx_http_request_t *r,
48
+ passenger_context_t *context);
49
+ static ngx_int_t process_header(ngx_http_request_t *r);
50
+ static void abort_request(ngx_http_request_t *r);
51
+ static void finalize_request(ngx_http_request_t *r, ngx_int_t rc);
52
+
53
+
54
+ static void
55
+ uint_to_str(ngx_uint_t i, u_char *str, ngx_uint_t size) {
56
+ ngx_memzero(str, size);
57
+ ngx_snprintf(str, size, "%ui", i);
58
+ }
59
+
60
+ static FileType
61
+ get_file_type(const u_char *filename, unsigned int throttle_rate) {
62
+ struct stat buf;
63
+ int ret;
64
+
65
+ ret = cached_multi_file_stat_perform(passenger_stat_cache,
66
+ (const char *) filename,
67
+ &buf,
68
+ throttle_rate);
69
+ if (ret == 0) {
70
+ if (S_ISREG(buf.st_mode)) {
71
+ return FT_FILE;
72
+ } else if (S_ISDIR(buf.st_mode)) {
73
+ return FT_DIRECTORY;
74
+ } else {
75
+ return FT_OTHER;
76
+ }
77
+ } else {
78
+ return FT_ERROR;
79
+ }
80
+ }
81
+
82
+ static int
83
+ file_exists(const u_char *filename, unsigned int throttle_rate) {
84
+ return get_file_type(filename, throttle_rate) == FT_FILE;
85
+ }
86
+
87
+ static passenger_app_type_t
88
+ detect_application_type(const ngx_str_t *public_dir) {
89
+ u_char filename[NGX_MAX_PATH];
90
+
91
+ ngx_memzero(filename, sizeof(filename));
92
+ ngx_snprintf(filename, sizeof(filename), "%s/%s",
93
+ public_dir->data, "../config/environment.rb");
94
+ if (file_exists(filename, 1)) {
95
+ return AP_RAILS;
96
+ }
97
+
98
+ ngx_memzero(filename, sizeof(filename));
99
+ ngx_snprintf(filename, sizeof(filename), "%s/%s",
100
+ public_dir->data, "../config.ru");
101
+ if (file_exists(filename, 1)) {
102
+ return AP_RACK;
103
+ }
104
+
105
+ ngx_memzero(filename, sizeof(filename));
106
+ ngx_snprintf(filename, sizeof(filename), "%s/%s",
107
+ public_dir->data, "../config/passenger_wsgi.py");
108
+ if (file_exists(filename, 1)) {
109
+ return AP_WSGI;
110
+ }
111
+
112
+ return AP_NONE;
113
+ }
114
+
115
+ /**
116
+ * Maps the URI for the given request to a page cache file, if possible.
117
+ *
118
+ * @return Whether the URI has been successfully mapped to a page cache file.
119
+ * @param r The corresponding request.
120
+ * @param public_dir The web application's 'public' directory.
121
+ * @param filename The filename that the URI normally maps to.
122
+ * @param filename_len The length of the <tt>filename</tt> string.
123
+ * @param root The size of the root path in <tt>filename</tt>.
124
+ * @param page_cache_file If mapping was successful, then the page cache
125
+ * file's filename will be stored in here.
126
+ * <tt>page_cache_file.data</tt> must already point to
127
+ * a buffer, and <tt>page_cache_file.len</tt> must be set
128
+ * to the size of this buffer, including terminating NUL.
129
+ */
130
+ static int
131
+ map_uri_to_page_cache_file(ngx_http_request_t *r, ngx_str_t *public_dir,
132
+ const u_char *filename, size_t filename_len,
133
+ ngx_str_t *page_cache_file)
134
+ {
135
+ u_char *end;
136
+
137
+ if ((r->method != NGX_HTTP_GET && r->method != NGX_HTTP_HEAD) || filename_len == 0) {
138
+ return 0;
139
+ }
140
+
141
+ /* From this point on we know that filename is not an empty string. */
142
+
143
+ /* Check whether filename is equal to public_dir. filename may also be equal to
144
+ * public_dir + "/" so check for that as well.
145
+ */
146
+ if ((public_dir->len == filename_len && memcmp(public_dir->data, filename,
147
+ filename_len) == 0) ||
148
+ (public_dir->len == filename_len - 1 &&
149
+ filename[filename_len - 1] == '/' &&
150
+ memcmp(public_dir->data, filename, filename_len - 1) == 0)
151
+ ) {
152
+ /* If the URI maps to the 'public' directory (i.e. the request is the
153
+ * base URI) then index.html is the page cache file.
154
+ */
155
+
156
+ if (filename_len + sizeof("/index.html") > page_cache_file->len) {
157
+ /* Page cache filename doesn't fit in the buffer. */
158
+ return 0;
159
+ }
160
+
161
+ end = ngx_copy(page_cache_file->data, filename, filename_len);
162
+ if (filename[filename_len - 1] != '/') {
163
+ end = ngx_copy(end, "/", 1);
164
+ }
165
+ end = ngx_copy(end, "index.html", sizeof("index.html"));
166
+
167
+ } else {
168
+ /* Otherwise, the page cache file is just filename + ".html". */
169
+
170
+ if (filename_len + sizeof(".html") > page_cache_file->len) {
171
+ /* Page cache filename doesn't fit in the buffer. */
172
+ return 0;
173
+ }
174
+
175
+ end = ngx_copy(page_cache_file->data, filename, filename_len);
176
+ end = ngx_copy(end, ".html", sizeof(".html"));
177
+ }
178
+
179
+ if (file_exists(page_cache_file->data, 0)) {
180
+ page_cache_file->len = end - page_cache_file->data - 1;
181
+ return 1;
182
+ } else {
183
+ return 0;
184
+ }
185
+ }
186
+
187
+ static int
188
+ find_base_uri(ngx_http_request_t *r, const passenger_loc_conf_t *loc,
189
+ ngx_str_t *found_base_uri)
190
+ {
191
+ ngx_uint_t i;
192
+ ngx_str_t *base_uris, *base_uri, *uri;
193
+
194
+ if (loc->base_uris == NGX_CONF_UNSET_PTR) {
195
+ return 0;
196
+ } else {
197
+ base_uris = (ngx_str_t *) loc->base_uris->elts;
198
+ for (i = 0; i < loc->base_uris->nelts; i++) {
199
+ base_uri = &base_uris[i];
200
+ uri = &r->uri;
201
+
202
+ if (uri->len == 1 && uri->data[0] == '/') {
203
+ /* Ignore 'passenger_base_uri /' options. Users usually
204
+ * specify this out of ignorance.
205
+ */
206
+ continue;
207
+ }
208
+
209
+ if (( uri->len == base_uri->len
210
+ && ngx_strncmp(uri->data, base_uri->data, uri->len) == 0 )
211
+ || ( uri->len > base_uri->len
212
+ && ngx_strncmp(uri->data, base_uri->data, base_uri->len) == 0
213
+ && uri->data[base_uri->len] == (u_char) '/' )) {
214
+ *found_base_uri = base_uris[i];
215
+ return 1;
216
+ }
217
+ }
218
+ return 0;
219
+ }
220
+ }
221
+
222
+
223
+ static ngx_int_t
224
+ create_request(ngx_http_request_t *r)
225
+ {
226
+ u_char ch;
227
+ u_char buf[sizeof("4294967296")];
228
+ size_t len, size, key_len, val_len, content_length;
229
+ const u_char *app_type_string;
230
+ size_t app_type_string_len;
231
+ u_char framework_spawner_idle_time_string[12];
232
+ u_char app_spawner_idle_time_string[12];
233
+ u_char *end;
234
+ ngx_uint_t i, n;
235
+ ngx_buf_t *b;
236
+ ngx_chain_t *cl, *body;
237
+ ngx_list_part_t *part;
238
+ ngx_table_elt_t *header;
239
+ ngx_http_script_code_pt code;
240
+ ngx_http_script_engine_t e, le;
241
+ passenger_loc_conf_t *slcf;
242
+ passenger_main_conf_t *main_conf;
243
+ passenger_context_t *context;
244
+ ngx_http_script_len_code_pt lcode;
245
+
246
+ slcf = ngx_http_get_module_loc_conf(r, ngx_http_passenger_module);
247
+ main_conf = &passenger_main_conf;
248
+ context = ngx_http_get_module_ctx(r, ngx_http_passenger_module);
249
+ if (context == NULL) {
250
+ return NGX_HTTP_INTERNAL_SERVER_ERROR;
251
+ }
252
+
253
+ switch (context->app_type) {
254
+ case AP_RAILS:
255
+ app_type_string = (const u_char *) "rails";
256
+ app_type_string_len = sizeof("rails");
257
+ break;
258
+ case AP_RACK:
259
+ app_type_string = (const u_char *) "rack";
260
+ app_type_string_len = sizeof("rack");
261
+ break;
262
+ case AP_WSGI:
263
+ app_type_string = (const u_char *) "wsgi";
264
+ app_type_string_len = sizeof("wsgi");
265
+ break;
266
+ default:
267
+ app_type_string = (const u_char *) "rails";
268
+ app_type_string_len = sizeof("rails");
269
+ break;
270
+ }
271
+
272
+
273
+ /**************************************************
274
+ * Determine the request header length.
275
+ **************************************************/
276
+
277
+ /* Length of the Content-Length header. */
278
+ if (r->headers_in.content_length_n < 0) {
279
+ content_length = 0;
280
+ } else {
281
+ content_length = r->headers_in.content_length_n;
282
+ }
283
+ uint_to_str(content_length, buf, sizeof(buf));
284
+ /* +1 for trailing null */
285
+ len = sizeof("CONTENT_LENGTH") + ngx_strlen(buf) + 1;
286
+
287
+ /* DOCUMENT_ROOT, PATH_INFO and base URI */
288
+ len += sizeof("DOCUMENT_ROOT") + context->public_dir.len + 1;
289
+ len += sizeof("PATH_INFO") + context->public_dir.len + 1;
290
+ if (context->base_uri.len > 0) {
291
+ len += sizeof("RAILS_RELATIVE_URL_ROOT") +
292
+ context->base_uri.len + 1;
293
+ }
294
+
295
+ /* Various other HTTP headers. */
296
+ if (r->headers_in.content_type != NULL
297
+ && r->headers_in.content_type->value.len > 0) {
298
+ len += sizeof("CONTENT_TYPE") + r->headers_in.content_type->value.len + 1;
299
+ }
300
+
301
+
302
+ /* Lengths of Passenger application pool options. */
303
+ if (slcf->use_global_queue) {
304
+ len += sizeof("PASSENGER_USE_GLOBAL_QUEUE") + sizeof("true");
305
+ } else {
306
+ len += sizeof("PASSENGER_USE_GLOBAL_QUEUE") + sizeof("false");
307
+ }
308
+ len += sizeof("PASSENGER_ENVIRONMENT") + slcf->environment.len + 1;
309
+ len += sizeof("PASSENGER_SPAWN_METHOD") + slcf->spawn_method.len + 1;
310
+ len += sizeof("PASSENGER_APP_TYPE") + app_type_string_len;
311
+
312
+ end = ngx_snprintf(framework_spawner_idle_time_string,
313
+ sizeof(framework_spawner_idle_time_string) - 1,
314
+ "%d", slcf->framework_spawner_idle_time);
315
+ *end = '\0';
316
+ len += sizeof("PASSENGER_FRAMEWORK_SPAWNER_IDLE_TIME") +
317
+ ngx_strlen(framework_spawner_idle_time_string) + 1;
318
+
319
+ end = ngx_snprintf(app_spawner_idle_time_string,
320
+ sizeof(app_spawner_idle_time_string) - 1,
321
+ "%d", slcf->app_spawner_idle_time);
322
+ *end = '\0';
323
+ len += sizeof("PASSENGER_APP_SPAWNER_IDLE_TIME") +
324
+ ngx_strlen(app_spawner_idle_time_string) + 1;
325
+
326
+ /* Lengths of various CGI variables. */
327
+ if (slcf->vars_len) {
328
+ ngx_memzero(&le, sizeof(ngx_http_script_engine_t));
329
+
330
+ ngx_http_script_flush_no_cacheable_variables(r, slcf->flushes);
331
+ le.flushed = 1;
332
+
333
+ le.ip = slcf->vars_len->elts;
334
+ le.request = r;
335
+
336
+ while (*(uintptr_t *) le.ip) {
337
+
338
+ lcode = *(ngx_http_script_len_code_pt *) le.ip;
339
+ key_len = lcode(&le);
340
+
341
+ for (val_len = 0; *(uintptr_t *) le.ip; val_len += lcode(&le)) {
342
+ lcode = *(ngx_http_script_len_code_pt *) le.ip;
343
+ }
344
+ le.ip += sizeof(uintptr_t);
345
+
346
+ len += key_len + val_len;
347
+ }
348
+ }
349
+
350
+ /* Lengths of HTTP headers. */
351
+ if (slcf->upstream.pass_request_headers) {
352
+
353
+ part = &r->headers_in.headers.part;
354
+ header = part->elts;
355
+
356
+ for (i = 0; /* void */; i++) {
357
+
358
+ if (i >= part->nelts) {
359
+ if (part->next == NULL) {
360
+ break;
361
+ }
362
+
363
+ part = part->next;
364
+ header = part->elts;
365
+ i = 0;
366
+ }
367
+
368
+ len += sizeof("HTTP_") - 1 + header[i].key.len + 1
369
+ + header[i].value.len + 1;
370
+ }
371
+ }
372
+
373
+
374
+ /**************************************************
375
+ * Build the request header data.
376
+ **************************************************/
377
+
378
+ size = passenger_helper_server_password.len +
379
+ /* netstring length + ":" + trailing "," */
380
+ /* note: 10 == sizeof("4294967296") - 1 */
381
+ len + 10 + 1 + 1;
382
+
383
+ b = ngx_create_temp_buf(r->pool, size);
384
+ if (b == NULL) {
385
+ return NGX_ERROR;
386
+ }
387
+
388
+ cl = ngx_alloc_chain_link(r->pool);
389
+ if (cl == NULL) {
390
+ return NGX_ERROR;
391
+ }
392
+
393
+ cl->buf = b;
394
+
395
+ /* Build SCGI header netstring length part. */
396
+ b->last = ngx_copy(b->last, passenger_helper_server_password.data,
397
+ passenger_helper_server_password.len);
398
+
399
+ b->last = ngx_snprintf(b->last, 10, "%ui", len);
400
+ *b->last++ = (u_char) ':';
401
+
402
+ /* Build CONTENT_LENGTH header. This must always be sent, even if 0. */
403
+ b->last = ngx_copy(b->last, "CONTENT_LENGTH",
404
+ sizeof("CONTENT_LENGTH"));
405
+
406
+ b->last = ngx_snprintf(b->last, 10, "%ui", content_length);
407
+ *b->last++ = (u_char) 0;
408
+
409
+ /* Build DOCUMENT_ROOT and base URI. */
410
+ b->last = ngx_copy(b->last, "DOCUMENT_ROOT", sizeof("DOCUMENT_ROOT"));
411
+ b->last = ngx_copy(b->last, context->public_dir.data,
412
+ context->public_dir.len + 1);
413
+
414
+ b->last = ngx_copy(b->last, "PATH_INFO", sizeof("PATH_INFO"));
415
+ b->last = ngx_copy(b->last, context->public_dir.data,
416
+ context->public_dir.len + 1);
417
+
418
+ if (context->base_uri.len > 0) {
419
+ b->last = ngx_copy(b->last, "RAILS_RELATIVE_URL_ROOT",
420
+ sizeof("RAILS_RELATIVE_URL_ROOT"));
421
+ b->last = ngx_copy(b->last, context->base_uri.data,
422
+ context->base_uri.len + 1);
423
+ }
424
+
425
+ /* Various other HTTP headers. */
426
+ if (r->headers_in.content_type != NULL
427
+ && r->headers_in.content_type->value.len > 0) {
428
+ b->last = ngx_copy(b->last, "CONTENT_TYPE", sizeof("CONTENT_TYPE"));
429
+ b->last = ngx_copy(b->last, r->headers_in.content_type->value.data,
430
+ r->headers_in.content_type->value.len + 1);
431
+ }
432
+
433
+
434
+ /* Build Passenger application pool option headers. */
435
+ b->last = ngx_copy(b->last, "PASSENGER_USE_GLOBAL_QUEUE",
436
+ sizeof("PASSENGER_USE_GLOBAL_QUEUE"));
437
+ if (slcf->use_global_queue) {
438
+ b->last = ngx_copy(b->last, "true", sizeof("true"));
439
+ } else {
440
+ b->last = ngx_copy(b->last, "false", sizeof("false"));
441
+ }
442
+
443
+ b->last = ngx_copy(b->last, "PASSENGER_ENVIRONMENT",
444
+ sizeof("PASSENGER_ENVIRONMENT"));
445
+ b->last = ngx_copy(b->last, slcf->environment.data,
446
+ slcf->environment.len + 1);
447
+
448
+ b->last = ngx_copy(b->last, "PASSENGER_SPAWN_METHOD",
449
+ sizeof("PASSENGER_SPAWN_METHOD"));
450
+ b->last = ngx_copy(b->last, slcf->spawn_method.data,
451
+ slcf->spawn_method.len + 1);
452
+
453
+ b->last = ngx_copy(b->last, "PASSENGER_APP_TYPE",
454
+ sizeof("PASSENGER_APP_TYPE"));
455
+ b->last = ngx_copy(b->last, app_type_string, app_type_string_len);
456
+
457
+ b->last = ngx_copy(b->last, "PASSENGER_FRAMEWORK_SPAWNER_IDLE_TIME",
458
+ sizeof("PASSENGER_FRAMEWORK_SPAWNER_IDLE_TIME"));
459
+ b->last = ngx_copy(b->last, framework_spawner_idle_time_string,
460
+ ngx_strlen(framework_spawner_idle_time_string) + 1);
461
+
462
+ b->last = ngx_copy(b->last, "PASSENGER_APP_SPAWNER_IDLE_TIME",
463
+ sizeof("PASSENGER_APP_SPAWNER_IDLE_TIME"));
464
+ b->last = ngx_copy(b->last, app_spawner_idle_time_string,
465
+ ngx_strlen(app_spawner_idle_time_string) + 1);
466
+
467
+ if (slcf->vars_len) {
468
+ ngx_memzero(&e, sizeof(ngx_http_script_engine_t));
469
+
470
+ e.ip = slcf->vars->elts;
471
+ e.pos = b->last;
472
+ e.request = r;
473
+ e.flushed = 1;
474
+
475
+ le.ip = slcf->vars_len->elts;
476
+
477
+ while (*(uintptr_t *) le.ip) {
478
+
479
+ lcode = *(ngx_http_script_len_code_pt *) le.ip;
480
+ (void) lcode(&le);
481
+
482
+ for (val_len = 0; *(uintptr_t *) le.ip; val_len += lcode(&le)) {
483
+ lcode = *(ngx_http_script_len_code_pt *) le.ip;
484
+ }
485
+ le.ip += sizeof(uintptr_t);
486
+
487
+ while (*(uintptr_t *) e.ip) {
488
+ code = *(ngx_http_script_code_pt *) e.ip;
489
+ code((ngx_http_script_engine_t *) &e);
490
+ }
491
+ e.ip += sizeof(uintptr_t);
492
+ }
493
+
494
+ b->last = e.pos;
495
+ }
496
+
497
+
498
+ if (slcf->upstream.pass_request_headers) {
499
+
500
+ part = &r->headers_in.headers.part;
501
+ header = part->elts;
502
+
503
+ for (i = 0; /* void */; i++) {
504
+
505
+ if (i >= part->nelts) {
506
+ if (part->next == NULL) {
507
+ break;
508
+ }
509
+
510
+ part = part->next;
511
+ header = part->elts;
512
+ i = 0;
513
+ }
514
+
515
+ b->last = ngx_cpymem(b->last, "HTTP_", sizeof("HTTP_") - 1);
516
+
517
+ for (n = 0; n < header[i].key.len; n++) {
518
+ ch = header[i].key.data[n];
519
+
520
+ if (ch >= 'a' && ch <= 'z') {
521
+ ch &= ~0x20;
522
+
523
+ } else if (ch == '-') {
524
+ ch = '_';
525
+ }
526
+
527
+ *b->last++ = ch;
528
+ }
529
+
530
+ *b->last++ = (u_char) 0;
531
+
532
+ b->last = ngx_copy(b->last, header[i].value.data,
533
+ header[i].value.len);
534
+ *b->last++ = (u_char) 0;
535
+ }
536
+ }
537
+
538
+
539
+ *b->last++ = (u_char) ',';
540
+
541
+ if (slcf->upstream.pass_request_body) {
542
+
543
+ body = r->upstream->request_bufs;
544
+ r->upstream->request_bufs = cl;
545
+
546
+ while (body) {
547
+ b = ngx_alloc_buf(r->pool);
548
+ if (b == NULL) {
549
+ return NGX_ERROR;
550
+ }
551
+
552
+ ngx_memcpy(b, body->buf, sizeof(ngx_buf_t));
553
+
554
+ cl->next = ngx_alloc_chain_link(r->pool);
555
+ if (cl->next == NULL) {
556
+ return NGX_ERROR;
557
+ }
558
+
559
+ cl = cl->next;
560
+ cl->buf = b;
561
+
562
+ body = body->next;
563
+ }
564
+
565
+ b->flush = 1;
566
+
567
+ } else {
568
+ r->upstream->request_bufs = cl;
569
+ }
570
+
571
+
572
+ cl->next = NULL;
573
+
574
+ return NGX_OK;
575
+ }
576
+
577
+
578
+ static ngx_int_t
579
+ reinit_request(ngx_http_request_t *r)
580
+ {
581
+ passenger_context_t *context;
582
+
583
+ context = ngx_http_get_module_ctx(r, ngx_http_passenger_module);
584
+
585
+ if (context == NULL) {
586
+ return NGX_OK;
587
+ }
588
+
589
+ context->status = 0;
590
+ context->status_count = 0;
591
+ context->status_start = NULL;
592
+ context->status_end = NULL;
593
+
594
+ r->upstream->process_header = process_status_line;
595
+
596
+ return NGX_OK;
597
+ }
598
+
599
+
600
+ static ngx_int_t
601
+ process_status_line(ngx_http_request_t *r)
602
+ {
603
+ ngx_int_t rc;
604
+ ngx_http_upstream_t *u;
605
+ passenger_context_t *context;
606
+
607
+ context = ngx_http_get_module_ctx(r, ngx_http_passenger_module);
608
+
609
+ if (context == NULL) {
610
+ return NGX_HTTP_INTERNAL_SERVER_ERROR;
611
+ }
612
+
613
+ rc = parse_status_line(r, context);
614
+
615
+ if (rc == NGX_AGAIN) {
616
+ return rc;
617
+ }
618
+
619
+ u = r->upstream;
620
+
621
+ if (rc == NGX_HTTP_SCGI_PARSE_NO_HEADER) {
622
+ ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
623
+ "upstream sent no valid HTTP/1.0 header");
624
+
625
+ #if 0
626
+ if (u->accel) {
627
+ return NGX_HTTP_UPSTREAM_INVALID_HEADER;
628
+ }
629
+ #endif
630
+
631
+ r->http_version = NGX_HTTP_VERSION_9;
632
+ u->headers_in.status_n = NGX_HTTP_OK;
633
+ u->state->status = NGX_HTTP_OK;
634
+
635
+ return NGX_OK;
636
+ }
637
+
638
+ u->headers_in.status_n = context->status;
639
+ u->state->status = context->status;
640
+
641
+ u->headers_in.status_line.len = context->status_end - context->status_start;
642
+ u->headers_in.status_line.data = ngx_palloc(r->pool,
643
+ u->headers_in.status_line.len);
644
+ if (u->headers_in.status_line.data == NULL) {
645
+ return NGX_HTTP_INTERNAL_SERVER_ERROR;
646
+ }
647
+
648
+ ngx_memcpy(u->headers_in.status_line.data, context->status_start,
649
+ u->headers_in.status_line.len);
650
+
651
+ ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
652
+ "http scgi status %ui \"%V\"",
653
+ u->headers_in.status_n, &u->headers_in.status_line);
654
+
655
+ u->process_header = process_header;
656
+
657
+ return process_header(r);
658
+ }
659
+
660
+
661
+ static ngx_int_t
662
+ parse_status_line(ngx_http_request_t *r, passenger_context_t *context)
663
+ {
664
+ u_char ch;
665
+ u_char *pos;
666
+ ngx_http_upstream_t *u;
667
+ enum {
668
+ sw_start = 0,
669
+ sw_H,
670
+ sw_HT,
671
+ sw_HTT,
672
+ sw_HTTP,
673
+ sw_first_major_digit,
674
+ sw_major_digit,
675
+ sw_first_minor_digit,
676
+ sw_minor_digit,
677
+ sw_status,
678
+ sw_space_after_status,
679
+ sw_status_text,
680
+ sw_almost_done
681
+ } state;
682
+
683
+ u = r->upstream;
684
+
685
+ state = r->state;
686
+
687
+ for (pos = u->buffer.pos; pos < u->buffer.last; pos++) {
688
+ ch = *pos;
689
+
690
+ switch (state) {
691
+
692
+ /* "HTTP/" */
693
+ case sw_start:
694
+ switch (ch) {
695
+ case 'H':
696
+ state = sw_H;
697
+ break;
698
+ default:
699
+ return NGX_HTTP_SCGI_PARSE_NO_HEADER;
700
+ }
701
+ break;
702
+
703
+ case sw_H:
704
+ switch (ch) {
705
+ case 'T':
706
+ state = sw_HT;
707
+ break;
708
+ default:
709
+ return NGX_HTTP_SCGI_PARSE_NO_HEADER;
710
+ }
711
+ break;
712
+
713
+ case sw_HT:
714
+ switch (ch) {
715
+ case 'T':
716
+ state = sw_HTT;
717
+ break;
718
+ default:
719
+ return NGX_HTTP_SCGI_PARSE_NO_HEADER;
720
+ }
721
+ break;
722
+
723
+ case sw_HTT:
724
+ switch (ch) {
725
+ case 'P':
726
+ state = sw_HTTP;
727
+ break;
728
+ default:
729
+ return NGX_HTTP_SCGI_PARSE_NO_HEADER;
730
+ }
731
+ break;
732
+
733
+ case sw_HTTP:
734
+ switch (ch) {
735
+ case '/':
736
+ state = sw_first_major_digit;
737
+ break;
738
+ default:
739
+ return NGX_HTTP_SCGI_PARSE_NO_HEADER;
740
+ }
741
+ break;
742
+
743
+ /* the first digit of major HTTP version */
744
+ case sw_first_major_digit:
745
+ if (ch < '1' || ch > '9') {
746
+ return NGX_HTTP_SCGI_PARSE_NO_HEADER;
747
+ }
748
+
749
+ state = sw_major_digit;
750
+ break;
751
+
752
+ /* the major HTTP version or dot */
753
+ case sw_major_digit:
754
+ if (ch == '.') {
755
+ state = sw_first_minor_digit;
756
+ break;
757
+ }
758
+
759
+ if (ch < '0' || ch > '9') {
760
+ return NGX_HTTP_SCGI_PARSE_NO_HEADER;
761
+ }
762
+
763
+ break;
764
+
765
+ /* the first digit of minor HTTP version */
766
+ case sw_first_minor_digit:
767
+ if (ch < '0' || ch > '9') {
768
+ return NGX_HTTP_SCGI_PARSE_NO_HEADER;
769
+ }
770
+
771
+ state = sw_minor_digit;
772
+ break;
773
+
774
+ /* the minor HTTP version or the end of the request line */
775
+ case sw_minor_digit:
776
+ if (ch == ' ') {
777
+ state = sw_status;
778
+ break;
779
+ }
780
+
781
+ if (ch < '0' || ch > '9') {
782
+ return NGX_HTTP_SCGI_PARSE_NO_HEADER;
783
+ }
784
+
785
+ break;
786
+
787
+ /* HTTP status code */
788
+ case sw_status:
789
+ if (ch == ' ') {
790
+ break;
791
+ }
792
+
793
+ if (ch < '0' || ch > '9') {
794
+ return NGX_HTTP_SCGI_PARSE_NO_HEADER;
795
+ }
796
+
797
+ context->status = context->status * 10 + ch - '0';
798
+
799
+ if (++context->status_count == 3) {
800
+ state = sw_space_after_status;
801
+ context->status_start = pos - 2;
802
+ }
803
+
804
+ break;
805
+
806
+ /* space or end of line */
807
+ case sw_space_after_status:
808
+ switch (ch) {
809
+ case ' ':
810
+ state = sw_status_text;
811
+ break;
812
+ case '.': /* IIS may send 403.1, 403.2, etc */
813
+ state = sw_status_text;
814
+ break;
815
+ case CR:
816
+ state = sw_almost_done;
817
+ break;
818
+ case LF:
819
+ goto done;
820
+ default:
821
+ return NGX_HTTP_SCGI_PARSE_NO_HEADER;
822
+ }
823
+ break;
824
+
825
+ /* any text until end of line */
826
+ case sw_status_text:
827
+ switch (ch) {
828
+ case CR:
829
+ state = sw_almost_done;
830
+
831
+ break;
832
+ case LF:
833
+ goto done;
834
+ }
835
+ break;
836
+
837
+ /* end of status line */
838
+ case sw_almost_done:
839
+ context->status_end = pos - 1;
840
+ switch (ch) {
841
+ case LF:
842
+ goto done;
843
+ default:
844
+ return NGX_HTTP_SCGI_PARSE_NO_HEADER;
845
+ }
846
+ }
847
+ }
848
+
849
+ u->buffer.pos = pos;
850
+ r->state = state;
851
+
852
+ return NGX_AGAIN;
853
+
854
+ done:
855
+
856
+ u->buffer.pos = pos + 1;
857
+
858
+ if (context->status_end == NULL) {
859
+ context->status_end = pos;
860
+ }
861
+
862
+ r->state = sw_start;
863
+
864
+ return NGX_OK;
865
+ }
866
+
867
+
868
+ static ngx_int_t
869
+ process_header(ngx_http_request_t *r)
870
+ {
871
+ ngx_int_t rc;
872
+ ngx_uint_t i;
873
+ ngx_table_elt_t *h;
874
+ ngx_http_upstream_header_t *hh;
875
+ ngx_http_upstream_main_conf_t *umcf;
876
+
877
+ umcf = ngx_http_get_module_main_conf(r, ngx_http_upstream_module);
878
+
879
+ for ( ;; ) {
880
+
881
+ #if NGINX_VERSION_NUM >= 7000
882
+ rc = ngx_http_parse_header_line(r, &r->upstream->buffer, 1);
883
+ #else
884
+ rc = ngx_http_parse_header_line(r, &r->upstream->buffer);
885
+ #endif
886
+
887
+ if (rc == NGX_OK) {
888
+
889
+ /* a header line has been parsed successfully */
890
+
891
+ h = ngx_list_push(&r->upstream->headers_in.headers);
892
+ if (h == NULL) {
893
+ return NGX_HTTP_INTERNAL_SERVER_ERROR;
894
+ }
895
+
896
+ h->hash = r->header_hash;
897
+
898
+ h->key.len = r->header_name_end - r->header_name_start;
899
+ h->value.len = r->header_end - r->header_start;
900
+
901
+ h->key.data = ngx_palloc(r->pool,
902
+ h->key.len + 1 + h->value.len + 1 + h->key.len);
903
+ if (h->key.data == NULL) {
904
+ return NGX_HTTP_INTERNAL_SERVER_ERROR;
905
+ }
906
+
907
+ h->value.data = h->key.data + h->key.len + 1;
908
+ h->lowcase_key = h->key.data + h->key.len + 1 + h->value.len + 1;
909
+
910
+ ngx_cpystrn(h->key.data, r->header_name_start, h->key.len + 1);
911
+ ngx_cpystrn(h->value.data, r->header_start, h->value.len + 1);
912
+
913
+ if (h->key.len == r->lowcase_index) {
914
+ ngx_memcpy(h->lowcase_key, r->lowcase_header, h->key.len);
915
+
916
+ } else {
917
+ for (i = 0; i < h->key.len; i++) {
918
+ h->lowcase_key[i] = ngx_tolower(h->key.data[i]);
919
+ }
920
+ }
921
+
922
+ hh = ngx_hash_find(&umcf->headers_in_hash, h->hash,
923
+ h->lowcase_key, h->key.len);
924
+
925
+ if (hh && hh->handler(r, h, hh->offset) != NGX_OK) {
926
+ return NGX_HTTP_INTERNAL_SERVER_ERROR;
927
+ }
928
+
929
+ ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
930
+ "http scgi header: \"%V: %V\"",
931
+ &h->key, &h->value);
932
+
933
+ continue;
934
+ }
935
+
936
+ if (rc == NGX_HTTP_PARSE_HEADER_DONE) {
937
+
938
+ /* a whole header has been parsed successfully */
939
+
940
+ ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
941
+ "http scgi header done");
942
+
943
+ /*
944
+ * if no "Server" and "Date" in header line,
945
+ * then add the default headers
946
+ */
947
+
948
+ if (r->upstream->headers_in.server == NULL) {
949
+ h = ngx_list_push(&r->upstream->headers_in.headers);
950
+ if (h == NULL) {
951
+ return NGX_HTTP_INTERNAL_SERVER_ERROR;
952
+ }
953
+
954
+ h->hash = ngx_hash(ngx_hash(ngx_hash(ngx_hash(
955
+ ngx_hash('s', 'e'), 'r'), 'v'), 'e'), 'r');
956
+
957
+ h->key.len = sizeof("Server") - 1;
958
+ h->key.data = (u_char *) "Server";
959
+ h->value.data = (u_char *) (NGINX_VER " + Phusion Passenger (mod_rails/mod_rack)");
960
+ h->value.len = ngx_strlen(h->value.data);
961
+ h->lowcase_key = (u_char *) "server";
962
+ }
963
+
964
+ if (r->upstream->headers_in.date == NULL) {
965
+ h = ngx_list_push(&r->upstream->headers_in.headers);
966
+ if (h == NULL) {
967
+ return NGX_HTTP_INTERNAL_SERVER_ERROR;
968
+ }
969
+
970
+ h->hash = ngx_hash(ngx_hash(ngx_hash('d', 'a'), 't'), 'e');
971
+
972
+ h->key.len = sizeof("Date") - 1;
973
+ h->key.data = (u_char *) "Date";
974
+ h->value.len = 0;
975
+ h->value.data = NULL;
976
+ h->lowcase_key = (u_char *) "date";
977
+ }
978
+
979
+ return NGX_OK;
980
+ }
981
+
982
+ if (rc == NGX_AGAIN) {
983
+ return NGX_AGAIN;
984
+ }
985
+
986
+ /* there was error while a header line parsing */
987
+
988
+ ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
989
+ "upstream sent invalid header");
990
+
991
+ return NGX_HTTP_UPSTREAM_INVALID_HEADER;
992
+ }
993
+ }
994
+
995
+
996
+ static void
997
+ abort_request(ngx_http_request_t *r)
998
+ {
999
+ ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1000
+ "abort Passenger request");
1001
+ }
1002
+
1003
+
1004
+ static void
1005
+ finalize_request(ngx_http_request_t *r, ngx_int_t rc)
1006
+ {
1007
+ ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1008
+ "finalize Passenger request");
1009
+ }
1010
+
1011
+
1012
+ ngx_int_t
1013
+ passenger_content_handler(ngx_http_request_t *r)
1014
+ {
1015
+ ngx_int_t rc;
1016
+ ngx_http_upstream_t *u;
1017
+ passenger_loc_conf_t *slcf;
1018
+ ngx_str_t path, base_uri;
1019
+ u_char *path_last, *end;
1020
+ u_char root_path_str[NGX_MAX_PATH + 1];
1021
+ ngx_str_t root_path;
1022
+ size_t root, len;
1023
+ u_char page_cache_file_str[NGX_MAX_PATH + 1];
1024
+ ngx_str_t page_cache_file;
1025
+ passenger_context_t *context;
1026
+
1027
+ if (r->subrequest_in_memory) {
1028
+ ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
1029
+ "ngx_http_passenger_module does not support "
1030
+ "subrequest in memory");
1031
+ return NGX_HTTP_INTERNAL_SERVER_ERROR;
1032
+ }
1033
+
1034
+ slcf = ngx_http_get_module_loc_conf(r, ngx_http_passenger_module);
1035
+
1036
+ /* Let the next content handler take care of this request if Phusion
1037
+ * Passenger is disabled for this URL.
1038
+ */
1039
+ if (!slcf->enabled) {
1040
+ return NGX_DECLINED;
1041
+ }
1042
+
1043
+ /* Let the next content handler take care of this request if this URL
1044
+ * maps to an existing file.
1045
+ */
1046
+ path_last = ngx_http_map_uri_to_path(r, &path, &root, 0);
1047
+ if (path_last != NULL && file_exists(path.data, 0)) {
1048
+ return NGX_DECLINED;
1049
+ }
1050
+
1051
+ /* Create a string containing the root path. This path already
1052
+ * contains a trailing slash.
1053
+ */
1054
+ end = ngx_copy(root_path_str, path.data, root);
1055
+ *end = '\0';
1056
+ root_path.data = root_path_str;
1057
+ root_path.len = root;
1058
+
1059
+
1060
+ context = ngx_pcalloc(r->pool, sizeof(passenger_context_t));
1061
+ if (context == NULL) {
1062
+ return NGX_HTTP_INTERNAL_SERVER_ERROR;
1063
+ }
1064
+ ngx_http_set_ctx(r, context, ngx_http_passenger_module);
1065
+
1066
+
1067
+ /* Find the base URI for this web application, if any. */
1068
+ if (find_base_uri(r, slcf, &base_uri)) {
1069
+ /* Store the found base URI in context->public_dir. We infer that the 'public'
1070
+ * directory of the web application is document root + base URI.
1071
+ */
1072
+ len = root_path.len + base_uri.len + 1;
1073
+ context->public_dir.data = ngx_palloc(r->pool, sizeof(u_char) * len);
1074
+ end = ngx_copy(context->public_dir.data, root_path.data, root_path.len);
1075
+ end = ngx_copy(end, base_uri.data, base_uri.len);
1076
+ *end = '\0';
1077
+ context->public_dir.len = len - 1;
1078
+ context->base_uri = base_uri;
1079
+ } else {
1080
+ /* No base URI directives are applicable for this request. So assume that
1081
+ * the web application's public directory is the document root.
1082
+ * context->base_uri is now a NULL string.
1083
+ */
1084
+ len = sizeof(u_char *) * (root_path.len + 1);
1085
+ context->public_dir.data = ngx_palloc(r->pool, len);
1086
+ end = ngx_copy(context->public_dir.data, root_path.data,
1087
+ root_path.len);
1088
+ *end = '\0';
1089
+ context->public_dir.len = root_path.len;
1090
+ }
1091
+
1092
+ /* If there's a corresponding page cache file for this URL, then serve that
1093
+ * file instead.
1094
+ */
1095
+ page_cache_file.data = page_cache_file_str;
1096
+ page_cache_file.len = sizeof(page_cache_file_str);
1097
+ if (map_uri_to_page_cache_file(r, &context->public_dir, path.data,
1098
+ path_last - path.data, &page_cache_file)) {
1099
+ return passenger_static_content_handler(r, &page_cache_file);
1100
+ }
1101
+
1102
+ context->app_type = detect_application_type(&context->public_dir);
1103
+ if (context->app_type == AP_NONE) {
1104
+ return NGX_DECLINED;
1105
+ }
1106
+
1107
+
1108
+ /* Setup upstream stuff and prepare sending the request to the backend. */
1109
+
1110
+ u = ngx_pcalloc(r->pool, sizeof(ngx_http_upstream_t));
1111
+ if (u == NULL) {
1112
+ return NGX_HTTP_INTERNAL_SERVER_ERROR;
1113
+ }
1114
+
1115
+ #if NGINX_VERSION_NUM >= 7000
1116
+ u->schema = passenger_schema_string;
1117
+ #endif
1118
+
1119
+ u->peer.log = r->connection->log;
1120
+ u->peer.log_error = NGX_ERROR_ERR;
1121
+ #if (NGX_THREADS)
1122
+ u->peer.lock = &r->connection->lock;
1123
+ #endif
1124
+
1125
+ u->output.tag = (ngx_buf_tag_t) &ngx_http_passenger_module;
1126
+
1127
+ u->conf = &slcf->upstream;
1128
+
1129
+ u->create_request = create_request;
1130
+ u->reinit_request = reinit_request;
1131
+ u->process_header = process_status_line;
1132
+ u->abort_request = abort_request;
1133
+ u->finalize_request = finalize_request;
1134
+
1135
+ u->buffering = 1;
1136
+
1137
+ u->pipe = ngx_pcalloc(r->pool, sizeof(ngx_event_pipe_t));
1138
+ if (u->pipe == NULL) {
1139
+ return NGX_HTTP_INTERNAL_SERVER_ERROR;
1140
+ }
1141
+
1142
+ u->pipe->input_filter = ngx_event_pipe_copy_input_filter;
1143
+
1144
+ r->upstream = u;
1145
+
1146
+ rc = ngx_http_read_client_request_body(r, ngx_http_upstream_init);
1147
+
1148
+ if (rc >= NGX_HTTP_SPECIAL_RESPONSE) {
1149
+ return rc;
1150
+ }
1151
+
1152
+ return NGX_DONE;
1153
+ }
1154
+