mongrel2 0.24.0 → 0.25.0.pre.285

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.
@@ -12,6 +12,8 @@ BEGIN {
12
12
 
13
13
  require 'rspec'
14
14
  require 'tnetstring'
15
+ require 'tmpdir'
16
+ require 'tempfile'
15
17
 
16
18
  require 'spec/lib/helpers'
17
19
 
@@ -27,6 +29,7 @@ describe Mongrel2::Request do
27
29
 
28
30
  before( :all ) do
29
31
  setup_logging( :fatal )
32
+ @factory = Mongrel2::RequestFactory.new( route: '/form' )
30
33
  end
31
34
 
32
35
  after( :all ) do
@@ -79,9 +82,7 @@ describe Mongrel2::Request do
79
82
  "don't look like HTTP ones" do
80
83
 
81
84
  message = make_request( :headers => {'METHOD' => '!DIVULGE'} )
82
- expect {
83
- Mongrel2::Request.parse( message )
84
- }.to raise_error( Mongrel2::UnhandledMethodError, /!DIVULGE/ )
85
+ expect { Mongrel2::Request.parse(message) }.to raise_error( Mongrel2::UnhandledMethodError, /!DIVULGE/ )
85
86
  end
86
87
 
87
88
  it "knows what kind of response it should return" do
@@ -110,6 +111,31 @@ describe Mongrel2::Request do
110
111
  end
111
112
 
112
113
 
114
+ describe "content-type charset support" do
115
+
116
+ it "uses the charset in the content-type header, if present" do
117
+ body = "some data".encode( 'binary' )
118
+ req = @factory.post( '/form', body, content_type: 'text/plain; charset=iso-8859-1' )
119
+
120
+ req.body.string.encoding.should be( Encoding::ISO_8859_1 )
121
+ end
122
+
123
+ it "keeps the data as ascii-8bit if no charset is in the content-type header" do
124
+ body = "some data".encode( 'binary' )
125
+ req = @factory.post( '/form', body, content_type: 'application/octet-stream' )
126
+
127
+ req.body.string.encoding.should be( Encoding::ASCII_8BIT )
128
+ end
129
+
130
+ it "keeps the data as ascii-8bit if there is no content-type header" do
131
+ body = "some data".encode( 'binary' )
132
+ req = @factory.post( '/form', body )
133
+
134
+ req.body.string.encoding.should be( Encoding::ASCII_8BIT )
135
+ end
136
+
137
+ end
138
+
113
139
  describe "framework support" do
114
140
 
115
141
  before( :all ) do
@@ -161,5 +187,88 @@ describe Mongrel2::Request do
161
187
 
162
188
  end
163
189
 
190
+
191
+ describe "async upload support" do
192
+
193
+ before( :all ) do
194
+ setup_config_db()
195
+ Mongrel2::Config::Server.create(
196
+ uuid: Mongrel2::RequestFactory::DEFAULT_TEST_UUID,
197
+ access_log: 'access.log',
198
+ error_log: 'error.log',
199
+ pid_file: '/var/run/mongrel2.pid',
200
+ default_host: 'localhost',
201
+ port: 663,
202
+ chroot: Dir.tmpdir
203
+ )
204
+ end
205
+
206
+ before( :each ) do
207
+ @spoolfile = Tempfile.new( 'mongrel2.upload', Dir.tmpdir )
208
+ @spoolfile.print( File.read(__FILE__) )
209
+ @spoolpath = @spoolfile.path.slice( Dir.tmpdir.length + 1..-1 )
210
+ end
211
+
212
+ it "knows if it's an 'async upload started' notification" do
213
+ req = @factory.post( '/form', '', x_mongrel2_upload_start: @spoolpath )
214
+
215
+ req.should be_upload_started()
216
+ req.should_not be_upload_done()
217
+ end
218
+
219
+ it "knows if it's an 'async upload done' notification" do
220
+ req = @factory.post( '/form', '',
221
+ x_mongrel2_upload_start: @spoolpath,
222
+ x_mongrel2_upload_done: @spoolpath )
223
+
224
+ req.should_not be_upload_started()
225
+ req.should be_upload_done()
226
+ req.should be_valid_upload()
227
+ end
228
+
229
+ it "knows if it's not a valid 'async upload done' notification" do
230
+ req = @factory.post( '/form', '',
231
+ x_mongrel2_upload_start: @spoolpath,
232
+ x_mongrel2_upload_done: '/etc/passwd' )
233
+
234
+ req.should_not be_upload_started()
235
+ req.should be_upload_done()
236
+ req.should_not be_valid_upload()
237
+ end
238
+
239
+ it "raises an exception if the uploaded file fetched with mismatched headers" do
240
+ req = @factory.post( '/form', '',
241
+ x_mongrel2_upload_start: @spoolpath,
242
+ x_mongrel2_upload_done: '/etc/passwd' )
243
+
244
+ expect {
245
+ req.uploaded_file
246
+ }.to raise_error( Mongrel2::UploadError, /upload headers/i )
247
+ end
248
+
249
+ it "can return a Pathname object for the uploaded file if it's valid" do
250
+ req = @factory.post( '/form', '',
251
+ x_mongrel2_upload_start: @spoolpath,
252
+ x_mongrel2_upload_done: @spoolpath )
253
+
254
+ req.should be_valid_upload()
255
+
256
+ req.uploaded_file.should be_a( Pathname )
257
+ req.uploaded_file.to_s.should == @spoolfile.path
258
+ end
259
+
260
+ it "sets the body of the request to the uploaded File if it's valid" do
261
+ req = @factory.post( '/form', '',
262
+ x_mongrel2_upload_start: @spoolpath,
263
+ x_mongrel2_upload_done: @spoolpath )
264
+
265
+ req.should be_valid_upload()
266
+
267
+ req.body.should be_a( File )
268
+ req.body.path.should == @spoolfile.path
269
+ end
270
+
271
+ end
272
+
164
273
  end
165
274
 
@@ -48,7 +48,7 @@ describe Mongrel2::Response do
48
48
 
49
49
  it "can be created with a body" do
50
50
  response = Mongrel2::Response.new( TEST_UUID, 8, 'the body' )
51
- response.body.should == 'the body'
51
+ response.body.read.should == 'the body'
52
52
  end
53
53
 
54
54
  it "stringifies to its body contents" do
@@ -56,24 +56,39 @@ describe Mongrel2::Response do
56
56
  response.to_s.should == 'the body'
57
57
  end
58
58
 
59
+ it "can be streamed in chunks" do
60
+ response = Mongrel2::Response.new( TEST_UUID, 8, 'the body' )
61
+ expect {|b| response.each_chunk(&b) }.to yield_with_args( 'the body' )
62
+ end
63
+
64
+ it "wraps non-IO bodies set via the #body= accessor in a StringIO" do
65
+ response = Mongrel2::Response.new( TEST_UUID, 8 )
66
+ response.body = 'a stringioed body'
67
+ response.body.should be_a( StringIO )
68
+ response.body.string.should == 'a stringioed body'
69
+ end
70
+
59
71
  context "an instance with default values" do
60
72
 
61
73
  before( :each ) do
62
74
  @response = Mongrel2::Response.new( TEST_UUID, 8 )
63
75
  end
64
76
 
65
- it "has an empty-string body" do
66
- @response.body.should == ''
77
+ it "has an empty-IO body" do
78
+ @response.body.rewind
79
+ @response.body.read.should == ''
67
80
  end
68
81
 
69
- it "supports the append operator to append objects to the body" do
82
+ it "supports the append operator to append objects to the body IO" do
70
83
  @response << 'some body stuff' << ' and some more body stuff'
71
- @response.body.should == 'some body stuff and some more body stuff'
84
+ @response.body.rewind
85
+ @response.body.read.should == 'some body stuff and some more body stuff'
72
86
  end
73
87
 
74
- it "supports #puts for appending objects separated by EOL" do
88
+ it "supports #puts for appending objects to the body IO separated by EOL" do
75
89
  @response.puts( "some body stuff\n", " and some more body stuff\n\n", :and_a_symbol )
76
- @response.body.should == "some body stuff\n and some more body stuff\n\nand_a_symbol\n"
90
+ @response.body.rewind
91
+ @response.body.read.should == "some body stuff\n and some more body stuff\n\nand_a_symbol\n"
77
92
  end
78
93
 
79
94
  end
@@ -144,7 +144,8 @@ describe Mongrel2::WebSocket do
144
144
  result.conn_id.should == frame.conn_id
145
145
  result.opcode.should == :text
146
146
 
147
- result.payload.should == ''
147
+ result.payload.rewind
148
+ result.payload.read.should == ''
148
149
  end
149
150
 
150
151
  it "creates PONG responses with the same payload for PING frames" do
@@ -157,7 +158,8 @@ describe Mongrel2::WebSocket do
157
158
  result.conn_id.should == frame.conn_id
158
159
  result.opcode.should == :pong
159
160
 
160
- result.payload.should == 'WOO'
161
+ result.payload.rewind
162
+ result.payload.read.should == 'WOO'
161
163
  end
162
164
 
163
165
  it "allows header flags and/or opcode to be specified when creating a response" do
@@ -171,7 +173,19 @@ describe Mongrel2::WebSocket do
171
173
  result.opcode.should == :close
172
174
  result.should be_fin()
173
175
 
174
- result.payload.should == ''
176
+ result.payload.rewind
177
+ result.payload.read.should == ''
178
+ end
179
+
180
+ it "can be streamed in chunks instead of read all at once" do
181
+ data = BINARY_DATA * 256
182
+ binary = @factory.binary( '/websock', data, :fin )
183
+
184
+ binary.chunksize = 16
185
+ binary.each_chunk.to_a[0,2].should == [
186
+ "\x82\x7F\x00\x00\x00\x00\x00\x01\x00\x00\a\xBD\xB3\xFE\x87\xEB".force_encoding('binary'),
187
+ "\xA9\x0En2q\xCE\x85\xAF)\x88w_d\xD6M\x9E".force_encoding('binary'),
188
+ ]
175
189
  end
176
190
 
177
191
  end
@@ -180,14 +194,15 @@ describe Mongrel2::WebSocket do
180
194
  describe "a WebSocket text frame" do
181
195
 
182
196
  before( :each ) do
183
- @frame = @factory.text( '/websock', 'Damn the torpedoes!', :fin )
197
+ @frame = @factory.text( '/websock', '', :fin )
184
198
  end
185
199
 
186
200
  it "automatically transcodes its payload to UTF8" do
187
201
  text = "Стрелке!".encode( Encoding::KOI8_U )
188
- @frame.payload.replace( text )
202
+ @frame << text
189
203
 
190
- @frame.to_s[ 2..-1 ].bytes.to_a.should ==
204
+ # 2-byte header
205
+ @frame.bytes.to_a[ 2..-1 ].should ==
191
206
  [0xD0, 0xA1, 0xD1, 0x82, 0xD1, 0x80, 0xD0, 0xB5, 0xD0, 0xBB, 0xD0,
192
207
  0xBA, 0xD0, 0xB5, 0x21]
193
208
  end
@@ -201,7 +216,10 @@ describe Mongrel2::WebSocket do
201
216
  end
202
217
 
203
218
  it "doesn't try to transcode non-UTF8 data" do
204
- @frame.to_s.encoding.should == Encoding::ASCII_8BIT
219
+ # 4-byte header
220
+ @frame.bytes.to_a[ 4, 16 ].should ==
221
+ [ 0x07, 0xbd, 0xb3, 0xfe, 0x87, 0xeb, 0xa9, 0x0e, 0x6e, 0x32, 0x71,
222
+ 0xce, 0x85, 0xaf, 0x29, 0x88 ]
205
223
  end
206
224
  end
207
225
 
@@ -213,7 +231,8 @@ describe Mongrel2::WebSocket do
213
231
 
214
232
  it "has convenience methods for setting its payload via integer status code" do
215
233
  @frame.set_status( CLOSE_BAD_DATA )
216
- @frame.to_s[ 2..-1 ].should == "%d %s" %
234
+ @frame.payload.rewind
235
+ @frame.payload.read.should == "%d %s\n" %
217
236
  [ CLOSE_BAD_DATA, CLOSING_STATUS_DESC[CLOSE_BAD_DATA] ]
218
237
  end
219
238
 
@@ -227,16 +246,16 @@ describe Mongrel2::WebSocket do
227
246
 
228
247
 
229
248
  it "raises an exception if its payload is bigger than 125 bytes" do
230
- @frame.body = "x" * 126
249
+ @frame.body << "x" * 126
231
250
  expect {
232
- @frame.to_s
251
+ @frame.validate
233
252
  }.to raise_error( Mongrel2::WebSocket::FrameError, /cannot exceed 125 bytes/i )
234
253
  end
235
254
 
236
255
  it "raises an exception if it's fragmented" do
237
256
  @frame.fin = false
238
257
  expect {
239
- @frame.to_s
258
+ @frame.validate
240
259
  }.to raise_error( Mongrel2::WebSocket::FrameError, /fragmented/i )
241
260
  end
242
261
 
@@ -274,7 +293,7 @@ describe Mongrel2::WebSocket do
274
293
  binary = @factory.binary( '/websock', BINARY_DATA, :fin )
275
294
 
276
295
  # 1 + 1 + 2
277
- binary.to_s[0,4].bytes.to_a.should == [ 0x82, 0x7E, 0x01, 0x00 ]
296
+ binary.bytes.to_a[0,4].should == [ 0x82, 0x7E, 0x01, 0x00 ]
278
297
  binary.to_s[4..-1].should == BINARY_DATA
279
298
  end
280
299
 
@@ -284,7 +303,7 @@ describe Mongrel2::WebSocket do
284
303
  binary = @factory.binary( '/websock', data, :fin )
285
304
 
286
305
  # 1 + 1 + 8
287
- binary.to_s[0,10].bytes.to_a.should ==
306
+ binary.bytes.to_a[0,10].should ==
288
307
  [ 0x82, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00 ]
289
308
  binary.to_s[10..-1].should == data
290
309
  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.24.0
4
+ version: 0.25.0.pre.285
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-05-31 00:00:00.000000000 Z
39
+ date: 2012-06-20 00:00:00.000000000 Z
40
40
  dependencies:
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: nokogiri
metadata.gz.sig CHANGED
Binary file