mongrel 0.3.12.4 → 0.3.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/Rakefile +44 -33
- data/bin/mongrel_rails +67 -34
- data/doc/rdoc/classes/IO.html +10 -10
- data/doc/rdoc/classes/IO.src/{M000005.html → M000001.html} +5 -5
- data/doc/rdoc/classes/IO.src/{M000006.html → M000002.html} +5 -5
- data/doc/rdoc/classes/Kernel.html +10 -10
- data/doc/rdoc/classes/Kernel.src/{M000025.html → M000020.html} +5 -5
- data/doc/rdoc/classes/Kernel.src/M000021.html +23 -0
- data/doc/rdoc/classes/Mongrel.html +25 -4
- data/doc/rdoc/classes/Mongrel/CGIWrapper.html +383 -0
- data/doc/rdoc/classes/Mongrel/CGIWrapper.src/M000096.html +11 -5
- data/doc/rdoc/classes/Mongrel/CGIWrapper.src/M000097.html +34 -5
- data/doc/rdoc/classes/Mongrel/CGIWrapper.src/M000098.html +21 -6
- data/doc/rdoc/classes/Mongrel/CGIWrapper.src/{M000093.html → M000099.html} +13 -13
- data/doc/rdoc/classes/Mongrel/CGIWrapper.src/{M000094.html → M000100.html} +11 -11
- data/doc/rdoc/classes/Mongrel/CGIWrapper.src/{M000095.html → M000101.html} +4 -4
- data/doc/rdoc/classes/Mongrel/CGIWrapper.src/M000102.html +18 -0
- data/doc/rdoc/classes/Mongrel/{URIClassifier.src/M000084.html → CGIWrapper.src/M000103.html} +5 -5
- data/doc/rdoc/classes/Mongrel/CGIWrapper.src/M000104.html +19 -0
- data/doc/rdoc/classes/Mongrel/Camping.html +5 -5
- data/doc/rdoc/classes/Mongrel/Camping.src/M000046.html +22 -0
- data/doc/rdoc/classes/Mongrel/Camping/CampingHandler.html +10 -10
- data/doc/rdoc/classes/Mongrel/Camping/CampingHandler.src/{M000049.html → M000047.html} +4 -4
- data/doc/rdoc/classes/Mongrel/Camping/CampingHandler.src/M000048.html +51 -0
- data/doc/rdoc/classes/Mongrel/Command.html +13 -0
- data/doc/rdoc/classes/Mongrel/Command/Base.html +95 -50
- data/doc/rdoc/classes/Mongrel/Command/Base.src/M000024.html +24 -0
- data/doc/rdoc/classes/Mongrel/Command/Base.src/M000025.html +42 -0
- data/doc/rdoc/classes/Mongrel/Command/Base.src/M000026.html +18 -0
- data/doc/rdoc/classes/Mongrel/Command/Base.src/M000027.html +18 -0
- data/doc/rdoc/classes/Mongrel/Command/Base.src/M000028.html +18 -0
- data/doc/rdoc/classes/Mongrel/Command/Base.src/M000029.html +5 -11
- data/doc/rdoc/classes/Mongrel/Command/Base.src/M000030.html +9 -28
- data/doc/rdoc/classes/Mongrel/Command/Base.src/M000031.html +5 -5
- data/doc/rdoc/classes/Mongrel/Command/Base.src/M000032.html +5 -5
- data/doc/rdoc/classes/Mongrel/Command/Base.src/M000033.html +5 -5
- data/doc/rdoc/classes/Mongrel/Command/Base.src/M000034.html +11 -9
- data/doc/rdoc/classes/Mongrel/Command/Base.src/M000035.html +11 -5
- data/doc/rdoc/classes/Mongrel/Command/Base.src/M000036.html +5 -5
- data/doc/rdoc/classes/Mongrel/Command/Registry.html +15 -15
- data/doc/rdoc/classes/Mongrel/Command/Registry.src/M000037.html +20 -0
- data/doc/rdoc/classes/Mongrel/Command/Registry.src/{M000040.html → M000038.html} +11 -11
- data/doc/rdoc/classes/Mongrel/Command/Registry.src/M000039.html +37 -7
- data/doc/rdoc/classes/Mongrel/Configurator.html +651 -0
- data/doc/rdoc/classes/Mongrel/Configurator.src/M000105.html +16 -20
- data/doc/rdoc/classes/Mongrel/Configurator.src/M000106.html +18 -5
- data/doc/rdoc/classes/Mongrel/Configurator.src/M000107.html +7 -11
- data/doc/rdoc/classes/Mongrel/Configurator.src/M000108.html +7 -6
- data/doc/rdoc/classes/Mongrel/Configurator.src/M000109.html +10 -9
- data/doc/rdoc/classes/Mongrel/Configurator.src/M000110.html +5 -8
- data/doc/rdoc/classes/Mongrel/Configurator.src/M000111.html +21 -5
- data/doc/rdoc/classes/Mongrel/Configurator.src/M000112.html +6 -15
- data/doc/rdoc/classes/Mongrel/Configurator.src/M000113.html +17 -5
- data/doc/rdoc/classes/Mongrel/Configurator.src/M000114.html +20 -33
- data/doc/rdoc/classes/Mongrel/Configurator.src/M000115.html +5 -5
- data/doc/rdoc/classes/Mongrel/Configurator.src/M000116.html +24 -0
- data/doc/rdoc/classes/Mongrel/Configurator.src/M000117.html +19 -0
- data/doc/rdoc/classes/Mongrel/Configurator.src/M000118.html +22 -0
- data/doc/rdoc/classes/Mongrel/Configurator.src/M000119.html +25 -0
- data/doc/rdoc/classes/Mongrel/Configurator.src/M000120.html +18 -0
- data/doc/rdoc/classes/Mongrel/Configurator.src/M000121.html +35 -0
- data/doc/rdoc/classes/Mongrel/Configurator.src/M000122.html +18 -0
- data/doc/rdoc/classes/Mongrel/Configurator.src/M000123.html +33 -0
- data/doc/rdoc/classes/Mongrel/Configurator.src/M000124.html +18 -0
- data/doc/rdoc/classes/Mongrel/Const.html +39 -7
- data/doc/rdoc/classes/Mongrel/DeflateFilter.html +181 -0
- data/doc/rdoc/classes/Mongrel/DeflateFilter.src/M000094.html +19 -0
- data/doc/rdoc/classes/Mongrel/DeflateFilter.src/M000095.html +28 -0
- data/doc/rdoc/classes/Mongrel/DirHandler.html +48 -33
- data/doc/rdoc/classes/Mongrel/DirHandler.src/M000056.html +21 -0
- data/doc/rdoc/classes/Mongrel/DirHandler.src/M000057.html +43 -0
- data/doc/rdoc/classes/Mongrel/DirHandler.src/M000058.html +29 -7
- data/doc/rdoc/classes/Mongrel/DirHandler.src/M000059.html +50 -29
- data/doc/rdoc/classes/Mongrel/DirHandler.src/M000060.html +26 -27
- data/doc/rdoc/classes/Mongrel/DirHandler.src/M000061.html +5 -38
- data/doc/rdoc/classes/Mongrel/Error404Handler.html +171 -0
- data/doc/rdoc/classes/Mongrel/Error404Handler.src/{M000116.html → M000125.html} +4 -4
- data/doc/rdoc/classes/Mongrel/Error404Handler.src/{M000117.html → M000126.html} +4 -4
- data/doc/rdoc/classes/Mongrel/HeaderOut.html +185 -0
- data/doc/rdoc/classes/Mongrel/HeaderOut.src/{M000072.html → M000069.html} +4 -4
- data/doc/rdoc/classes/Mongrel/HeaderOut.src/{M000073.html → M000070.html} +4 -4
- data/doc/rdoc/classes/Mongrel/HttpHandler.html +170 -0
- data/doc/rdoc/classes/Mongrel/HttpHandler.src/{M000074.html → M000075.html} +3 -3
- data/doc/rdoc/classes/Mongrel/HttpHandlerPlugin.html +20 -10
- data/doc/rdoc/classes/Mongrel/HttpHandlerPlugin.src/{M000027.html → M000022.html} +5 -4
- data/doc/rdoc/classes/Mongrel/HttpHandlerPlugin.src/{M000028.html → M000023.html} +3 -3
- data/doc/rdoc/classes/Mongrel/HttpParser.html +41 -36
- data/doc/rdoc/classes/Mongrel/HttpParser.src/{M000056.html → M000049.html} +6 -5
- data/doc/rdoc/classes/Mongrel/HttpParser.src/{M000057.html → M000050.html} +7 -6
- data/doc/rdoc/classes/Mongrel/HttpParser.src/M000051.html +7 -6
- data/doc/rdoc/classes/Mongrel/HttpParser.src/M000052.html +37 -7
- data/doc/rdoc/classes/Mongrel/HttpParser.src/M000053.html +5 -7
- data/doc/rdoc/classes/Mongrel/HttpParser.src/M000054.html +6 -22
- data/doc/rdoc/classes/Mongrel/HttpParser.src/M000055.html +6 -5
- data/doc/rdoc/classes/Mongrel/HttpRequest.html +239 -0
- data/doc/rdoc/classes/Mongrel/HttpRequest.src/M000130.html +52 -0
- data/doc/rdoc/classes/Mongrel/HttpRequest.src/{M000119.html → M000131.html} +6 -6
- data/doc/rdoc/classes/Mongrel/HttpRequest.src/{M000120.html → M000132.html} +6 -6
- data/doc/rdoc/classes/Mongrel/HttpRequest.src/{M000121.html → M000133.html} +18 -18
- data/doc/rdoc/classes/Mongrel/HttpResponse.html +439 -0
- data/doc/rdoc/classes/Mongrel/HttpResponse.src/M000076.html +12 -7
- data/doc/rdoc/classes/Mongrel/HttpResponse.src/M000077.html +7 -12
- data/doc/rdoc/classes/Mongrel/HttpResponse.src/M000078.html +12 -9
- data/doc/rdoc/classes/Mongrel/HttpResponse.src/M000079.html +9 -9
- data/doc/rdoc/classes/Mongrel/HttpResponse.src/M000080.html +9 -10
- data/doc/rdoc/classes/Mongrel/HttpResponse.src/M000081.html +9 -5
- data/doc/rdoc/classes/Mongrel/HttpResponse.src/M000082.html +18 -7
- data/doc/rdoc/classes/Mongrel/HttpResponse.src/M000083.html +8 -5
- data/doc/rdoc/classes/Mongrel/HttpResponse.src/M000084.html +20 -0
- data/doc/rdoc/classes/Mongrel/{HttpServer.src/M000069.html → HttpResponse.src/M000085.html} +7 -5
- data/doc/rdoc/classes/Mongrel/HttpResponse.src/M000086.html +20 -0
- data/doc/rdoc/classes/Mongrel/{Configurator.src/M000101.html → HttpResponse.src/M000087.html} +5 -5
- data/doc/rdoc/classes/Mongrel/HttpServer.html +68 -59
- data/doc/rdoc/classes/Mongrel/HttpServer.src/M000062.html +25 -0
- data/doc/rdoc/classes/Mongrel/HttpServer.src/M000063.html +83 -0
- data/doc/rdoc/classes/Mongrel/HttpServer.src/M000064.html +13 -11
- data/doc/rdoc/classes/Mongrel/HttpServer.src/M000065.html +50 -53
- data/doc/rdoc/classes/Mongrel/HttpServer.src/M000066.html +21 -11
- data/doc/rdoc/classes/Mongrel/HttpServer.src/M000067.html +5 -47
- data/doc/rdoc/classes/Mongrel/HttpServer.src/M000068.html +9 -15
- data/doc/rdoc/classes/Mongrel/Rails/RailsConfigurator.html +16 -16
- data/doc/rdoc/classes/Mongrel/Rails/RailsConfigurator.src/M000040.html +39 -0
- data/doc/rdoc/classes/Mongrel/Rails/RailsConfigurator.src/{M000043.html → M000041.html} +11 -11
- data/doc/rdoc/classes/Mongrel/Rails/RailsConfigurator.src/M000042.html +13 -22
- data/doc/rdoc/classes/Mongrel/Rails/RailsHandler.html +17 -17
- data/doc/rdoc/classes/Mongrel/Rails/RailsHandler.src/M000043.html +22 -0
- data/doc/rdoc/classes/Mongrel/Rails/RailsHandler.src/M000044.html +51 -0
- data/doc/rdoc/classes/Mongrel/Rails/RailsHandler.src/M000045.html +10 -9
- data/doc/rdoc/classes/Mongrel/StatisticsFilter.html +211 -0
- data/doc/rdoc/classes/Mongrel/StatisticsFilter.src/M000127.html +24 -0
- data/doc/rdoc/classes/Mongrel/StatisticsFilter.src/M000128.html +24 -0
- data/doc/rdoc/classes/Mongrel/StatisticsFilter.src/M000129.html +18 -0
- data/doc/rdoc/classes/{Class.html → Mongrel/StatusHandler.html} +42 -45
- data/doc/rdoc/classes/Mongrel/StatusHandler.src/M000071.html +18 -0
- data/doc/rdoc/classes/Mongrel/StatusHandler.src/M000072.html +24 -0
- data/doc/rdoc/classes/Mongrel/StatusHandler.src/M000073.html +42 -0
- data/doc/rdoc/classes/Mongrel/StatusHandler.src/M000074.html +20 -0
- data/doc/rdoc/classes/Mongrel/StopServer.html +117 -0
- data/doc/rdoc/classes/Mongrel/URIClassifier.html +314 -0
- data/doc/rdoc/classes/Mongrel/URIClassifier.src/M000088.html +5 -23
- data/doc/rdoc/classes/Mongrel/URIClassifier.src/M000089.html +5 -70
- data/doc/rdoc/classes/Mongrel/URIClassifier.src/{M000086.html → M000090.html} +0 -0
- data/doc/rdoc/classes/Mongrel/URIClassifier.src/{M000087.html → M000091.html} +0 -0
- data/doc/rdoc/classes/Mongrel/URIClassifier.src/M000092.html +36 -0
- data/doc/rdoc/classes/Mongrel/URIClassifier.src/M000093.html +83 -0
- data/doc/rdoc/classes/MongrelDbg.html +25 -25
- data/doc/rdoc/classes/MongrelDbg.src/{M000020.html → M000015.html} +5 -5
- data/doc/rdoc/classes/MongrelDbg.src/{M000021.html → M000016.html} +6 -6
- data/doc/rdoc/classes/MongrelDbg.src/{M000022.html → M000017.html} +8 -8
- data/doc/rdoc/classes/MongrelDbg.src/{M000023.html → M000018.html} +7 -7
- data/doc/rdoc/classes/MongrelDbg.src/{M000024.html → M000019.html} +4 -4
- data/doc/rdoc/classes/ObjectTracker.html +10 -40
- data/doc/rdoc/classes/ObjectTracker.src/M000013.html +27 -0
- data/doc/rdoc/classes/ObjectTracker.src/M000014.html +44 -0
- data/doc/rdoc/classes/RequestLog.html +115 -0
- data/doc/rdoc/classes/RequestLog/Access.html +151 -0
- data/doc/rdoc/classes/RequestLog/Access.src/{M000122.html → M000134.html} +5 -5
- data/doc/rdoc/classes/RequestLog/Files.html +144 -0
- data/doc/rdoc/classes/RequestLog/Files.src/{M000123.html → M000135.html} +5 -5
- data/doc/rdoc/classes/RequestLog/Objects.html +144 -0
- data/doc/rdoc/classes/RequestLog/Objects.src/{M000124.html → M000137.html} +5 -5
- data/doc/rdoc/classes/RequestLog/Params.html +144 -0
- data/doc/rdoc/classes/RequestLog/Params.src/{M000125.html → M000138.html} +5 -5
- data/doc/rdoc/classes/RequestLog/Threads.html +144 -0
- data/doc/rdoc/classes/RequestLog/Threads.src/M000136.html +34 -0
- data/doc/rdoc/classes/Stats.html +54 -36
- data/doc/rdoc/classes/Stats.src/{M000013.html → M000005.html} +6 -5
- data/doc/rdoc/classes/Stats.src/M000006.html +23 -0
- data/doc/rdoc/classes/Stats.src/M000007.html +26 -0
- data/doc/rdoc/classes/Stats.src/M000008.html +18 -0
- data/doc/rdoc/classes/Stats.src/M000009.html +5 -6
- data/doc/rdoc/classes/Stats.src/M000010.html +5 -10
- data/doc/rdoc/classes/Stats.src/M000011.html +10 -13
- data/doc/rdoc/classes/Stats.src/M000012.html +7 -5
- data/doc/rdoc/classes/TCPServer.html +9 -9
- data/doc/rdoc/classes/TCPServer.src/M000003.html +19 -0
- data/doc/rdoc/created.rid +1 -1
- data/doc/rdoc/files/COPYING.html +1 -1
- data/doc/rdoc/files/LICENSE.html +1 -1
- data/doc/rdoc/files/README.html +1 -1
- data/doc/rdoc/files/ext/http11/http11_c.html +1 -1
- data/doc/rdoc/files/lib/mongrel/camping_rb.html +28 -1
- data/doc/rdoc/files/lib/mongrel/cgi_rb.html +28 -1
- data/doc/rdoc/files/lib/mongrel/command_rb.html +28 -1
- data/doc/rdoc/files/lib/mongrel/debug_rb.html +28 -1
- data/doc/rdoc/files/lib/mongrel/handlers_rb.html +3 -3
- data/doc/rdoc/files/lib/mongrel/init_rb.html +28 -1
- data/doc/rdoc/files/lib/mongrel/rails_rb.html +28 -1
- data/doc/rdoc/files/lib/mongrel/stats_rb.html +21 -10
- data/doc/rdoc/files/lib/mongrel/tcphack_rb.html +23 -4
- data/doc/rdoc/files/lib/mongrel_rb.html +33 -1
- data/doc/rdoc/fr_class_index.html +65 -0
- data/doc/rdoc/fr_file_index.html +40 -0
- data/doc/rdoc/fr_method_index.html +164 -0
- data/doc/rdoc/index.html +24 -0
- data/examples/camping/blog.rb +1 -1
- data/examples/camping/tepee.rb +4 -3
- data/examples/simpletest.rb +15 -14
- data/ext/http11/http11.c +52 -18
- data/ext/http11/http11_parser.c +194 -177
- data/ext/http11/http11_parser.h +23 -5
- data/lib/mongrel.rb +295 -134
- data/lib/mongrel/camping.rb +48 -6
- data/lib/mongrel/cgi.rb +20 -2
- data/lib/mongrel/command.rb +76 -27
- data/lib/mongrel/debug.rb +42 -13
- data/lib/mongrel/handlers.rb +218 -59
- data/lib/mongrel/init.rb +18 -0
- data/lib/mongrel/rails.rb +61 -44
- data/lib/mongrel/stats.rb +30 -2
- data/lib/mongrel/tcphack.rb +18 -0
- data/setup.rb +799 -574
- data/test/mime.yaml +3 -0
- data/test/mongrel.conf +1 -0
- data/test/test_command.rb +101 -0
- data/test/test_conditional.rb +124 -0
- data/test/test_configurator.rb +56 -22
- data/test/test_debug.rb +18 -2
- data/test/test_handlers.rb +105 -0
- data/test/test_http11.rb +27 -9
- data/test/test_response.rb +38 -0
- data/test/test_stats.rb +21 -2
- data/test/test_uriclassifier.rb +18 -0
- data/test/test_ws.rb +105 -19
- data/test/testhelp.rb +36 -0
- data/tools/rakehelp.rb +52 -46
- data/tools/trickletest.rb +37 -0
- metadata +127 -76
- data/doc/rdoc/classes/Class.src/M000001.html +0 -24
- data/doc/rdoc/classes/Class.src/M000002.html +0 -62
- data/doc/rdoc/classes/Class.src/M000003.html +0 -21
- data/doc/rdoc/classes/Class.src/M000004.html +0 -20
- data/doc/rdoc/classes/Kernel.src/M000026.html +0 -25
- data/doc/rdoc/classes/Mongrel/CGIWrapper.src/M000090.html +0 -24
- data/doc/rdoc/classes/Mongrel/CGIWrapper.src/M000091.html +0 -47
- data/doc/rdoc/classes/Mongrel/CGIWrapper.src/M000092.html +0 -34
- data/doc/rdoc/classes/Mongrel/Camping.src/M000048.html +0 -22
- data/doc/rdoc/classes/Mongrel/Camping/CampingHandler.src/M000050.html +0 -27
- data/doc/rdoc/classes/Mongrel/Command/Base.src/M000037.html +0 -18
- data/doc/rdoc/classes/Mongrel/Command/Base.src/M000038.html +0 -18
- data/doc/rdoc/classes/Mongrel/Command/Registry.src/M000041.html +0 -46
- data/doc/rdoc/classes/Mongrel/Configurator.src/M000099.html +0 -24
- data/doc/rdoc/classes/Mongrel/Configurator.src/M000100.html +0 -23
- data/doc/rdoc/classes/Mongrel/Configurator.src/M000102.html +0 -32
- data/doc/rdoc/classes/Mongrel/Configurator.src/M000103.html +0 -19
- data/doc/rdoc/classes/Mongrel/Configurator.src/M000104.html +0 -31
- data/doc/rdoc/classes/Mongrel/DirHandler.src/M000062.html +0 -40
- data/doc/rdoc/classes/Mongrel/DirHandler.src/M000063.html +0 -18
- data/doc/rdoc/classes/Mongrel/HttpRequest.src/M000118.html +0 -28
- data/doc/rdoc/classes/Mongrel/HttpResponse.src/M000075.html +0 -26
- data/doc/rdoc/classes/Mongrel/HttpServer.src/M000070.html +0 -22
- data/doc/rdoc/classes/Mongrel/HttpServer.src/M000071.html +0 -18
- data/doc/rdoc/classes/Mongrel/Rails/RailsConfigurator.src/M000044.html +0 -32
- data/doc/rdoc/classes/Mongrel/Rails/RailsHandler.src/M000046.html +0 -48
- data/doc/rdoc/classes/Mongrel/Rails/RailsHandler.src/M000047.html +0 -23
- data/doc/rdoc/classes/Mongrel/URIClassifier.src/M000085.html +0 -18
- data/doc/rdoc/classes/ObjectTracker.src/M000016.html +0 -22
- data/doc/rdoc/classes/ObjectTracker.src/M000017.html +0 -18
- data/doc/rdoc/classes/ObjectTracker.src/M000018.html +0 -18
- data/doc/rdoc/classes/ObjectTracker.src/M000019.html +0 -44
- data/doc/rdoc/classes/Stats.src/M000014.html +0 -19
- data/doc/rdoc/classes/Stats.src/M000015.html +0 -20
- data/doc/rdoc/classes/TCPServer.src/M000007.html +0 -19
- data/lib/mongrel/#rails.rb# +0 -178
data/lib/mongrel/camping.rb
CHANGED
|
@@ -1,3 +1,21 @@
|
|
|
1
|
+
# Mongrel Web Server - A Mostly Ruby Webserver and Library
|
|
2
|
+
#
|
|
3
|
+
# Copyright (C) 2005 Zed A. Shaw zedshaw AT zedshaw dot com
|
|
4
|
+
#
|
|
5
|
+
# This library is free software; you can redistribute it and/or
|
|
6
|
+
# modify it under the terms of the GNU Lesser General Public
|
|
7
|
+
# License as published by the Free Software Foundation; either
|
|
8
|
+
# version 2.1 of the License, or (at your option) any later version.
|
|
9
|
+
#
|
|
10
|
+
# This library is distributed in the hope that it will be useful,
|
|
11
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
12
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
13
|
+
# Lesser General Public License for more details.
|
|
14
|
+
#
|
|
15
|
+
# You should have received a copy of the GNU Lesser General Public
|
|
16
|
+
# License along with this library; if not, write to the Free Software
|
|
17
|
+
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
18
|
+
|
|
1
19
|
require 'mongrel'
|
|
2
20
|
|
|
3
21
|
|
|
@@ -32,15 +50,39 @@ module Mongrel
|
|
|
32
50
|
end
|
|
33
51
|
|
|
34
52
|
def process(request, response)
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
response.
|
|
38
|
-
|
|
53
|
+
controller = @klass.run(request.body, request.params)
|
|
54
|
+
sendfile, clength = nil
|
|
55
|
+
response.status = controller.status
|
|
56
|
+
controller.headers.each do |k, v|
|
|
57
|
+
if k =~ /^X-SENDFILE$/i
|
|
58
|
+
sendfile = v
|
|
59
|
+
elsif k =~ /^CONTENT-LENGTH$/i
|
|
60
|
+
clength = v.to_i
|
|
61
|
+
else
|
|
39
62
|
[*v].each do |vi|
|
|
40
|
-
|
|
63
|
+
response.header[k] = vi
|
|
41
64
|
end
|
|
42
65
|
end
|
|
43
|
-
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
if sendfile
|
|
69
|
+
response.send_status(File.size(sendfile))
|
|
70
|
+
response.send_header
|
|
71
|
+
response.send_file(sendfile)
|
|
72
|
+
elsif controller.body.respond_to? :read
|
|
73
|
+
response.send_status(clength)
|
|
74
|
+
response.send_header
|
|
75
|
+
while chunk = controller.body.read(16384)
|
|
76
|
+
response.write(chunk)
|
|
77
|
+
end
|
|
78
|
+
if controller.body.respond_to? :close
|
|
79
|
+
controller.body.close
|
|
80
|
+
end
|
|
81
|
+
else
|
|
82
|
+
body = controller.body.to_s
|
|
83
|
+
response.send_status(body.length)
|
|
84
|
+
response.send_header
|
|
85
|
+
response.write(body)
|
|
44
86
|
end
|
|
45
87
|
end
|
|
46
88
|
end
|
data/lib/mongrel/cgi.rb
CHANGED
|
@@ -1,3 +1,21 @@
|
|
|
1
|
+
# Mongrel Web Server - A Mostly Ruby Webserver and Library
|
|
2
|
+
#
|
|
3
|
+
# Copyright (C) 2005 Zed A. Shaw zedshaw AT zedshaw dot com
|
|
4
|
+
#
|
|
5
|
+
# This library is free software; you can redistribute it and/or
|
|
6
|
+
# modify it under the terms of the GNU Lesser General Public
|
|
7
|
+
# License as published by the Free Software Foundation; either
|
|
8
|
+
# version 2.1 of the License, or (at your option) any later version.
|
|
9
|
+
#
|
|
10
|
+
# This library is distributed in the hope that it will be useful,
|
|
11
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
12
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
13
|
+
# Lesser General Public License for more details.
|
|
14
|
+
#
|
|
15
|
+
# You should have received a copy of the GNU Lesser General Public
|
|
16
|
+
# License along with this library; if not, write to the Free Software
|
|
17
|
+
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
18
|
+
|
|
1
19
|
require 'cgi'
|
|
2
20
|
|
|
3
21
|
module Mongrel
|
|
@@ -10,7 +28,7 @@ module Mongrel
|
|
|
10
28
|
# The CGIWrapper.handler attribute is normally not set and is available for
|
|
11
29
|
# frameworks that need to get back to the handler. Rails uses this to give
|
|
12
30
|
# people access to the RailsHandler#files (DirHandler really) so they can
|
|
13
|
-
# look-up paths and do other things
|
|
31
|
+
# look-up paths and do other things with the files managed there.
|
|
14
32
|
#
|
|
15
33
|
# In Rails you can get the real file for a request with:
|
|
16
34
|
#
|
|
@@ -35,7 +53,7 @@ module Mongrel
|
|
|
35
53
|
@request = request
|
|
36
54
|
@response = response
|
|
37
55
|
@args = *args
|
|
38
|
-
@input =
|
|
56
|
+
@input = request.body
|
|
39
57
|
@head = {}
|
|
40
58
|
@out_called = false
|
|
41
59
|
super(*args)
|
data/lib/mongrel/command.rb
CHANGED
|
@@ -1,3 +1,21 @@
|
|
|
1
|
+
# Mongrel Web Server - A Mostly Ruby Webserver and Library
|
|
2
|
+
#
|
|
3
|
+
# Copyright (C) 2005 Zed A. Shaw zedshaw AT zedshaw dot com
|
|
4
|
+
#
|
|
5
|
+
# This library is free software; you can redistribute it and/or
|
|
6
|
+
# modify it under the terms of the GNU Lesser General Public
|
|
7
|
+
# License as published by the Free Software Foundation; either
|
|
8
|
+
# version 2.1 of the License, or (at your option) any later version.
|
|
9
|
+
#
|
|
10
|
+
# This library is distributed in the hope that it will be useful,
|
|
11
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
12
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
13
|
+
# Lesser General Public License for more details.
|
|
14
|
+
#
|
|
15
|
+
# You should have received a copy of the GNU Lesser General Public
|
|
16
|
+
# License along with this library; if not, write to the Free Software
|
|
17
|
+
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
18
|
+
|
|
1
19
|
require 'rubygems'
|
|
2
20
|
require 'singleton'
|
|
3
21
|
require 'optparse'
|
|
@@ -10,11 +28,13 @@ module Mongrel
|
|
|
10
28
|
|
|
11
29
|
module Command
|
|
12
30
|
|
|
31
|
+
BANNER = "Usage: mongrel_rails <command> [options]"
|
|
32
|
+
|
|
13
33
|
# A Command pattern implementation used to create the set of command available to the user
|
|
14
34
|
# from Mongrel. The script uses objects which implement this interface to do the
|
|
15
35
|
# user's bidding.
|
|
16
36
|
module Base
|
|
17
|
-
|
|
37
|
+
|
|
18
38
|
attr_reader :valid, :done_validating, :original_args
|
|
19
39
|
|
|
20
40
|
# Called by the implemented command to set the options for that command.
|
|
@@ -35,6 +55,7 @@ module Mongrel
|
|
|
35
55
|
def initialize(options={})
|
|
36
56
|
argv = options[:argv] || []
|
|
37
57
|
@opt = OptionParser.new
|
|
58
|
+
@opt.banner = Mongrel::Command::BANNER
|
|
38
59
|
@valid = true
|
|
39
60
|
# this is retarded, but it has to be done this way because -h and -v exit
|
|
40
61
|
@done_validating = false
|
|
@@ -47,35 +68,39 @@ module Mongrel
|
|
|
47
68
|
@done_validating = true
|
|
48
69
|
puts @opt
|
|
49
70
|
end
|
|
50
|
-
|
|
51
|
-
# I need to add my own -v definition to prevent the -
|
|
71
|
+
|
|
72
|
+
# I need to add my own -v definition to prevent the -v from exiting by default as well.
|
|
52
73
|
@opt.on_tail("--version", "Show version") do
|
|
53
74
|
@done_validating = true
|
|
54
75
|
if VERSION
|
|
55
|
-
puts "Version #{MONGREL_VERSION}"
|
|
76
|
+
puts "Version #{Mongrel::Const::MONGREL_VERSION}"
|
|
56
77
|
end
|
|
57
78
|
end
|
|
58
|
-
|
|
79
|
+
|
|
59
80
|
@opt.parse! argv
|
|
60
81
|
end
|
|
61
|
-
|
|
82
|
+
|
|
83
|
+
def configure
|
|
84
|
+
options []
|
|
85
|
+
end
|
|
86
|
+
|
|
62
87
|
# Returns true/false depending on whether the command is configured properly.
|
|
63
88
|
def validate
|
|
64
89
|
return @valid
|
|
65
90
|
end
|
|
66
|
-
|
|
91
|
+
|
|
67
92
|
# Returns a help message. Defaults to OptionParser#help which should be good.
|
|
68
93
|
def help
|
|
69
94
|
@opt.help
|
|
70
95
|
end
|
|
71
|
-
|
|
96
|
+
|
|
72
97
|
# Runs the command doing it's job. You should implement this otherwise it will
|
|
73
98
|
# throw a NotImplementedError as a reminder.
|
|
74
99
|
def run
|
|
75
100
|
raise NotImplementedError
|
|
76
101
|
end
|
|
77
|
-
|
|
78
|
-
|
|
102
|
+
|
|
103
|
+
|
|
79
104
|
# Validates the given expression is true and prints the message if not, exiting.
|
|
80
105
|
def valid?(exp, message)
|
|
81
106
|
if not @done_validating and (not exp)
|
|
@@ -89,29 +114,49 @@ module Mongrel
|
|
|
89
114
|
def valid_exists?(file, message)
|
|
90
115
|
valid?(file != nil && File.exist?(file), message)
|
|
91
116
|
end
|
|
92
|
-
|
|
93
|
-
|
|
117
|
+
|
|
118
|
+
|
|
94
119
|
# Validates that the file is a file and not a directory or something else.
|
|
95
120
|
def valid_file?(file, message)
|
|
96
121
|
valid?(file != nil && File.file?(file), message)
|
|
97
122
|
end
|
|
98
|
-
|
|
123
|
+
|
|
99
124
|
# Validates that the given directory exists
|
|
100
125
|
def valid_dir?(file, message)
|
|
101
126
|
valid?(file != nil && File.directory?(file), message)
|
|
102
127
|
end
|
|
103
128
|
|
|
129
|
+
def valid_user?(user)
|
|
130
|
+
valid?(@group, "You must also specify a group.")
|
|
131
|
+
begin
|
|
132
|
+
Etc.getpwnam(user)
|
|
133
|
+
rescue
|
|
134
|
+
failure "User does not exist: #{user}"
|
|
135
|
+
@valid = false
|
|
136
|
+
end
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
def valid_group?(group)
|
|
140
|
+
valid?(@user, "You must also specify a user.")
|
|
141
|
+
begin
|
|
142
|
+
Etc.getgrnam(group)
|
|
143
|
+
rescue
|
|
144
|
+
failure "Group does not exist: #{group}"
|
|
145
|
+
@valid = false
|
|
146
|
+
end
|
|
147
|
+
end
|
|
148
|
+
|
|
104
149
|
# Just a simple method to display failure until something better is developed.
|
|
105
150
|
def failure(message)
|
|
106
151
|
STDERR.puts "!!! #{message}"
|
|
107
152
|
end
|
|
108
153
|
end
|
|
109
|
-
|
|
154
|
+
|
|
110
155
|
# A Singleton class that manages all of the available commands
|
|
111
156
|
# and handles running them.
|
|
112
157
|
class Registry
|
|
113
158
|
include Singleton
|
|
114
|
-
|
|
159
|
+
|
|
115
160
|
# Builds a list of possible commands from the Command derivates list
|
|
116
161
|
def commands
|
|
117
162
|
pmgr = GemPlugin::Manager.instance
|
|
@@ -121,51 +166,55 @@ module Mongrel
|
|
|
121
166
|
|
|
122
167
|
# Prints a list of available commands.
|
|
123
168
|
def print_command_list
|
|
124
|
-
puts "
|
|
125
|
-
|
|
169
|
+
puts "#{Mongrel::Command::BANNER}\nAvailable commands are:\n\n"
|
|
170
|
+
|
|
126
171
|
self.commands.each do |name|
|
|
127
172
|
puts " - #{name[1 .. -1]}\n"
|
|
128
173
|
end
|
|
129
|
-
|
|
174
|
+
|
|
130
175
|
puts "\nEach command takes -h as an option to get help."
|
|
131
|
-
|
|
176
|
+
|
|
132
177
|
end
|
|
133
|
-
|
|
134
|
-
|
|
178
|
+
|
|
179
|
+
|
|
135
180
|
# Runs the args against the first argument as the command name.
|
|
136
181
|
# If it has any errors it returns a false, otherwise it return true.
|
|
137
182
|
def run(args)
|
|
138
183
|
# find the command
|
|
139
184
|
cmd_name = args.shift
|
|
140
|
-
|
|
185
|
+
|
|
141
186
|
if !cmd_name or cmd_name == "?" or cmd_name == "help"
|
|
142
187
|
print_command_list
|
|
143
188
|
return true
|
|
189
|
+
elsif cmd_name == "--version"
|
|
190
|
+
STDERR.puts "Mongrel Web Server #{Mongrel::Const::MONGREL_VERSION}"
|
|
191
|
+
return true
|
|
144
192
|
end
|
|
145
|
-
|
|
193
|
+
|
|
146
194
|
# command exists, set it up and validate it
|
|
147
195
|
begin
|
|
148
196
|
command = GemPlugin::Manager.instance.create("/commands/#{cmd_name}", :argv => args)
|
|
149
197
|
rescue
|
|
150
198
|
STDERR.puts "INVALID COMMAND: #$!"
|
|
151
199
|
print_command_list
|
|
152
|
-
return
|
|
200
|
+
return false
|
|
153
201
|
end
|
|
154
|
-
|
|
202
|
+
|
|
155
203
|
# Normally the command is NOT valid right after being created
|
|
156
204
|
# but sometimes (like with -h or -v) there's no further processing
|
|
157
205
|
# needed so the command is already valid so we can skip it.
|
|
158
206
|
if not command.done_validating
|
|
159
207
|
if not command.validate
|
|
160
|
-
STDERR.puts "#{cmd_name} reported an error. Use -h to get help."
|
|
208
|
+
STDERR.puts "#{cmd_name} reported an error. Use mongrel_rails #{cmd_name} -h to get help."
|
|
161
209
|
return false
|
|
162
210
|
else
|
|
163
211
|
command.run
|
|
164
212
|
end
|
|
165
213
|
end
|
|
214
|
+
|
|
166
215
|
return true
|
|
167
216
|
end
|
|
168
|
-
|
|
217
|
+
|
|
169
218
|
end
|
|
170
219
|
end
|
|
171
220
|
end
|
data/lib/mongrel/debug.rb
CHANGED
|
@@ -1,3 +1,21 @@
|
|
|
1
|
+
# Mongrel Web Server - A Mostly Ruby Webserver and Library
|
|
2
|
+
#
|
|
3
|
+
# Copyright (C) 2005 Zed A. Shaw zedshaw AT zedshaw dot com
|
|
4
|
+
#
|
|
5
|
+
# This library is free software; you can redistribute it and/or
|
|
6
|
+
# modify it under the terms of the GNU Lesser General Public
|
|
7
|
+
# License as published by the Free Software Foundation; either
|
|
8
|
+
# version 2.1 of the License, or (at your option) any later version.
|
|
9
|
+
#
|
|
10
|
+
# This library is distributed in the hope that it will be useful,
|
|
11
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
12
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
13
|
+
# Lesser General Public License for more details.
|
|
14
|
+
#
|
|
15
|
+
# You should have received a copy of the GNU Lesser General Public
|
|
16
|
+
# License along with this library; if not, write to the Free Software
|
|
17
|
+
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
18
|
+
|
|
1
19
|
require 'logger'
|
|
2
20
|
require 'set'
|
|
3
21
|
require 'socket'
|
|
@@ -48,7 +66,12 @@ module ObjectTracker
|
|
|
48
66
|
@active_objects = Set.new
|
|
49
67
|
|
|
50
68
|
ObjectSpace.each_object do |obj|
|
|
51
|
-
|
|
69
|
+
begin
|
|
70
|
+
# believe it or not, some idiots actually alter the object_id method
|
|
71
|
+
@active_objects << obj.object_id
|
|
72
|
+
rescue Object
|
|
73
|
+
# skip this one, he's an idiot
|
|
74
|
+
end
|
|
52
75
|
end
|
|
53
76
|
end
|
|
54
77
|
|
|
@@ -56,12 +79,14 @@ module ObjectTracker
|
|
|
56
79
|
ospace = Set.new
|
|
57
80
|
counts = {}
|
|
58
81
|
|
|
59
|
-
# Strings can't be tracked easily and are so numerous that they drown out all else
|
|
60
|
-
# so we just ignore them in the counts.
|
|
61
82
|
ObjectSpace.each_object do |obj|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
83
|
+
begin
|
|
84
|
+
ospace << obj.object_id
|
|
85
|
+
counts[obj.class] ||= 0
|
|
86
|
+
counts[obj.class] += 1
|
|
87
|
+
rescue Object
|
|
88
|
+
# skip since object_id can magically get parameters
|
|
89
|
+
end
|
|
65
90
|
end
|
|
66
91
|
|
|
67
92
|
dead_objects = @active_objects - ospace
|
|
@@ -171,15 +196,19 @@ module RequestLog
|
|
|
171
196
|
def process(request, response)
|
|
172
197
|
MongrelDbg::trace(:threads, "#{Time.now} REQUEST #{request.params['PATH_INFO']}")
|
|
173
198
|
ObjectSpace.each_object do |obj|
|
|
174
|
-
|
|
175
|
-
|
|
199
|
+
begin
|
|
200
|
+
if obj.class == Mongrel::HttpServer
|
|
201
|
+
worker_list = obj.workers.list
|
|
176
202
|
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
203
|
+
if worker_list.length > 0
|
|
204
|
+
keys = "-----\n\tKEYS:"
|
|
205
|
+
worker_list.each {|t| keys << "\n\t\t-- #{t}: #{t.keys.inspect}" }
|
|
206
|
+
end
|
|
181
207
|
|
|
182
|
-
|
|
208
|
+
MongrelDbg::trace(:threads, "#{obj.host}:#{obj.port} -- THREADS: #{worker_list.length} #{keys}")
|
|
209
|
+
end
|
|
210
|
+
rescue Object
|
|
211
|
+
# ignore since obj.class can sometimes take parameters
|
|
183
212
|
end
|
|
184
213
|
end
|
|
185
214
|
end
|
data/lib/mongrel/handlers.rb
CHANGED
|
@@ -1,11 +1,23 @@
|
|
|
1
|
-
require '
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
1
|
+
require 'mongrel/stats'
|
|
2
|
+
require 'zlib'
|
|
3
|
+
|
|
4
|
+
# Mongrel Web Server - A Mostly Ruby Webserver and Library
|
|
5
|
+
#
|
|
6
|
+
# Copyright (C) 2005 Zed A. Shaw zedshaw AT zedshaw dot com
|
|
7
|
+
#
|
|
8
|
+
# This library is free software; you can redistribute it and/or
|
|
9
|
+
# modify it under the terms of the GNU Lesser General Public
|
|
10
|
+
# License as published by the Free Software Foundation; either
|
|
11
|
+
# version 2.1 of the License, or (at your option) any later version.
|
|
12
|
+
#
|
|
13
|
+
# This library is distributed in the hope that it will be useful,
|
|
14
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
15
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
16
|
+
# Lesser General Public License for more details.
|
|
17
|
+
#
|
|
18
|
+
# You should have received a copy of the GNU Lesser General Public
|
|
19
|
+
# License along with this library; if not, write to the Free Software
|
|
20
|
+
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
9
21
|
|
|
10
22
|
module Mongrel
|
|
11
23
|
|
|
@@ -19,6 +31,8 @@ module Mongrel
|
|
|
19
31
|
# should be implemented using the HttpHandlerPlugin mixin.
|
|
20
32
|
#
|
|
21
33
|
class HttpHandler
|
|
34
|
+
attr_reader :header_only
|
|
35
|
+
attr_accessor :listener
|
|
22
36
|
|
|
23
37
|
def process(request, response)
|
|
24
38
|
end
|
|
@@ -31,9 +45,12 @@ module Mongrel
|
|
|
31
45
|
# the process method later.
|
|
32
46
|
module HttpHandlerPlugin
|
|
33
47
|
attr_reader :options
|
|
48
|
+
attr_reader :header_only
|
|
49
|
+
attr_accessor :listener
|
|
34
50
|
|
|
35
51
|
def initialize(options={})
|
|
36
52
|
@options = options
|
|
53
|
+
@header_only = false
|
|
37
54
|
end
|
|
38
55
|
|
|
39
56
|
def process(request, response)
|
|
@@ -52,7 +69,7 @@ module Mongrel
|
|
|
52
69
|
def initialize(msg)
|
|
53
70
|
@response = Const::ERROR_404_RESPONSE + msg
|
|
54
71
|
end
|
|
55
|
-
|
|
72
|
+
|
|
56
73
|
# Just kicks back the standard 404 response with your special message.
|
|
57
74
|
def process(request, response)
|
|
58
75
|
response.socket.write(@response)
|
|
@@ -104,26 +121,27 @@ module Mongrel
|
|
|
104
121
|
|
|
105
122
|
# Checks if the given path can be served and returns the full path (or nil if not).
|
|
106
123
|
def can_serve(path_info)
|
|
107
|
-
|
|
124
|
+
# TODO: investigate freezing the path_info to prevent double escaping
|
|
125
|
+
req_path = File.expand_path(File.join(@path,HttpRequest.unescape(path_info)), @path)
|
|
108
126
|
|
|
109
|
-
if
|
|
127
|
+
if req_path.index(@path) == 0 and File.exist? req_path
|
|
110
128
|
# it exists and it's in the right location
|
|
111
|
-
if File.directory?
|
|
129
|
+
if File.directory? req_path
|
|
112
130
|
# the request is for a directory
|
|
113
|
-
index = File.join(
|
|
131
|
+
index = File.join(req_path, @index_html)
|
|
114
132
|
if File.exist? index
|
|
115
133
|
# serve the index
|
|
116
134
|
return index
|
|
117
135
|
elsif @listing_allowed
|
|
118
136
|
# serve the directory
|
|
119
|
-
|
|
137
|
+
return req_path
|
|
120
138
|
else
|
|
121
139
|
# do not serve anything
|
|
122
140
|
return nil
|
|
123
141
|
end
|
|
124
142
|
else
|
|
125
143
|
# it's a file and it's there
|
|
126
|
-
return
|
|
144
|
+
return req_path
|
|
127
145
|
end
|
|
128
146
|
else
|
|
129
147
|
# does not exist or isn't in the right spot
|
|
@@ -138,6 +156,7 @@ module Mongrel
|
|
|
138
156
|
# object to send the results on.
|
|
139
157
|
def send_dir_listing(base, dir, response)
|
|
140
158
|
# take off any trailing / so the links come out right
|
|
159
|
+
base = HttpRequest.unescape(base)
|
|
141
160
|
base.chop! if base[-1] == "/"[-1]
|
|
142
161
|
|
|
143
162
|
if @listing_allowed
|
|
@@ -145,12 +164,13 @@ module Mongrel
|
|
|
145
164
|
head[Const::CONTENT_TYPE] = "text/html"
|
|
146
165
|
out << "<html><head><title>Directory Listing</title></head><body>"
|
|
147
166
|
Dir.entries(dir).each do |child|
|
|
167
|
+
child = HttpRequest.unescape(child)
|
|
148
168
|
next if child == "."
|
|
149
169
|
|
|
150
170
|
if child == ".."
|
|
151
171
|
out << "<a href=\"#{base}/#{child}\">Up to parent..</a><br/>"
|
|
152
172
|
else
|
|
153
|
-
out << "<a href=\"#{base}/#{child}
|
|
173
|
+
out << "<a href=\"#{base}/#{child}/\">#{child}</a><br/>"
|
|
154
174
|
end
|
|
155
175
|
end
|
|
156
176
|
out << "</body></html>"
|
|
@@ -162,72 +182,81 @@ module Mongrel
|
|
|
162
182
|
end
|
|
163
183
|
end
|
|
164
184
|
|
|
165
|
-
|
|
185
|
+
|
|
166
186
|
# Sends the contents of a file back to the user. Not terribly efficient since it's
|
|
167
187
|
# opening and closing the file for each read.
|
|
168
|
-
def send_file(
|
|
188
|
+
def send_file(req_path, request, response, header_only=false)
|
|
169
189
|
|
|
170
|
-
|
|
171
|
-
response.status = 200
|
|
172
|
-
stat = File.stat(req)
|
|
173
|
-
header = response.header
|
|
190
|
+
stat = File.stat(req_path)
|
|
174
191
|
|
|
175
192
|
# Set the last modified times as well and etag for all files
|
|
176
|
-
|
|
193
|
+
mtime = stat.mtime
|
|
177
194
|
# Calculated the same as apache, not sure how well the works on win32
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
195
|
+
etag = Const::ETAG_FORMAT % [mtime.to_i, stat.size, stat.ino]
|
|
196
|
+
|
|
197
|
+
unmodified_since = request.params[Const::HTTP_IF_UNMODIFIED_SINCE]
|
|
198
|
+
none_match = request.params[Const::HTTP_IF_NONE_MATCH]
|
|
199
|
+
|
|
200
|
+
# test to see if this is a conditional request, and test if
|
|
201
|
+
# the response would be identical to the last response
|
|
202
|
+
same_response = case
|
|
203
|
+
when unmodified_since && !last_response_time = Time.httpdate(unmodified_since) rescue nil : false
|
|
204
|
+
when unmodified_since && last_response_time > Time.now : false
|
|
205
|
+
when unmodified_since && mtime > last_response_time : false
|
|
206
|
+
when none_match && none_match == '*' : false
|
|
207
|
+
when none_match && !none_match.strip.split(/\s*,\s*/).include?(etag) : false
|
|
208
|
+
else unmodified_since || none_match # validation successful if we get this far and at least one of the header exists
|
|
209
|
+
end
|
|
210
|
+
|
|
211
|
+
header = response.header
|
|
212
|
+
header[Const::ETAG] = etag
|
|
185
213
|
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
response.send_header
|
|
189
|
-
|
|
190
|
-
if not header_only
|
|
191
|
-
begin
|
|
192
|
-
if $mongrel_has_sendfile
|
|
193
|
-
File.open(req, "rb") { |f| response.socket.sendfile(f) }
|
|
194
|
-
else
|
|
195
|
-
File.open(req, "rb") { |f| response.socket.write(f.read) }
|
|
196
|
-
end
|
|
197
|
-
rescue EOFError,Errno::ECONNRESET,Errno::EPIPE,Errno::EINVAL,Errno::EBADF
|
|
198
|
-
# ignore these since it means the client closed off early
|
|
199
|
-
STDERR.puts "Client closed socket requesting file #{req}: #$!"
|
|
200
|
-
end
|
|
214
|
+
if same_response
|
|
215
|
+
response.start(304) {}
|
|
201
216
|
else
|
|
202
|
-
|
|
217
|
+
# first we setup the headers and status then we do a very fast send on the socket directly
|
|
218
|
+
response.status = 200
|
|
219
|
+
header[Const::LAST_MODIFIED] = mtime.httpdate
|
|
220
|
+
|
|
221
|
+
# set the mime type from our map based on the ending
|
|
222
|
+
dot_at = req_path.rindex('.')
|
|
223
|
+
if dot_at
|
|
224
|
+
header[Const::CONTENT_TYPE] = MIME_TYPES[req_path[dot_at .. -1]] || @default_content_type
|
|
225
|
+
end
|
|
226
|
+
|
|
227
|
+
# send a status with out content length
|
|
228
|
+
response.send_status(stat.size)
|
|
229
|
+
response.send_header
|
|
230
|
+
|
|
231
|
+
if not header_only
|
|
232
|
+
response.send_file(req_path)
|
|
233
|
+
end
|
|
203
234
|
end
|
|
204
235
|
end
|
|
205
236
|
|
|
206
|
-
|
|
207
237
|
# Process the request to either serve a file or a directory listing
|
|
208
|
-
# if allowed (based on the listing_allowed
|
|
238
|
+
# if allowed (based on the listing_allowed parameter to the constructor).
|
|
209
239
|
def process(request, response)
|
|
210
240
|
req_method = request.params[Const::REQUEST_METHOD] || Const::GET
|
|
211
|
-
|
|
212
|
-
if not
|
|
241
|
+
req_path = can_serve request.params[Const::PATH_INFO]
|
|
242
|
+
if not req_path
|
|
213
243
|
# not found, return a 404
|
|
214
244
|
response.start(404) do |head,out|
|
|
215
245
|
out << "File not found"
|
|
216
246
|
end
|
|
217
247
|
else
|
|
218
248
|
begin
|
|
219
|
-
if File.directory?
|
|
220
|
-
send_dir_listing(request.params[Const::REQUEST_URI],
|
|
249
|
+
if File.directory? req_path
|
|
250
|
+
send_dir_listing(request.params[Const::REQUEST_URI], req_path, response)
|
|
221
251
|
elsif req_method == Const::HEAD
|
|
222
|
-
send_file(
|
|
223
|
-
|
|
224
|
-
send_file(
|
|
225
|
-
|
|
226
|
-
|
|
252
|
+
send_file(req_path, request, response, true)
|
|
253
|
+
elsif req_method == Const::GET
|
|
254
|
+
send_file(req_path, request, response, false)
|
|
255
|
+
else
|
|
256
|
+
response.start(403) {|head,out| out.write(ONLY_HEAD_GET) }
|
|
227
257
|
end
|
|
228
258
|
rescue => details
|
|
229
|
-
STDERR.puts "Error
|
|
230
|
-
STDERR.puts details.backtrace.join("\n")
|
|
259
|
+
STDERR.puts "Error sending file #{req_path}: #{details}"
|
|
231
260
|
end
|
|
232
261
|
end
|
|
233
262
|
end
|
|
@@ -239,4 +268,134 @@ module Mongrel
|
|
|
239
268
|
end
|
|
240
269
|
|
|
241
270
|
end
|
|
271
|
+
|
|
272
|
+
|
|
273
|
+
# When added to a config script (-S in mongrel_rails) it will
|
|
274
|
+
# look at the client's allowed response types and then gzip
|
|
275
|
+
# compress anything that is going out.
|
|
276
|
+
#
|
|
277
|
+
# Valid option is :always_deflate => false which tells the handler to
|
|
278
|
+
# deflate everything even if the client can't handle it.
|
|
279
|
+
class DeflateFilter < HttpHandler
|
|
280
|
+
HTTP_ACCEPT_ENCODING = "HTTP_ACCEPT_ENCODING"
|
|
281
|
+
|
|
282
|
+
def initialize(ops={})
|
|
283
|
+
@options = ops
|
|
284
|
+
@always_deflate = ops[:always_deflate] || false
|
|
285
|
+
end
|
|
286
|
+
|
|
287
|
+
def process(request, response)
|
|
288
|
+
accepts = request.params[HTTP_ACCEPT_ENCODING]
|
|
289
|
+
# only process if they support compression
|
|
290
|
+
if @always_deflate or (accepts and (accepts.include? "deflate" and not response.body_sent))
|
|
291
|
+
response.header["Content-Encoding"] = "deflate"
|
|
292
|
+
# we can't just rewind the body and gzip it since the body could be an attached file
|
|
293
|
+
response.body.rewind
|
|
294
|
+
gzout = StringIO.new(Zlib::Deflate.deflate(response.body.read))
|
|
295
|
+
gzout.rewind
|
|
296
|
+
response.body.close
|
|
297
|
+
response.body = gzout
|
|
298
|
+
end
|
|
299
|
+
end
|
|
300
|
+
end
|
|
301
|
+
|
|
302
|
+
|
|
303
|
+
# Implements a few basic statistics for a particular URI. Register it anywhere
|
|
304
|
+
# you want in the request chain and it'll quickly gather some numbers for you
|
|
305
|
+
# to analyze. It is pretty fast, but don't put it out in production.
|
|
306
|
+
#
|
|
307
|
+
# You should pass the filter to StatusHandler as StatusHandler.new(:stats_filter => stats).
|
|
308
|
+
# This lets you then hit the status URI you want and get these stats from a browser.
|
|
309
|
+
#
|
|
310
|
+
# StatisticsFilter takes an option of :sample_rate. This is a number that's passed to
|
|
311
|
+
# rand and if that number gets hit then a sample is taken. This helps reduce the load
|
|
312
|
+
# and keeps the statistics valid (since sampling is a part of how they work).
|
|
313
|
+
#
|
|
314
|
+
# The exception to :sample_rate is that inter-request time is sampled on every request.
|
|
315
|
+
# If this wasn't done then it wouldn't be accurate as a measure of time between requests.
|
|
316
|
+
class StatisticsFilter < HttpHandler
|
|
317
|
+
attr_reader :stats
|
|
318
|
+
|
|
319
|
+
def initialize(ops={})
|
|
320
|
+
@sample_rate = ops[:sample_rate] || 300
|
|
321
|
+
|
|
322
|
+
@processors = Stats.new("processors")
|
|
323
|
+
@reqsize = Stats.new("request Kb")
|
|
324
|
+
@headcount = Stats.new("req param count")
|
|
325
|
+
@respsize = Stats.new("response Kb")
|
|
326
|
+
@interreq = Stats.new("inter-request time")
|
|
327
|
+
end
|
|
328
|
+
|
|
329
|
+
|
|
330
|
+
def process(request, response)
|
|
331
|
+
if rand(@sample_rate)+1 == @sample_rate
|
|
332
|
+
@processors.sample(listener.workers.list.length)
|
|
333
|
+
@headcount.sample(request.params.length)
|
|
334
|
+
@reqsize.sample(request.body.length / 1024.0)
|
|
335
|
+
@respsize.sample((response.body.length + response.header.out.length) / 1024.0)
|
|
336
|
+
end
|
|
337
|
+
@interreq.tick
|
|
338
|
+
end
|
|
339
|
+
|
|
340
|
+
def dump
|
|
341
|
+
"#{@processors.to_s}\n#{@reqsize.to_s}\n#{@headcount.to_s}\n#{@respsize.to_s}\n#{@interreq.to_s}"
|
|
342
|
+
end
|
|
343
|
+
end
|
|
344
|
+
|
|
345
|
+
|
|
346
|
+
# The :stats_filter is basically any configured stats filter that you've added to this same
|
|
347
|
+
# URI. This lets the status handler print out statistics on how Mongrel is doing.
|
|
348
|
+
class StatusHandler < HttpHandler
|
|
349
|
+
def initialize(ops={})
|
|
350
|
+
@stats = ops[:stats_filter]
|
|
351
|
+
end
|
|
352
|
+
|
|
353
|
+
def table(title, rows)
|
|
354
|
+
results = "<table border=\"1\"><tr><th colspan=\"#{rows[0].length}\">#{title}</th></tr>"
|
|
355
|
+
rows.each do |cols|
|
|
356
|
+
results << "<tr>"
|
|
357
|
+
cols.each {|col| results << "<td>#{col}</td>" }
|
|
358
|
+
results << "</tr>"
|
|
359
|
+
end
|
|
360
|
+
results + "</table>"
|
|
361
|
+
end
|
|
362
|
+
|
|
363
|
+
def describe_listener
|
|
364
|
+
results = ""
|
|
365
|
+
results << "<h1>Listener #{listener.host}:#{listener.port}</h1>"
|
|
366
|
+
results << table("settings", [
|
|
367
|
+
["host",listener.host],
|
|
368
|
+
["port",listener.port],
|
|
369
|
+
["timeout",listener.timeout],
|
|
370
|
+
["workers max",listener.num_processors],
|
|
371
|
+
])
|
|
372
|
+
|
|
373
|
+
if @stats
|
|
374
|
+
results << "<h2>Statistics</h2><p>N means the number of samples, pay attention to MEAN, SD, MIN and MAX."
|
|
375
|
+
results << "<pre>#{@stats.dump}</pre>"
|
|
376
|
+
end
|
|
377
|
+
|
|
378
|
+
results << "<h2>Registered Handlers</h2>"
|
|
379
|
+
uris = listener.classifier.handler_map
|
|
380
|
+
results << table("handlers", uris.map {|uri,handlers|
|
|
381
|
+
[uri,
|
|
382
|
+
"<pre>" +
|
|
383
|
+
handlers.map {|h| h.class.to_s }.join("\n") +
|
|
384
|
+
"</pre>"
|
|
385
|
+
]
|
|
386
|
+
})
|
|
387
|
+
|
|
388
|
+
results
|
|
389
|
+
end
|
|
390
|
+
|
|
391
|
+
def process(request, response)
|
|
392
|
+
response.start do |head,out|
|
|
393
|
+
out.write <<-END
|
|
394
|
+
<html><body><title>Mongrel Server Status</title>
|
|
395
|
+
#{describe_listener}
|
|
396
|
+
</body></html>
|
|
397
|
+
END
|
|
398
|
+
end
|
|
399
|
+
end
|
|
400
|
+
end
|
|
242
401
|
end
|