mongrel2 0.25.0 → 0.26.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.
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