mongrel2 0.24.0 → 0.25.0.pre.285

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