mongrel2 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data.tar.gz.sig +0 -0
- data/.gemtest +0 -0
- data/History.rdoc +4 -0
- data/Manifest.txt +66 -0
- data/README.rdoc +169 -0
- data/Rakefile +77 -0
- data/bin/m2sh.rb +600 -0
- data/data/mongrel2/bootstrap.html +25 -0
- data/data/mongrel2/config.sql +84 -0
- data/data/mongrel2/mimetypes.sql +855 -0
- data/examples/README.txt +6 -0
- data/examples/config.rb +54 -0
- data/examples/helloworld-handler.rb +31 -0
- data/examples/request-dumper.rb +45 -0
- data/examples/request-dumper.tmpl +71 -0
- data/examples/run +17 -0
- data/lib/mongrel2.rb +62 -0
- data/lib/mongrel2/config.rb +212 -0
- data/lib/mongrel2/config/directory.rb +78 -0
- data/lib/mongrel2/config/dsl.rb +206 -0
- data/lib/mongrel2/config/handler.rb +124 -0
- data/lib/mongrel2/config/host.rb +88 -0
- data/lib/mongrel2/config/log.rb +48 -0
- data/lib/mongrel2/config/mimetype.rb +15 -0
- data/lib/mongrel2/config/proxy.rb +15 -0
- data/lib/mongrel2/config/route.rb +51 -0
- data/lib/mongrel2/config/server.rb +58 -0
- data/lib/mongrel2/config/setting.rb +15 -0
- data/lib/mongrel2/config/statistic.rb +23 -0
- data/lib/mongrel2/connection.rb +212 -0
- data/lib/mongrel2/constants.rb +159 -0
- data/lib/mongrel2/control.rb +165 -0
- data/lib/mongrel2/exceptions.rb +59 -0
- data/lib/mongrel2/handler.rb +309 -0
- data/lib/mongrel2/httprequest.rb +51 -0
- data/lib/mongrel2/httpresponse.rb +187 -0
- data/lib/mongrel2/jsonrequest.rb +43 -0
- data/lib/mongrel2/logging.rb +241 -0
- data/lib/mongrel2/mixins.rb +143 -0
- data/lib/mongrel2/request.rb +148 -0
- data/lib/mongrel2/response.rb +74 -0
- data/lib/mongrel2/table.rb +216 -0
- data/lib/mongrel2/xmlrequest.rb +36 -0
- data/spec/lib/constants.rb +237 -0
- data/spec/lib/helpers.rb +246 -0
- data/spec/lib/matchers.rb +50 -0
- data/spec/mongrel2/config/directory_spec.rb +91 -0
- data/spec/mongrel2/config/dsl_spec.rb +218 -0
- data/spec/mongrel2/config/handler_spec.rb +118 -0
- data/spec/mongrel2/config/host_spec.rb +30 -0
- data/spec/mongrel2/config/log_spec.rb +95 -0
- data/spec/mongrel2/config/proxy_spec.rb +30 -0
- data/spec/mongrel2/config/route_spec.rb +83 -0
- data/spec/mongrel2/config/server_spec.rb +84 -0
- data/spec/mongrel2/config/setting_spec.rb +30 -0
- data/spec/mongrel2/config/statistic_spec.rb +30 -0
- data/spec/mongrel2/config_spec.rb +111 -0
- data/spec/mongrel2/connection_spec.rb +172 -0
- data/spec/mongrel2/constants_spec.rb +32 -0
- data/spec/mongrel2/control_spec.rb +192 -0
- data/spec/mongrel2/handler_spec.rb +261 -0
- data/spec/mongrel2/httpresponse_spec.rb +232 -0
- data/spec/mongrel2/logging_spec.rb +76 -0
- data/spec/mongrel2/mixins_spec.rb +62 -0
- data/spec/mongrel2/request_spec.rb +157 -0
- data/spec/mongrel2/response_spec.rb +81 -0
- data/spec/mongrel2/table_spec.rb +176 -0
- data/spec/mongrel2_spec.rb +34 -0
- metadata +294 -0
- metadata.gz.sig +0 -0
@@ -0,0 +1,78 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'mongrel2' unless defined?( Mongrel2 )
|
4
|
+
require 'mongrel2/config' unless defined?( Mongrel2::Config )
|
5
|
+
|
6
|
+
# Mongrel2 Directory (Dir) configuration class
|
7
|
+
class Mongrel2::Config::Directory < Mongrel2::Config( :directory )
|
8
|
+
|
9
|
+
### As of Mongrel2/1.7.5:
|
10
|
+
# CREATE TABLE directory (id INTEGER PRIMARY KEY,
|
11
|
+
# base TEXT,
|
12
|
+
# index_file TEXT,
|
13
|
+
# default_ctype TEXT,
|
14
|
+
# cache_ttl INTEGER DEFAULT 0);
|
15
|
+
|
16
|
+
### Sequel validation callback: add errors if the record is invalid.
|
17
|
+
def validate
|
18
|
+
self.validate_base
|
19
|
+
self.validate_index_file
|
20
|
+
self.validate_default_ctype
|
21
|
+
self.validate_cache_ttl
|
22
|
+
end
|
23
|
+
|
24
|
+
|
25
|
+
#########
|
26
|
+
protected
|
27
|
+
#########
|
28
|
+
|
29
|
+
### Validate the 'base' directory which will be served.
|
30
|
+
def validate_base
|
31
|
+
if self.base
|
32
|
+
if self.base.start_with?( '/' )
|
33
|
+
errmsg = "[%p]: shouldn't start with '/'; that will fail when not in chroot." %
|
34
|
+
[ self.base ]
|
35
|
+
self.log.error( 'base ' + errmsg )
|
36
|
+
self.errors.add( :base, errmsg )
|
37
|
+
end
|
38
|
+
|
39
|
+
unless self.base.end_with?( '/' )
|
40
|
+
errmsg = "[%p]: must end with '/' or it won't work right." %
|
41
|
+
[ self.base ]
|
42
|
+
self.log.error( 'base ' + errmsg )
|
43
|
+
self.errors.add( :base, errmsg )
|
44
|
+
end
|
45
|
+
else
|
46
|
+
errmsg = "missing or nil"
|
47
|
+
self.log.error( 'base ' + errmsg )
|
48
|
+
self.errors.add( :base, errmsg )
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
|
53
|
+
### Validate the 'index_file' attribute.
|
54
|
+
def validate_index_file
|
55
|
+
self.validates_presence( :index_file, :message => "must not be nil" )
|
56
|
+
end
|
57
|
+
|
58
|
+
|
59
|
+
### Validate the index file attribute.
|
60
|
+
def validate_default_ctype
|
61
|
+
self.validates_presence( :default_ctype, :message => "must not be nil" )
|
62
|
+
end
|
63
|
+
|
64
|
+
|
65
|
+
### Validate the cache TTL if one is set.
|
66
|
+
def validate_cache_ttl
|
67
|
+
if self.cache_ttl && Integer( self.cache_ttl ) < 0
|
68
|
+
errmsg = "[%p]: not a positive Integer" % [ self.cache_ttl ]
|
69
|
+
self.log.error( 'cache_ttl' + errmsg )
|
70
|
+
self.errors.add( :cache_ttl, errmsg )
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
|
75
|
+
|
76
|
+
|
77
|
+
end # class Mongrel2::Config::Directory
|
78
|
+
|
@@ -0,0 +1,206 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'mongrel2' unless defined?( Mongrel2 )
|
4
|
+
require 'mongrel2/config' unless defined?( Mongrel2::Config )
|
5
|
+
|
6
|
+
# Mongrel2 configuration DSL mixin
|
7
|
+
#
|
8
|
+
# == Example
|
9
|
+
#
|
10
|
+
# This is the mongrel2.org config re-expressed in the Ruby DSL:
|
11
|
+
#
|
12
|
+
# # the server to run them all
|
13
|
+
# server '2f62bd5-9e59-49cd-993c-3b6013c28f05' do
|
14
|
+
#
|
15
|
+
# access_log "/logs/access.log"
|
16
|
+
# error_log "/logs/error.log"
|
17
|
+
# chroot "./"
|
18
|
+
# pid_file "/run/mongrel2.pid"
|
19
|
+
# default_host "mongrel2.org"
|
20
|
+
# name "main"
|
21
|
+
# port 6767
|
22
|
+
#
|
23
|
+
# # your main host
|
24
|
+
# host "mongrel2.org" do
|
25
|
+
#
|
26
|
+
# # a sample of doing some handlers
|
27
|
+
# route '@chat', handler(
|
28
|
+
# 'tcp://127.0.0.1:9999',
|
29
|
+
# '54c6755b-9628-40a4-9a2d-cc82a816345e',
|
30
|
+
# 'tcp://127.0.0.1:9998'
|
31
|
+
# )
|
32
|
+
#
|
33
|
+
# route '/handlertest', handler(
|
34
|
+
# 'tcp://127.0.0.1:9997',
|
35
|
+
# '34f9ceee-cd52-4b7f-b197-88bf2f0ec378',
|
36
|
+
# 'tcp://127.0.0.1:9996'
|
37
|
+
# )
|
38
|
+
#
|
39
|
+
# # a sample proxy route
|
40
|
+
# web_app_proxy = proxy( '127.0.0.1', 8080 )
|
41
|
+
#
|
42
|
+
# route '/chat/', web_app_proxy
|
43
|
+
# route '/', web_app_proxy
|
44
|
+
#
|
45
|
+
# # here's a sample directory
|
46
|
+
# test_directory = directory(
|
47
|
+
# 'tests/',
|
48
|
+
# :index_file => 'index.html',
|
49
|
+
# :default_ctype => 'text/plain'
|
50
|
+
# )
|
51
|
+
#
|
52
|
+
# route '/tests/', test_directory
|
53
|
+
# route '/testsmulti/(.*.json)', test_directory
|
54
|
+
#
|
55
|
+
# chat_demo_dir = directory(
|
56
|
+
# 'examples/chat/static/',
|
57
|
+
# :index_file => 'index.html',
|
58
|
+
# :default_ctype => 'text/plain'
|
59
|
+
# )
|
60
|
+
#
|
61
|
+
# route '/chatdemo/', chat_demo_dir
|
62
|
+
# route '/static/', chat_demo_dir
|
63
|
+
#
|
64
|
+
# route '/mp3stream', handler(
|
65
|
+
# 'tcp://127.0.0.1:9995',
|
66
|
+
# '53f9f1d1-1116-4751-b6ff-4fbe3e43d142',
|
67
|
+
# 'tcp://127.0.0.1:9994'
|
68
|
+
# )
|
69
|
+
# end
|
70
|
+
#
|
71
|
+
# end
|
72
|
+
#
|
73
|
+
# settings(
|
74
|
+
# "zeromq.threads" => 1,
|
75
|
+
# "upload.temp_store" => "/home/zedshaw/projects/mongrel2/tmp/upload.XXXXXX",
|
76
|
+
# "upload.temp_store_mode" => "0666"
|
77
|
+
# )
|
78
|
+
#
|
79
|
+
module Mongrel2::Config::DSL
|
80
|
+
|
81
|
+
|
82
|
+
# A decorator object that provides the DSL-ish interface to the various Config
|
83
|
+
# objects. It derives its interface on the fly from columns of the class it's
|
84
|
+
# created with and a DSLMethods mixin if the target class defines one.
|
85
|
+
class Adapter
|
86
|
+
include Mongrel2::Loggable
|
87
|
+
|
88
|
+
### Adapt the specified +target+ to use a declarative interface.
|
89
|
+
def initialize( targetclass, opts={} )
|
90
|
+
self.log.debug "Wrapping a %p" % [ targetclass ]
|
91
|
+
@targetclass = targetclass
|
92
|
+
@target = @targetclass.new( opts )
|
93
|
+
self.decorate_with_column_declaratives( @target )
|
94
|
+
self.decorate_with_custom_declaratives( @targetclass )
|
95
|
+
end
|
96
|
+
|
97
|
+
|
98
|
+
######
|
99
|
+
public
|
100
|
+
######
|
101
|
+
|
102
|
+
# The decorated object
|
103
|
+
attr_reader :target
|
104
|
+
|
105
|
+
|
106
|
+
### Backport the singleton_class method if there isn't one.
|
107
|
+
unless instance_methods.include?( :singleton_class )
|
108
|
+
def singleton_class
|
109
|
+
class << self; self; end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
### Add a declarative singleton method for the columns of the +adapted_object+.
|
114
|
+
def decorate_with_column_declaratives( adapted_object )
|
115
|
+
columns = adapted_object.columns
|
116
|
+
self.log.debug " decorating for columns: %s" % [ columns.map( &:to_s ).sort.join(', ') ]
|
117
|
+
|
118
|
+
columns.each do |colname|
|
119
|
+
|
120
|
+
# Create a method that will act as a writer if called with an
|
121
|
+
# argument, and a reader if not.
|
122
|
+
method_body = Proc.new do |*args|
|
123
|
+
if args.empty?
|
124
|
+
self.target.send( colname )
|
125
|
+
else
|
126
|
+
self.target.send( "#{colname}=", *args )
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
# Install the method
|
131
|
+
self.singleton_class.send( :define_method, colname, &method_body )
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
|
136
|
+
### Mix in methods defined by the "DSLMethods" mixin defined by the class
|
137
|
+
### of the object being adapted.
|
138
|
+
def decorate_with_custom_declaratives( objectclass )
|
139
|
+
return unless objectclass.const_defined?( :DSLMethods )
|
140
|
+
self.singleton_class.send( :include, objectclass.const_get(:DSLMethods) )
|
141
|
+
end
|
142
|
+
|
143
|
+
|
144
|
+
end # class Adapter
|
145
|
+
|
146
|
+
|
147
|
+
### Create a Mongrel2::Config::Server with the specified +uuid+, evaluate
|
148
|
+
### the block (if given) within its context, and return it.
|
149
|
+
def server( uuid, &block )
|
150
|
+
Mongrel2::Config.init_database
|
151
|
+
|
152
|
+
Mongrel2.log.debug "Server [%s] (block: %p)" % [ uuid, block ]
|
153
|
+
adapter = Adapter.new( Mongrel2::Config::Server, :uuid => uuid )
|
154
|
+
adapter.instance_eval( &block ) if block
|
155
|
+
return adapter.target
|
156
|
+
end
|
157
|
+
|
158
|
+
|
159
|
+
### Set the value of one of the 'Tweakable Expert Settings'
|
160
|
+
def setting( key, val )
|
161
|
+
Mongrel2::Config.init_database
|
162
|
+
return Mongrel2::Config::Setting.create( :key => key, :value => val )
|
163
|
+
end
|
164
|
+
|
165
|
+
|
166
|
+
### Set some 'Tweakable Expert Settings' en masse
|
167
|
+
def settings( hash )
|
168
|
+
result = []
|
169
|
+
|
170
|
+
Mongrel2::Config.db.transaction do
|
171
|
+
hash.each do |key, val|
|
172
|
+
result << setting( key, val )
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
return result
|
177
|
+
end
|
178
|
+
|
179
|
+
|
180
|
+
### Set up a mimetype mapping between files with the given +extension+ and +mimetype+.
|
181
|
+
def mimetype( extension, mimetype )
|
182
|
+
Mongrel2::Config.init_database
|
183
|
+
|
184
|
+
type = Mongrel2::Config::Mimetype.find_or_create( :extension => extension )
|
185
|
+
type.mimetype = mimetype
|
186
|
+
type.save
|
187
|
+
|
188
|
+
return type
|
189
|
+
end
|
190
|
+
|
191
|
+
|
192
|
+
### Set some mimetypes en masse.
|
193
|
+
def mimetypes( hash )
|
194
|
+
result = []
|
195
|
+
|
196
|
+
Mongrel2::Config.db.transaction do
|
197
|
+
hash.each do |ext, mimetype|
|
198
|
+
result << mimetype( ext, mimetype )
|
199
|
+
end
|
200
|
+
end
|
201
|
+
|
202
|
+
return result
|
203
|
+
end
|
204
|
+
|
205
|
+
end # module Mongrel2::Config::DSL
|
206
|
+
|
@@ -0,0 +1,124 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'mongrel2' unless defined?( Mongrel2 )
|
4
|
+
require 'mongrel2/config' unless defined?( Mongrel2::Config )
|
5
|
+
|
6
|
+
# Mongrel2 Handler configuration class
|
7
|
+
class Mongrel2::Config::Handler < Mongrel2::Config( :handler )
|
8
|
+
|
9
|
+
### As of Mongrel2/1.7.5:
|
10
|
+
# CREATE TABLE handler (id INTEGER PRIMARY KEY,
|
11
|
+
# send_spec TEXT,
|
12
|
+
# send_ident TEXT,
|
13
|
+
# recv_spec TEXT,
|
14
|
+
# recv_ident TEXT,
|
15
|
+
# raw_payload INTEGER DEFAULT 0,
|
16
|
+
# protocol TEXT DEFAULT 'json');
|
17
|
+
|
18
|
+
|
19
|
+
# The list of 0mq transports Mongrel2 can use; "You need to use the
|
20
|
+
# ZeroMQ syntax for configuring them, but this means with one
|
21
|
+
# configuration format you can use handlers that are using UDP, TCP,
|
22
|
+
# Unix, or PGM transports." Note that I'm assuming by 'udp' Zed means
|
23
|
+
# 'epgm', as I can't find any udp 0mq transport.
|
24
|
+
VALID_SPEC_SCHEMES = %w[epgm tcp ipc pgm]
|
25
|
+
|
26
|
+
# The list of valid protocols
|
27
|
+
#--
|
28
|
+
# handler.h: typedef enum { HANDLER_PROTO_JSON, HANDLER_PROTO_TNET } handler_protocol_t;
|
29
|
+
VALID_PROTOCOLS = %w[json tnetstring]
|
30
|
+
|
31
|
+
|
32
|
+
##
|
33
|
+
# :method: by_send_ident( uuid )
|
34
|
+
#
|
35
|
+
# Look up a Handler by its send_ident, which should be a +uuid+ or similar String.
|
36
|
+
def_dataset_method( :by_send_ident ) do |ident|
|
37
|
+
filter( :send_ident => ident )
|
38
|
+
end
|
39
|
+
|
40
|
+
|
41
|
+
### Validate the object prior to saving it.
|
42
|
+
def validate
|
43
|
+
self.validate_idents
|
44
|
+
self.validate_specs
|
45
|
+
self.validate_protocol
|
46
|
+
end
|
47
|
+
|
48
|
+
|
49
|
+
#########
|
50
|
+
protected
|
51
|
+
#########
|
52
|
+
|
53
|
+
### Turn nil recv_ident values into the empty string before validating.
|
54
|
+
def before_validation
|
55
|
+
self.recv_ident ||= ''
|
56
|
+
end
|
57
|
+
|
58
|
+
|
59
|
+
### Validate the send_ident and recv_ident
|
60
|
+
### --
|
61
|
+
### :FIXME: I'm not sure if this is actually necessary, but it seems like
|
62
|
+
### the ident should at least be UUID-like like the server ident.
|
63
|
+
def validate_idents
|
64
|
+
unless self.send_ident =~ /^\w[\w\-]+$/
|
65
|
+
errmsg = "[%p]: invalid sender identity (should be UUID-like)" % [ self.send_ident ]
|
66
|
+
self.log.error( 'send_ident: ' + errmsg )
|
67
|
+
self.errors.add( :send_ident, errmsg )
|
68
|
+
end
|
69
|
+
|
70
|
+
unless self.recv_ident == '' || self.send_ident =~ /^\w[\w\-]+$/
|
71
|
+
errmsg = "[%p]: invalid receiver identity (should be empty string or UUID-like)" %
|
72
|
+
[ self.recv_ident ]
|
73
|
+
self.log.error( 'send_ident: ' + errmsg )
|
74
|
+
self.errors.add( :send_ident, errmsg )
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
|
79
|
+
### Validate the send_spec and recv_spec.
|
80
|
+
def validate_specs
|
81
|
+
if err = check_0mq_spec( self.send_spec )
|
82
|
+
errmsg = "[%p]: %s" % [ self.send_spec, err ]
|
83
|
+
self.log.error( 'send_spec: ' + errmsg )
|
84
|
+
self.errors.add( :recv_spec, errmsg )
|
85
|
+
end
|
86
|
+
|
87
|
+
if err = check_0mq_spec( self.recv_spec )
|
88
|
+
errmsg = "[%p]: %s" % [ self.recv_spec, err ]
|
89
|
+
self.log.error( 'recv_spec: ' + errmsg )
|
90
|
+
self.errors.add( :recv_spec, errmsg )
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
|
95
|
+
### Validate the handler's protocol.
|
96
|
+
def validate_protocol
|
97
|
+
return unless self.protocol # nil == default
|
98
|
+
unless VALID_PROTOCOLS.include?( self.protocol )
|
99
|
+
errmsg = "[%p]: invalid" % [ self.protocol ]
|
100
|
+
self.log.error( 'protocol: ' + errmsg )
|
101
|
+
self.errors.add( :protocol, errmsg )
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
|
106
|
+
|
107
|
+
#######
|
108
|
+
private
|
109
|
+
#######
|
110
|
+
|
111
|
+
### Returns +true+ if +url+ is a valid 0mq transport specification.
|
112
|
+
def check_0mq_spec( url )
|
113
|
+
return "must not be nil" unless url
|
114
|
+
|
115
|
+
u = URI( url )
|
116
|
+
return "invalid 0mq transport #{u.scheme}" unless VALID_SPEC_SCHEMES.include?( u.scheme )
|
117
|
+
|
118
|
+
return nil
|
119
|
+
rescue URI::InvalidURIError
|
120
|
+
return 'not a URI; should be something like "tcp://127.0.0.1:9998"'
|
121
|
+
end
|
122
|
+
|
123
|
+
end # class Mongrel2::Config::Handler
|
124
|
+
|
@@ -0,0 +1,88 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'mongrel2' unless defined?( Mongrel2 )
|
4
|
+
require 'mongrel2/config' unless defined?( Mongrel2::Config )
|
5
|
+
|
6
|
+
# Mongrel2 Host configuration class
|
7
|
+
class Mongrel2::Config::Host < Mongrel2::Config( :host )
|
8
|
+
|
9
|
+
### As of Mongrel2/1.7.5:
|
10
|
+
# CREATE TABLE host (id INTEGER PRIMARY KEY,
|
11
|
+
# server_id INTEGER,
|
12
|
+
# maintenance BOOLEAN DEFAULT 0,
|
13
|
+
# name TEXT,
|
14
|
+
# matching TEXT);
|
15
|
+
|
16
|
+
one_to_many :routes
|
17
|
+
many_to_one :server
|
18
|
+
|
19
|
+
### DSL methods for the Server context besides those automatically-generated from its
|
20
|
+
### columns.
|
21
|
+
module DSLMethods
|
22
|
+
|
23
|
+
### Add a Mongrel2::Config::Route to the Host object.
|
24
|
+
def route( path, target, opts={} )
|
25
|
+
self.target.save
|
26
|
+
Mongrel2.log.debug "Route %s -> %p [%p]" % [ path, target, opts ]
|
27
|
+
|
28
|
+
args = { :path => path, :target => target }
|
29
|
+
args.merge!( opts )
|
30
|
+
route = Mongrel2::Config::Route.new( args )
|
31
|
+
|
32
|
+
self.target.add_route( route )
|
33
|
+
end
|
34
|
+
|
35
|
+
|
36
|
+
# These are route _arguments_, so they need to be declared in Host's scope rather
|
37
|
+
# than Route's.
|
38
|
+
|
39
|
+
### Create a new Mongrel2::Config::Directory object for the specified +base+ and
|
40
|
+
### return it.
|
41
|
+
def directory( base, index_file, default_ctype='text/plain', opts={} )
|
42
|
+
opts.merge!( :base => base, :index_file => index_file, :default_ctype => default_ctype )
|
43
|
+
return Mongrel2::Config::Directory.create( opts )
|
44
|
+
end
|
45
|
+
|
46
|
+
|
47
|
+
### Create a new Mongrel2::Config::Proxy object for the specified +addr+ and
|
48
|
+
### +port+ and return it.
|
49
|
+
def proxy( addr, port=80 )
|
50
|
+
return Mongrel2::Config::Proxy.create( :addr => addr, :port => port )
|
51
|
+
end
|
52
|
+
|
53
|
+
|
54
|
+
### Create a new Mongrel2::Config::Handler object with the specified +send_spec+,
|
55
|
+
### +send_ident+, +recv_spec+, +recv_ident+, and +options+ and return it.
|
56
|
+
def handler( send_spec, send_ident, recv_spec=nil, recv_ident='', options={} )
|
57
|
+
# Shift the opts hash over if the other optional args were omitted
|
58
|
+
if recv_spec.is_a?( Hash )
|
59
|
+
options = recv_spec
|
60
|
+
recv_spec = nil
|
61
|
+
elsif recv_ident.is_a?( Hash )
|
62
|
+
options = recv_ident
|
63
|
+
recv_ident = ''
|
64
|
+
end
|
65
|
+
|
66
|
+
# Default to one port below the request spec
|
67
|
+
unless recv_spec
|
68
|
+
port = send_spec[ /:(\d+)$/, 1 ] or
|
69
|
+
"Can't guess default port for a send_spec without one (%p)" % [ send_spec ]
|
70
|
+
recv_spec = URI( send_spec )
|
71
|
+
recv_spec.port = port.to_i - 1
|
72
|
+
end
|
73
|
+
|
74
|
+
options.merge!(
|
75
|
+
:send_spec => send_spec.to_s,
|
76
|
+
:send_ident => send_ident,
|
77
|
+
:recv_spec => recv_spec.to_s,
|
78
|
+
:recv_ident => recv_ident
|
79
|
+
)
|
80
|
+
|
81
|
+
Mongrel2.log.debug "Creating handler with options: %p" % [ options ]
|
82
|
+
return Mongrel2::Config::Handler.create( options )
|
83
|
+
end
|
84
|
+
|
85
|
+
end # module DSLMethods
|
86
|
+
|
87
|
+
end # class Mongrel2::Config::Host
|
88
|
+
|