mongrel2 0.0.1

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.
Files changed (70) hide show
  1. data.tar.gz.sig +0 -0
  2. data/.gemtest +0 -0
  3. data/History.rdoc +4 -0
  4. data/Manifest.txt +66 -0
  5. data/README.rdoc +169 -0
  6. data/Rakefile +77 -0
  7. data/bin/m2sh.rb +600 -0
  8. data/data/mongrel2/bootstrap.html +25 -0
  9. data/data/mongrel2/config.sql +84 -0
  10. data/data/mongrel2/mimetypes.sql +855 -0
  11. data/examples/README.txt +6 -0
  12. data/examples/config.rb +54 -0
  13. data/examples/helloworld-handler.rb +31 -0
  14. data/examples/request-dumper.rb +45 -0
  15. data/examples/request-dumper.tmpl +71 -0
  16. data/examples/run +17 -0
  17. data/lib/mongrel2.rb +62 -0
  18. data/lib/mongrel2/config.rb +212 -0
  19. data/lib/mongrel2/config/directory.rb +78 -0
  20. data/lib/mongrel2/config/dsl.rb +206 -0
  21. data/lib/mongrel2/config/handler.rb +124 -0
  22. data/lib/mongrel2/config/host.rb +88 -0
  23. data/lib/mongrel2/config/log.rb +48 -0
  24. data/lib/mongrel2/config/mimetype.rb +15 -0
  25. data/lib/mongrel2/config/proxy.rb +15 -0
  26. data/lib/mongrel2/config/route.rb +51 -0
  27. data/lib/mongrel2/config/server.rb +58 -0
  28. data/lib/mongrel2/config/setting.rb +15 -0
  29. data/lib/mongrel2/config/statistic.rb +23 -0
  30. data/lib/mongrel2/connection.rb +212 -0
  31. data/lib/mongrel2/constants.rb +159 -0
  32. data/lib/mongrel2/control.rb +165 -0
  33. data/lib/mongrel2/exceptions.rb +59 -0
  34. data/lib/mongrel2/handler.rb +309 -0
  35. data/lib/mongrel2/httprequest.rb +51 -0
  36. data/lib/mongrel2/httpresponse.rb +187 -0
  37. data/lib/mongrel2/jsonrequest.rb +43 -0
  38. data/lib/mongrel2/logging.rb +241 -0
  39. data/lib/mongrel2/mixins.rb +143 -0
  40. data/lib/mongrel2/request.rb +148 -0
  41. data/lib/mongrel2/response.rb +74 -0
  42. data/lib/mongrel2/table.rb +216 -0
  43. data/lib/mongrel2/xmlrequest.rb +36 -0
  44. data/spec/lib/constants.rb +237 -0
  45. data/spec/lib/helpers.rb +246 -0
  46. data/spec/lib/matchers.rb +50 -0
  47. data/spec/mongrel2/config/directory_spec.rb +91 -0
  48. data/spec/mongrel2/config/dsl_spec.rb +218 -0
  49. data/spec/mongrel2/config/handler_spec.rb +118 -0
  50. data/spec/mongrel2/config/host_spec.rb +30 -0
  51. data/spec/mongrel2/config/log_spec.rb +95 -0
  52. data/spec/mongrel2/config/proxy_spec.rb +30 -0
  53. data/spec/mongrel2/config/route_spec.rb +83 -0
  54. data/spec/mongrel2/config/server_spec.rb +84 -0
  55. data/spec/mongrel2/config/setting_spec.rb +30 -0
  56. data/spec/mongrel2/config/statistic_spec.rb +30 -0
  57. data/spec/mongrel2/config_spec.rb +111 -0
  58. data/spec/mongrel2/connection_spec.rb +172 -0
  59. data/spec/mongrel2/constants_spec.rb +32 -0
  60. data/spec/mongrel2/control_spec.rb +192 -0
  61. data/spec/mongrel2/handler_spec.rb +261 -0
  62. data/spec/mongrel2/httpresponse_spec.rb +232 -0
  63. data/spec/mongrel2/logging_spec.rb +76 -0
  64. data/spec/mongrel2/mixins_spec.rb +62 -0
  65. data/spec/mongrel2/request_spec.rb +157 -0
  66. data/spec/mongrel2/response_spec.rb +81 -0
  67. data/spec/mongrel2/table_spec.rb +176 -0
  68. data/spec/mongrel2_spec.rb +34 -0
  69. metadata +294 -0
  70. metadata.gz.sig +0 -0
@@ -0,0 +1,50 @@
1
+ #!/usr/bin/ruby
2
+ # coding: utf-8
3
+
4
+ BEGIN {
5
+ require 'pathname'
6
+ basedir = Pathname.new( __FILE__ ).dirname.parent
7
+
8
+ libdir = basedir + "lib"
9
+
10
+ $LOAD_PATH.unshift( libdir.to_s ) unless $LOAD_PATH.include?( libdir.to_s )
11
+ }
12
+
13
+ require 'rspec'
14
+ require 'mongrel2'
15
+
16
+
17
+ ### RSpec matchers for Mongrel2 specs
18
+ module Mongrel2::Matchers
19
+
20
+ ### A matcher for unordered array contents
21
+ class EnumerableAllBeMatcher
22
+
23
+ def initialize( expected_mod )
24
+ @expected_mod = expected_mod
25
+ end
26
+
27
+ def matches?( collection )
28
+ collection.all? {|obj| obj.is_a?(@expected_mod) }
29
+ end
30
+
31
+ def description
32
+ return "all be a kind of %p" % [ @expected_mod ]
33
+ end
34
+ end
35
+
36
+
37
+ ###############
38
+ module_function
39
+ ###############
40
+
41
+ ### Returns true if the actual value is an Array, all of which respond truly to
42
+ ### .is_a?( expected_mod )
43
+ def all_be_a( expected_mod )
44
+ EnumerableAllBeMatcher.new( expected_mod )
45
+ end
46
+
47
+
48
+ end # module Mongrel2::Matchers
49
+
50
+
@@ -0,0 +1,91 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ BEGIN {
4
+ require 'pathname'
5
+ basedir = Pathname.new( __FILE__ ).dirname.parent.parent.parent
6
+
7
+ libdir = basedir + "lib"
8
+
9
+ $LOAD_PATH.unshift( basedir ) unless $LOAD_PATH.include?( basedir )
10
+ $LOAD_PATH.unshift( libdir ) unless $LOAD_PATH.include?( libdir )
11
+ }
12
+
13
+ require 'rspec'
14
+
15
+ require 'spec/lib/helpers'
16
+
17
+ require 'mongrel2'
18
+ require 'mongrel2/config'
19
+
20
+
21
+ #####################################################################
22
+ ### C O N T E X T S
23
+ #####################################################################
24
+
25
+ describe Mongrel2::Config::Directory do
26
+
27
+ before( :all ) do
28
+ setup_logging( :fatal )
29
+ setup_config_db()
30
+ end
31
+
32
+ before( :each ) do
33
+ @dir = Mongrel2::Config::Directory.new(
34
+ :base => 'var/www/public/',
35
+ :index_file => 'index.html',
36
+ :default_ctype => 'text/plain'
37
+ )
38
+ end
39
+
40
+ after( :all ) do
41
+ reset_logging()
42
+ end
43
+
44
+
45
+ it "is valid if its base, index_file, and default_ctype are all valid" do
46
+ @dir.should be_valid()
47
+ end
48
+
49
+ it "isn't valid if it doesn't have a base" do
50
+ @dir.base = nil
51
+ @dir.should_not be_valid()
52
+ @dir.errors.full_messages.first.should =~ /missing or nil/i
53
+ end
54
+
55
+ it "isn't valid when its base starts with '/'" do
56
+ @dir.base = '/var/www/public/'
57
+ @dir.should_not be_valid()
58
+ @dir.errors.full_messages.first.should =~ %r{shouldn't start with '/'}i
59
+ end
60
+
61
+ it "isn't valid when its base doesn't end with '/'" do
62
+ @dir.base = 'var/www/public'
63
+ @dir.should_not be_valid()
64
+ @dir.errors.full_messages.first.should =~ %r{must end with '/'}i
65
+ end
66
+
67
+ it "isn't valid if it doesn't have an index file" do
68
+ @dir.index_file = nil
69
+ @dir.should_not be_valid()
70
+ @dir.errors.full_messages.first.should =~ /must not be nil/i
71
+ end
72
+
73
+ it "isn't valid if it doesn't have a default content-type" do
74
+ @dir.default_ctype = nil
75
+ @dir.should_not be_valid()
76
+ @dir.errors.full_messages.first.should =~ /must not be nil/i
77
+ end
78
+
79
+ it "isn't valid if its cache TTL is set to a negative value" do
80
+ @dir.cache_ttl = -5
81
+ @dir.should_not be_valid()
82
+ @dir.errors.full_messages.first.should =~ /not a positive integer/i
83
+ end
84
+
85
+ it "is valid if its cache TTL is set to zero" do
86
+ @dir.cache_ttl = 0
87
+ @dir.should be_valid()
88
+ end
89
+
90
+ end
91
+
@@ -0,0 +1,218 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ BEGIN {
4
+ require 'pathname'
5
+ basedir = Pathname.new( __FILE__ ).dirname.parent.parent.parent
6
+
7
+ libdir = basedir + "lib"
8
+
9
+ $LOAD_PATH.unshift( basedir ) unless $LOAD_PATH.include?( basedir )
10
+ $LOAD_PATH.unshift( libdir ) unless $LOAD_PATH.include?( libdir )
11
+ }
12
+
13
+ require 'rspec'
14
+
15
+ require 'spec/lib/helpers'
16
+
17
+ require 'mongrel2'
18
+ require 'mongrel2/config'
19
+
20
+
21
+ #####################################################################
22
+ ### C O N T E X T S
23
+ #####################################################################
24
+
25
+ describe Mongrel2::Config::DSL do
26
+
27
+ include described_class
28
+
29
+ before( :all ) do
30
+ setup_logging( :fatal )
31
+ setup_config_db()
32
+ end
33
+
34
+ after( :all ) do
35
+ reset_logging()
36
+ end
37
+
38
+
39
+ describe 'servers' do
40
+ it "can generate a default server config using the 'server' declarative" do
41
+ result = server '965A7196-99BC-46FA-945B-3478AE92BFB5'
42
+
43
+ result.should be_a( Mongrel2::Config::Server )
44
+ result.uuid.should == '965A7196-99BC-46FA-945B-3478AE92BFB5'
45
+ end
46
+
47
+
48
+ it "can generate a more-elaborate server config using the 'server' declarative with a block" do
49
+ result = server '965A7196-99BC-46FA-945B-3478AE92BFB5' do
50
+ name 'Intranet'
51
+ chroot '/service/mongrel2'
52
+ access_log '/var/log/access'
53
+ error_log '/var/log/errors'
54
+ end
55
+
56
+ result.should be_a( Mongrel2::Config::Server )
57
+ result.uuid.should == '965A7196-99BC-46FA-945B-3478AE92BFB5'
58
+ result.name.should == 'Intranet'
59
+ result.chroot.should == '/service/mongrel2'
60
+ result.access_log.should == '/var/log/access'
61
+ result.error_log.should == '/var/log/errors'
62
+ end
63
+ end
64
+
65
+ describe 'hosts' do
66
+
67
+ it "can add a host to a server config with the 'host' declarative" do
68
+ result = server '965A7196-99BC-46FA-945B-3478AE92BFB5' do
69
+
70
+ host 'localhost'
71
+
72
+ end
73
+
74
+ result.should be_a( Mongrel2::Config::Server )
75
+ result.hosts.should have( 1 ).member
76
+ host = result.hosts.first
77
+
78
+ host.should be_a( Mongrel2::Config::Host )
79
+ host.name.should == 'localhost'
80
+ end
81
+
82
+ it "can add several elaborately-configured hosts to a server via a block" do
83
+ result = server '965A7196-99BC-46FA-945B-3478AE92BFB5' do
84
+
85
+ host 'brillianttaste' do
86
+ matching '*.brillianttasteinthefoodmouth.com'
87
+
88
+ route '/images', directory( 'var/www/images/', 'index.html', 'image/jpeg' )
89
+ route '/css', directory( 'var/www/css/', 'index.html', 'text/css' )
90
+ route '/vote', proxy( 'localhost', 6667 )
91
+ route '/admin', handler(
92
+ 'tcp://127.0.0.1:9998',
93
+ 'D613E7EE-E2EB-4699-A200-5C8ECAB45D5E'
94
+ )
95
+
96
+ dir_handler = handler(
97
+ 'tcp://127.0.0.1:9996',
98
+ 'B7EFA46D-FEE4-432B-B80F-E8A9A2CC6FDB',
99
+ 'tcp://127.0.0.1:9992',
100
+ 'protocol' => 'tnetstring'
101
+ )
102
+ route '@directory', dir_handler
103
+ route '/directory', dir_handler
104
+ end
105
+
106
+ host 'deveiate.org' do
107
+ route '', directory('usr/local/deveiate/www/public/', 'index.html')
108
+ end
109
+
110
+ end
111
+
112
+ result.should be_a( Mongrel2::Config::Server )
113
+ result.hosts.should have( 2 ).members
114
+ host1, host2 = result.hosts
115
+
116
+ host1.should be_a( Mongrel2::Config::Host )
117
+ host1.name.should == 'brillianttaste'
118
+ host1.matching.should == '*.brillianttasteinthefoodmouth.com'
119
+ host1.routes.should have( 6 ).members
120
+ host1.routes.should all_be_a( Mongrel2::Config::Route )
121
+
122
+ host1.routes[0].path.should == '/images'
123
+ host1.routes[0].target.should be_a( Mongrel2::Config::Directory )
124
+ host1.routes[0].target.base.should == 'var/www/images/'
125
+
126
+ host1.routes[1].path.should == '/css'
127
+ host1.routes[1].target.should be_a( Mongrel2::Config::Directory )
128
+ host1.routes[1].target.base.should == 'var/www/css/'
129
+
130
+ host1.routes[2].path.should == '/vote'
131
+ host1.routes[2].target.should be_a( Mongrel2::Config::Proxy )
132
+ host1.routes[2].target.addr.should == 'localhost'
133
+ host1.routes[2].target.port.should == 6667
134
+
135
+ host1.routes[3].path.should == '/admin'
136
+ host1.routes[3].target.should be_a( Mongrel2::Config::Handler )
137
+ host1.routes[3].target.send_ident.should == 'D613E7EE-E2EB-4699-A200-5C8ECAB45D5E'
138
+ host1.routes[3].target.send_spec.should == 'tcp://127.0.0.1:9998'
139
+ host1.routes[3].target.recv_ident.should == ''
140
+ host1.routes[3].target.recv_spec.should == 'tcp://127.0.0.1:9997'
141
+
142
+ host1.routes[4].path.should == '@directory'
143
+ host1.routes[4].target.should be_a( Mongrel2::Config::Handler )
144
+ host1.routes[4].target.send_ident.should == 'B7EFA46D-FEE4-432B-B80F-E8A9A2CC6FDB'
145
+ host1.routes[4].target.send_spec.should == 'tcp://127.0.0.1:9996'
146
+ host1.routes[4].target.recv_spec.should == 'tcp://127.0.0.1:9992'
147
+ host1.routes[4].target.recv_ident.should == ''
148
+ host1.routes[4].target.protocol.should == 'tnetstring'
149
+
150
+ host1.routes[5].path.should == '/directory'
151
+ host1.routes[5].target.should == host1.routes[4].target
152
+
153
+ host2.should be_a( Mongrel2::Config::Host )
154
+ host2.name.should == 'deveiate.org'
155
+ host2.routes.should have( 1 ).member
156
+ host2.routes.first.should be_a( Mongrel2::Config::Route )
157
+ end
158
+
159
+
160
+ end
161
+
162
+ describe 'settings' do
163
+
164
+ it "can set the expert tweakable settings en masse" do
165
+ result = settings(
166
+ "zeromq.threads" => 8,
167
+ "upload.temp_store" => "/home/zedshaw/projects/mongrel2/tmp/upload.XXXXXX",
168
+ "upload.temp_store_mode" => "0666"
169
+ )
170
+
171
+ result.should be_an( Array )
172
+ result.should have( 3 ).members
173
+ result.should all_be_a( Mongrel2::Config::Setting )
174
+ result[0].key.should == 'zeromq.threads'
175
+ result[0].value.should == '8'
176
+ result[1].key.should == 'upload.temp_store'
177
+ result[1].value.should == '/home/zedshaw/projects/mongrel2/tmp/upload.XXXXXX'
178
+ result[2].key.should == 'upload.temp_store_mode'
179
+ result[2].value.should == '0666'
180
+ end
181
+
182
+ it "can set a single expert setting" do
183
+ result = setting "zeromq.threads", 16
184
+ result.should be_a( Mongrel2::Config::Setting )
185
+ result.key.should == 'zeromq.threads'
186
+ result.value.should == '16'
187
+ end
188
+
189
+ end
190
+
191
+ describe 'mimetypes' do
192
+
193
+ it "can set new mimetype mappings en masse" do
194
+ result = mimetypes(
195
+ '.md' => 'text/x-markdown',
196
+ '.textile' => 'text/x-textile'
197
+ )
198
+
199
+ result.should be_an( Array )
200
+ result.should have( 2 ).members
201
+ result.should all_be_a( Mongrel2::Config::Mimetype )
202
+ result[0].extension.should == '.md'
203
+ result[0].mimetype.should == 'text/x-markdown'
204
+ result[1].extension.should == '.textile'
205
+ result[1].mimetype.should == 'text/x-textile'
206
+ end
207
+
208
+ it "can set a single mimetype mapping" do
209
+ result = mimetype '.tmpl', 'text/x-inversion-template'
210
+ result.should be_a( Mongrel2::Config::Mimetype )
211
+ result.extension.should == '.tmpl'
212
+ result.mimetype.should == 'text/x-inversion-template'
213
+ end
214
+
215
+ end
216
+
217
+ end
218
+
@@ -0,0 +1,118 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ BEGIN {
4
+ require 'pathname'
5
+ basedir = Pathname.new( __FILE__ ).dirname.parent.parent.parent
6
+
7
+ libdir = basedir + "lib"
8
+
9
+ $LOAD_PATH.unshift( basedir ) unless $LOAD_PATH.include?( basedir )
10
+ $LOAD_PATH.unshift( libdir ) unless $LOAD_PATH.include?( libdir )
11
+ }
12
+
13
+ require 'rspec'
14
+
15
+ require 'spec/lib/helpers'
16
+
17
+ require 'mongrel2'
18
+ require 'mongrel2/config'
19
+
20
+
21
+ #####################################################################
22
+ ### C O N T E X T S
23
+ #####################################################################
24
+
25
+ describe Mongrel2::Config::Handler do
26
+
27
+ before( :all ) do
28
+ setup_logging( :fatal )
29
+ setup_config_db()
30
+ end
31
+
32
+ before( :each ) do
33
+ @handler = Mongrel2::Config::Handler.new(
34
+ :send_spec => TEST_SEND_SPEC,
35
+ :send_ident => TEST_UUID,
36
+ :recv_spec => TEST_RECV_SPEC,
37
+ :recv_ident => ''
38
+ )
39
+ end
40
+
41
+ after( :all ) do
42
+ reset_logging()
43
+ end
44
+
45
+ it "is valid if its specs and identities are all valid" do
46
+ @handler.should be_valid()
47
+ end
48
+
49
+
50
+ it "isn't valid if it doesn't have a send_spec" do
51
+ @handler.send_spec = nil
52
+ @handler.should_not be_valid()
53
+ @handler.errors.full_messages.first.should =~ /must not be nil/i
54
+ end
55
+
56
+ it "isn't valid if it doesn't have a recv_spec" do
57
+ @handler.recv_spec = nil
58
+ @handler.should_not be_valid()
59
+ @handler.errors.full_messages.first.should =~ /must not be nil/i
60
+ end
61
+
62
+
63
+ it "isn't valid if it doesn't have a valid URL in its send_spec" do
64
+ @handler.send_spec = 'carrier pigeon'
65
+ @handler.should_not be_valid()
66
+ @handler.errors.full_messages.first.should =~ /not a uri/i
67
+ end
68
+
69
+ it "isn't valid if it doesn't have a valid URL in its recv_spec" do
70
+ @handler.recv_spec = 'smoke signals'
71
+ @handler.should_not be_valid()
72
+ @handler.errors.full_messages.first.should =~ /not a uri/i
73
+ end
74
+
75
+
76
+ it "isn't valid if has an unsupported transport in its send_spec" do
77
+ @handler.send_spec = 'inproc://application'
78
+ @handler.should_not be_valid()
79
+ @handler.errors.full_messages.first.should =~ /invalid 0mq transport/i
80
+ end
81
+
82
+ it "isn't valid if has an unsupported transport in its recv_spec" do
83
+ @handler.recv_spec = 'inproc://application'
84
+ @handler.should_not be_valid()
85
+ @handler.errors.full_messages.first.should =~ /invalid 0mq transport/i
86
+ end
87
+
88
+
89
+ it "isn't valid if it doesn't have a send_ident" do
90
+ @handler.send_ident = nil
91
+ @handler.should_not be_valid()
92
+ @handler.errors.full_messages.first.should =~ /invalid sender identity/i
93
+ end
94
+
95
+ it "*is* valid if it doesn't have a recv_ident" do
96
+ @handler.recv_ident = nil
97
+ @handler.should be_valid()
98
+ end
99
+
100
+
101
+ it "is valid if it has 'json' set as the protocol" do
102
+ @handler.protocol = 'json'
103
+ @handler.should be_valid()
104
+ end
105
+
106
+ it "is valid if it has 'tnetstring' set as the protocol" do
107
+ @handler.protocol = 'tnetstring'
108
+ @handler.should be_valid()
109
+ end
110
+
111
+ it "isn't valid if it has an invalid protocol" do
112
+ @handler.protocol = 'morsecode'
113
+ @handler.should_not be_valid()
114
+ @handler.errors.full_messages.first.should =~ /invalid/i
115
+ end
116
+
117
+ end
118
+