mongrel 1.0.1 → 1.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (263) hide show
  1. data.tar.gz.sig +2 -0
  2. data/CHANGELOG +2 -0
  3. data/Manifest +68 -0
  4. data/bin/mongrel_rails +55 -22
  5. data/examples/camping/README +3 -0
  6. data/examples/httpd.conf +474 -0
  7. data/examples/mime.yaml +3 -0
  8. data/examples/mongrel.conf +9 -0
  9. data/examples/monitrc +57 -0
  10. data/ext/http11/http11.c +25 -12
  11. data/ext/http11/http11_parser.c +456 -331
  12. data/ext/http11/http11_parser.h +1 -0
  13. data/ext/http11/http11_parser.java.rl +170 -0
  14. data/ext/http11/http11_parser.rl +8 -48
  15. data/ext/http11/http11_parser_common.rl +54 -0
  16. data/ext/http11/tst.h +2 -2
  17. data/ext/http11/tst_cleanup.c +0 -1
  18. data/ext/http11/tst_insert.c +29 -3
  19. data/ext/http11/tst_search.c +60 -55
  20. data/lib/mongrel.rb +68 -53
  21. data/lib/mongrel/cgi.rb +3 -3
  22. data/lib/mongrel/command.rb +1 -1
  23. data/lib/mongrel/configurator.rb +41 -31
  24. data/lib/mongrel/debug.rb +2 -5
  25. data/lib/mongrel/handlers.rb +23 -9
  26. data/lib/mongrel/mime_types.yml +2 -1
  27. data/lib/mongrel/rails.rb +7 -15
  28. data/mongrel-public_cert.pem +20 -0
  29. data/mongrel.gemspec +211 -0
  30. data/test/jruby_socket.rb +39 -0
  31. data/test/test_cgi_wrapper.rb +26 -0
  32. data/test/test_command.rb +1 -4
  33. data/test/test_conditional.rb +6 -18
  34. data/test/test_configurator.rb +5 -8
  35. data/test/test_debug.rb +3 -11
  36. data/test/test_handlers.rb +8 -10
  37. data/test/test_http11.rb +24 -5
  38. data/test/test_redirect_handler.rb +2 -6
  39. data/test/test_request_progress.rb +5 -9
  40. data/test/test_response.rb +24 -3
  41. data/test/test_stats.rb +1 -3
  42. data/test/test_uriclassifier.rb +170 -81
  43. data/test/test_ws.rb +25 -24
  44. data/test/testhelp.rb +26 -3
  45. data/tools/trickletest.rb +2 -2
  46. metadata +138 -333
  47. metadata.gz.sig +0 -0
  48. data/Rakefile +0 -117
  49. data/doc/rdoc/classes/IO.html +0 -170
  50. data/doc/rdoc/classes/IO.src/M000003.html +0 -19
  51. data/doc/rdoc/classes/IO.src/M000004.html +0 -19
  52. data/doc/rdoc/classes/Kernel.html +0 -159
  53. data/doc/rdoc/classes/Kernel.src/M000012.html +0 -19
  54. data/doc/rdoc/classes/Kernel.src/M000013.html +0 -23
  55. data/doc/rdoc/classes/Mongrel.html +0 -204
  56. data/doc/rdoc/classes/Mongrel/CGIWrapper.html +0 -404
  57. data/doc/rdoc/classes/Mongrel/CGIWrapper.src/M000115.html +0 -25
  58. data/doc/rdoc/classes/Mongrel/CGIWrapper.src/M000116.html +0 -47
  59. data/doc/rdoc/classes/Mongrel/CGIWrapper.src/M000117.html +0 -34
  60. data/doc/rdoc/classes/Mongrel/CGIWrapper.src/M000118.html +0 -32
  61. data/doc/rdoc/classes/Mongrel/CGIWrapper.src/M000119.html +0 -25
  62. data/doc/rdoc/classes/Mongrel/CGIWrapper.src/M000120.html +0 -18
  63. data/doc/rdoc/classes/Mongrel/CGIWrapper.src/M000121.html +0 -18
  64. data/doc/rdoc/classes/Mongrel/CGIWrapper.src/M000122.html +0 -18
  65. data/doc/rdoc/classes/Mongrel/CGIWrapper.src/M000123.html +0 -19
  66. data/doc/rdoc/classes/Mongrel/Camping.html +0 -177
  67. data/doc/rdoc/classes/Mongrel/Camping.src/M000041.html +0 -22
  68. data/doc/rdoc/classes/Mongrel/Camping/CampingHandler.html +0 -184
  69. data/doc/rdoc/classes/Mongrel/Camping/CampingHandler.src/M000042.html +0 -20
  70. data/doc/rdoc/classes/Mongrel/Camping/CampingHandler.src/M000043.html +0 -58
  71. data/doc/rdoc/classes/Mongrel/Command.html +0 -132
  72. data/doc/rdoc/classes/Mongrel/Command/Base.html +0 -384
  73. data/doc/rdoc/classes/Mongrel/Command/Base.src/M000018.html +0 -24
  74. data/doc/rdoc/classes/Mongrel/Command/Base.src/M000019.html +0 -42
  75. data/doc/rdoc/classes/Mongrel/Command/Base.src/M000020.html +0 -18
  76. data/doc/rdoc/classes/Mongrel/Command/Base.src/M000021.html +0 -18
  77. data/doc/rdoc/classes/Mongrel/Command/Base.src/M000022.html +0 -18
  78. data/doc/rdoc/classes/Mongrel/Command/Base.src/M000023.html +0 -18
  79. data/doc/rdoc/classes/Mongrel/Command/Base.src/M000024.html +0 -22
  80. data/doc/rdoc/classes/Mongrel/Command/Base.src/M000025.html +0 -18
  81. data/doc/rdoc/classes/Mongrel/Command/Base.src/M000026.html +0 -18
  82. data/doc/rdoc/classes/Mongrel/Command/Base.src/M000027.html +0 -18
  83. data/doc/rdoc/classes/Mongrel/Command/Base.src/M000028.html +0 -24
  84. data/doc/rdoc/classes/Mongrel/Command/Base.src/M000029.html +0 -24
  85. data/doc/rdoc/classes/Mongrel/Command/Base.src/M000030.html +0 -18
  86. data/doc/rdoc/classes/Mongrel/Command/Registry.html +0 -192
  87. data/doc/rdoc/classes/Mongrel/Command/Registry.src/M000031.html +0 -20
  88. data/doc/rdoc/classes/Mongrel/Command/Registry.src/M000032.html +0 -29
  89. data/doc/rdoc/classes/Mongrel/Command/Registry.src/M000033.html +0 -58
  90. data/doc/rdoc/classes/Mongrel/Configurator.html +0 -716
  91. data/doc/rdoc/classes/Mongrel/Configurator.src/M000093.html +0 -27
  92. data/doc/rdoc/classes/Mongrel/Configurator.src/M000094.html +0 -31
  93. data/doc/rdoc/classes/Mongrel/Configurator.src/M000095.html +0 -18
  94. data/doc/rdoc/classes/Mongrel/Configurator.src/M000096.html +0 -21
  95. data/doc/rdoc/classes/Mongrel/Configurator.src/M000097.html +0 -20
  96. data/doc/rdoc/classes/Mongrel/Configurator.src/M000098.html +0 -23
  97. data/doc/rdoc/classes/Mongrel/Configurator.src/M000099.html +0 -18
  98. data/doc/rdoc/classes/Mongrel/Configurator.src/M000100.html +0 -38
  99. data/doc/rdoc/classes/Mongrel/Configurator.src/M000101.html +0 -19
  100. data/doc/rdoc/classes/Mongrel/Configurator.src/M000102.html +0 -39
  101. data/doc/rdoc/classes/Mongrel/Configurator.src/M000103.html +0 -33
  102. data/doc/rdoc/classes/Mongrel/Configurator.src/M000104.html +0 -18
  103. data/doc/rdoc/classes/Mongrel/Configurator.src/M000105.html +0 -24
  104. data/doc/rdoc/classes/Mongrel/Configurator.src/M000106.html +0 -19
  105. data/doc/rdoc/classes/Mongrel/Configurator.src/M000107.html +0 -18
  106. data/doc/rdoc/classes/Mongrel/Configurator.src/M000108.html +0 -22
  107. data/doc/rdoc/classes/Mongrel/Configurator.src/M000109.html +0 -22
  108. data/doc/rdoc/classes/Mongrel/Configurator.src/M000110.html +0 -18
  109. data/doc/rdoc/classes/Mongrel/Configurator.src/M000111.html +0 -34
  110. data/doc/rdoc/classes/Mongrel/Configurator.src/M000112.html +0 -18
  111. data/doc/rdoc/classes/Mongrel/Configurator.src/M000113.html +0 -36
  112. data/doc/rdoc/classes/Mongrel/Configurator.src/M000114.html +0 -18
  113. data/doc/rdoc/classes/Mongrel/Const.html +0 -337
  114. data/doc/rdoc/classes/Mongrel/DeflateFilter.html +0 -188
  115. data/doc/rdoc/classes/Mongrel/DeflateFilter.src/M000124.html +0 -19
  116. data/doc/rdoc/classes/Mongrel/DeflateFilter.src/M000125.html +0 -23
  117. data/doc/rdoc/classes/Mongrel/DirHandler.html +0 -303
  118. data/doc/rdoc/classes/Mongrel/DirHandler.src/M000051.html +0 -21
  119. data/doc/rdoc/classes/Mongrel/DirHandler.src/M000052.html +0 -42
  120. data/doc/rdoc/classes/Mongrel/DirHandler.src/M000053.html +0 -38
  121. data/doc/rdoc/classes/Mongrel/DirHandler.src/M000054.html +0 -65
  122. data/doc/rdoc/classes/Mongrel/DirHandler.src/M000055.html +0 -39
  123. data/doc/rdoc/classes/Mongrel/DirHandler.src/M000056.html +0 -18
  124. data/doc/rdoc/classes/Mongrel/Error404Handler.html +0 -171
  125. data/doc/rdoc/classes/Mongrel/Error404Handler.src/M000126.html +0 -18
  126. data/doc/rdoc/classes/Mongrel/Error404Handler.src/M000127.html +0 -18
  127. data/doc/rdoc/classes/Mongrel/HeaderOut.html +0 -190
  128. data/doc/rdoc/classes/Mongrel/HeaderOut.src/M000066.html +0 -21
  129. data/doc/rdoc/classes/Mongrel/HeaderOut.src/M000067.html +0 -21
  130. data/doc/rdoc/classes/Mongrel/HttpHandler.html +0 -215
  131. data/doc/rdoc/classes/Mongrel/HttpHandler.src/M000072.html +0 -17
  132. data/doc/rdoc/classes/Mongrel/HttpHandler.src/M000073.html +0 -17
  133. data/doc/rdoc/classes/Mongrel/HttpHandler.src/M000074.html +0 -17
  134. data/doc/rdoc/classes/Mongrel/HttpHandlerPlugin.html +0 -210
  135. data/doc/rdoc/classes/Mongrel/HttpHandlerPlugin.src/M000014.html +0 -17
  136. data/doc/rdoc/classes/Mongrel/HttpHandlerPlugin.src/M000015.html +0 -17
  137. data/doc/rdoc/classes/Mongrel/HttpHandlerPlugin.src/M000016.html +0 -19
  138. data/doc/rdoc/classes/Mongrel/HttpHandlerPlugin.src/M000017.html +0 -17
  139. data/doc/rdoc/classes/Mongrel/HttpParams.html +0 -131
  140. data/doc/rdoc/classes/Mongrel/HttpParser.html +0 -278
  141. data/doc/rdoc/classes/Mongrel/HttpParser.src/M000044.html +0 -28
  142. data/doc/rdoc/classes/Mongrel/HttpParser.src/M000045.html +0 -29
  143. data/doc/rdoc/classes/Mongrel/HttpParser.src/M000046.html +0 -29
  144. data/doc/rdoc/classes/Mongrel/HttpParser.src/M000047.html +0 -59
  145. data/doc/rdoc/classes/Mongrel/HttpParser.src/M000048.html +0 -27
  146. data/doc/rdoc/classes/Mongrel/HttpParser.src/M000049.html +0 -27
  147. data/doc/rdoc/classes/Mongrel/HttpParser.src/M000050.html +0 -28
  148. data/doc/rdoc/classes/Mongrel/HttpParserError.html +0 -111
  149. data/doc/rdoc/classes/Mongrel/HttpRequest.html +0 -284
  150. data/doc/rdoc/classes/Mongrel/HttpRequest.src/M000133.html +0 -50
  151. data/doc/rdoc/classes/Mongrel/HttpRequest.src/M000134.html +0 -41
  152. data/doc/rdoc/classes/Mongrel/HttpRequest.src/M000135.html +0 -29
  153. data/doc/rdoc/classes/Mongrel/HttpRequest.src/M000136.html +0 -20
  154. data/doc/rdoc/classes/Mongrel/HttpRequest.src/M000137.html +0 -20
  155. data/doc/rdoc/classes/Mongrel/HttpRequest.src/M000138.html +0 -32
  156. data/doc/rdoc/classes/Mongrel/HttpResponse.html +0 -443
  157. data/doc/rdoc/classes/Mongrel/HttpResponse.src/M000075.html +0 -25
  158. data/doc/rdoc/classes/Mongrel/HttpResponse.src/M000076.html +0 -20
  159. data/doc/rdoc/classes/Mongrel/HttpResponse.src/M000077.html +0 -26
  160. data/doc/rdoc/classes/Mongrel/HttpResponse.src/M000078.html +0 -22
  161. data/doc/rdoc/classes/Mongrel/HttpResponse.src/M000079.html +0 -22
  162. data/doc/rdoc/classes/Mongrel/HttpResponse.src/M000080.html +0 -22
  163. data/doc/rdoc/classes/Mongrel/HttpResponse.src/M000081.html +0 -31
  164. data/doc/rdoc/classes/Mongrel/HttpResponse.src/M000082.html +0 -21
  165. data/doc/rdoc/classes/Mongrel/HttpResponse.src/M000083.html +0 -20
  166. data/doc/rdoc/classes/Mongrel/HttpResponse.src/M000084.html +0 -20
  167. data/doc/rdoc/classes/Mongrel/HttpResponse.src/M000085.html +0 -20
  168. data/doc/rdoc/classes/Mongrel/HttpResponse.src/M000086.html +0 -18
  169. data/doc/rdoc/classes/Mongrel/HttpServer.html +0 -402
  170. data/doc/rdoc/classes/Mongrel/HttpServer.src/M000057.html +0 -25
  171. data/doc/rdoc/classes/Mongrel/HttpServer.src/M000058.html +0 -100
  172. data/doc/rdoc/classes/Mongrel/HttpServer.src/M000059.html +0 -32
  173. data/doc/rdoc/classes/Mongrel/HttpServer.src/M000060.html +0 -21
  174. data/doc/rdoc/classes/Mongrel/HttpServer.src/M000061.html +0 -29
  175. data/doc/rdoc/classes/Mongrel/HttpServer.src/M000062.html +0 -65
  176. data/doc/rdoc/classes/Mongrel/HttpServer.src/M000063.html +0 -34
  177. data/doc/rdoc/classes/Mongrel/HttpServer.src/M000064.html +0 -18
  178. data/doc/rdoc/classes/Mongrel/HttpServer.src/M000065.html +0 -22
  179. data/doc/rdoc/classes/Mongrel/Rails.html +0 -112
  180. data/doc/rdoc/classes/Mongrel/Rails/RailsConfigurator.html +0 -225
  181. data/doc/rdoc/classes/Mongrel/Rails/RailsConfigurator.src/M000034.html +0 -37
  182. data/doc/rdoc/classes/Mongrel/Rails/RailsConfigurator.src/M000035.html +0 -25
  183. data/doc/rdoc/classes/Mongrel/Rails/RailsConfigurator.src/M000036.html +0 -26
  184. data/doc/rdoc/classes/Mongrel/Rails/RailsHandler.html +0 -263
  185. data/doc/rdoc/classes/Mongrel/Rails/RailsHandler.src/M000037.html +0 -23
  186. data/doc/rdoc/classes/Mongrel/Rails/RailsHandler.src/M000038.html +0 -56
  187. data/doc/rdoc/classes/Mongrel/Rails/RailsHandler.src/M000039.html +0 -20
  188. data/doc/rdoc/classes/Mongrel/Rails/RailsHandler.src/M000040.html +0 -25
  189. data/doc/rdoc/classes/Mongrel/RedirectHandler.html +0 -187
  190. data/doc/rdoc/classes/Mongrel/RedirectHandler.src/M000131.html +0 -22
  191. data/doc/rdoc/classes/Mongrel/RedirectHandler.src/M000132.html +0 -27
  192. data/doc/rdoc/classes/Mongrel/StatisticsFilter.html +0 -211
  193. data/doc/rdoc/classes/Mongrel/StatisticsFilter.src/M000128.html +0 -24
  194. data/doc/rdoc/classes/Mongrel/StatisticsFilter.src/M000129.html +0 -24
  195. data/doc/rdoc/classes/Mongrel/StatisticsFilter.src/M000130.html +0 -18
  196. data/doc/rdoc/classes/Mongrel/Stats.html +0 -309
  197. data/doc/rdoc/classes/Mongrel/Stats.src/M000139.html +0 -19
  198. data/doc/rdoc/classes/Mongrel/Stats.src/M000140.html +0 -23
  199. data/doc/rdoc/classes/Mongrel/Stats.src/M000141.html +0 -26
  200. data/doc/rdoc/classes/Mongrel/Stats.src/M000142.html +0 -18
  201. data/doc/rdoc/classes/Mongrel/Stats.src/M000143.html +0 -18
  202. data/doc/rdoc/classes/Mongrel/Stats.src/M000144.html +0 -18
  203. data/doc/rdoc/classes/Mongrel/Stats.src/M000145.html +0 -23
  204. data/doc/rdoc/classes/Mongrel/Stats.src/M000146.html +0 -20
  205. data/doc/rdoc/classes/Mongrel/StatusHandler.html +0 -194
  206. data/doc/rdoc/classes/Mongrel/StatusHandler.src/M000068.html +0 -18
  207. data/doc/rdoc/classes/Mongrel/StatusHandler.src/M000069.html +0 -24
  208. data/doc/rdoc/classes/Mongrel/StatusHandler.src/M000070.html +0 -42
  209. data/doc/rdoc/classes/Mongrel/StatusHandler.src/M000071.html +0 -20
  210. data/doc/rdoc/classes/Mongrel/StopServer.html +0 -117
  211. data/doc/rdoc/classes/Mongrel/TimeoutError.html +0 -117
  212. data/doc/rdoc/classes/Mongrel/URIClassifier.html +0 -317
  213. data/doc/rdoc/classes/Mongrel/URIClassifier.src/M000087.html +0 -18
  214. data/doc/rdoc/classes/Mongrel/URIClassifier.src/M000088.html +0 -18
  215. data/doc/rdoc/classes/Mongrel/URIClassifier.src/M000089.html +0 -39
  216. data/doc/rdoc/classes/Mongrel/URIClassifier.src/M000090.html +0 -51
  217. data/doc/rdoc/classes/Mongrel/URIClassifier.src/M000091.html +0 -36
  218. data/doc/rdoc/classes/Mongrel/URIClassifier.src/M000092.html +0 -83
  219. data/doc/rdoc/classes/MongrelDbg.html +0 -209
  220. data/doc/rdoc/classes/MongrelDbg.src/M000007.html +0 -24
  221. data/doc/rdoc/classes/MongrelDbg.src/M000008.html +0 -20
  222. data/doc/rdoc/classes/MongrelDbg.src/M000009.html +0 -22
  223. data/doc/rdoc/classes/MongrelDbg.src/M000010.html +0 -21
  224. data/doc/rdoc/classes/MongrelDbg.src/M000011.html +0 -18
  225. data/doc/rdoc/classes/Mutex.html +0 -158
  226. data/doc/rdoc/classes/Mutex.src/M000001.html +0 -24
  227. data/doc/rdoc/classes/Mutex.src/M000002.html +0 -32
  228. data/doc/rdoc/classes/RequestLog.html +0 -115
  229. data/doc/rdoc/classes/RequestLog/Access.html +0 -151
  230. data/doc/rdoc/classes/RequestLog/Access.src/M000147.html +0 -19
  231. data/doc/rdoc/classes/RequestLog/Files.html +0 -144
  232. data/doc/rdoc/classes/RequestLog/Files.src/M000148.html +0 -19
  233. data/doc/rdoc/classes/RequestLog/Objects.html +0 -150
  234. data/doc/rdoc/classes/RequestLog/Objects.src/M000150.html +0 -51
  235. data/doc/rdoc/classes/RequestLog/Params.html +0 -144
  236. data/doc/rdoc/classes/RequestLog/Params.src/M000151.html +0 -19
  237. data/doc/rdoc/classes/RequestLog/Threads.html +0 -144
  238. data/doc/rdoc/classes/RequestLog/Threads.src/M000149.html +0 -34
  239. data/doc/rdoc/classes/TCPServer.html +0 -173
  240. data/doc/rdoc/classes/TCPServer.src/M000005.html +0 -19
  241. data/doc/rdoc/created.rid +0 -1
  242. data/doc/rdoc/files/COPYING.html +0 -168
  243. data/doc/rdoc/files/LICENSE.html +0 -168
  244. data/doc/rdoc/files/README.html +0 -213
  245. data/doc/rdoc/files/ext/http11/http11_c.html +0 -101
  246. data/doc/rdoc/files/lib/mongrel/camping_rb.html +0 -120
  247. data/doc/rdoc/files/lib/mongrel/cgi_rb.html +0 -120
  248. data/doc/rdoc/files/lib/mongrel/command_rb.html +0 -123
  249. data/doc/rdoc/files/lib/mongrel/configurator_rb.html +0 -111
  250. data/doc/rdoc/files/lib/mongrel/debug_rb.html +0 -122
  251. data/doc/rdoc/files/lib/mongrel/handlers_rb.html +0 -122
  252. data/doc/rdoc/files/lib/mongrel/init_rb.html +0 -121
  253. data/doc/rdoc/files/lib/mongrel/rails_rb.html +0 -123
  254. data/doc/rdoc/files/lib/mongrel/stats_rb.html +0 -113
  255. data/doc/rdoc/files/lib/mongrel/tcphack_rb.html +0 -113
  256. data/doc/rdoc/files/lib/mongrel_rb.html +0 -135
  257. data/doc/rdoc/files/lib/mutex_fix_rb.html +0 -108
  258. data/doc/rdoc/fr_class_index.html +0 -68
  259. data/doc/rdoc/fr_file_index.html +0 -42
  260. data/doc/rdoc/fr_method_index.html +0 -177
  261. data/doc/rdoc/index.html +0 -24
  262. data/doc/rdoc/rdoc-style.css +0 -208
  263. data/tools/rakehelp.rb +0 -117
@@ -4,12 +4,10 @@
4
4
  # Additional work donated by contributors. See http://mongrel.rubyforge.org/attributions.html
5
5
  # for more information.
6
6
 
7
- $mongrel_debug_client = false
8
-
9
- require 'rubygems'
10
7
  require 'socket'
11
8
  require 'http11'
12
9
  require 'tempfile'
10
+
13
11
  begin
14
12
  require 'fastthread'
15
13
  rescue RuntimeError => e
@@ -18,6 +16,9 @@ rescue LoadError
18
16
  ensure
19
17
  require 'thread'
20
18
  end
19
+
20
+ require 'cgi_multipart_eof_fix'
21
+
21
22
  require 'stringio'
22
23
  require 'mongrel/cgi'
23
24
  require 'mongrel/handlers'
@@ -36,30 +37,27 @@ require 'uri'
36
37
  module Mongrel
37
38
 
38
39
  class URIClassifier
39
- attr_reader :handler_map
40
-
40
+ attr_reader :handler_map
41
+
41
42
  # Returns the URIs that have been registered with this classifier so far.
42
43
  # The URIs returned should not be modified as this will cause a memory leak.
43
44
  # You can use this to inspect the contents of the URIClassifier.
44
45
  def uris
45
46
  @handler_map.keys
46
47
  end
47
-
48
48
  # Simply does an inspect that looks like a Hash inspect.
49
49
  def inspect
50
50
  @handler_map.inspect
51
51
  end
52
- end
53
52
 
53
+ end
54
54
 
55
55
  # Used to stop the HttpServer via Thread.raise.
56
56
  class StopServer < Exception; end
57
57
 
58
-
59
58
  # Thrown at a thread when it is timed out.
60
59
  class TimeoutError < Exception; end
61
60
 
62
-
63
61
  # Every standard HTTP code mapped to the appropriate message. These are
64
62
  # used so frequently that they are placed directly in Mongrel for easy
65
63
  # access rather than Mongrel::Const.
@@ -125,7 +123,7 @@ module Mongrel
125
123
  REQUEST_URI='REQUEST_URI'.freeze
126
124
  REQUEST_PATH='REQUEST_PATH'.freeze
127
125
 
128
- MONGREL_VERSION="1.0.1".freeze
126
+ MONGREL_VERSION="1.0.2".freeze
129
127
 
130
128
  MONGREL_TMP_BASE="mongrel".freeze
131
129
 
@@ -261,11 +259,11 @@ module Mongrel
261
259
 
262
260
  update_request_progress(remain, total)
263
261
  end
264
- rescue Object
265
- STDERR.puts "ERROR reading http body: #$!"
266
- $!.backtrace.join("\n")
262
+ rescue Object => e
263
+ STDERR.puts "#{Time.now}: Error reading HTTP body: #{e.inspect}"
264
+ STDERR.puts e.backtrace.join("\n")
267
265
  # any errors means we should delete the file, including if the file is dumped
268
- @socket.close rescue Object
266
+ @socket.close rescue nil
269
267
  @body.delete if @body.class == Tempfile
270
268
  @body = nil # signals that there was a problem
271
269
  end
@@ -399,6 +397,7 @@ module Mongrel
399
397
  @socket = socket
400
398
  @body = StringIO.new
401
399
  @status = 404
400
+ @reason = HTTP_STATUS_CODES[@status]
402
401
  @header = HeaderOut.new(StringIO.new)
403
402
  @header[Const::DATE] = Time.now.httpdate
404
403
  @body_sent = false
@@ -414,8 +413,9 @@ module Mongrel
414
413
  # by simple passing "finalize=true" to the start method. By default
415
414
  # all handlers run and then mongrel finalizes the request when they're
416
415
  # all done.
417
- def start(status=200, finalize=false)
416
+ def start(status=200, finalize=false, reason=HTTP_STATUS_CODES[status])
418
417
  @status = status.to_i
418
+ @reason = reason
419
419
  yield @header, @body
420
420
  finished if finalize
421
421
  end
@@ -437,8 +437,8 @@ module Mongrel
437
437
 
438
438
  def send_status(content_length=@body.length)
439
439
  if not @status_sent
440
- @header['Content-Length'] = content_length unless @status == 304
441
- write(Const::STATUS_FORMAT % [@status, HTTP_STATUS_CODES[@status]])
440
+ @header['Content-Length'] = content_length if content_length and @status != 304
441
+ write(Const::STATUS_FORMAT % [@status, @reason])
442
442
  @status_sent = true
443
443
  end
444
444
  end
@@ -482,7 +482,7 @@ module Mongrel
482
482
 
483
483
  def socket_error(details)
484
484
  # ignore these since it means the client closed off early
485
- @socket.close rescue Object
485
+ @socket.close rescue nil
486
486
  done = true
487
487
  raise details
488
488
  end
@@ -540,6 +540,7 @@ module Mongrel
540
540
  attr_reader :classifier
541
541
  attr_reader :host
542
542
  attr_reader :port
543
+ attr_reader :throttle
543
544
  attr_reader :timeout
544
545
  attr_reader :num_processors
545
546
 
@@ -553,18 +554,18 @@ module Mongrel
553
554
  # way to deal with overload. Other schemes involve still parsing the client's request
554
555
  # which defeats the point of an overload handling system.
555
556
  #
556
- # The timeout parameter is a sleep timeout (in hundredths of a second) that is placed between
557
+ # The throttle parameter is a sleep timeout (in hundredths of a second) that is placed between
557
558
  # socket.accept calls in order to give the server a cheap throttle time. It defaults to 0 and
558
559
  # actually if it is 0 then the sleep is not done at all.
559
- def initialize(host, port, num_processors=(2**30-1), timeout=0)
560
+ def initialize(host, port, num_processors=950, throttle=0, timeout=60)
560
561
  @socket = TCPServer.new(host, port)
561
562
  @classifier = URIClassifier.new
562
563
  @host = host
563
564
  @port = port
564
565
  @workers = ThreadGroup.new
565
- @timeout = timeout
566
+ @throttle = throttle
566
567
  @num_processors = num_processors
567
- @death_time = 60
568
+ @timeout = timeout
568
569
  end
569
570
 
570
571
  # Does the majority of the IO processing. It has been written in Ruby using
@@ -591,7 +592,7 @@ module Mongrel
591
592
  if not params[Const::REQUEST_PATH]
592
593
  # it might be a dumbass full host request header
593
594
  uri = URI.parse(params[Const::REQUEST_URI])
594
- params[Const::REQUEST_PATH] = uri.request_uri
595
+ params[Const::REQUEST_PATH] = uri.path
595
596
  end
596
597
 
597
598
  raise "No REQUEST PATH" if not params[Const::REQUEST_PATH]
@@ -601,7 +602,14 @@ module Mongrel
601
602
  if handlers
602
603
  params[Const::PATH_INFO] = path_info
603
604
  params[Const::SCRIPT_NAME] = script_name
604
- params[Const::REMOTE_ADDR] = params[Const::HTTP_X_FORWARDED_FOR] || client.peeraddr.last
605
+
606
+ # From http://www.ietf.org/rfc/rfc3875 :
607
+ # "Script authors should be aware that the REMOTE_ADDR and REMOTE_HOST
608
+ # meta-variables (see sections 4.1.8 and 4.1.9) may not identify the
609
+ # ultimate source of the request. They identify the client for the
610
+ # immediate request to the server; that client may be a proxy, gateway,
611
+ # or other intermediary acting on behalf of the actual source client."
612
+ params[Const::REMOTE_ADDR] = client.peeraddr.last
605
613
 
606
614
  # select handlers that want more detailed request notification
607
615
  notifiers = handlers.select { |h| h.request_notify }
@@ -641,19 +649,24 @@ module Mongrel
641
649
  end
642
650
  end
643
651
  rescue EOFError,Errno::ECONNRESET,Errno::EPIPE,Errno::EINVAL,Errno::EBADF
644
- client.close rescue Object
645
- rescue HttpParserError
646
- if $mongrel_debug_client
647
- STDERR.puts "#{Time.now}: BAD CLIENT (#{params[Const::HTTP_X_FORWARDED_FOR] || client.peeraddr.last}): #$!"
648
- STDERR.puts "#{Time.now}: REQUEST DATA: #{data.inspect}\n---\nPARAMS: #{params.inspect}\n---\n"
649
- end
652
+ client.close rescue nil
653
+ rescue HttpParserError => e
654
+ STDERR.puts "#{Time.now}: HTTP parse error, malformed request (#{params[Const::HTTP_X_FORWARDED_FOR] || client.peeraddr.last}): #{e.inspect}"
655
+ STDERR.puts "#{Time.now}: REQUEST DATA: #{data.inspect}\n---\nPARAMS: #{params.inspect}\n---\n"
650
656
  rescue Errno::EMFILE
651
657
  reap_dead_workers('too many files')
652
- rescue Object
653
- STDERR.puts "#{Time.now}: ERROR: #$!"
654
- STDERR.puts $!.backtrace.join("\n") if $mongrel_debug_client
658
+ rescue Object => e
659
+ STDERR.puts "#{Time.now}: Read error: #{e.inspect}"
660
+ STDERR.puts e.backtrace.join("\n")
655
661
  ensure
656
- client.close rescue Object
662
+ begin
663
+ client.close
664
+ rescue IOError
665
+ # Already closed
666
+ rescue Object => e
667
+ STDERR.puts "#{Time.now}: Client error: #{e.inspect}"
668
+ STDERR.puts e.backtrace.join("\n")
669
+ end
657
670
  request.body.delete if request and request.body.class == Tempfile
658
671
  end
659
672
  end
@@ -670,7 +683,7 @@ module Mongrel
670
683
  @workers.list.each do |w|
671
684
  w[:started_on] = Time.now if not w[:started_on]
672
685
 
673
- if mark - w[:started_on] > @death_time + @timeout
686
+ if mark - w[:started_on] > @timeout + @throttle
674
687
  STDERR.puts "Thread #{w.inspect} is too old, killing."
675
688
  w.raise(TimeoutError.new(error_msg))
676
689
  end
@@ -681,13 +694,13 @@ module Mongrel
681
694
  end
682
695
 
683
696
  # Performs a wait on all the currently running threads and kills any that take
684
- # too long. Right now it just waits 60 seconds, but will expand this to
685
- # allow setting. The @timeout setting does extend this waiting period by
697
+ # too long. It waits by @timeout seconds, which can be set in .initialize or
698
+ # via mongrel_rails. The @throttle setting does extend this waiting period by
686
699
  # that much longer.
687
700
  def graceful_shutdown
688
701
  while reap_dead_workers("shutdown") > 0
689
- STDERR.print "Waiting for #{@workers.list.length} requests to finish, could take #{@death_time + @timeout} seconds."
690
- sleep @death_time / 10
702
+ STDERR.print "Waiting for #{@workers.list.length} requests to finish, could take #{@timeout + @throttle} seconds."
703
+ sleep @timeout / 10
691
704
  end
692
705
  end
693
706
 
@@ -697,6 +710,8 @@ module Mongrel
697
710
  # 9 is currently TCP_DEFER_ACCEPT
698
711
  $tcp_defer_accept_opts = [Socket::SOL_TCP, 9, 1]
699
712
  $tcp_cork_opts = [Socket::SOL_TCP, 3, 1]
713
+ when /freebsd(([1-4]\..{1,2})|5\.[0-4])/
714
+ # Do nothing, just closing a bug when freebsd <= 5.4
700
715
  when /freebsd/
701
716
  # Use the HTTP accept filter if available.
702
717
  # The struct made by pack() is defined in /usr/include/sys/socket.h as accept_filter_arg
@@ -713,7 +728,7 @@ module Mongrel
713
728
 
714
729
  configure_socket_options
715
730
 
716
- if $tcp_defer_accept_opts
731
+ if defined?($tcp_defer_accept_opts) and $tcp_defer_accept_opts
717
732
  @socket.setsockopt(*$tcp_defer_accept_opts) rescue nil
718
733
  end
719
734
 
@@ -722,7 +737,7 @@ module Mongrel
722
737
  begin
723
738
  client = @socket.accept
724
739
 
725
- if $tcp_cork_opts
740
+ if defined?($tcp_cork_opts) and $tcp_cork_opts
726
741
  client.setsockopt(*$tcp_cork_opts) rescue nil
727
742
  end
728
743
 
@@ -730,27 +745,27 @@ module Mongrel
730
745
 
731
746
  if worker_list.length >= @num_processors
732
747
  STDERR.puts "Server overloaded with #{worker_list.length} processors (#@num_processors max). Dropping connection."
733
- client.close rescue Object
748
+ client.close rescue nil
734
749
  reap_dead_workers("max processors")
735
750
  else
736
751
  thread = Thread.new(client) {|c| process_client(c) }
737
752
  thread[:started_on] = Time.now
738
753
  @workers.add(thread)
739
754
 
740
- sleep @timeout/100 if @timeout > 0
755
+ sleep @throttle/100.0 if @throttle > 0
741
756
  end
742
757
  rescue StopServer
743
- @socket.close rescue Object
758
+ @socket.close
744
759
  break
745
760
  rescue Errno::EMFILE
746
761
  reap_dead_workers("too many open files")
747
762
  sleep 0.5
748
763
  rescue Errno::ECONNABORTED
749
764
  # client closed the socket even before accept
750
- client.close rescue Object
751
- rescue Object => exc
752
- STDERR.puts "!!!!!! UNHANDLED EXCEPTION! #{exc}. TELL ZED HE'S A MORON."
753
- STDERR.puts $!.backtrace.join("\n") if $mongrel_debug_client
765
+ client.close rescue nil
766
+ rescue Object => e
767
+ STDERR.puts "#{Time.now}: Unhandled listen loop exception #{e.inspect}."
768
+ STDERR.puts e.backtrace.join("\n")
754
769
  end
755
770
  end
756
771
  graceful_shutdown
@@ -794,12 +809,12 @@ module Mongrel
794
809
 
795
810
  # Stops the acceptor thread and then causes the worker threads to finish
796
811
  # off the request queue before finally exiting.
797
- def stop
798
- stopper = Thread.new do
799
- exc = StopServer.new
800
- @acceptor.raise(exc)
812
+ def stop(synchronous=false)
813
+ @acceptor.raise(StopServer.new)
814
+
815
+ if synchronous
816
+ sleep(0.5) while @acceptor.alive?
801
817
  end
802
- stopper.priority = 10
803
818
  end
804
819
 
805
820
  end
@@ -109,10 +109,10 @@ module Mongrel
109
109
  end
110
110
 
111
111
  @head.delete('cookie')
112
-
113
- # @output_cookies seems to never be used, but we'll process it just in case
114
- @output_cookies.each {|c| to['Set-Cookie'] = c.to_s } if @output_cookies
115
112
  end
113
+
114
+ # @output_cookies seems to never be used, but we'll process it just in case
115
+ @output_cookies.each {|c| to['Set-Cookie'] = c.to_s } if @output_cookies
116
116
  end
117
117
 
118
118
  # The dumb thing is people can call header or this or both and in any order.
@@ -179,7 +179,7 @@ module Mongrel
179
179
  print_command_list
180
180
  return true
181
181
  elsif cmd_name == "--version"
182
- STDERR.puts "Mongrel Web Server #{Mongrel::Const::MONGREL_VERSION}"
182
+ puts "Mongrel Web Server #{Mongrel::Const::MONGREL_VERSION}"
183
183
  return true
184
184
  end
185
185
 
@@ -1,7 +1,6 @@
1
1
  require 'yaml'
2
2
  require 'etc'
3
3
 
4
-
5
4
  module Mongrel
6
5
  # Implements a simple DSL for configuring a Mongrel server for your
7
6
  # purposes. More used by framework implementers to setup Mongrel
@@ -39,7 +38,7 @@ module Mongrel
39
38
  attr_reader :needs_restart
40
39
 
41
40
  # You pass in initial defaults and then a block to continue configuring.
42
- def initialize(defaults={}, &blk)
41
+ def initialize(defaults={}, &block)
43
42
  @listener = nil
44
43
  @listener_name = nil
45
44
  @listeners = {}
@@ -47,25 +46,31 @@ module Mongrel
47
46
  @needs_restart = false
48
47
  @pid_file = defaults[:pid_file]
49
48
 
50
- if blk
51
- cloaker(&blk).bind(self).call
49
+ if block
50
+ cloaker(&block).bind(self).call
52
51
  end
53
52
  end
54
53
 
55
- # Change privilege of the process to specified user and group.
54
+ # Change privileges of the process to specified user and group.
56
55
  def change_privilege(user, group)
57
56
  begin
58
- if group
59
- log "Changing group to #{group}."
60
- Process::GID.change_privilege(Etc.getgrnam(group).gid)
61
- end
62
-
63
- if user
64
- log "Changing user to #{user}."
65
- Process::UID.change_privilege(Etc.getpwnam(user).uid)
57
+ uid, gid = Process.euid, Process.egid
58
+ target_uid = Etc.getpwnam(user).uid if user
59
+ target_gid = Etc.getgrnam(group).gid if group
60
+
61
+ if uid != target_uid or gid != target_gid
62
+ log "Initiating groups for #{user.inspect}:#{group.inspect}."
63
+ Process.initgroups(user, target_id)
64
+
65
+ log "Changing group to #{group.inspect}."
66
+ Process::GID.change_privilege(target_gid)
67
+
68
+ log "Changing user to #{user.inspect}."
69
+ Process::UID.change_privilege(target_uid)
66
70
  end
67
- rescue Errno::EPERM
68
- log "FAILED to change user:group #{user}:#{group}: #$!"
71
+ rescue Errno::EPERM => e
72
+ log "Couldn't change user and group to #{user.inspect}:#{group.inspect}: #{e.to_s}."
73
+ log "Mongrel failed to start."
69
74
  exit 1
70
75
  end
71
76
  end
@@ -74,15 +79,19 @@ module Mongrel
74
79
  File.unlink(@pid_file) if @pid_file and File.exists?(@pid_file)
75
80
  end
76
81
 
77
- # Writes the PID file but only if we're on windows.
82
+ # Writes the PID file if we're not on Windows.
78
83
  def write_pid_file
79
84
  if RUBY_PLATFORM !~ /mswin/
80
85
  log "Writing PID file to #{@pid_file}"
81
86
  open(@pid_file,"w") {|f| f.write(Process.pid) }
87
+ open(@pid_file,"w") do |f|
88
+ f.write(Process.pid)
89
+ File.chmod(0644, @pid_file)
90
+ end
82
91
  end
83
92
  end
84
93
 
85
- # generates a class for cloaking the current self and making the DSL nicer
94
+ # Generates a class for cloaking the current self and making the DSL nicer.
86
95
  def cloaking_class
87
96
  class << self
88
97
  self
@@ -90,9 +99,9 @@ module Mongrel
90
99
  end
91
100
 
92
101
  # Do not call this. You were warned.
93
- def cloaker(&blk)
102
+ def cloaker(&block)
94
103
  cloaking_class.class_eval do
95
- define_method :cloaker_, &blk
104
+ define_method :cloaker_, &block
96
105
  meth = instance_method( :cloaker_ )
97
106
  remove_method :cloaker_
98
107
  meth
@@ -114,18 +123,20 @@ module Mongrel
114
123
  #
115
124
  # * :host => Host name to bind.
116
125
  # * :port => Port to bind.
117
- # * :num_processors => The maximum number of concurrent threads allowed. (950 default)
118
- # * :timeout => 1/100th of a second timeout between requests. (10 is 1/10th, 0 is timeout)
126
+ # * :num_processors => The maximum number of concurrent threads allowed.
127
+ # * :throttle => Time to pause (in hundredths of a second) between accepting clients.
128
+ # * :timeout => Time to wait (in seconds) before killing a stalled thread.
119
129
  # * :user => User to change to, must have :group as well.
120
130
  # * :group => Group to change to, must have :user as well.
121
131
  #
122
- def listener(options={},&blk)
132
+ def listener(options={},&block)
123
133
  raise "Cannot call listener inside another listener block." if (@listener or @listener_name)
124
134
  ops = resolve_defaults(options)
125
135
  ops[:num_processors] ||= 950
126
- ops[:timeout] ||= 0
136
+ ops[:throttle] ||= 0
137
+ ops[:timeout] ||= 60
127
138
 
128
- @listener = Mongrel::HttpServer.new(ops[:host], ops[:port].to_i, ops[:num_processors].to_i, ops[:timeout].to_i)
139
+ @listener = Mongrel::HttpServer.new(ops[:host], ops[:port].to_i, ops[:num_processors].to_i, ops[:throttle].to_i, ops[:timeout].to_i)
129
140
  @listener_name = "#{ops[:host]}:#{ops[:port]}"
130
141
  @listeners[@listener_name] = @listener
131
142
 
@@ -134,8 +145,8 @@ module Mongrel
134
145
  end
135
146
 
136
147
  # Does the actual cloaking operation to give the new implicit self.
137
- if blk
138
- cloaker(&blk).bind(self).call
148
+ if block
149
+ cloaker(&block).bind(self).call
139
150
  end
140
151
 
141
152
  # all done processing this listener setup, reset implicit variables
@@ -277,11 +288,10 @@ module Mongrel
277
288
  # Calls .stop on all the configured listeners so they
278
289
  # stop processing requests (gracefully). By default it
279
290
  # assumes that you don't want to restart.
280
- def stop(needs_restart=false)
281
- @listeners.each {|name,s|
282
- s.stop
283
- }
284
-
291
+ def stop(needs_restart=false, synchronous=false)
292
+ @listeners.each do |name,s|
293
+ s.stop(synchronous)
294
+ end
285
295
  @needs_restart = needs_restart
286
296
  end
287
297