mongrel2 0.9.2 → 0.10.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -21,7 +21,7 @@
21
21
 
22
22
  <footer>
23
23
  <p>Copyright © 2011 Michael Granger &lt;<a href="mailto:ged@FaerieMUD.org">ged@FaerieMUD.org</a>&gt;.</p>
24
- <p><tt>$Id$</tt></p>
24
+ <p><tt>$Id: bootstrap.html,v 032124c021b5 2011/09/18 20:01:52 ged $</tt></p>
25
25
  </footer>
26
26
  </body>
27
27
  </html>
@@ -1,5 +1,3 @@
1
- begin transaction;
2
-
3
1
  DROP TABLE IF EXISTS server;
4
2
  DROP TABLE IF EXISTS host;
5
3
  DROP TABLE IF EXISTS handler;
@@ -9,6 +7,7 @@ DROP TABLE IF EXISTS statistic;
9
7
  DROP TABLE IF EXISTS mimetype;
10
8
  DROP TABLE IF EXISTS setting;
11
9
  DROP TABLE IF EXISTS directory;
10
+ DROP TABLE IF EXISTS filter;
12
11
 
13
12
  CREATE TABLE server (id INTEGER PRIMARY KEY,
14
13
  uuid TEXT,
@@ -53,14 +52,12 @@ CREATE TABLE route (id INTEGER PRIMARY KEY,
53
52
  target_id INTEGER,
54
53
  target_type TEXT);
55
54
 
56
-
57
55
  CREATE TABLE setting (id INTEGER PRIMARY KEY, key TEXT, value TEXT);
58
56
 
59
-
60
57
  CREATE TABLE statistic (id SERIAL,
61
58
  other_type TEXT,
62
59
  other_id INTEGER,
63
- name text,
60
+ name TEXT,
64
61
  sum REAL,
65
62
  sumsq REAL,
66
63
  n INTEGER,
@@ -70,9 +67,13 @@ CREATE TABLE statistic (id SERIAL,
70
67
  sd REAL,
71
68
  primary key (other_type, other_id, name));
72
69
 
73
-
74
70
  CREATE TABLE mimetype (id INTEGER PRIMARY KEY, mimetype TEXT, extension TEXT);
75
71
 
72
+ CREATE TABLE filter (id INTEGER PRIMARY KEY,
73
+ server_id INTEGER,
74
+ name TEXT,
75
+ settings TEXT);
76
+
76
77
  CREATE TABLE IF NOT EXISTS log(id INTEGER PRIMARY KEY,
77
78
  who TEXT,
78
79
  what TEXT,
@@ -81,4 +82,3 @@ CREATE TABLE IF NOT EXISTS log(id INTEGER PRIMARY KEY,
81
82
  how TEXT,
82
83
  why TEXT);
83
84
 
84
- commit;
data/examples/config.rb CHANGED
@@ -28,7 +28,7 @@ server '34D8E57C-3E91-4F24-9BBE-0B53C1827CB4' do
28
28
 
29
29
  access_log "/logs/access.log"
30
30
  error_log "/logs/error.log"
31
- chroot "./"
31
+ chroot "/var/mongrel2"
32
32
  pid_file "/run/mongrel2.pid"
33
33
  default_host "localhost"
34
34
  name "main"
@@ -41,14 +41,19 @@ server '34D8E57C-3E91-4F24-9BBE-0B53C1827CB4' do
41
41
  route '/source', directory( 'examples/', 'README.txt', 'text/plain' )
42
42
 
43
43
  # Handlers
44
- route '/hello', handler( 'tcp://127.0.0.1:9999', 'helloworld-handler' )
45
- route '/dump', handler( 'tcp://127.0.0.1:9997', 'request-dumper' )
44
+ route '/hello', handler( 'tcp://127.0.0.1:9999', 'helloworld-handler' )
45
+ route '/dump', handler( 'tcp://127.0.0.1:9997', 'request-dumper' )
46
46
 
47
47
  end
48
48
 
49
+ filter "/usr/local/lib/mongrel2/filters/null.so",
50
+ extensions: ["*.html", "*.txt"],
51
+ min_size: 1000
52
+
49
53
  end
50
54
 
51
- setting "zeromq.threads", 2
55
+ setting "zeromq.threads", 1
52
56
 
53
57
  mkdir_p 'run'
54
- mkdir_p 'logs'
58
+ mkdir_p 'logs'
59
+
data/lib/mongrel2.rb CHANGED
@@ -14,10 +14,10 @@ module Mongrel2
14
14
  abort "\n\n>>> Mongrel2 requires Ruby 1.9.2 or later. <<<\n\n" if RUBY_VERSION < '1.9.2'
15
15
 
16
16
  # Library version constant
17
- VERSION = '0.9.2'
17
+ VERSION = '0.10.0'
18
18
 
19
19
  # Version-control revision constant
20
- REVISION = %q$Revision: c0a5ad8a50f7 $
20
+ REVISION = %q$Revision: b3ed6f931afa $
21
21
 
22
22
 
23
23
  require 'mongrel2/logging'
@@ -1,7 +1,10 @@
1
1
  #!/usr/bin/ruby
2
2
 
3
+ require 'yajl'
4
+ require 'yaml'
3
5
  require 'pathname'
4
6
  require 'uri'
7
+ require 'tnetstring'
5
8
 
6
9
  require 'sequel'
7
10
 
@@ -45,6 +48,9 @@ module Mongrel2
45
48
 
46
49
  plugin :validation_helpers
47
50
  plugin :subclasses
51
+ plugin :json_serializer
52
+ plugin :serialization
53
+
48
54
 
49
55
  # Configuration defaults
50
56
  DEFAULTS = {
@@ -73,6 +79,12 @@ module Mongrel2
73
79
  end
74
80
 
75
81
 
82
+ # Register custom serializer/deserializer type
83
+ Sequel::Plugins::Serialization.register_format( :tnetstring,
84
+ TNetstring.method( :dump ),
85
+ lambda {|raw| TNetstring.parse( raw ).first} )
86
+
87
+
76
88
  ### Return a bound Method object to the Sequel constructor of choice for the
77
89
  ### config DB. This is used to choose either 'amalgalite' or 'sqlite3', preferring
78
90
  ### the former.
@@ -124,6 +136,18 @@ module Mongrel2
124
136
  end
125
137
 
126
138
 
139
+ ### Return a Hash of current settings from the config database. The keys are converted to
140
+ ### Symbols.
141
+ def self::settings
142
+ setting_hash = Mongrel2::Config::Setting.to_hash( :key, :value )
143
+ setting_hash.keys.each do |k|
144
+ setting_hash[ k.to_sym ] = setting_hash.delete( k )
145
+ end
146
+
147
+ return setting_hash
148
+ end
149
+
150
+
127
151
  ### Return the contents of the configuration schema SQL file.
128
152
  def self::load_config_schema
129
153
  return CONFIG_SQL.read
@@ -182,7 +206,7 @@ module Mongrel2
182
206
  def self::Config( source )
183
207
  unless Sequel::Model::ANONYMOUS_MODEL_CLASSES.key?( source )
184
208
  anonclass = nil
185
- if source.is_a?( Sequel::Database )
209
+ if source.is_a?( Sequel::Database )
186
210
  anonclass = Class.new( Mongrel2::Config )
187
211
  anonclass.db = source
188
212
  else
@@ -196,6 +220,7 @@ module Mongrel2
196
220
  end
197
221
 
198
222
  require 'mongrel2/config/directory'
223
+ require 'mongrel2/config/filter'
199
224
  require 'mongrel2/config/handler'
200
225
  require 'mongrel2/config/host'
201
226
  require 'mongrel2/config/proxy'
@@ -9,7 +9,7 @@ require 'mongrel2/config' unless defined?( Mongrel2::Config )
9
9
  #
10
10
  # This is the mongrel2.org config re-expressed in the Ruby DSL:
11
11
  #
12
- # # the server to run them all
12
+ # # the server to run them all
13
13
  # server '2f62bd5-9e59-49cd-993c-3b6013c28f05' do
14
14
  #
15
15
  # access_log "/logs/access.log"
@@ -20,29 +20,29 @@ require 'mongrel2/config' unless defined?( Mongrel2::Config )
20
20
  # name "main"
21
21
  # port 6767
22
22
  #
23
- # # your main host
23
+ # # your main host
24
24
  # host "mongrel2.org" do
25
25
  #
26
- # # a sample of doing some handlers
26
+ # # a sample of doing some handlers
27
27
  # route '@chat', handler(
28
- # 'tcp://127.0.0.1:9999',
29
- # '54c6755b-9628-40a4-9a2d-cc82a816345e',
28
+ # 'tcp://127.0.0.1:9999',
29
+ # '54c6755b-9628-40a4-9a2d-cc82a816345e',
30
30
  # 'tcp://127.0.0.1:9998'
31
- # )
31
+ # )
32
32
  #
33
33
  # route '/handlertest', handler(
34
- # 'tcp://127.0.0.1:9997',
35
- # '34f9ceee-cd52-4b7f-b197-88bf2f0ec378',
34
+ # 'tcp://127.0.0.1:9997',
35
+ # '34f9ceee-cd52-4b7f-b197-88bf2f0ec378',
36
36
  # 'tcp://127.0.0.1:9996'
37
- # )
37
+ # )
38
38
  #
39
- # # a sample proxy route
40
- # web_app_proxy = proxy( '127.0.0.1', 8080 )
39
+ # # a sample proxy route
40
+ # web_app_proxy = proxy( '127.0.0.1', 8080 )
41
41
  #
42
42
  # route '/chat/', web_app_proxy
43
43
  # route '/', web_app_proxy
44
44
  #
45
- # # here's a sample directory
45
+ # # here's a sample directory
46
46
  # test_directory = directory(
47
47
  # 'tests/',
48
48
  # :index_file => 'index.html',
@@ -53,34 +53,34 @@ require 'mongrel2/config' unless defined?( Mongrel2::Config )
53
53
  # route '/testsmulti/(.*.json)', test_directory
54
54
  #
55
55
  # chat_demo_dir = directory(
56
- # 'examples/chat/static/',
57
- # :index_file => 'index.html',
56
+ # 'examples/chat/static/',
57
+ # :index_file => 'index.html',
58
58
  # :default_ctype => 'text/plain'
59
59
  # )
60
60
  #
61
61
  # route '/chatdemo/', chat_demo_dir
62
62
  # route '/static/', chat_demo_dir
63
63
  #
64
- # route '/mp3stream', handler(
65
- # 'tcp://127.0.0.1:9995',
66
- # '53f9f1d1-1116-4751-b6ff-4fbe3e43d142',
64
+ # route '/mp3stream', handler(
65
+ # 'tcp://127.0.0.1:9995',
66
+ # '53f9f1d1-1116-4751-b6ff-4fbe3e43d142',
67
67
  # 'tcp://127.0.0.1:9994'
68
- # )
68
+ # )
69
69
  # end
70
70
  #
71
71
  # end
72
72
  #
73
73
  # settings(
74
74
  # "zeromq.threads" => 1,
75
- # "upload.temp_store" => "/home/zedshaw/projects/mongrel2/tmp/upload.XXXXXX",
76
- # "upload.temp_store_mode" => "0666"
75
+ # "upload.temp_store" => "/home/zedshaw/projects/mongrel2/tmp/upload.XXXXXX",
76
+ # "upload.temp_store_mode" => "0666"
77
77
  # )
78
78
  #
79
79
  module Mongrel2::Config::DSL
80
80
 
81
81
 
82
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
83
+ # objects. It derives its interface on the fly from columns of the class it's
84
84
  # created with and a DSLMethods mixin if the target class defines one.
85
85
  class Adapter
86
86
  include Mongrel2::Loggable
@@ -144,7 +144,7 @@ module Mongrel2::Config::DSL
144
144
  end # class Adapter
145
145
 
146
146
 
147
- ### Create a Mongrel2::Config::Server with the specified +uuid+, evaluate
147
+ ### Create a Mongrel2::Config::Server with the specified +uuid+, evaluate
148
148
  ### the block (if given) within its context, and return it.
149
149
  def server( uuid, &block )
150
150
  Mongrel2::Config.init_database
@@ -0,0 +1,24 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'tnetstring'
4
+
5
+ require 'mongrel2' unless defined?( Mongrel2 )
6
+ require 'mongrel2/config' unless defined?( Mongrel2::Config )
7
+
8
+ # Mongrel2 Host configuration class
9
+ class Mongrel2::Config::Filter < Mongrel2::Config( :filter )
10
+
11
+ ### As of Mongrel2/1.7.5:
12
+ # CREATE TABLE filter (id INTEGER PRIMARY KEY,
13
+ # server_id INTEGER,
14
+ # name TEXT,
15
+ # settings TEXT);
16
+
17
+ many_to_one :server
18
+
19
+
20
+ # Serialize the settings column as TNetStrings
21
+ plugin :serialization, :tnetstring, :settings
22
+
23
+ end # class Mongrel2::Config::Filter
24
+
@@ -1,5 +1,8 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
+ require 'uri'
4
+ require 'pathname'
5
+
3
6
  require 'mongrel2' unless defined?( Mongrel2 )
4
7
  require 'mongrel2/config' unless defined?( Mongrel2::Config )
5
8
 
@@ -21,6 +24,8 @@ class Mongrel2::Config::Server < Mongrel2::Config( :server )
21
24
  # use_ssl INTEGER default 0);
22
25
 
23
26
  one_to_many :hosts
27
+ one_to_many :filters
28
+
24
29
 
25
30
  ##
26
31
  # Look up a server by its +uuid+.
@@ -30,6 +35,40 @@ class Mongrel2::Config::Server < Mongrel2::Config( :server )
30
35
  def_dataset_method( :by_uuid ) {|uuid| filter(:uuid => uuid).first }
31
36
 
32
37
 
38
+ ### Return the URI for its control socket.
39
+ def control_socket_uri
40
+ # Find the control socket relative to the server's chroot
41
+ csock_uri = Mongrel2::Config.settings[:control_port] || DEFAULT_CONTROL_SOCKET
42
+ Mongrel2.log.debug "Chrooted control socket uri is: %p" % [ csock_uri ]
43
+
44
+ scheme, sock_path = csock_uri.split( '://', 2 )
45
+ Mongrel2.log.debug " chrooted socket path is: %p" % [ sock_path ]
46
+
47
+ csock_path = Pathname( self.chroot ) + sock_path
48
+ Mongrel2.log.debug " fully-qualified path is: %p" % [ csock_path ]
49
+ csock_uri = "%s:/%s" % [ scheme, csock_path ]
50
+
51
+ Mongrel2.log.debug " control socket URI is: %p" % [ csock_uri ]
52
+ return csock_uri
53
+ end
54
+
55
+
56
+ ### Return the Mongrel2::Control object for the server's control socket.
57
+ def control_socket
58
+ return Mongrel2::Control.new( self.control_socket_uri )
59
+ end
60
+
61
+
62
+ ### Return a Pathname for the server's PID file with its chroot directory prepended.
63
+ def pid_file_path
64
+ base = Pathname( self.chroot )
65
+ pidfile = self.pid_file
66
+ pidfile.slice!( 0, 1 ) if pidfile.start_with?( '/' )
67
+
68
+ return base + pidfile
69
+ end
70
+
71
+
33
72
  #
34
73
  # :section: Validation Callbacks
35
74
  #
@@ -41,7 +80,6 @@ class Mongrel2::Config::Server < Mongrel2::Config( :server )
41
80
  end
42
81
 
43
82
 
44
-
45
83
  ### DSL methods for the Server context besides those automatically-generated from its
46
84
  ### columns.
47
85
  module DSLMethods
@@ -58,6 +96,14 @@ class Mongrel2::Config::Server < Mongrel2::Config( :server )
58
96
  self.target.add_host( adapter.target )
59
97
  end
60
98
 
99
+ ### Add a Mongrel2::Config::Filter to the Server object with the specified
100
+ ### +path+ (name) and +settings+ hash.
101
+ def filter( path, settings={} )
102
+ self.target.save( :validate => false )
103
+
104
+ Mongrel2.log.debug "Filter [%s]: %p" % [ path, settings ]
105
+ self.target.add_filter( name: path, settings: settings )
106
+ end
61
107
 
62
108
  end # module DSLMethods
63
109
 
@@ -11,6 +11,9 @@ module Mongrel2::Constants
11
11
  # The path to the default Sqlite configuration database
12
12
  DEFAULT_CONFIG_URI = 'config.sqlite'
13
13
 
14
+ # The default URI of the control socket
15
+ DEFAULT_CONTROL_SOCKET = 'ipc://run/control'
16
+
14
17
  # Maximum number of identifiers that can be included in a broadcast response
15
18
  MAX_BROADCAST_IDENTS = 100
16
19
 
@@ -163,19 +163,19 @@ class Mongrel2::HTTPResponse < Mongrel2::Response
163
163
  ### one, or using #seek and #tell if it implements those. If neither of those are
164
164
  ### possible, an exception is raised.
165
165
  def get_content_length
166
- if @body.respond_to?( :bytesize )
167
- return @body.bytesize
168
- elsif @body.respond_to?( :seek ) && @body.respond_to?( :tell )
169
- starting_pos = @body.tell
170
- @body.seek( 0, IO::SEEK_END )
171
- length = @body.tell - starting_pos
172
- @body.seek( starting_pos, IO::SEEK_SET )
166
+ if self.body.respond_to?( :bytesize )
167
+ return self.body.bytesize
168
+ elsif self.body.respond_to?( :seek ) && self.body.respond_to?( :tell )
169
+ starting_pos = self.body.tell
170
+ self.body.seek( 0, IO::SEEK_END )
171
+ length = self.body.tell - starting_pos
172
+ self.body.seek( starting_pos, IO::SEEK_SET )
173
173
 
174
174
  return length
175
175
  else
176
176
  raise Mongrel2::ResponseError,
177
177
  "No way to calculate the content length of the response (a %s)." %
178
- [ @body.class.name ]
178
+ [ self.body.class.name ]
179
179
  end
180
180
  end
181
181
 
@@ -49,8 +49,8 @@ class Mongrel2::Response
49
49
 
50
50
  # The body of the response
51
51
  attr_accessor :body
52
- # The request that this response is for, if there is one
53
52
 
53
+ # The request that this response is for, if there is one
54
54
  attr_accessor :request
55
55
 
56
56
 
@@ -75,6 +75,7 @@ class Mongrel2::Response
75
75
  return self.body
76
76
  end
77
77
 
78
+
78
79
  ### Returns a string containing a human-readable representation of the Response,
79
80
  ### suitable for debugging.
80
81
  def inspect
@@ -41,6 +41,10 @@ class Mongrel2::Table
41
41
  end
42
42
 
43
43
 
44
+ #################################################################
45
+ ### I N S T A N C E M E T H O D S
46
+ #################################################################
47
+
44
48
  ### Create a new Mongrel2::Table using the given +hash+ for initial
45
49
  ### values.
46
50
  def initialize( initial_values={} )