mongrel2 0.25.0 → 0.26.0

Sign up to get free protection for your applications and to get access to all the features.
data.tar.gz.sig CHANGED
Binary file
data/ChangeLog CHANGED
@@ -1,11 +1,61 @@
1
+ 2012-06-26 Michael Granger <ged@FaerieMUD.org>
2
+
3
+ * lib/mongrel2/config/handler.rb, lib/mongrel2/config/host.rb,
4
+ lib/mongrel2/config/route.rb, lib/mongrel2/config/server.rb,
5
+ lib/mongrel2/connection.rb, lib/mongrel2/handler.rb,
6
+ lib/mongrel2/httprequest.rb, lib/mongrel2/request.rb,
7
+ spec/mongrel2/handler_spec.rb, spec/mongrel2/httprequest_spec.rb,
8
+ spec/mongrel2/request_spec.rb:
9
+ Fix the async upload body path
10
+ [782174dcba2e] [tip]
11
+
12
+ 2012-06-21 Michael Granger <ged@FaerieMUD.org>
13
+
14
+ * .hgtags:
15
+ Added tag v0.25.0 for changeset 79bf424c93cd
16
+ [0cb15359e25b]
17
+
18
+ * .hgsigs:
19
+ Added signature for changeset 893e0493be04
20
+ [79bf424c93cd] [v0.25.0]
21
+
22
+ * History.rdoc, lib/mongrel2.rb, lib/mongrel2/request.rb:
23
+ Bumped minor version, updated history
24
+ [893e0493be04]
25
+
26
+ * lib/mongrel2/httprequest.rb, lib/mongrel2/request.rb,
27
+ lib/mongrel2/response.rb, spec/mongrel2/httprequest_spec.rb,
28
+ spec/mongrel2/request_spec.rb:
29
+ Make similar stream adjustments to request as had previously been
30
+ done to response.
31
+ [9f061f269db6]
32
+
33
+ * spec/mongrel2/response_spec.rb:
34
+ Fix spelling
35
+ [7fcb08e469ae]
36
+
37
+ * lib/mongrel2/response.rb, spec/mongrel2/response_spec.rb:
38
+ Don't try to wrap objects that don't support #to_str in a StringIO.
39
+ [22f3d1c88c37]
40
+
1
41
  2012-06-20 Michael Granger <ged@FaerieMUD.org>
2
42
 
43
+ * examples/request-dumper.rb, examples/request-dumper.tmpl,
44
+ lib/mongrel2/connection.rb, lib/mongrel2/request.rb,
45
+ spec/mongrel2/request_spec.rb:
46
+ Add support for Content-type charset to Mongrel2::Request.
47
+ [dae4f2b16ef7]
48
+
49
+ * lib/mongrel2/request.rb:
50
+ Set the body on Mongrel2::Request if constructed with an IO, too.
51
+ [8721f2abc3c0]
52
+
3
53
  * examples/async-upload.rb, examples/config.rb,
4
54
  lib/mongrel2/httprequest.rb, lib/mongrel2/request.rb,
5
55
  lib/mongrel2/testing.rb, spec/mongrel2/httprequest_spec.rb,
6
56
  spec/mongrel2/request_spec.rb:
7
57
  Hook up the async uploaded entity body to the request
8
- [349c0049a4a1] [tip]
58
+ [349c0049a4a1]
9
59
 
10
60
  2012-06-19 Michael Granger <ged@FaerieMUD.org>
11
61
 
data/History.rdoc CHANGED
@@ -1,3 +1,9 @@
1
+ == v0.26.0 [2012-06-26] Michael Granger <ged@FaerieMUD.org>
2
+
3
+ - Fix the derived path to the async upload body
4
+ - Add a default async upload handler method that cancels the upload
5
+
6
+
1
7
  == v0.25.0 [2012-06-20] Michael Granger <ged@FaerieMUD.org>
2
8
 
3
9
  NOTE: This revision contains non-backward-compatible changes to
data/lib/mongrel2.rb CHANGED
@@ -20,10 +20,10 @@ module Mongrel2
20
20
  abort "\n\n>>> Mongrel2 requires Ruby 1.9.2 or later. <<<\n\n" if RUBY_VERSION < '1.9.2'
21
21
 
22
22
  # Library version constant
23
- VERSION = '0.25.0'
23
+ VERSION = '0.26.0'
24
24
 
25
25
  # Version-control revision constant
26
- REVISION = %q$Revision: 893e0493be04 $
26
+ REVISION = %q$Revision: c2eac469ca66 $
27
27
 
28
28
 
29
29
  require 'mongrel2/constants'
@@ -16,6 +16,15 @@ class Mongrel2::Config::Handler < Mongrel2::Config( :handler )
16
16
  # protocol TEXT DEFAULT 'json');
17
17
 
18
18
 
19
+ #
20
+ # :section: Associations
21
+ #
22
+
23
+ ##
24
+ # The routes[rdoc-ref:Mongrel2::Config::Route] that refer to this Handler
25
+ one_to_many :routes, :key => :target_id, :conditions => { target_type: 'handler' }
26
+
27
+
19
28
  # The list of 0mq transports Mongrel2 can use; "You need to use the
20
29
  # ZeroMQ syntax for configuring them, but this means with one
21
30
  # configuration format you can use handlers that are using UDP, TCP,
@@ -13,16 +13,34 @@ class Mongrel2::Config::Host < Mongrel2::Config( :host )
13
13
  # name TEXT,
14
14
  # matching TEXT);
15
15
 
16
+
17
+ #
18
+ # :section: Associations
19
+ #
20
+
21
+ ##
22
+ # The routes[rdoc-ref:Mongrel2::Config::Route] that this host has.
16
23
  one_to_many :routes
24
+
25
+ ##
26
+ # The server[rdoc-ref:Mongrel2::Config::Server] this host belongs to.
17
27
  many_to_one :server
18
28
 
19
29
 
30
+ #
31
+ # :section: Hooks
32
+ #
33
+
20
34
  ### Clean up the host's routes when it's destroyed.
21
35
  def before_destroy
22
36
  self.routes.each( &:destroy )
23
37
  end
24
38
 
25
39
 
40
+ #
41
+ # :section: DSL mixin
42
+ #
43
+
26
44
  ### DSL methods for the Server context besides those automatically-generated from its
27
45
  ### columns.
28
46
  module DSLMethods
@@ -14,6 +14,23 @@ class Mongrel2::Config::Route < Mongrel2::Config( :route )
14
14
  # target_id INTEGER,
15
15
  # target_type TEXT);
16
16
 
17
+
18
+ ### Return the Route that corresponds to the given +request+.
19
+ def self::for_request( request )
20
+ pattern = request.headers.pattern
21
+ return self.filter( path: pattern ).first
22
+ end
23
+
24
+
25
+ #
26
+ # :section: Associations
27
+ #
28
+
29
+ ##
30
+ # The Mongrel2::Config::Host this route belongs to.
31
+ many_to_one :host
32
+
33
+
17
34
  ### Fetch the route's target, which is either a Mongrel2::Config::Directory,
18
35
  ### Mongrel2::Config::Proxy, or Mongrel2::Config::Handler object.
19
36
  def target
@@ -25,10 +25,23 @@ class Mongrel2::Config::Server < Mongrel2::Config( :server )
25
25
  # port INTEGER,
26
26
  # use_ssl INTEGER default 0);
27
27
 
28
+ #
29
+ # :section: Associations
30
+ #
31
+
32
+ ##
33
+ # The hosts[rdoc-ref:Mongrel2::Config::Host] that belong to this server.
28
34
  one_to_many :hosts
35
+
36
+ ##
37
+ # The filters[rdoc-ref:Mongrel2::Config::Filter] that will be loaded by this server.
29
38
  one_to_many :filters
30
39
 
31
40
 
41
+ #
42
+ # :section: Dataset Methods
43
+ #
44
+
32
45
  ##
33
46
  # Return the dataset for looking up a server by its UUID.
34
47
  # :singleton-method: by_uuid
@@ -37,6 +50,16 @@ class Mongrel2::Config::Server < Mongrel2::Config( :server )
37
50
  def_dataset_method( :by_uuid ) {|uuid| filter(:uuid => uuid).limit(1) }
38
51
 
39
52
 
53
+ #
54
+ # :section: Socket/Pathname Convenience Methods
55
+ #
56
+
57
+ ### Return a Pathname for the server's chroot directory.
58
+ def chroot_path
59
+ return Pathname( self.chroot )
60
+ end
61
+
62
+
40
63
  ### Return the URI for its control socket.
41
64
  def control_socket_uri
42
65
  # Find the control socket relative to the server's chroot
@@ -46,7 +69,7 @@ class Mongrel2::Config::Server < Mongrel2::Config( :server )
46
69
  scheme, sock_path = csock_uri.split( '://', 2 )
47
70
  self.log.debug " chrooted socket path is: %p" % [ sock_path ]
48
71
 
49
- csock_path = Pathname( self.chroot ) + sock_path
72
+ csock_path = self.chroot_path + sock_path
50
73
  self.log.debug " fully-qualified path is: %p" % [ csock_path ]
51
74
  csock_uri = "%s://%s" % [ scheme, csock_path ]
52
75
 
@@ -63,11 +86,10 @@ class Mongrel2::Config::Server < Mongrel2::Config( :server )
63
86
 
64
87
  ### Return a Pathname for the server's PID file with its chroot directory prepended.
65
88
  def pid_file_path
66
- base = Pathname( self.chroot )
67
89
  pidfile = self.pid_file
68
90
  pidfile.slice!( 0, 1 ) if pidfile.start_with?( '/' )
69
91
 
70
- return base + pidfile
92
+ return self.chroot_path + pidfile
71
93
  end
72
94
 
73
95
 
@@ -149,6 +149,7 @@ class Mongrel2::Connection
149
149
  ### Tell the server to close the connection associated with the given +sender_id+ and
150
150
  ### +conn_id+.
151
151
  def send_close( sender_id, conn_id )
152
+ self.log.info "Sending kill message to connection %d" % [ conn_id ]
152
153
  self.send( sender_id, conn_id, '' )
153
154
  end
154
155
 
@@ -202,6 +202,10 @@ class Mongrel2::Handler
202
202
  self.handle_disconnect( request )
203
203
  return nil
204
204
 
205
+ elsif request.upload_started?
206
+ self.log.debug "async upload start!"
207
+ return self.handle_async_upload_start( request )
208
+
205
209
  else
206
210
  case request
207
211
  when Mongrel2::HTTPRequest
@@ -290,6 +294,28 @@ class Mongrel2::Handler
290
294
  end
291
295
 
292
296
 
297
+ ### Handle an asynchronous upload start notification. These are sent to notify the
298
+ ### handler that a request that exceeds the server's <tt>limits.content_length</tt>
299
+ ### has been received. The default implementation cancels any such uploads by
300
+ ### replying with an empty string. If the request should be accepted, your handler
301
+ ### should override this and do nothing if the request should continue. You'll receive
302
+ ### a new request via the regular callback when the upload completes whose entity body
303
+ ### is open to the spooled file.
304
+ def handle_async_upload_start( request )
305
+ explanation = "If you wish to handle requests like this, either set your server's "
306
+ explanation << "'limits.content_length' setting to a higher value than %d, or override " %
307
+ [ request.content_length ]
308
+ explanation << "#handle_async_upload_start."
309
+
310
+ self.log.warn "Async upload from %s dropped." % [ request.remote_ip ]
311
+ self.log.info( explanation )
312
+
313
+ self.conn.reply_close( request )
314
+
315
+ return nil
316
+ end
317
+
318
+
293
319
  #
294
320
  # :section: Signal Handling
295
321
  # These methods set up some behavior for starting, restarting, and stopping
@@ -1,6 +1,5 @@
1
1
  #!/usr/bin/ruby
2
2
 
3
- require 'ipaddr'
4
3
  require 'loggability'
5
4
 
6
5
  require 'mongrel2/request' unless defined?( Mongrel2::Request )
@@ -89,13 +88,6 @@ class Mongrel2::HTTPRequest < Mongrel2::Request
89
88
  end
90
89
 
91
90
 
92
- ### Fetch the original requestor IP address.
93
- def remote_ip
94
- ips = [ self.headers.x_forwarded_for ]
95
- return IPAddr.new( ips.flatten.first )
96
- end
97
-
98
-
99
91
  #########
100
92
  protected
101
93
  #########
@@ -107,7 +99,7 @@ class Mongrel2::HTTPRequest < Mongrel2::Request
107
99
  self.headers[:method],
108
100
  self.headers.uri,
109
101
  self.headers.version,
110
- (self.body.length / 1024.0),
102
+ (self.body.size / 1024.0),
111
103
  ]
112
104
  end
113
105
 
@@ -1,5 +1,6 @@
1
1
  #!/usr/bin/ruby
2
2
 
3
+ require 'ipaddr'
3
4
  require 'stringio'
4
5
  require 'tnetstring'
5
6
  require 'yajl'
@@ -171,6 +172,13 @@ class Mongrel2::Request
171
172
  end
172
173
 
173
174
 
175
+ ### Fetch the original requestor IP address.
176
+ def remote_ip
177
+ ips = [ self.headers.x_forwarded_for ]
178
+ return IPAddr.new( ips.flatten.first )
179
+ end
180
+
181
+
174
182
  #
175
183
  # :section: Async Upload Support
176
184
  # See http://mongrel2.org/static/book-finalch6.html#x8-810005.5 for details.
@@ -181,12 +189,12 @@ class Mongrel2::Request
181
189
  raise Mongrel2::UploadError, "invalid upload: upload headers don't match" unless
182
190
  self.upload_headers_match?
183
191
 
184
- server = Mongrel2::Config::Server.by_uuid( self.sender_id ).first or
185
- raise Mongrel2::UploadError, "couldn't find the server %p in the config DB" %
186
- [ self.sender_id ]
192
+ route = Mongrel2::Config::Route.for_request( self ) or
193
+ raise Mongrel2::UploadError, "couldn't find the route config for %s" % [ self ]
194
+ server = route.host.server
187
195
 
188
196
  relpath = Pathname( self.headers.x_mongrel2_upload_done )
189
- chrooted = Pathname( server.chroot ) + relpath
197
+ chrooted = server.chroot_path + relpath
190
198
 
191
199
  if chrooted.exist?
192
200
  return chrooted
data/spec/lib/helpers.rb CHANGED
@@ -208,6 +208,8 @@ RSpec.configure do |c|
208
208
  c.include( Mongrel2::TestConstants )
209
209
  c.include( Mongrel2::SpecHelpers )
210
210
  c.include( Mongrel2::Matchers )
211
+
212
+ c.include( Mongrel2::Config::DSL )
211
213
  end
212
214
 
213
215
  # vim: set nosta noet ts=4 sw=4:
@@ -254,6 +254,18 @@ describe Mongrel2::Handler do
254
254
  response.should be_nil()
255
255
  end
256
256
 
257
+ it "cancels async upload notices by default" do
258
+ req = make_request( 'METHOD' => 'POST', :headers => {'x-mongrel2-upload-start' => 'uploadfile.XXX'} )
259
+ @request_sock.should_receive( :recv ).and_return( req )
260
+ @response_sock.should_receive( :send ).with( "#{TEST_UUID} 1:8, " )
261
+
262
+ res = OneShotHandler.new( TEST_UUID, TEST_SEND_SPEC, TEST_RECV_SPEC ).run
263
+
264
+ res.transactions.should have( 1 ).member
265
+ request, response = res.transactions.first
266
+ response.should be_nil()
267
+ end
268
+
257
269
  it "re-establishes its connection when told to restart" do
258
270
  res = OneShotHandler.new( TEST_UUID, TEST_SEND_SPEC, TEST_RECV_SPEC )
259
271
  original_conn = res.conn
@@ -123,20 +123,6 @@ describe Mongrel2::HTTPRequest do
123
123
  }.to raise_error( ArgumentError, /invalid value for integer/i )
124
124
  end
125
125
 
126
- it "provides a convenience method for fetching the requestor's IP address" do
127
- @req.headers.merge!(
128
- 'X-Forwarded-For' => '127.0.0.1'
129
- )
130
- @req.remote_ip.to_s.should == '127.0.0.1'
131
- end
132
-
133
- it "fetching the requestor's IP address even when travelling via proxies" do
134
- @req.headers.merge!(
135
- 'X-Forwarded-For' => [ '127.0.0.1', '8.8.8.8', '4.4.4.4' ]
136
- )
137
- @req.remote_ip.to_s.should == '127.0.0.1'
138
- end
139
-
140
126
  end
141
127
 
142
128
  end
@@ -120,6 +120,20 @@ describe Mongrel2::Request do
120
120
  @req.body.should be( testobj )
121
121
  end
122
122
 
123
+ it "provides a convenience method for fetching the requestor's IP address" do
124
+ @req.headers.merge!(
125
+ 'X-Forwarded-For' => '127.0.0.1'
126
+ )
127
+ @req.remote_ip.to_s.should == '127.0.0.1'
128
+ end
129
+
130
+ it "fetching the requestor's IP address even when travelling via proxies" do
131
+ @req.headers.merge!(
132
+ 'X-Forwarded-For' => [ '127.0.0.1', '8.8.8.8', '4.4.4.4' ]
133
+ )
134
+ @req.remote_ip.to_s.should == '127.0.0.1'
135
+ end
136
+
123
137
  end
124
138
 
125
139
 
@@ -204,15 +218,20 @@ describe Mongrel2::Request do
204
218
 
205
219
  before( :all ) do
206
220
  setup_config_db()
207
- Mongrel2::Config::Server.create(
208
- uuid: Mongrel2::RequestFactory::DEFAULT_TEST_UUID,
209
- access_log: 'access.log',
210
- error_log: 'error.log',
211
- pid_file: '/var/run/mongrel2.pid',
212
- default_host: 'localhost',
213
- port: 663,
214
- chroot: Dir.tmpdir
215
- )
221
+
222
+ # Set up a test server config so the request can find the server's chroot
223
+ server 'specs' do
224
+ default_host 'localhost'
225
+ access_log 'access.log'
226
+ error_log 'error.log'
227
+ chroot Dir.tmpdir
228
+ pid_file '/var/run/mongrel2.pid'
229
+ port 8113
230
+
231
+ host 'localhost' do
232
+ route '/form', handler( TEST_SEND_SPEC, 'upload-handler', TEST_RECV_SPEC )
233
+ end
234
+ end
216
235
  end
217
236
 
218
237
  before( :each ) do
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mongrel2
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.25.0
4
+ version: 0.26.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -36,7 +36,7 @@ cert_chain:
36
36
  YUhDS0xaZFNLai9SSHVUT3QrZ2JsUmV4OEZBaDhOZUEKY21saFhlNDZwWk5K
37
37
  Z1dLYnhaYWg4NWpJang5NWhSOHZPSStOQU01aUg5a09xSzEzRHJ4YWNUS1Bo
38
38
  cWo1UGp3RgotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg==
39
- date: 2012-06-22 00:00:00.000000000 Z
39
+ date: 2012-06-26 00:00:00.000000000 Z
40
40
  dependencies:
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: nokogiri
metadata.gz.sig CHANGED
Binary file