mongrel2 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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
+