mongrel2 0.9.2 → 0.10.0

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.
@@ -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={} )