mongrel 0.3.6 → 0.3.7
Sign up to get free protection for your applications and to get access to all the features.
- data/README +28 -1
- data/Rakefile +2 -2
- data/bin/mongrel_rails +102 -65
- data/bin/mongrel_rails_service +16 -7
- data/bin/mongrel_rails_svc +184 -87
- data/doc/rdoc/classes/Mongrel.html +1 -0
- data/doc/rdoc/classes/Mongrel/Const.html +3 -3
- data/doc/rdoc/classes/Mongrel/HeaderOut.html +10 -10
- data/doc/rdoc/classes/Mongrel/HeaderOut.src/{M000028.html → M000014.html} +4 -4
- data/doc/rdoc/classes/Mongrel/HeaderOut.src/{M000029.html → M000015.html} +7 -7
- data/doc/rdoc/classes/Mongrel/HttpParser.html +35 -35
- data/doc/rdoc/classes/Mongrel/HttpParser.src/{M000015.html → M000001.html} +0 -0
- data/doc/rdoc/classes/Mongrel/HttpParser.src/{M000016.html → M000002.html} +0 -0
- data/doc/rdoc/classes/Mongrel/HttpParser.src/{M000017.html → M000003.html} +0 -0
- data/doc/rdoc/classes/Mongrel/HttpParser.src/{M000018.html → M000004.html} +0 -0
- data/doc/rdoc/classes/Mongrel/HttpParser.src/{M000019.html → M000005.html} +0 -0
- data/doc/rdoc/classes/Mongrel/HttpParser.src/{M000020.html → M000006.html} +0 -0
- data/doc/rdoc/classes/Mongrel/HttpParser.src/{M000021.html → M000007.html} +0 -0
- data/doc/rdoc/classes/Mongrel/HttpRequest.html +5 -5
- data/doc/rdoc/classes/Mongrel/HttpRequest.src/{M000041.html → M000029.html} +25 -25
- data/doc/rdoc/classes/Mongrel/HttpResponse.html +36 -36
- data/doc/rdoc/classes/Mongrel/HttpResponse.src/{M000034.html → M000016.html} +7 -7
- data/doc/rdoc/classes/Mongrel/HttpResponse.src/{M000035.html → M000017.html} +6 -6
- data/doc/rdoc/classes/Mongrel/HttpResponse.src/{M000036.html → M000018.html} +5 -5
- data/doc/rdoc/classes/Mongrel/HttpResponse.src/{M000037.html → M000019.html} +5 -5
- data/doc/rdoc/classes/Mongrel/HttpResponse.src/{M000038.html → M000020.html} +6 -6
- data/doc/rdoc/classes/Mongrel/HttpResponse.src/{M000039.html → M000021.html} +6 -6
- data/doc/rdoc/classes/Mongrel/HttpResponse.src/{M000040.html → M000022.html} +6 -6
- data/doc/rdoc/classes/Mongrel/HttpServer.html +34 -35
- data/doc/rdoc/classes/Mongrel/HttpServer.src/M000008.html +36 -0
- data/doc/rdoc/classes/Mongrel/HttpServer.src/{M000023.html → M000009.html} +43 -43
- data/doc/rdoc/classes/Mongrel/HttpServer.src/{M000024.html → M000010.html} +31 -31
- data/doc/rdoc/classes/Mongrel/HttpServer.src/{M000025.html → M000011.html} +4 -4
- data/doc/rdoc/classes/Mongrel/HttpServer.src/{M000026.html → M000012.html} +4 -4
- data/doc/rdoc/classes/Mongrel/HttpServer.src/M000013.html +23 -0
- data/doc/rdoc/classes/{FactoryError.html → Mongrel/TimeoutWorker.html} +7 -34
- data/doc/rdoc/classes/Mongrel/URIClassifier.html +63 -20
- data/doc/rdoc/classes/Mongrel/URIClassifier.src/M000023.html +18 -0
- data/doc/rdoc/classes/Mongrel/URIClassifier.src/M000024.html +18 -0
- data/doc/rdoc/classes/Mongrel/URIClassifier.src/{M000030.html → M000025.html} +0 -0
- data/doc/rdoc/classes/Mongrel/URIClassifier.src/{M000031.html → M000026.html} +0 -0
- data/doc/rdoc/classes/Mongrel/URIClassifier.src/{M000032.html → M000027.html} +0 -0
- data/doc/rdoc/classes/Mongrel/URIClassifier.src/{M000033.html → M000028.html} +0 -0
- data/doc/rdoc/created.rid +1 -1
- data/doc/rdoc/files/README.html +35 -2
- data/doc/rdoc/files/lib/mongrel_rb.html +4 -1
- data/doc/rdoc/fr_class_index.html +1 -2
- data/doc/rdoc/fr_file_index.html +0 -1
- data/doc/rdoc/fr_method_index.html +29 -41
- data/lib/mongrel.rb +37 -9
- data/lib/mongrel/command.rb +13 -34
- data/lib/mongrel/plugins.rb +156 -0
- data/lib/mongrel/rails.rb +70 -0
- data/test/plugins/commands/test1.rb +19 -0
- data/test/test_plugins.rb +45 -0
- data/test/test_uriclassifier.rb +5 -1
- metadata +38 -49
- data/doc/rdoc/classes/FactoryError.src/M000001.html +0 -23
- data/doc/rdoc/classes/Mongrel/HttpServer.src/M000022.html +0 -33
- data/doc/rdoc/classes/Mongrel/HttpServer.src/M000027.html +0 -19
- data/doc/rdoc/classes/PluginFactory.html +0 -409
- data/doc/rdoc/classes/PluginFactory.src/M000002.html +0 -18
- data/doc/rdoc/classes/PluginFactory.src/M000003.html +0 -18
- data/doc/rdoc/classes/PluginFactory.src/M000004.html +0 -22
- data/doc/rdoc/classes/PluginFactory.src/M000005.html +0 -22
- data/doc/rdoc/classes/PluginFactory.src/M000006.html +0 -33
- data/doc/rdoc/classes/PluginFactory.src/M000007.html +0 -32
- data/doc/rdoc/classes/PluginFactory.src/M000008.html +0 -18
- data/doc/rdoc/classes/PluginFactory.src/M000009.html +0 -24
- data/doc/rdoc/classes/PluginFactory.src/M000010.html +0 -40
- data/doc/rdoc/classes/PluginFactory.src/M000011.html +0 -39
- data/doc/rdoc/classes/PluginFactory.src/M000012.html +0 -24
- data/doc/rdoc/classes/PluginFactory.src/M000013.html +0 -70
- data/doc/rdoc/classes/PluginFactory.src/M000014.html +0 -34
- data/doc/rdoc/files/lib/pluginfactory_rb.html +0 -132
- data/lib/pluginfactory.rb +0 -384
data/lib/mongrel.rb
CHANGED
@@ -4,16 +4,38 @@ require 'thread'
|
|
4
4
|
require 'stringio'
|
5
5
|
require 'mongrel/cgi'
|
6
6
|
require 'mongrel/handlers'
|
7
|
+
require 'mongrel/command'
|
8
|
+
require 'mongrel/plugins'
|
9
|
+
require 'timeout'
|
7
10
|
|
8
11
|
# Mongrel module containing all of the classes (include C extensions) for running
|
9
12
|
# a Mongrel web server. It contains a minimalist HTTP server with just enough
|
10
13
|
# functionality to service web application requests fast as possible.
|
11
14
|
module Mongrel
|
12
15
|
|
16
|
+
class URIClassifier
|
17
|
+
# Returns the URIs that have been registered with this classifier so far.
|
18
|
+
# The URIs returned should not be modified as this will cause a memory leak.
|
19
|
+
# You can use this to inspect the contents of the URIClassifier.
|
20
|
+
def uris
|
21
|
+
@handler_map.keys
|
22
|
+
end
|
23
|
+
|
24
|
+
# Simply does an inspect that looks like a Hash inspect.
|
25
|
+
def inspect
|
26
|
+
@handler_map.inspect
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
|
13
31
|
# Used to stop the HttpServer via Thread.raise.
|
14
32
|
class StopServer < Exception
|
15
33
|
end
|
16
34
|
|
35
|
+
# Used to timeout worker threads that have taken too long
|
36
|
+
class TimeoutWorker < Exception
|
37
|
+
end
|
38
|
+
|
17
39
|
# Every standard HTTP code mapped to the appropriate message. These are
|
18
40
|
# used so frequently that they are placed directly in Mongrel for easy
|
19
41
|
# access rather than Mongrel::Const.
|
@@ -118,7 +140,7 @@ module Mongrel
|
|
118
140
|
SERVER_SOFTWARE='SERVER_SOFTWARE'
|
119
141
|
|
120
142
|
# Current Mongrel version (used for SERVER_SOFTWARE and other response headers).
|
121
|
-
MONGREL_VERSION='Mongrel 0.3.
|
143
|
+
MONGREL_VERSION='Mongrel 0.3.7'
|
122
144
|
|
123
145
|
# The standard empty 404 response for bad requests. Use Error4040Handler for custom stuff.
|
124
146
|
ERROR_404_RESPONSE="HTTP/1.1 404 Not Found\r\nConnection: close\r\nServer: #{MONGREL_VERSION}\r\n\r\nNOT FOUND"
|
@@ -320,24 +342,26 @@ module Mongrel
|
|
320
342
|
# systems. If you find that you overload Mongrel too much
|
321
343
|
# try changing it higher. If you find that responses are way too slow
|
322
344
|
# try lowering it (after you've tuned your stuff of course).
|
323
|
-
# Future versions of Mongrel will make this more dynamic (hopefully).
|
324
345
|
def initialize(host, port, num_processors=20, timeout=120)
|
325
|
-
@socket = TCPServer.new(host, port)
|
346
|
+
@socket = TCPServer.new(host, port)
|
326
347
|
|
327
348
|
@classifier = URIClassifier.new
|
328
349
|
@req_queue = Queue.new
|
329
350
|
@host = host
|
330
351
|
@port = port
|
331
352
|
@processors = []
|
332
|
-
@timeout = timeout
|
333
353
|
|
334
|
-
|
354
|
+
# create the worker threads
|
355
|
+
num_processors.times do |i|
|
335
356
|
@processors << Thread.new do
|
336
357
|
while client = @req_queue.deq
|
337
|
-
|
358
|
+
Timeout::timeout(timeout) do
|
359
|
+
process_client(client)
|
360
|
+
end
|
338
361
|
end
|
339
362
|
end
|
340
|
-
|
363
|
+
end
|
364
|
+
|
341
365
|
end
|
342
366
|
|
343
367
|
|
@@ -440,8 +464,12 @@ module Mongrel
|
|
440
464
|
# Stops the acceptor thread and then causes the worker threads to finish
|
441
465
|
# off the request queue before finally exiting.
|
442
466
|
def stop
|
443
|
-
|
444
|
-
|
467
|
+
stopper = Thread.new do
|
468
|
+
@acceptor[:stopped] = true
|
469
|
+
exc = StopServer.new
|
470
|
+
@acceptor.raise(exc)
|
471
|
+
end
|
472
|
+
stopper.priority = 10
|
445
473
|
end
|
446
474
|
|
447
475
|
end
|
data/lib/mongrel/command.rb
CHANGED
@@ -1,7 +1,6 @@
|
|
1
1
|
require 'singleton'
|
2
2
|
require 'optparse'
|
3
|
-
require '
|
4
|
-
|
3
|
+
require 'mongrel/plugins'
|
5
4
|
|
6
5
|
module Mongrel
|
7
6
|
|
@@ -10,17 +9,10 @@ module Mongrel
|
|
10
9
|
|
11
10
|
module Command
|
12
11
|
|
13
|
-
|
14
12
|
# A Command pattern implementation used to create the set of command available to the user
|
15
13
|
# from Mongrel. The script uses objects which implement this interface to do the
|
16
14
|
# user's bidding.
|
17
|
-
|
18
|
-
# Creating a new command is very easy, and you can do it without modifying the source
|
19
|
-
# of Mongrel thanks to PluginFactory. What you do is the following:
|
20
|
-
#
|
21
|
-
# 1.
|
22
|
-
class Command
|
23
|
-
include PluginFactory
|
15
|
+
module Base
|
24
16
|
|
25
17
|
attr_reader :valid, :done_validating
|
26
18
|
|
@@ -39,11 +31,13 @@ module Mongrel
|
|
39
31
|
|
40
32
|
# Called by the subclass to setup the command and parse the argv arguments.
|
41
33
|
# The call is destructive on argv since it uses the OptionParser#parse! function.
|
42
|
-
def initialize(
|
34
|
+
def initialize(options={})
|
35
|
+
argv = options[:argv]
|
43
36
|
@opt = OptionParser.new
|
44
37
|
@valid = true
|
45
38
|
# this is retarded, but it has to be done this way because -h and -v exit
|
46
39
|
@done_validating = false
|
40
|
+
@original_args = argv.dup
|
47
41
|
|
48
42
|
configure
|
49
43
|
|
@@ -61,13 +55,7 @@ module Mongrel
|
|
61
55
|
end
|
62
56
|
end
|
63
57
|
|
64
|
-
@opt.parse! argv
|
65
|
-
end
|
66
|
-
|
67
|
-
# Tells the PluginFactory where to look for additional commands. By default
|
68
|
-
# it's just a "plugins" directory wherever we are located.
|
69
|
-
def self.derivativeDirs
|
70
|
-
return ["plugins"]
|
58
|
+
@opt.parse! options[:argv]
|
71
59
|
end
|
72
60
|
|
73
61
|
# Returns true/false depending on whether the command is configured properly.
|
@@ -118,8 +106,6 @@ module Mongrel
|
|
118
106
|
end
|
119
107
|
end
|
120
108
|
|
121
|
-
|
122
|
-
|
123
109
|
# A Singleton class that manages all of the available commands
|
124
110
|
# and handles running them.
|
125
111
|
class Registry
|
@@ -127,15 +113,9 @@ module Mongrel
|
|
127
113
|
|
128
114
|
# Builds a list of possible commands from the Command derivates list
|
129
115
|
def commands
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
results = []
|
134
|
-
list.keys.each do |key|
|
135
|
-
results << key.to_s unless match.match(key.to_s)
|
136
|
-
end
|
137
|
-
|
138
|
-
return results.sort
|
116
|
+
pmgr = PluginManager.instance
|
117
|
+
list = pmgr.available["/commands"]
|
118
|
+
return list.sort
|
139
119
|
end
|
140
120
|
|
141
121
|
# Prints a list of available commands.
|
@@ -143,7 +123,7 @@ module Mongrel
|
|
143
123
|
puts "Available commands are:\n\n"
|
144
124
|
|
145
125
|
self.commands.each do |name|
|
146
|
-
puts " - #{name}\n"
|
126
|
+
puts " - #{name[1 .. -1]}\n"
|
147
127
|
end
|
148
128
|
|
149
129
|
puts "\nEach command takes -h as an option to get help."
|
@@ -154,9 +134,8 @@ module Mongrel
|
|
154
134
|
# Runs the args against the first argument as the command name.
|
155
135
|
# If it has any errors it returns a false, otherwise it return true.
|
156
136
|
def run(args)
|
157
|
-
# find the command
|
137
|
+
# find the command
|
158
138
|
cmd_name = args.shift
|
159
|
-
$0 = "#{cmd_name}"
|
160
139
|
|
161
140
|
if !cmd_name or cmd_name == "?" or cmd_name == "help"
|
162
141
|
print_command_list
|
@@ -165,8 +144,8 @@ module Mongrel
|
|
165
144
|
|
166
145
|
# command exists, set it up and validate it
|
167
146
|
begin
|
168
|
-
command =
|
169
|
-
rescue
|
147
|
+
command = PluginManager.instance.create("/commands/#{cmd_name}", :argv => args)
|
148
|
+
rescue
|
170
149
|
STDERR.puts "INVALID COMMAND: #$!"
|
171
150
|
print_command_list
|
172
151
|
return
|
@@ -0,0 +1,156 @@
|
|
1
|
+
require 'singleton'
|
2
|
+
|
3
|
+
module Mongrel
|
4
|
+
|
5
|
+
# Implements the main method of managing plugins for Mongrel.
|
6
|
+
# "Plugins" in this sense are any classes which get registered
|
7
|
+
# with Mongrel for possible use when it's operating. These can
|
8
|
+
# be Handlers, Commands, or other classes. When you create a
|
9
|
+
# Plugin you register it into a URI-like namespace that makes
|
10
|
+
# it easy for you (and others) to reference it later during
|
11
|
+
# configuration.
|
12
|
+
#
|
13
|
+
# PluginManager is used as nothing more than a holder of all the
|
14
|
+
# plugins that have registered themselves. Let's say you have:
|
15
|
+
#
|
16
|
+
# class StopNow < Plugin "/commands"
|
17
|
+
# ...
|
18
|
+
# end
|
19
|
+
#
|
20
|
+
# Then you can get at this plugin with:
|
21
|
+
#
|
22
|
+
# cmd = PluginManager.create("/commands/stopnow")
|
23
|
+
#
|
24
|
+
# The funky syntax for StopNow is a weird trick borrowed from
|
25
|
+
# the Camping framework. See the Mongrel::Plugin *function* (yes,
|
26
|
+
# function). What this basically does is register it
|
27
|
+
# into the namespace for plugins at /commands. You could go
|
28
|
+
# as arbitrarily nested as you like.
|
29
|
+
#
|
30
|
+
# Why this strange almost second namespace? Why not just use
|
31
|
+
# the ObjectSpace and/or Modules? The main reason is speed and
|
32
|
+
# to avoid cluttering the Ruby namespace with what is really a
|
33
|
+
# configuration statement. This lets implementors put code
|
34
|
+
# into the Ruby structuring they need, and still have Plugins
|
35
|
+
# available to Mongrel via simple URI-like names.
|
36
|
+
#
|
37
|
+
# The alternative (as pluginfactory does it) is to troll through
|
38
|
+
# ObjectSpace looking for stuff that *might* be plugins every time
|
39
|
+
# one is needed. This alternative also means that you are stuck
|
40
|
+
# naming your commands in specific ways and putting them in specific
|
41
|
+
# modules in order to configure how Mongrel should use them.
|
42
|
+
#
|
43
|
+
# One downside to this is that you need to subclass plugin to
|
44
|
+
# make it work. In this case use mixins to add other functionality.
|
45
|
+
class PluginManager
|
46
|
+
include Singleton
|
47
|
+
|
48
|
+
def initialize
|
49
|
+
@plugins = URIClassifier.new
|
50
|
+
end
|
51
|
+
|
52
|
+
# Tell the PluginManager to scan the given path (recursively)
|
53
|
+
# and load the *.rb files found there. This is how you'd
|
54
|
+
# setup your own plugin directory.
|
55
|
+
def load(path)
|
56
|
+
Dir.chdir(path) do
|
57
|
+
Dir["**/*.rb"].each do |rbfile|
|
58
|
+
STDERR.puts "Loading plugins from #{rbfile}"
|
59
|
+
require rbfile
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
# Not necessary for you to call directly, but this is
|
65
|
+
# how Mongrel::PluginBase.inherited actually adds a
|
66
|
+
# plugin to a category.
|
67
|
+
def register(category, name, klass)
|
68
|
+
cat, ignored, map = @plugins.resolve(category)
|
69
|
+
|
70
|
+
if not cat or ignored.length > 0
|
71
|
+
map = {name => klass}
|
72
|
+
@plugins.register(category, map)
|
73
|
+
elsif not map
|
74
|
+
raise "Unknown category #{category}"
|
75
|
+
else
|
76
|
+
map[name] = klass
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
# Resolves the given name (should include /category/name) to
|
81
|
+
# find the plugin class and create an instance. It uses
|
82
|
+
# the same URIClassifier that the rest of Mongrel does so it
|
83
|
+
# is fast.
|
84
|
+
def create(name, options = {})
|
85
|
+
category, plugin, map = @plugins.resolve(name)
|
86
|
+
|
87
|
+
if category and plugin and plugin.length > 0
|
88
|
+
map[plugin].new(options)
|
89
|
+
else
|
90
|
+
raise "Plugin #{name} does not exist"
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
# Returns a map of URIs->[handlers] that you can
|
95
|
+
# use to investigate available handlers.
|
96
|
+
def available
|
97
|
+
map = {}
|
98
|
+
@plugins.uris.each do |u|
|
99
|
+
cat, name, plugins = @plugins.resolve(u)
|
100
|
+
map[cat] ||= []
|
101
|
+
map[cat] += plugins.keys
|
102
|
+
end
|
103
|
+
|
104
|
+
return map
|
105
|
+
end
|
106
|
+
|
107
|
+
end
|
108
|
+
|
109
|
+
# This base class for plugins reallys does nothing
|
110
|
+
# more than wire up the new class into the right category.
|
111
|
+
# It is not thread-safe yet but will be soon.
|
112
|
+
class PluginBase
|
113
|
+
|
114
|
+
attr_reader :options
|
115
|
+
|
116
|
+
|
117
|
+
# See Mongrel::Plugin for an explanation.
|
118
|
+
def PluginBase.inherited(klass)
|
119
|
+
name = "/" + klass.to_s.downcase
|
120
|
+
PluginManager.instance.register(@@category, name, klass)
|
121
|
+
@@category = nil
|
122
|
+
end
|
123
|
+
|
124
|
+
# See Mongrel::Plugin for an explanation.
|
125
|
+
def PluginBase.category=(category)
|
126
|
+
@@category = category
|
127
|
+
end
|
128
|
+
|
129
|
+
def initialize(options = {})
|
130
|
+
@options = options
|
131
|
+
end
|
132
|
+
|
133
|
+
end
|
134
|
+
|
135
|
+
# This nifty function works with the PluginBase to give you
|
136
|
+
# the syntax:
|
137
|
+
#
|
138
|
+
# class MyThing < Plugin "/things"
|
139
|
+
# ...
|
140
|
+
# end
|
141
|
+
#
|
142
|
+
# What it does is temporarily sets the PluginBase.category, and then
|
143
|
+
# returns PluginBase. Since the next immediate thing Ruby does is
|
144
|
+
# use this returned class to create the new class, PluginBase.inherited
|
145
|
+
# gets called. PluginBase.inherited then uses the set category, class name,
|
146
|
+
# and class to register the plugin in the right way.
|
147
|
+
def Mongrel::Plugin(c)
|
148
|
+
PluginBase.category = c
|
149
|
+
PluginBase
|
150
|
+
end
|
151
|
+
|
152
|
+
end
|
153
|
+
|
154
|
+
|
155
|
+
|
156
|
+
|
@@ -0,0 +1,70 @@
|
|
1
|
+
require 'mongrel'
|
2
|
+
|
3
|
+
|
4
|
+
# Implements a handler that can run Rails and serve files out of the
|
5
|
+
# Rails application's public directory. This lets you run your Rails
|
6
|
+
# application with Mongrel during development and testing, then use it
|
7
|
+
# also in production behind a server that's better at serving the
|
8
|
+
# static files.
|
9
|
+
#
|
10
|
+
# The RailsHandler takes a mime_map parameter which is a simple suffix=mimetype
|
11
|
+
# mapping that it should add to the list of valid mime types.
|
12
|
+
#
|
13
|
+
# It also supports page caching directly and will try to resolve a request
|
14
|
+
# in the following order:
|
15
|
+
#
|
16
|
+
# * If the requested exact PATH_INFO exists as a file then serve it.
|
17
|
+
# * If it exists at PATH_INFO+".html" exists then serve that.
|
18
|
+
# * Finally, construct a Mongrel::CGIWrapper and run Dispatcher.dispath to have Rails go.
|
19
|
+
#
|
20
|
+
# This means that if you are using page caching it will actually work with Mongrel
|
21
|
+
# and you should see a decent speed boost (but not as fast as if you use lighttpd).
|
22
|
+
class RailsHandler < Mongrel::HttpHandler
|
23
|
+
def initialize(dir, mime_map = {})
|
24
|
+
@files = Mongrel::DirHandler.new(dir,false)
|
25
|
+
@guard = Mutex.new
|
26
|
+
|
27
|
+
# register the requested mime types
|
28
|
+
mime_map.each {|k,v| Mongrel::DirHandler::add_mime_type(k,v) }
|
29
|
+
end
|
30
|
+
|
31
|
+
# Attempts to resolve the request as follows:
|
32
|
+
#
|
33
|
+
#
|
34
|
+
# * If the requested exact PATH_INFO exists as a file then serve it.
|
35
|
+
# * If it exists at PATH_INFO+".html" exists then serve that.
|
36
|
+
# * Finally, construct a Mongrel::CGIWrapper and run Dispatcher.dispath to have Rails go.
|
37
|
+
def process(request, response)
|
38
|
+
return if response.socket.closed?
|
39
|
+
|
40
|
+
path_info = request.params["PATH_INFO"]
|
41
|
+
page_cached = request.params["PATH_INFO"] + ".html"
|
42
|
+
|
43
|
+
if @files.can_serve(path_info)
|
44
|
+
# File exists as-is so serve it up
|
45
|
+
@files.process(request,response)
|
46
|
+
elsif @files.can_serve(page_cached)
|
47
|
+
# possible cached page, serve it up
|
48
|
+
request.params["PATH_INFO"] = page_cached
|
49
|
+
@files.process(request,response)
|
50
|
+
else
|
51
|
+
cgi = Mongrel::CGIWrapper.new(request, response)
|
52
|
+
|
53
|
+
begin
|
54
|
+
@guard.synchronize do
|
55
|
+
# Rails is not thread safe so must be run entirely within synchronize
|
56
|
+
Dispatcher.dispatch(cgi, ActionController::CgiRequest::DEFAULT_SESSION_OPTIONS, response.body)
|
57
|
+
end
|
58
|
+
|
59
|
+
# This finalizes the output using the proper HttpResponse way
|
60
|
+
cgi.out {""}
|
61
|
+
rescue Errno::EPIPE
|
62
|
+
# ignored
|
63
|
+
rescue Object => rails_error
|
64
|
+
STDERR.puts "Error calling Dispatcher.dispatch #{rails_error.inspect}"
|
65
|
+
STDERR.puts rails_error.backtrace.join("\n")
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
|
2
|
+
class First < Mongrel::Plugin "/commands"
|
3
|
+
def initialize(options = {})
|
4
|
+
puts "First with options: #{options.inspect}"
|
5
|
+
end
|
6
|
+
end
|
7
|
+
|
8
|
+
class Second < Mongrel::Plugin "/commands"
|
9
|
+
def initialize(options = {})
|
10
|
+
puts "Second with options: #{options.inspect}"
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
class Last < Mongrel::Plugin "/commands"
|
15
|
+
def initialize(options = {})
|
16
|
+
puts "Last with options: #{options.inspect}"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|