mongrel2 0.51.0 → 0.52.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.
- checksums.yaml +5 -5
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- data/ChangeLog +92 -1
- data/History.rdoc +8 -0
- data/Rakefile +1 -0
- data/lib/mongrel2.rb +2 -2
- data/lib/mongrel2/constants.rb +2 -2
- data/lib/mongrel2/handler.rb +40 -96
- data/lib/mongrel2/websocket.rb +13 -0
- data/spec/helpers.rb +36 -0
- data/spec/mongrel2/connection_spec.rb +19 -5
- data/spec/mongrel2/handler_spec.rb +129 -165
- metadata +17 -3
- metadata.gz.sig +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 2ed8340c773b16f74e9fdfba40baf608f96c13726fc7cdbe4649c414dcb489fc
|
4
|
+
data.tar.gz: 8079493638f14d5e7158687c9e6b0643934821ebb98af1be174704ae833d4cad
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5f9a258f6eeda490594c2601d9b8f8e4b11473f69dc0cffd4cfb324c4c49f62db8b9d26d8c55153895259fbd773bce0547070613ca931f491efcd055960c3b5c
|
7
|
+
data.tar.gz: 899fddeca183837af436fd89aafbf5bfcf9a64a79f2ae51ba25e0c039a2089bd9b115f7a4add96190596c9cb1e70e46e125e2d166cfaf609ba8c559453429599
|
checksums.yaml.gz.sig
CHANGED
Binary file
|
data.tar.gz.sig
CHANGED
Binary file
|
data/ChangeLog
CHANGED
@@ -1,8 +1,99 @@
|
|
1
|
+
2018-07-21 Michael Granger <ged@FaerieMUD.org>
|
2
|
+
|
3
|
+
* .gems, Rakefile, lib/mongrel2/handler.rb, lib/mongrel2/websocket.rb,
|
4
|
+
mongrel2.gemspec, spec/helpers.rb, spec/mongrel2/connection_spec.rb,
|
5
|
+
spec/mongrel2/handler_spec.rb:
|
6
|
+
Refactor IO code to use cztop-reactor
|
7
|
+
[d266df105426] [tip]
|
8
|
+
|
9
|
+
2018-05-31 Mahlon E. Smith <mahlon@martini.nu>
|
10
|
+
|
11
|
+
* lib/mongrel2/constants.rb:
|
12
|
+
Update for changes to gem upstream.
|
13
|
+
[667013d5334c]
|
14
|
+
|
15
|
+
2017-11-15 Michael Granger <ged@FaerieMUD.org>
|
16
|
+
|
17
|
+
* .hgtags:
|
18
|
+
Added tag v0.51.0 for changeset 89afed83e6e2
|
19
|
+
[1a6fcd8e3a52]
|
20
|
+
|
21
|
+
* .hgsigs:
|
22
|
+
Added signature for changeset 5c042cae7457
|
23
|
+
[89afed83e6e2] [v0.51.0]
|
24
|
+
|
25
|
+
* cert/ged.pem, certs/ged.pem:
|
26
|
+
Fix the name of and update my gem-signing cert
|
27
|
+
[5c042cae7457]
|
28
|
+
|
29
|
+
* History.rdoc, lib/mongrel2.rb:
|
30
|
+
Bump the minor version, update history.
|
31
|
+
[1a66a960918d]
|
32
|
+
|
33
|
+
* Rakefile, mongrel2.gemspec:
|
34
|
+
Update libxml-ruby dep to the latest
|
35
|
+
[9253c00b0a2f]
|
36
|
+
|
37
|
+
2017-11-08 Michael Granger <ged@FaerieMUD.org>
|
38
|
+
|
39
|
+
* mongrel2.gemspec:
|
40
|
+
Update the gemspec
|
41
|
+
[f1817db64b7b]
|
42
|
+
|
43
|
+
* Manifest.txt:
|
44
|
+
Update the manifest
|
45
|
+
[f69cd800ac94]
|
46
|
+
|
47
|
+
* .ruby-version, .tm_properties, Rakefile, lib/mongrel2/config.rb,
|
48
|
+
lib/mongrel2/constants.rb, mongrel2.gemspec:
|
49
|
+
Support Sequel 5
|
50
|
+
[56a2daf04013]
|
51
|
+
|
52
|
+
* data/mongrel2/config.rb.in:
|
53
|
+
Add config input file
|
54
|
+
[19ce3acb3839]
|
55
|
+
|
56
|
+
2017-07-05 Michael Granger <ged@FaerieMUD.org>
|
57
|
+
|
58
|
+
* .hgtags:
|
59
|
+
Added tag v0.50.2 for changeset 08baa3b61eea
|
60
|
+
[79f113fd0f93]
|
61
|
+
|
62
|
+
* .hgsigs:
|
63
|
+
Added signature for changeset 99ce0d32ae15
|
64
|
+
[08baa3b61eea] [v0.50.2]
|
65
|
+
|
66
|
+
* History.rdoc, lib/mongrel2.rb:
|
67
|
+
Bump the patch version, update history.
|
68
|
+
[99ce0d32ae15]
|
69
|
+
|
70
|
+
* lib/mongrel2/handler.rb:
|
71
|
+
Add missing require to Strelka::Handler.
|
72
|
+
[6ad07a7a7775]
|
73
|
+
|
74
|
+
2017-05-31 Michael Granger <ged@FaerieMUD.org>
|
75
|
+
|
76
|
+
* .hgtags:
|
77
|
+
Added tag v0.50.1 for changeset 181a78ed2587
|
78
|
+
[af48c723c110]
|
79
|
+
|
80
|
+
* .hgsigs:
|
81
|
+
Added signature for changeset d7b71efe6141
|
82
|
+
[181a78ed2587] [v0.50.1]
|
83
|
+
|
84
|
+
* History.rdoc, lib/mongrel2.rb:
|
85
|
+
Bump the patch version, update history.
|
86
|
+
[d7b71efe6141]
|
87
|
+
|
88
|
+
* Rakefile, mongrel2.gemspec:
|
89
|
+
Pin Sequel to 4.45 to avoid breaking changes.
|
90
|
+
[e12627bad969]
|
91
|
+
|
1
92
|
2017-05-31 Mahlon E. Smith <mahlon@martini.nu>
|
2
93
|
|
3
94
|
* lib/mongrel2/handler.rb, spec/mongrel2/handler_spec.rb:
|
4
95
|
Randomize the inproc selfpipe socket name.
|
5
|
-
[6beef2396fd4]
|
96
|
+
[6beef2396fd4]
|
6
97
|
|
7
98
|
2017-05-31 Mahlon E. Smith <mahlon@laika.com>
|
8
99
|
|
data/History.rdoc
CHANGED
data/Rakefile
CHANGED
@@ -26,6 +26,7 @@ hoespec = Hoe.spec 'mongrel2' do
|
|
26
26
|
self.developer 'Michael Granger', 'ged@FaerieMUD.org'
|
27
27
|
|
28
28
|
self.dependency 'cztop', '~> 0.11'
|
29
|
+
self.dependency 'cztop-reactor', '~> 0.3'
|
29
30
|
self.dependency 'libxml-ruby', '~> 3.0'
|
30
31
|
self.dependency 'loggability', '~> 0.12'
|
31
32
|
self.dependency 'sequel', '~> 5.2'
|
data/lib/mongrel2.rb
CHANGED
@@ -22,10 +22,10 @@ module Mongrel2
|
|
22
22
|
abort "\n\n>>> Mongrel2 requires Ruby 2.2 or later. <<<\n\n" if RUBY_VERSION < '2.2.0'
|
23
23
|
|
24
24
|
# Library version constant
|
25
|
-
VERSION = '0.
|
25
|
+
VERSION = '0.52.0'
|
26
26
|
|
27
27
|
# Version-control revision constant
|
28
|
-
REVISION = %q$Revision:
|
28
|
+
REVISION = %q$Revision: aa458f3f9ca9 $
|
29
29
|
|
30
30
|
|
31
31
|
require 'mongrel2/constants'
|
data/lib/mongrel2/constants.rb
CHANGED
@@ -11,8 +11,8 @@ module Mongrel2::Constants
|
|
11
11
|
# The Pathname of the data directory
|
12
12
|
DATA_DIR = if ENV['MONGREL2_DATADIR']
|
13
13
|
Pathname( ENV['MONGREL2_DATADIR'] )
|
14
|
-
elsif Gem.
|
15
|
-
Pathname( Gem.
|
14
|
+
elsif Gem.loaded_specs[ 'mongrel2' ] && File.exist?( Gem.loaded_specs['mongrel2'].datadir )
|
15
|
+
Pathname( Gem.loaded_specs['mongrel2'].datadir )
|
16
16
|
else
|
17
17
|
Pathname( __FILE__ ).dirname.parent.parent + 'data/mongrel2'
|
18
18
|
end
|
data/lib/mongrel2/handler.rb
CHANGED
@@ -2,6 +2,8 @@
|
|
2
2
|
#encoding: utf-8
|
3
3
|
|
4
4
|
require 'cztop'
|
5
|
+
require 'cztop/reactor'
|
6
|
+
require 'cztop/reactor/signal_handling'
|
5
7
|
require 'securerandom'
|
6
8
|
require 'loggability'
|
7
9
|
|
@@ -85,7 +87,8 @@ require 'mongrel2/websocket'
|
|
85
87
|
#
|
86
88
|
class Mongrel2::Handler
|
87
89
|
extend Loggability
|
88
|
-
include Mongrel2::Constants
|
90
|
+
include Mongrel2::Constants,
|
91
|
+
CZTop::Reactor::SignalHandling
|
89
92
|
|
90
93
|
|
91
94
|
# Loggability API -- set up logging under the 'mongrel2' log host
|
@@ -96,7 +99,7 @@ class Mongrel2::Handler
|
|
96
99
|
QUEUE_SIGS = [
|
97
100
|
:INT, :TERM, :HUP, :USR1,
|
98
101
|
# :TODO: :QUIT, :WINCH, :USR2, :TTIN, :TTOU
|
99
|
-
]
|
102
|
+
] & Signal.list.keys.map( &:to_sym )
|
100
103
|
|
101
104
|
|
102
105
|
### Create an instance of the handler using the config from the database with
|
@@ -136,14 +139,12 @@ class Mongrel2::Handler
|
|
136
139
|
### Create a new instance of the handler with the specified +app_id+, +send_spec+,
|
137
140
|
### and +recv_spec+.
|
138
141
|
def initialize( app_id, send_spec, recv_spec ) # :notnew:
|
142
|
+
super() # To the signal handler mixin
|
143
|
+
|
139
144
|
@app_id = app_id
|
140
145
|
|
141
146
|
@conn = Mongrel2::Connection.new( app_id, send_spec, recv_spec )
|
142
|
-
|
143
|
-
@self_pipe = nil
|
144
|
-
@poller = nil
|
145
|
-
|
146
|
-
Thread.main[:signal_queue] = []
|
147
|
+
@reactor = CZTop::Reactor.new
|
147
148
|
end
|
148
149
|
|
149
150
|
|
@@ -151,31 +152,30 @@ class Mongrel2::Handler
|
|
151
152
|
public
|
152
153
|
######
|
153
154
|
|
155
|
+
##
|
154
156
|
# The handler's Mongrel2::Connection object.
|
155
157
|
attr_reader :conn
|
156
158
|
|
159
|
+
##
|
157
160
|
# The app ID the app was created with
|
158
161
|
attr_reader :app_id
|
159
162
|
|
163
|
+
##
|
164
|
+
# The CZTop::Reactor that manages IO
|
165
|
+
attr_reader :reactor
|
166
|
+
|
160
167
|
|
161
168
|
### Run the handler.
|
162
169
|
def run
|
163
170
|
self.log.info "Starting up %p" % [ self ]
|
164
171
|
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
}
|
170
|
-
|
171
|
-
@poller = CZTop::Poller.new( @conn.request_sock, @self_pipe[:reader] )
|
172
|
-
|
173
|
-
self.set_signal_handlers
|
174
|
-
self.start_accepting_requests
|
172
|
+
self.reactor.register( @conn.request_sock, :read, &self.method(:on_socket_event) )
|
173
|
+
self.with_signal_handler( self.reactor, *QUEUE_SIGS ) do
|
174
|
+
self.start_accepting_requests
|
175
|
+
end
|
175
176
|
|
176
177
|
return self # For chaining
|
177
178
|
ensure
|
178
|
-
self.restore_signal_handlers
|
179
179
|
self.log.info "Done: %p" % [ self ]
|
180
180
|
@conn.close if @conn
|
181
181
|
end
|
@@ -224,7 +224,7 @@ class Mongrel2::Handler
|
|
224
224
|
### Shut down the handler.
|
225
225
|
def shutdown
|
226
226
|
self.log.info "Shutting down."
|
227
|
-
self.
|
227
|
+
self.reactor.stop_polling
|
228
228
|
@conn.close
|
229
229
|
end
|
230
230
|
|
@@ -234,9 +234,9 @@ class Mongrel2::Handler
|
|
234
234
|
def restart
|
235
235
|
self.log.info "Restarting"
|
236
236
|
if (( old_conn = @conn ))
|
237
|
+
self.reactor.unregister( old_conn.request_sock )
|
237
238
|
@conn = @conn.dup
|
238
|
-
|
239
|
-
@poller = CZTop::Poller.new( @conn.request_sock, @self_pipe[:reader] )
|
239
|
+
self.reactor.register( @conn.request_sock, :read, &self.method(:on_socket_event) )
|
240
240
|
|
241
241
|
self.log.debug " conn %p -> %p" % [ old_conn, @conn ]
|
242
242
|
old_conn.close
|
@@ -247,28 +247,20 @@ class Mongrel2::Handler
|
|
247
247
|
### Start a loop, accepting a request and handling it.
|
248
248
|
def start_accepting_requests
|
249
249
|
self.log.info "Starting the request loop."
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
case event.socket
|
254
|
-
when @conn.request_sock
|
255
|
-
req = @conn.receive
|
256
|
-
self.accept_request( req ) unless @conn.closed?
|
257
|
-
when @self_pipe[:reader]
|
258
|
-
@self_pipe[:reader].wait
|
259
|
-
self.process_signal_queue
|
260
|
-
else
|
261
|
-
self.log.warn "Got unhandled poller event: %p" % [ event ]
|
262
|
-
end
|
263
|
-
end
|
264
|
-
rescue Errno::EAGAIN
|
265
|
-
# self.log.debug "Got EAGAIN, retrying."
|
266
|
-
rescue Interrupt
|
267
|
-
# self.log.debug "Got an Interrupt; retrying."
|
268
|
-
end
|
269
|
-
end
|
250
|
+
self.reactor.start_polling( ignore_interrupts: true )
|
251
|
+
end
|
252
|
+
|
270
253
|
|
271
|
-
|
254
|
+
### Reactor callback -- handle an IO event.
|
255
|
+
def on_socket_event( event )
|
256
|
+
if event.readable?
|
257
|
+
req = self.conn.receive
|
258
|
+
self.accept_request( req )
|
259
|
+
elsif event.writable?
|
260
|
+
raise "Request socket became writable?!"
|
261
|
+
else
|
262
|
+
raise "Socket event was neither readable nor writable! (%s)" % [ event ]
|
263
|
+
end
|
272
264
|
end
|
273
265
|
|
274
266
|
|
@@ -379,9 +371,9 @@ class Mongrel2::Handler
|
|
379
371
|
def handle_websocket( request )
|
380
372
|
self.log.warn "Unhandled WEBSOCKET frame (%p)" % [ request.headers.path ]
|
381
373
|
res = request.response
|
382
|
-
res.make_close_frame( WebSocket::CLOSE_POLICY_VIOLATION )
|
383
|
-
self.conn.reply( res)
|
374
|
+
res.make_close_frame( Mongrel2::WebSocket::CLOSE_POLICY_VIOLATION )
|
384
375
|
|
376
|
+
self.conn.reply( res )
|
385
377
|
self.conn.reply_close( request )
|
386
378
|
|
387
379
|
return nil
|
@@ -391,8 +383,8 @@ class Mongrel2::Handler
|
|
391
383
|
### Handle a WebSocket handshake HTTP +request+. If not overridden, this method drops
|
392
384
|
### the connection.
|
393
385
|
def handle_websocket_handshake( handshake )
|
394
|
-
self.log.warn "Unhandled WEBSOCKET_HANDSHAKE request (%p)" % [
|
395
|
-
self.conn.reply_close(
|
386
|
+
self.log.warn "Unhandled WEBSOCKET_HANDSHAKE request (%p)" % [ handshake.headers.path ]
|
387
|
+
self.conn.reply_close( handshake )
|
396
388
|
|
397
389
|
return nil
|
398
390
|
end
|
@@ -401,7 +393,7 @@ class Mongrel2::Handler
|
|
401
393
|
### Handle a disconnect notice from Mongrel2 via the given +request+. Its return value
|
402
394
|
### is ignored.
|
403
395
|
def handle_disconnect( request )
|
404
|
-
self.log.info "
|
396
|
+
self.log.info "Connection %p closed." % [ request.conn_id ]
|
405
397
|
return nil
|
406
398
|
end
|
407
399
|
|
@@ -436,57 +428,9 @@ class Mongrel2::Handler
|
|
436
428
|
# :section: Signal Handling
|
437
429
|
# These methods set up some behavior for starting, restarting, and stopping
|
438
430
|
# your application when a signal is received. If you don't want signals to
|
439
|
-
# be handled, override #
|
431
|
+
# be handled, override #handle_signal with an empty method.
|
440
432
|
#
|
441
433
|
|
442
|
-
### Wake up the handler when a signal needs to be processed.
|
443
|
-
def wake_up
|
444
|
-
$stderr.puts "Waking up the signal handler"
|
445
|
-
@self_pipe[ :writer ].signal( 0 )
|
446
|
-
$stderr.puts "Done sending the wakeup."
|
447
|
-
end
|
448
|
-
|
449
|
-
|
450
|
-
### Set up signal handlers for common signals that will shut down, restart, etc.
|
451
|
-
def set_signal_handlers
|
452
|
-
self.log.debug "Setting up deferred signal handlers."
|
453
|
-
QUEUE_SIGS.each do |sig|
|
454
|
-
Signal.trap( sig ) do
|
455
|
-
Thread.main[:signal_queue] << sig
|
456
|
-
self.wake_up
|
457
|
-
$stderr.puts "Done handling the signal."
|
458
|
-
end
|
459
|
-
end
|
460
|
-
end
|
461
|
-
|
462
|
-
|
463
|
-
### Set all signal handlers to ignore.
|
464
|
-
def ignore_signals
|
465
|
-
self.log.debug "Ignoring signals."
|
466
|
-
QUEUE_SIGS.each do |sig|
|
467
|
-
Signal.trap( sig, :IGNORE )
|
468
|
-
end
|
469
|
-
end
|
470
|
-
|
471
|
-
|
472
|
-
### Set the signal handlers back to their defaults.
|
473
|
-
def restore_signal_handlers
|
474
|
-
self.log.debug "Restoring default signal handlers."
|
475
|
-
QUEUE_SIGS.each do |sig|
|
476
|
-
Signal.trap( sig, :DEFAULT )
|
477
|
-
end
|
478
|
-
end
|
479
|
-
|
480
|
-
|
481
|
-
### Handle any queued signals.
|
482
|
-
def process_signal_queue
|
483
|
-
# Look for any signals that arrived and handle them
|
484
|
-
while sig = Thread.main[:signal_queue].shift
|
485
|
-
self.handle_signal( sig )
|
486
|
-
end
|
487
|
-
end
|
488
|
-
|
489
|
-
|
490
434
|
### Handle signals.
|
491
435
|
def handle_signal( sig )
|
492
436
|
self.log.debug "Handling signal %s" % [ sig ]
|
data/lib/mongrel2/websocket.rb
CHANGED
@@ -463,6 +463,13 @@ module Mongrel2::WebSocket
|
|
463
463
|
end
|
464
464
|
|
465
465
|
|
466
|
+
### Set the :close opcode on this frame and set its status to +statuscode+.
|
467
|
+
def make_close_frame( statuscode=Mongrel2::WebSocket::CLOSE_NORMAL )
|
468
|
+
self.opcode = :close
|
469
|
+
self.set_status( statuscode )
|
470
|
+
end
|
471
|
+
|
472
|
+
|
466
473
|
### Overwrite the frame's payload with a status message based on
|
467
474
|
### +statuscode+.
|
468
475
|
def set_status( statuscode )
|
@@ -622,6 +629,12 @@ module Mongrel2::WebSocket
|
|
622
629
|
end
|
623
630
|
|
624
631
|
|
632
|
+
### Compatibility with Mongrel2::Response.
|
633
|
+
def extended_reply? # :nodoc:
|
634
|
+
return false
|
635
|
+
end
|
636
|
+
|
637
|
+
|
625
638
|
#########
|
626
639
|
protected
|
627
640
|
#########
|
data/spec/helpers.rb
CHANGED
@@ -91,6 +91,13 @@ module Mongrel2::SpecHelpers
|
|
91
91
|
end
|
92
92
|
|
93
93
|
|
94
|
+
### Make a Mongrel2::Request from the specified +opts+ and return it.
|
95
|
+
def make_request_object( opts={} )
|
96
|
+
data = make_request( opts )
|
97
|
+
return Mongrel2::Request.parse( data )
|
98
|
+
end
|
99
|
+
|
100
|
+
|
94
101
|
### Make a new-style (TNetstring headers) raw Mongrel2 request from the specified +opts+
|
95
102
|
### and return it as a String.
|
96
103
|
def make_tn_request( opts={} )
|
@@ -135,6 +142,13 @@ module Mongrel2::SpecHelpers
|
|
135
142
|
end
|
136
143
|
|
137
144
|
|
145
|
+
### Make a Mongrel2::JSONRequest from the specified +opts+ and return it.
|
146
|
+
def make_json_request_object( opts={} )
|
147
|
+
data = make_json_request( opts )
|
148
|
+
return Mongrel2::Request.parse( data )
|
149
|
+
end
|
150
|
+
|
151
|
+
|
138
152
|
### Make a Mongrel2 request for an XML route.
|
139
153
|
def make_xml_request( opts={} )
|
140
154
|
opts = TEST_XML_REQUEST_OPTS.merge( opts )
|
@@ -158,6 +172,13 @@ module Mongrel2::SpecHelpers
|
|
158
172
|
end
|
159
173
|
|
160
174
|
|
175
|
+
### Make a Mongrel2::XMLRequest from the specified +opts+ and return it.
|
176
|
+
def make_xml_request_object( opts={} )
|
177
|
+
data = make_xml_request( opts )
|
178
|
+
return Mongrel2::Request.parse( data )
|
179
|
+
end
|
180
|
+
|
181
|
+
|
161
182
|
### Make a Mongrel2 handshake request for a WebSocket route.
|
162
183
|
def make_websocket_handshake( opts={} )
|
163
184
|
opts = TEST_WEBSOCKET_REQUEST_OPTS.merge( opts )
|
@@ -180,6 +201,14 @@ module Mongrel2::SpecHelpers
|
|
180
201
|
end
|
181
202
|
|
182
203
|
|
204
|
+
### Make a Mongrel2::WebSocket::ClientHandshake from the specified +opts+ and
|
205
|
+
### return it.
|
206
|
+
def make_websocket_handshake_object( opts={} )
|
207
|
+
data = make_websocket_handshake( opts )
|
208
|
+
return Mongrel2::Request.parse( data )
|
209
|
+
end
|
210
|
+
|
211
|
+
|
183
212
|
### Make a Mongrel2 frame for a WebSocket route.
|
184
213
|
def make_websocket_frame( opts={} )
|
185
214
|
opts = TEST_WEBSOCKET_REQUEST_OPTS.merge( opts )
|
@@ -201,6 +230,13 @@ module Mongrel2::SpecHelpers
|
|
201
230
|
return data.encode( 'binary' )
|
202
231
|
end
|
203
232
|
|
233
|
+
|
234
|
+
### Make a Mongrel2::WebSocket::Frame from the specified +opts+ and return it.
|
235
|
+
def make_websocket_frame_object( opts={} )
|
236
|
+
data = make_websocket_frame( opts )
|
237
|
+
return Mongrel2::Request.parse( data )
|
238
|
+
end
|
239
|
+
|
204
240
|
end
|
205
241
|
|
206
242
|
|
@@ -14,9 +14,6 @@ require 'mongrel2/connection'
|
|
14
14
|
describe Mongrel2::Connection do
|
15
15
|
include Mongrel2::Config::DSL
|
16
16
|
|
17
|
-
before( :all ) do
|
18
|
-
end
|
19
|
-
|
20
17
|
# Ensure 0MQ never actually gets called
|
21
18
|
before( :each ) do
|
22
19
|
@conn = Mongrel2::Connection.new( TEST_UUID, TEST_SEND_SPEC, TEST_RECV_SPEC )
|
@@ -28,6 +25,7 @@ describe Mongrel2::Connection do
|
|
28
25
|
expect( @conn.instance_variable_get( :@response_sock ) ).to be_nil()
|
29
26
|
end
|
30
27
|
|
28
|
+
|
31
29
|
it "connects to the endpoints specified on demand" do
|
32
30
|
request_sock = double( "request socket", options: OpenStruct.new )
|
33
31
|
response_sock = double( "response socket", options: OpenStruct.new )
|
@@ -45,10 +43,12 @@ describe Mongrel2::Connection do
|
|
45
43
|
expect( @conn.response_sock ).to eq( response_sock )
|
46
44
|
end
|
47
45
|
|
46
|
+
|
48
47
|
it "stringifies as a description of the appid and both sockets" do
|
49
48
|
expect( @conn.to_s ).to eq( "{#{TEST_UUID}} #{TEST_SEND_SPEC} <-> #{TEST_RECV_SPEC}" )
|
50
49
|
end
|
51
50
|
|
51
|
+
|
52
52
|
context "after a connection has been established" do
|
53
53
|
|
54
54
|
before( :each ) do
|
@@ -69,6 +69,7 @@ describe Mongrel2::Connection do
|
|
69
69
|
@conn.close
|
70
70
|
end
|
71
71
|
|
72
|
+
|
72
73
|
it "raises an exception if asked to fetch data after being closed" do
|
73
74
|
allow( @request_sock ).to receive( :close )
|
74
75
|
allow( @response_sock ).to receive( :close )
|
@@ -80,6 +81,7 @@ describe Mongrel2::Connection do
|
|
80
81
|
}.to raise_error( Mongrel2::ConnectionError, /operation on closed connection/i )
|
81
82
|
end
|
82
83
|
|
84
|
+
|
83
85
|
it "doesn't keep its request and response sockets when duped" do
|
84
86
|
request_sock2 = double( "request socket", :options => OpenStruct.new, :connect => nil )
|
85
87
|
response_sock2 = double( "response socket", :options => OpenStruct.new, :connect => nil )
|
@@ -92,6 +94,7 @@ describe Mongrel2::Connection do
|
|
92
94
|
expect( duplicate.response_sock ).to eq( response_sock2 )
|
93
95
|
end
|
94
96
|
|
97
|
+
|
95
98
|
it "doesn't keep its closed state when duped" do
|
96
99
|
expect( @request_sock ).to receive( :close )
|
97
100
|
expect( @response_sock ).to receive( :close )
|
@@ -102,22 +105,26 @@ describe Mongrel2::Connection do
|
|
102
105
|
expect( duplicate ).to_not be_closed()
|
103
106
|
end
|
104
107
|
|
108
|
+
|
105
109
|
it "can read raw request messages off of the request_sock" do
|
106
110
|
expect( @request_sock ).to receive( :receive ).and_return( CZTop::Message.new( "the data" ) )
|
107
111
|
expect( @conn.recv ).to eq( "the data" )
|
108
112
|
end
|
109
113
|
|
114
|
+
|
110
115
|
it "can read request messages off of the request_sock as Mongrel2::Request objects" do
|
111
|
-
|
112
|
-
expect( @request_sock ).to receive( :receive ).and_return( CZTop::Message.new(
|
116
|
+
req = make_request()
|
117
|
+
expect( @request_sock ).to receive( :receive ).and_return( CZTop::Message.new(req) )
|
113
118
|
expect( @conn.receive ).to be_a( Mongrel2::Request )
|
114
119
|
end
|
115
120
|
|
121
|
+
|
116
122
|
it "can write raw response messages with a TNetString header onto the response_sock" do
|
117
123
|
expect( @response_sock ).to receive( :<< ).with( "#{TEST_UUID} 1:8, the data" )
|
118
124
|
@conn.send( TEST_UUID, 8, "the data" )
|
119
125
|
end
|
120
126
|
|
127
|
+
|
121
128
|
it "can write Mongrel2::Responses to the response_sock" do
|
122
129
|
expect( @response_sock ).to receive( :<< ).with( "#{TEST_UUID} 1:8, the data" )
|
123
130
|
|
@@ -125,30 +132,35 @@ describe Mongrel2::Connection do
|
|
125
132
|
@conn.reply( response )
|
126
133
|
end
|
127
134
|
|
135
|
+
|
128
136
|
it "can write raw response messages to more than one conn_id at the same time" do
|
129
137
|
expect( @response_sock ).to receive( :<< ).
|
130
138
|
with( "#{TEST_UUID} 15:8 16 44 45 1833, the data" )
|
131
139
|
@conn.broadcast( TEST_UUID, [8, 16, 44, 45, 1833], 'the data' )
|
132
140
|
end
|
133
141
|
|
142
|
+
|
134
143
|
it "can write raw response messages to more than one conn_id at the same time" do
|
135
144
|
expect( @response_sock ).to receive( :<< ).
|
136
145
|
with( "#{TEST_UUID} 15:8 16 44 45 1833, the data" )
|
137
146
|
@conn.broadcast( TEST_UUID, [8, 16, 44, 45, 1833], 'the data' )
|
138
147
|
end
|
139
148
|
|
149
|
+
|
140
150
|
it "can write an extended response message" do
|
141
151
|
expect( @response_sock ).to receive( :<< ).
|
142
152
|
with( "#{TEST_UUID} 3:X 8, 27:8:sendfile,12:the_data.txt,]" )
|
143
153
|
@conn.send_extended( TEST_UUID, 8, :sendfile, "the_data.txt" )
|
144
154
|
end
|
145
155
|
|
156
|
+
|
146
157
|
it "can broadcast an extended response message" do
|
147
158
|
expect( @response_sock ).to receive( :<< ).
|
148
159
|
with( "#{TEST_UUID} 9:X 8 16 32, 27:8:sendfile,12:the_data.txt,]" )
|
149
160
|
@conn.broadcast_extended( TEST_UUID, [8,16,32], :sendfile, "the_data.txt" )
|
150
161
|
end
|
151
162
|
|
163
|
+
|
152
164
|
it "can write a Mongrel2::Response with extended reply" do
|
153
165
|
expect( @response_sock ).to receive( :<< ).
|
154
166
|
with( "#{TEST_UUID} 1:8, " )
|
@@ -162,6 +174,7 @@ describe Mongrel2::Connection do
|
|
162
174
|
@conn.reply( response )
|
163
175
|
end
|
164
176
|
|
177
|
+
|
165
178
|
it "can tell the connection a request or a response was from to close" do
|
166
179
|
expect( @response_sock ).to receive( :<< ).with( "#{TEST_UUID} 1:8, " )
|
167
180
|
|
@@ -169,6 +182,7 @@ describe Mongrel2::Connection do
|
|
169
182
|
@conn.reply_close( response )
|
170
183
|
end
|
171
184
|
|
185
|
+
|
172
186
|
it "can broadcast a close to multiple connection IDs" do
|
173
187
|
expect( @response_sock ).to receive( :<< ).with( "#{TEST_UUID} 15:8 16 44 45 1833, " )
|
174
188
|
@conn.broadcast_close( TEST_UUID, [8, 16, 44, 45, 1833] )
|
@@ -16,48 +16,9 @@ require 'mongrel2/handler'
|
|
16
16
|
|
17
17
|
describe Mongrel2::Handler, :db do
|
18
18
|
|
19
|
-
# Make a handler class for testing
|
20
|
-
|
21
|
-
|
22
|
-
def initialize( * )
|
23
|
-
@transactions = {}
|
24
|
-
super
|
25
|
-
end
|
26
|
-
|
27
|
-
attr_reader :transactions
|
28
|
-
|
29
|
-
# Overridden to accept one request and shut down
|
30
|
-
def dispatch_request( request )
|
31
|
-
response = super
|
32
|
-
self.transactions[ request ] = response
|
33
|
-
self.shutdown
|
34
|
-
return response
|
35
|
-
end
|
36
|
-
|
37
|
-
end # class OneShotHandler
|
38
|
-
|
39
|
-
|
40
|
-
# Ensure 0MQ never actually gets called
|
41
|
-
before( :each ) do
|
42
|
-
@request_sock = instance_double( CZTop::Socket::PULL, :options => OpenStruct.new, :connect => nil, :close => nil )
|
43
|
-
@response_sock = instance_double( CZTop::Socket::PUB, :options => OpenStruct.new, :connect => nil, :close => nil )
|
44
|
-
@selfpipe_reader = instance_double( CZTop::Socket::PAIR )
|
45
|
-
@selfpipe_writer = instance_double( CZTop::Socket::PAIR )
|
46
|
-
@poller = instance_double( CZTop::Poller )
|
47
|
-
@poller_event = instance_double( CZTop::Poller::Event )
|
48
|
-
|
49
|
-
allow( CZTop::Socket::PULL ).to receive( :new ).and_return( @request_sock )
|
50
|
-
allow( CZTop::Socket::PUB ).to receive( :new ).and_return( @response_sock )
|
51
|
-
allow( CZTop::Socket::PAIR ).to receive( :new ).with( %r|@inproc://signal-handler-\d+-\w{8}| ).
|
52
|
-
and_return( @selfpipe_reader )
|
53
|
-
allow( CZTop::Socket::PAIR ).to receive( :new ).with( %r|>inproc://signal-handler-\d+-\w{8}| ).
|
54
|
-
and_return( @selfpipe_writer )
|
55
|
-
allow( CZTop::Poller ).to receive( :new ).and_return( @poller )
|
56
|
-
|
57
|
-
allow( @poller ).to receive( :wait ).and_return( @poller_event )
|
58
|
-
allow( @poller_event ).to receive( :socket ).and_return( @request_sock )
|
59
|
-
end
|
60
|
-
|
19
|
+
# Make a handler class for testing
|
20
|
+
class TestingHandler < Mongrel2::Handler
|
21
|
+
end # class TestingHandler
|
61
22
|
|
62
23
|
|
63
24
|
context "with a Handler entry in the config database" do
|
@@ -85,30 +46,34 @@ describe Mongrel2::Handler, :db do
|
|
85
46
|
end
|
86
47
|
|
87
48
|
|
88
|
-
it "has a convenience method for instantiating and running a Handler given an "
|
89
|
-
|
49
|
+
it "has a convenience method for instantiating and running a Handler given an application ID" do
|
50
|
+
reactor = instance_double( CZTop::Reactor )
|
51
|
+
expect( CZTop::Reactor ).to receive( :new ).and_return( reactor )
|
52
|
+
expect( reactor ).to receive( :register ).at_least( :once )
|
53
|
+
expect( reactor ).to receive( :unregister ).at_least( :once )
|
54
|
+
expect( reactor ).to receive( :start_polling ).with( ignore_interrupts: true )
|
90
55
|
|
91
|
-
|
92
|
-
expect( @request_sock ).to receive( :receive ).and_return( CZTop::Message.new( req ) )
|
93
|
-
|
94
|
-
res = OneShotHandler.run( TEST_UUID )
|
56
|
+
handler = TestingHandler.run( TEST_UUID )
|
95
57
|
|
96
58
|
# It should have pulled its connection info from the Handler entry in the database
|
97
|
-
expect(
|
98
|
-
expect(
|
99
|
-
expect(
|
59
|
+
expect( handler.conn.app_id ).to eq( TEST_UUID )
|
60
|
+
expect( handler.conn.sub_addr ).to eq( TEST_SEND_SPEC )
|
61
|
+
expect( handler.conn.pub_addr ).to eq( TEST_RECV_SPEC )
|
100
62
|
end
|
101
63
|
|
102
64
|
|
103
|
-
it "knows what handler config corresponds to its" do
|
104
|
-
|
105
|
-
expect(
|
65
|
+
it "knows what handler config corresponds to its app UUID" do
|
66
|
+
reactor = instance_double( CZTop::Reactor )
|
67
|
+
expect( CZTop::Reactor ).to receive( :new ).and_return( reactor )
|
68
|
+
expect( reactor ).to receive( :register ).at_least( :once )
|
69
|
+
expect( reactor ).to receive( :unregister ).at_least( :once )
|
70
|
+
expect( reactor ).to receive( :start_polling ).with( ignore_interrupts: true )
|
106
71
|
|
107
|
-
|
72
|
+
handler = TestingHandler.run( TEST_UUID )
|
108
73
|
|
109
|
-
expect(
|
110
|
-
expect(
|
111
|
-
expect(
|
74
|
+
expect( handler.handler_config ).to be_a( Mongrel2::Config::Handler )
|
75
|
+
expect( handler.handler_config.send_spec ).to eq( TEST_SEND_SPEC )
|
76
|
+
expect( handler.handler_config.recv_spec ).to eq( TEST_RECV_SPEC )
|
112
77
|
end
|
113
78
|
|
114
79
|
end
|
@@ -130,194 +95,189 @@ describe Mongrel2::Handler, :db do
|
|
130
95
|
end
|
131
96
|
|
132
97
|
|
133
|
-
it "
|
134
|
-
|
135
|
-
|
98
|
+
it "responds to HTTP requests with a 204 No Content response by default" do
|
99
|
+
request = make_request_object()
|
100
|
+
handler = TestingHandler.new( TEST_UUID, TEST_SEND_SPEC, TEST_RECV_SPEC )
|
136
101
|
|
137
|
-
|
102
|
+
response = handler.dispatch_request( request )
|
138
103
|
|
139
|
-
expect( res.transactions.size ).to eq( 1 )
|
140
|
-
request, response = res.transactions.first
|
141
|
-
expect( request ).to be_a( Mongrel2::HTTPRequest )
|
142
104
|
expect( response ).to be_a( Mongrel2::HTTPResponse )
|
143
105
|
expect( response.status ).to eq( 204 )
|
144
106
|
end
|
145
107
|
|
146
108
|
|
147
109
|
it "ignores JSON messages by default" do
|
148
|
-
|
149
|
-
|
110
|
+
request = make_json_request_object()
|
111
|
+
handler = TestingHandler.new( TEST_UUID, TEST_SEND_SPEC, TEST_RECV_SPEC )
|
150
112
|
|
151
|
-
|
113
|
+
response = handler.dispatch_request( request )
|
152
114
|
|
153
|
-
expect(
|
154
|
-
request, response = res.transactions.first
|
155
|
-
expect( request ).to be_a( Mongrel2::JSONRequest )
|
156
|
-
expect( response ).to be_nil()
|
115
|
+
expect( response ).to be_nil
|
157
116
|
end
|
158
117
|
|
159
118
|
|
160
119
|
it "dispatches JSON message to the #handle_json method" do
|
161
|
-
|
120
|
+
json_handler_class = Class.new( TestingHandler ) do
|
162
121
|
def handle_json( request )
|
163
122
|
return request.response
|
164
123
|
end
|
165
124
|
end
|
125
|
+
request = make_json_request_object()
|
126
|
+
handler = json_handler_class.new( TEST_UUID, TEST_SEND_SPEC, TEST_RECV_SPEC )
|
166
127
|
|
167
|
-
|
168
|
-
expect( @request_sock ).to receive( :receive ).and_return( CZTop::Message.new( req ) )
|
169
|
-
|
170
|
-
res = json_handler.new( TEST_UUID, TEST_SEND_SPEC, TEST_RECV_SPEC ).run
|
128
|
+
response = handler.dispatch_request( request )
|
171
129
|
|
172
|
-
expect( res.transactions.size ).to eq( 1 )
|
173
|
-
request, response = res.transactions.first
|
174
|
-
expect( request ).to be_a( Mongrel2::JSONRequest )
|
175
130
|
expect( response ).to be_a( Mongrel2::Response )
|
176
131
|
end
|
177
132
|
|
178
133
|
|
179
134
|
it "ignores XML messages by default" do
|
180
|
-
|
181
|
-
|
135
|
+
request = make_xml_request_object()
|
136
|
+
handler = TestingHandler.new( TEST_UUID, TEST_SEND_SPEC, TEST_RECV_SPEC )
|
182
137
|
|
183
|
-
|
138
|
+
response = handler.dispatch_request( request )
|
184
139
|
|
185
|
-
expect(
|
186
|
-
request, response = res.transactions.first
|
187
|
-
expect( request ).to be_a( Mongrel2::XMLRequest )
|
188
|
-
expect( response ).to be_nil()
|
140
|
+
expect( response ).to be_nil
|
189
141
|
end
|
190
142
|
|
191
143
|
|
192
144
|
it "dispatches XML message to the #handle_xml method" do
|
193
|
-
|
145
|
+
xml_handler_class = Class.new( TestingHandler ) do
|
194
146
|
def handle_xml( request )
|
195
147
|
return request.response
|
196
148
|
end
|
197
149
|
end
|
150
|
+
request = make_xml_request_object()
|
151
|
+
handler = xml_handler_class.new( TEST_UUID, TEST_SEND_SPEC, TEST_RECV_SPEC )
|
198
152
|
|
199
|
-
|
200
|
-
expect( @request_sock ).to receive( :receive ).and_return( CZTop::Message.new( req ) )
|
201
|
-
|
202
|
-
res = xml_handler.new( TEST_UUID, TEST_SEND_SPEC, TEST_RECV_SPEC ).run
|
153
|
+
response = handler.dispatch_request( request )
|
203
154
|
|
204
|
-
expect( res.transactions.size ).to eq( 1 )
|
205
|
-
request, response = res.transactions.first
|
206
|
-
expect( request ).to be_a( Mongrel2::XMLRequest )
|
207
155
|
expect( response ).to be_a( Mongrel2::Response )
|
208
156
|
end
|
209
157
|
|
210
158
|
|
159
|
+
it "drops the connection on websocket opening handshakes by default" do
|
160
|
+
request = make_websocket_handshake_object()
|
161
|
+
handler = TestingHandler.new( TEST_UUID, TEST_SEND_SPEC, TEST_RECV_SPEC )
|
162
|
+
|
163
|
+
expect( handler.conn ).to receive( :reply_close ).with( request )
|
164
|
+
|
165
|
+
response = handler.dispatch_request( request )
|
166
|
+
|
167
|
+
expect( response ).to be_nil
|
168
|
+
end
|
169
|
+
|
170
|
+
|
211
171
|
it "dispatches WebSocket opening handshakes to the #handle_websocket_handshake method" do
|
212
|
-
|
172
|
+
ws_handler_class = Class.new( TestingHandler ) do
|
213
173
|
def handle_websocket_handshake( handshake )
|
214
174
|
return handshake.response
|
215
175
|
end
|
216
176
|
end
|
177
|
+
request = make_websocket_handshake_object()
|
178
|
+
handler = ws_handler_class.new( TEST_UUID, TEST_SEND_SPEC, TEST_RECV_SPEC )
|
217
179
|
|
218
|
-
|
219
|
-
expect( @request_sock ).to receive( :receive ).and_return( CZTop::Message.new( req ) )
|
180
|
+
response = handler.dispatch_request( request )
|
220
181
|
|
221
|
-
res = ws_handler.new( TEST_UUID, TEST_SEND_SPEC, TEST_RECV_SPEC ).run
|
222
|
-
|
223
|
-
expect( res.transactions.size ).to eq( 1 )
|
224
|
-
request, response = res.transactions.first
|
225
|
-
expect( request ).to be_a( Mongrel2::WebSocket::ClientHandshake )
|
226
182
|
expect( response ).to be_a( Mongrel2::WebSocket::ServerHandshake )
|
227
183
|
end
|
228
184
|
|
229
185
|
|
230
|
-
it "
|
231
|
-
|
232
|
-
|
233
|
-
return frame.response
|
234
|
-
end
|
235
|
-
end
|
186
|
+
it "directly closes the connection on websocket frames with a protocol violation by default" do
|
187
|
+
request = make_websocket_frame_object()
|
188
|
+
handler = TestingHandler.new( TEST_UUID, TEST_SEND_SPEC, TEST_RECV_SPEC )
|
236
189
|
|
237
|
-
|
238
|
-
expect(
|
190
|
+
expect( handler.conn ).to receive( :reply_close ).with( request )
|
191
|
+
expect( handler.conn ).to receive( :reply ) do |reply|
|
192
|
+
expect( reply ).to be_a( Mongrel2::WebSocket::Frame )
|
193
|
+
expect( reply.opcode ).to eq( :close )
|
194
|
+
reply.payload.rewind
|
195
|
+
expect( reply.payload.read ).to start_with( '1008 ' )
|
196
|
+
end
|
239
197
|
|
240
|
-
|
198
|
+
response = handler.dispatch_request( request )
|
241
199
|
|
242
|
-
expect(
|
243
|
-
request, response = res.transactions.first
|
244
|
-
expect( request ).to be_a( Mongrel2::WebSocket::Frame )
|
245
|
-
expect( response ).to be_a( Mongrel2::WebSocket::Frame )
|
200
|
+
expect( response ).to be_nil
|
246
201
|
end
|
247
202
|
|
248
203
|
|
249
|
-
it "
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
204
|
+
it "dispatches WebSocket protocol frames to the #handle_websocket method" do
|
205
|
+
ws_handler_class = Class.new( TestingHandler ) do
|
206
|
+
def handle_websocket( frame )
|
207
|
+
return frame.response
|
208
|
+
end
|
209
|
+
end
|
210
|
+
request = make_websocket_frame_object()
|
211
|
+
handler = ws_handler_class.new( TEST_UUID, TEST_SEND_SPEC, TEST_RECV_SPEC )
|
255
212
|
|
256
|
-
|
213
|
+
response = handler.dispatch_request( request )
|
257
214
|
|
258
|
-
expect(
|
259
|
-
request, response = res.transactions.first
|
260
|
-
expect( request ).to be_a( Mongrel2::HTTPRequest )
|
261
|
-
expect( response ).to be_a( Mongrel2::HTTPResponse )
|
262
|
-
expect( response.status ).to eq( 204 )
|
215
|
+
expect( response ).to be_a( Mongrel2::WebSocket::Frame )
|
263
216
|
end
|
264
217
|
|
265
218
|
|
266
219
|
it "ignores disconnect notices by default" do
|
267
|
-
|
268
|
-
|
220
|
+
request = make_json_request_object( :path => '@*', :body => {'type' => 'disconnect'} )
|
221
|
+
handler = TestingHandler.new( TEST_UUID, TEST_SEND_SPEC, TEST_RECV_SPEC )
|
269
222
|
|
270
|
-
|
223
|
+
response = handler.dispatch_request( request )
|
271
224
|
|
272
|
-
expect(
|
273
|
-
request, response = res.transactions.first
|
274
|
-
expect( request ).to be_a( Mongrel2::JSONRequest )
|
275
|
-
expect( response ).to be_nil()
|
225
|
+
expect( response ).to be_nil
|
276
226
|
end
|
277
227
|
|
278
228
|
|
279
229
|
it "dispatches disconnect notices to the #handle_disconnect method" do
|
280
|
-
|
230
|
+
disconnect_handler_class = Class.new( TestingHandler ) do
|
231
|
+
def initialize( * )
|
232
|
+
super
|
233
|
+
@handled_disconnect = false
|
234
|
+
end
|
235
|
+
|
236
|
+
attr_reader :handled_disconnect
|
237
|
+
|
281
238
|
def handle_disconnect( request )
|
239
|
+
@handled_disconnect = true
|
282
240
|
self.log.debug "Doing stuff for disconnected connection %d" % [ request.conn_id ]
|
283
241
|
end
|
284
242
|
end
|
243
|
+
request = make_json_request_object( :path => '@*', :body => {'type' => 'disconnect'} )
|
244
|
+
handler = disconnect_handler_class.new( TEST_UUID, TEST_SEND_SPEC, TEST_RECV_SPEC )
|
285
245
|
|
286
|
-
|
287
|
-
expect( @request_sock ).to receive( :receive ).and_return( CZTop::Message.new( req ) )
|
288
|
-
|
289
|
-
res = disconnect_handler.new( TEST_UUID, TEST_SEND_SPEC, TEST_RECV_SPEC ).run
|
246
|
+
response = handler.dispatch_request( request )
|
290
247
|
|
291
|
-
expect(
|
292
|
-
|
293
|
-
expect( request ).to be_a( Mongrel2::JSONRequest )
|
294
|
-
expect( response ).to be_nil()
|
248
|
+
expect( response ).to be_nil
|
249
|
+
expect( handler.handled_disconnect ).to eq( true )
|
295
250
|
end
|
296
251
|
|
297
252
|
|
298
253
|
it "cancels async upload notices by default" do
|
299
|
-
|
300
|
-
|
301
|
-
|
254
|
+
request = make_request_object(
|
255
|
+
'METHOD' => 'POST',
|
256
|
+
headers: {'x-mongrel2-upload-start' => 'uploadfile.XXX'}
|
257
|
+
)
|
258
|
+
handler = TestingHandler.new( TEST_UUID, TEST_SEND_SPEC, TEST_RECV_SPEC )
|
259
|
+
expect( handler.conn ).to receive( :reply_close ).with( request )
|
302
260
|
|
303
|
-
|
261
|
+
response = handler.dispatch_request( request )
|
304
262
|
|
305
|
-
expect(
|
306
|
-
request, response = res.transactions.first
|
307
|
-
expect( response ).to be_nil()
|
263
|
+
expect( response ).to be_nil
|
308
264
|
end
|
309
265
|
|
310
266
|
|
311
267
|
it "re-establishes its connection when told to restart" do
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
268
|
+
handler = TestingHandler.new( TEST_UUID, TEST_SEND_SPEC, TEST_RECV_SPEC )
|
269
|
+
original_conn = handler.conn
|
270
|
+
|
271
|
+
expect( handler.reactor ).to receive( :unregister ).with( original_conn.request_sock )
|
272
|
+
expect( handler.reactor ).to receive( :register ) do |request_sock, mode, &callback|
|
273
|
+
expect( request_sock ).to be_a( CZTop::Socket )
|
274
|
+
expect( request_sock ).to_not equal( original_conn.request_sock )
|
275
|
+
expect( mode ).to eq( :read )
|
276
|
+
end
|
316
277
|
|
317
|
-
|
318
|
-
res.restart
|
278
|
+
handler.restart
|
319
279
|
|
320
|
-
expect(
|
280
|
+
expect( handler.conn ).to_not equal( original_conn )
|
321
281
|
end
|
322
282
|
|
323
283
|
|
@@ -325,14 +285,18 @@ describe Mongrel2::Handler, :db do
|
|
325
285
|
spoolfile = Pathname.new( Dir.tmpdir + '/mongrel2.uskd8l1' )
|
326
286
|
spoolfile.write( "Hi!" )
|
327
287
|
|
328
|
-
|
329
|
-
'
|
330
|
-
|
331
|
-
|
332
|
-
|
288
|
+
request = make_request_object(
|
289
|
+
'METHOD' => 'POST',
|
290
|
+
headers: {
|
291
|
+
'x-mongrel2-upload-start' => spoolfile.basename,
|
292
|
+
'x-mongrel2-upload-done' => spoolfile.basename
|
293
|
+
}
|
294
|
+
)
|
295
|
+
handler = TestingHandler.new( TEST_UUID, TEST_SEND_SPEC, TEST_RECV_SPEC )
|
296
|
+
|
297
|
+
expect( handler.conn ).to receive( :reply ).with( a_kind_of(Mongrel2::Response) )
|
298
|
+
response = handler.accept_request( request )
|
333
299
|
|
334
|
-
res = OneShotHandler.new( TEST_UUID, TEST_SEND_SPEC, TEST_RECV_SPEC ).run
|
335
|
-
request, response = res.transactions.first
|
336
300
|
expect( request.body ).to be_closed
|
337
301
|
expect( spoolfile ).to_not exist
|
338
302
|
end
|
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.
|
4
|
+
version: 0.52.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Michael Granger
|
@@ -35,7 +35,7 @@ cert_chain:
|
|
35
35
|
X0qdrKi+2aZZ0NGuFj9AItBsVmAvkBGIpX4TEKQp5haEbPpmaqO5nIIhV26PXmyT
|
36
36
|
OMKv6pWsoS81vw5KAGBmfX8nht/Py90DQrbRvakATGI=
|
37
37
|
-----END CERTIFICATE-----
|
38
|
-
date:
|
38
|
+
date: 2018-07-21 00:00:00.000000000 Z
|
39
39
|
dependencies:
|
40
40
|
- !ruby/object:Gem::Dependency
|
41
41
|
name: cztop
|
@@ -51,6 +51,20 @@ dependencies:
|
|
51
51
|
- - "~>"
|
52
52
|
- !ruby/object:Gem::Version
|
53
53
|
version: '0.11'
|
54
|
+
- !ruby/object:Gem::Dependency
|
55
|
+
name: cztop-reactor
|
56
|
+
requirement: !ruby/object:Gem::Requirement
|
57
|
+
requirements:
|
58
|
+
- - "~>"
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: '0.3'
|
61
|
+
type: :runtime
|
62
|
+
prerelease: false
|
63
|
+
version_requirements: !ruby/object:Gem::Requirement
|
64
|
+
requirements:
|
65
|
+
- - "~>"
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
version: '0.3'
|
54
68
|
- !ruby/object:Gem::Dependency
|
55
69
|
name: libxml-ruby
|
56
70
|
requirement: !ruby/object:Gem::Requirement
|
@@ -399,7 +413,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
399
413
|
version: '0'
|
400
414
|
requirements: []
|
401
415
|
rubyforge_project:
|
402
|
-
rubygems_version: 2.
|
416
|
+
rubygems_version: 2.7.7
|
403
417
|
signing_key:
|
404
418
|
specification_version: 4
|
405
419
|
summary: Ruby-Mongrel2 is a complete Ruby connector for Mongrel2[http://mongrel2.org/]
|
metadata.gz.sig
CHANGED
Binary file
|