rack 1.2.8 → 1.3.0.beta
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of rack might be problematic. Click here for more details.
- data/README +9 -177
- data/Rakefile +2 -1
- data/SPEC +2 -2
- data/lib/rack.rb +2 -13
- data/lib/rack/auth/abstract/request.rb +7 -5
- data/lib/rack/auth/digest/md5.rb +6 -2
- data/lib/rack/auth/digest/params.rb +5 -7
- data/lib/rack/auth/digest/request.rb +1 -1
- data/lib/rack/backports/uri/common.rb +64 -0
- data/lib/rack/builder.rb +60 -3
- data/lib/rack/chunked.rb +29 -22
- data/lib/rack/conditionalget.rb +35 -16
- data/lib/rack/content_length.rb +3 -3
- data/lib/rack/deflater.rb +5 -2
- data/lib/rack/etag.rb +38 -10
- data/lib/rack/file.rb +76 -43
- data/lib/rack/handler.rb +13 -7
- data/lib/rack/handler/cgi.rb +0 -2
- data/lib/rack/handler/fastcgi.rb +13 -4
- data/lib/rack/handler/lsws.rb +0 -2
- data/lib/rack/handler/mongrel.rb +12 -2
- data/lib/rack/handler/scgi.rb +9 -1
- data/lib/rack/handler/thin.rb +7 -1
- data/lib/rack/handler/webrick.rb +12 -5
- data/lib/rack/lint.rb +2 -2
- data/lib/rack/lock.rb +29 -3
- data/lib/rack/methodoverride.rb +1 -1
- data/lib/rack/mime.rb +2 -2
- data/lib/rack/mock.rb +28 -33
- data/lib/rack/multipart.rb +34 -0
- data/lib/rack/multipart/generator.rb +93 -0
- data/lib/rack/multipart/parser.rb +164 -0
- data/lib/rack/multipart/uploaded_file.rb +30 -0
- data/lib/rack/request.rb +55 -19
- data/lib/rack/response.rb +10 -8
- data/lib/rack/sendfile.rb +14 -18
- data/lib/rack/server.rb +55 -8
- data/lib/rack/session/abstract/id.rb +233 -22
- data/lib/rack/session/cookie.rb +99 -46
- data/lib/rack/session/memcache.rb +30 -56
- data/lib/rack/session/pool.rb +22 -43
- data/lib/rack/showexceptions.rb +40 -11
- data/lib/rack/showstatus.rb +9 -2
- data/lib/rack/static.rb +29 -9
- data/lib/rack/urlmap.rb +6 -1
- data/lib/rack/utils.rb +67 -326
- data/rack.gemspec +2 -3
- data/test/builder/anything.rb +5 -0
- data/test/builder/comment.ru +4 -0
- data/test/builder/end.ru +3 -0
- data/test/builder/options.ru +2 -0
- data/test/cgi/lighttpd.conf +1 -1
- data/test/cgi/lighttpd.errors +412 -0
- data/test/multipart/content_type_and_no_filename +6 -0
- data/test/multipart/text +5 -0
- data/test/multipart/webkit +32 -0
- data/test/registering_handler/rack/handler/registering_myself.rb +8 -0
- data/test/spec_auth_digest.rb +20 -5
- data/test/spec_builder.rb +29 -0
- data/test/spec_cgi.rb +11 -0
- data/test/spec_chunked.rb +1 -1
- data/test/spec_commonlogger.rb +1 -1
- data/test/spec_conditionalget.rb +47 -0
- data/test/spec_content_length.rb +0 -6
- data/test/spec_content_type.rb +5 -5
- data/test/spec_deflater.rb +46 -2
- data/test/spec_etag.rb +68 -1
- data/test/spec_fastcgi.rb +11 -0
- data/test/spec_file.rb +54 -3
- data/test/spec_handler.rb +23 -5
- data/test/spec_lint.rb +2 -2
- data/test/spec_lock.rb +111 -5
- data/test/spec_methodoverride.rb +2 -2
- data/test/spec_mock.rb +3 -3
- data/test/spec_mongrel.rb +1 -2
- data/test/spec_multipart.rb +279 -0
- data/test/spec_request.rb +222 -38
- data/test/spec_response.rb +9 -3
- data/test/spec_server.rb +74 -0
- data/test/spec_session_abstract_id.rb +43 -0
- data/test/spec_session_cookie.rb +97 -15
- data/test/spec_session_memcache.rb +60 -50
- data/test/spec_session_pool.rb +63 -40
- data/test/spec_showexceptions.rb +64 -0
- data/test/spec_static.rb +23 -0
- data/test/spec_utils.rb +65 -351
- data/test/spec_webrick.rb +23 -4
- metadata +35 -15
- data/test/spec_auth.rb +0 -57
data/test/spec_request.rb
CHANGED
@@ -16,6 +16,7 @@ describe Rack::Request do
|
|
16
16
|
req.should.not.be.put
|
17
17
|
req.should.not.be.delete
|
18
18
|
req.should.not.be.head
|
19
|
+
req.should.not.be.patch
|
19
20
|
|
20
21
|
req.script_name.should.equal ""
|
21
22
|
req.path_info.should.equal "/"
|
@@ -52,6 +53,70 @@ describe Rack::Request do
|
|
52
53
|
req.host.should.equal ""
|
53
54
|
end
|
54
55
|
|
56
|
+
should "figure out the correct port" do
|
57
|
+
req = Rack::Request.new \
|
58
|
+
Rack::MockRequest.env_for("/", "HTTP_HOST" => "www2.example.org")
|
59
|
+
req.port.should.equal 80
|
60
|
+
|
61
|
+
req = Rack::Request.new \
|
62
|
+
Rack::MockRequest.env_for("/", "HTTP_HOST" => "www2.example.org:81")
|
63
|
+
req.port.should.equal 81
|
64
|
+
|
65
|
+
req = Rack::Request.new \
|
66
|
+
Rack::MockRequest.env_for("/", "SERVER_NAME" => "example.org", "SERVER_PORT" => "9292")
|
67
|
+
req.port.should.equal 9292
|
68
|
+
|
69
|
+
req = Rack::Request.new \
|
70
|
+
Rack::MockRequest.env_for("/", "HTTP_HOST" => "localhost:81", "HTTP_X_FORWARDED_HOST" => "example.org:9292")
|
71
|
+
req.port.should.equal 9292
|
72
|
+
|
73
|
+
req = Rack::Request.new \
|
74
|
+
Rack::MockRequest.env_for("/", "HTTP_HOST" => "localhost:81", "HTTP_X_FORWARDED_HOST" => "example.org")
|
75
|
+
req.port.should.equal 80
|
76
|
+
|
77
|
+
req = Rack::Request.new \
|
78
|
+
Rack::MockRequest.env_for("/", "HTTP_HOST" => "localhost:81", "HTTP_X_FORWARDED_HOST" => "example.org", "HTTP_X_FORWARDED_SSL" => "on")
|
79
|
+
req.port.should.equal 443
|
80
|
+
|
81
|
+
req = Rack::Request.new \
|
82
|
+
Rack::MockRequest.env_for("/", "HTTP_HOST" => "localhost:81", "HTTP_X_FORWARDED_HOST" => "example.org", "HTTP_X_FORWARDED_PROTO" => "https")
|
83
|
+
req.port.should.equal 443
|
84
|
+
|
85
|
+
req = Rack::Request.new \
|
86
|
+
Rack::MockRequest.env_for("/", "HTTP_HOST" => "localhost:81", "HTTP_X_FORWARDED_HOST" => "example.org", "HTTP_X_FORWARDED_PORT" => "9393")
|
87
|
+
req.port.should.equal 9393
|
88
|
+
|
89
|
+
req = Rack::Request.new \
|
90
|
+
Rack::MockRequest.env_for("/", "HTTP_HOST" => "localhost:81", "HTTP_X_FORWARDED_HOST" => "example.org:9393", "SERVER_PORT" => "80")
|
91
|
+
req.port.should.equal 9393
|
92
|
+
|
93
|
+
req = Rack::Request.new \
|
94
|
+
Rack::MockRequest.env_for("/", "HTTP_HOST" => "localhost:81", "HTTP_X_FORWARDED_HOST" => "example.org", "SERVER_PORT" => "9393")
|
95
|
+
req.port.should.equal 80
|
96
|
+
end
|
97
|
+
|
98
|
+
should "figure out the correct host with port" do
|
99
|
+
req = Rack::Request.new \
|
100
|
+
Rack::MockRequest.env_for("/", "HTTP_HOST" => "www2.example.org")
|
101
|
+
req.host_with_port.should.equal "www2.example.org"
|
102
|
+
|
103
|
+
req = Rack::Request.new \
|
104
|
+
Rack::MockRequest.env_for("/", "HTTP_HOST" => "localhost:81")
|
105
|
+
req.host_with_port.should.equal "localhost:81"
|
106
|
+
|
107
|
+
req = Rack::Request.new \
|
108
|
+
Rack::MockRequest.env_for("/", "SERVER_NAME" => "example.org", "SERVER_PORT" => "9292")
|
109
|
+
req.host_with_port.should.equal "example.org:9292"
|
110
|
+
|
111
|
+
req = Rack::Request.new \
|
112
|
+
Rack::MockRequest.env_for("/", "HTTP_HOST" => "localhost:81", "HTTP_X_FORWARDED_HOST" => "example.org:9292")
|
113
|
+
req.host_with_port.should.equal "example.org:9292"
|
114
|
+
|
115
|
+
req = Rack::Request.new \
|
116
|
+
Rack::MockRequest.env_for("/", "HTTP_HOST" => "localhost:81", "HTTP_X_FORWARDED_HOST" => "example.org", "SERVER_PORT" => "9393")
|
117
|
+
req.host_with_port.should.equal "example.org"
|
118
|
+
end
|
119
|
+
|
55
120
|
should "parse the query string" do
|
56
121
|
req = Rack::Request.new(Rack::MockRequest.env_for("/?foo=bar&quux=bla"))
|
57
122
|
req.query_string.should.equal "foo=bar&quux=bla"
|
@@ -60,6 +125,20 @@ describe Rack::Request do
|
|
60
125
|
req.params.should.equal "foo" => "bar", "quux" => "bla"
|
61
126
|
end
|
62
127
|
|
128
|
+
should "not unify GET and POST when calling params" do
|
129
|
+
mr = Rack::MockRequest.env_for("/?foo=quux",
|
130
|
+
"REQUEST_METHOD" => 'POST',
|
131
|
+
:input => "foo=bar&quux=bla"
|
132
|
+
)
|
133
|
+
req = Rack::Request.new mr
|
134
|
+
|
135
|
+
req.params
|
136
|
+
|
137
|
+
req.GET.should.equal "foo" => "quux"
|
138
|
+
req.POST.should.equal "foo" => "bar", "quux" => "bla"
|
139
|
+
req.params.should.equal req.GET.merge(req.POST)
|
140
|
+
end
|
141
|
+
|
63
142
|
should "raise if rack.input is missing" do
|
64
143
|
req = Rack::Request.new({})
|
65
144
|
lambda { req.POST }.should.raise(RuntimeError)
|
@@ -78,32 +157,6 @@ describe Rack::Request do
|
|
78
157
|
req.params.should.equal "foo" => "bar", "quux" => "bla"
|
79
158
|
end
|
80
159
|
|
81
|
-
should "limit the keys from the GET query string" do
|
82
|
-
env = Rack::MockRequest.env_for("/?foo=bar")
|
83
|
-
|
84
|
-
old, Rack::Utils.key_space_limit = Rack::Utils.key_space_limit, 1
|
85
|
-
begin
|
86
|
-
req = Rack::Request.new(env)
|
87
|
-
lambda { req.GET }.should.raise(RangeError)
|
88
|
-
ensure
|
89
|
-
Rack::Utils.key_space_limit = old
|
90
|
-
end
|
91
|
-
end
|
92
|
-
|
93
|
-
should "limit the keys from the POST form data" do
|
94
|
-
env = Rack::MockRequest.env_for("",
|
95
|
-
"REQUEST_METHOD" => 'POST',
|
96
|
-
:input => "foo=bar&quux=bla")
|
97
|
-
|
98
|
-
old, Rack::Utils.key_space_limit = Rack::Utils.key_space_limit, 1
|
99
|
-
begin
|
100
|
-
req = Rack::Request.new(env)
|
101
|
-
lambda { req.POST }.should.raise(RangeError)
|
102
|
-
ensure
|
103
|
-
Rack::Utils.key_space_limit = old
|
104
|
-
end
|
105
|
-
end
|
106
|
-
|
107
160
|
should "parse POST data with explicit content type regardless of method" do
|
108
161
|
req = Rack::Request.new \
|
109
162
|
Rack::MockRequest.env_for("/",
|
@@ -197,7 +250,7 @@ describe Rack::Request do
|
|
197
250
|
|
198
251
|
req = Rack::Request.new \
|
199
252
|
Rack::MockRequest.env_for("/")
|
200
|
-
req.referer.should.equal
|
253
|
+
req.referer.should.equal nil
|
201
254
|
end
|
202
255
|
|
203
256
|
should "extract user agent correctly" do
|
@@ -210,6 +263,24 @@ describe Rack::Request do
|
|
210
263
|
req.user_agent.should.equal nil
|
211
264
|
end
|
212
265
|
|
266
|
+
should "treat missing content type as nil" do
|
267
|
+
req = Rack::Request.new \
|
268
|
+
Rack::MockRequest.env_for("/")
|
269
|
+
req.content_type.should.equal nil
|
270
|
+
end
|
271
|
+
|
272
|
+
should "treat empty content type as nil" do
|
273
|
+
req = Rack::Request.new \
|
274
|
+
Rack::MockRequest.env_for("/", "CONTENT_TYPE" => "")
|
275
|
+
req.content_type.should.equal nil
|
276
|
+
end
|
277
|
+
|
278
|
+
should "return nil media type for empty content type" do
|
279
|
+
req = Rack::Request.new \
|
280
|
+
Rack::MockRequest.env_for("/", "CONTENT_TYPE" => "")
|
281
|
+
req.media_type.should.equal nil
|
282
|
+
end
|
283
|
+
|
213
284
|
should "cache, but invalidates the cache" do
|
214
285
|
req = Rack::Request.new \
|
215
286
|
Rack::MockRequest.env_for("/?foo=quux",
|
@@ -237,6 +308,40 @@ describe Rack::Request do
|
|
237
308
|
req.should.be.xhr
|
238
309
|
end
|
239
310
|
|
311
|
+
should "ssl detection" do
|
312
|
+
request = Rack::Request.new(Rack::MockRequest.env_for("/"))
|
313
|
+
request.scheme.should.equal "http"
|
314
|
+
request.should.not.be.ssl?
|
315
|
+
|
316
|
+
request = Rack::Request.new(Rack::MockRequest.env_for("/", 'HTTPS' => 'on'))
|
317
|
+
request.scheme.should.equal "https"
|
318
|
+
request.should.be.ssl?
|
319
|
+
|
320
|
+
request = Rack::Request.new(Rack::MockRequest.env_for("/", 'rack.url_scheme' => 'https'))
|
321
|
+
request.scheme.should.equal "https"
|
322
|
+
request.should.be.ssl?
|
323
|
+
|
324
|
+
request = Rack::Request.new(Rack::MockRequest.env_for("/", 'HTTP_HOST' => 'www.example.org:8080'))
|
325
|
+
request.scheme.should.equal "http"
|
326
|
+
request.should.not.be.ssl?
|
327
|
+
|
328
|
+
request = Rack::Request.new(Rack::MockRequest.env_for("/", 'HTTP_HOST' => 'www.example.org:8443', 'HTTPS' => 'on'))
|
329
|
+
request.scheme.should.equal "https"
|
330
|
+
request.should.be.ssl?
|
331
|
+
|
332
|
+
request = Rack::Request.new(Rack::MockRequest.env_for("/", 'HTTP_HOST' => 'www.example.org:8443', 'HTTP_X_FORWARDED_SSL' => 'on'))
|
333
|
+
request.scheme.should.equal "https"
|
334
|
+
request.should.be.ssl?
|
335
|
+
|
336
|
+
request = Rack::Request.new(Rack::MockRequest.env_for("/", 'HTTP_X_FORWARDED_PROTO' => 'https'))
|
337
|
+
request.scheme.should.equal "https"
|
338
|
+
request.should.be.ssl?
|
339
|
+
|
340
|
+
request = Rack::Request.new(Rack::MockRequest.env_for("/", 'HTTP_X_FORWARDED_PROTO' => 'https, http, http'))
|
341
|
+
request.scheme.should.equal "https"
|
342
|
+
request.should.be.ssl
|
343
|
+
end
|
344
|
+
|
240
345
|
should "parse cookies" do
|
241
346
|
req = Rack::Request.new \
|
242
347
|
Rack::MockRequest.env_for("", "HTTP_COOKIE" => "foo=bar;quux=h&m")
|
@@ -252,6 +357,18 @@ describe Rack::Request do
|
|
252
357
|
req.cookies.should.equal 'foo' => 'bar'
|
253
358
|
end
|
254
359
|
|
360
|
+
should 'parse cookies with quotes' do
|
361
|
+
req = Rack::Request.new Rack::MockRequest.env_for('', {
|
362
|
+
'HTTP_COOKIE' => '$Version="1"; Customer="WILE_E_COYOTE"; $Path="/acme"; Part_Number="Rocket_Launcher_0001"; $Path="/acme"'
|
363
|
+
})
|
364
|
+
req.cookies.should.equal({
|
365
|
+
'$Version' => '"1"',
|
366
|
+
'Customer' => '"WILE_E_COYOTE"',
|
367
|
+
'$Path' => '"/acme"',
|
368
|
+
'Part_Number' => '"Rocket_Launcher_0001"',
|
369
|
+
})
|
370
|
+
end
|
371
|
+
|
255
372
|
should "provide setters" do
|
256
373
|
req = Rack::Request.new(e=Rack::MockRequest.env_for(""))
|
257
374
|
req.script_name.should.equal ""
|
@@ -270,6 +387,13 @@ describe Rack::Request do
|
|
270
387
|
req.env.should == e
|
271
388
|
end
|
272
389
|
|
390
|
+
should "restore the base URL" do
|
391
|
+
Rack::Request.new(Rack::MockRequest.env_for("")).base_url.
|
392
|
+
should.equal "http://example.org"
|
393
|
+
Rack::Request.new(Rack::MockRequest.env_for("", "SCRIPT_NAME" => "/foo")).base_url.
|
394
|
+
should.equal "http://example.org"
|
395
|
+
end
|
396
|
+
|
273
397
|
should "restore the URL" do
|
274
398
|
Rack::Request.new(Rack::MockRequest.env_for("")).url.
|
275
399
|
should.equal "http://example.org/"
|
@@ -320,29 +444,71 @@ describe Rack::Request do
|
|
320
444
|
req.media_type_params['bling'].should.equal 'bam'
|
321
445
|
end
|
322
446
|
|
323
|
-
should "
|
447
|
+
should "parse with junk before boundry" do
|
448
|
+
# Adapted from RFC 1867.
|
324
449
|
input = <<EOF
|
450
|
+
blah blah\r
|
451
|
+
\r
|
452
|
+
--AaB03x\r
|
453
|
+
content-disposition: form-data; name="reply"\r
|
454
|
+
\r
|
455
|
+
yes\r
|
325
456
|
--AaB03x\r
|
326
|
-
|
327
|
-
Content-Type:
|
457
|
+
content-disposition: form-data; name="fileupload"; filename="dj.jpg"\r
|
458
|
+
Content-Type: image/jpeg\r
|
459
|
+
Content-Transfer-Encoding: base64\r
|
328
460
|
\r
|
329
|
-
|
461
|
+
/9j/4AAQSkZJRgABAQAAAQABAAD//gA+Q1JFQVRPUjogZ2QtanBlZyB2MS4wICh1c2luZyBJSkcg\r
|
330
462
|
--AaB03x--\r
|
331
463
|
EOF
|
464
|
+
req = Rack::Request.new Rack::MockRequest.env_for("/",
|
465
|
+
"CONTENT_TYPE" => "multipart/form-data, boundary=AaB03x",
|
466
|
+
"CONTENT_LENGTH" => input.size,
|
467
|
+
:input => input)
|
468
|
+
|
469
|
+
req.POST.should.include "fileupload"
|
470
|
+
req.POST.should.include "reply"
|
471
|
+
|
472
|
+
req.should.be.form_data
|
473
|
+
req.content_length.should.equal input.size
|
474
|
+
req.media_type.should.equal 'multipart/form-data'
|
475
|
+
req.media_type_params.should.include 'boundary'
|
476
|
+
req.media_type_params['boundary'].should.equal 'AaB03x'
|
477
|
+
|
478
|
+
req.POST["reply"].should.equal "yes"
|
479
|
+
|
480
|
+
f = req.POST["fileupload"]
|
481
|
+
f.should.be.kind_of Hash
|
482
|
+
f[:type].should.equal "image/jpeg"
|
483
|
+
f[:filename].should.equal "dj.jpg"
|
484
|
+
f.should.include :tempfile
|
485
|
+
f[:tempfile].size.should.equal 76
|
486
|
+
end
|
487
|
+
|
488
|
+
should "not infinite loop with a malformed HTTP request" do
|
489
|
+
# Adapted from RFC 1867.
|
490
|
+
input = <<EOF
|
491
|
+
--AaB03x
|
492
|
+
content-disposition: form-data; name="reply"
|
332
493
|
|
333
|
-
|
494
|
+
yes
|
495
|
+
--AaB03x
|
496
|
+
content-disposition: form-data; name="fileupload"; filename="dj.jpg"
|
497
|
+
Content-Type: image/jpeg
|
498
|
+
Content-Transfer-Encoding: base64
|
499
|
+
|
500
|
+
/9j/4AAQSkZJRgABAQAAAQABAAD//gA+Q1JFQVRPUjogZ2QtanBlZyB2MS4wICh1c2luZyBJSkcg
|
501
|
+
--AaB03x--
|
502
|
+
EOF
|
503
|
+
req = Rack::Request.new Rack::MockRequest.env_for("/",
|
334
504
|
"CONTENT_TYPE" => "multipart/form-data, boundary=AaB03x",
|
335
505
|
"CONTENT_LENGTH" => input.size,
|
336
506
|
:input => input)
|
337
507
|
|
338
|
-
|
339
|
-
begin
|
340
|
-
lambda { Rack::Utils::Multipart.parse_multipart(env) }.should.raise(RangeError)
|
341
|
-
ensure
|
342
|
-
Rack::Utils.key_space_limit = old
|
343
|
-
end
|
508
|
+
lambda{req.POST}.should.raise(EOFError)
|
344
509
|
end
|
345
510
|
|
511
|
+
|
346
512
|
should "parse multipart form data" do
|
347
513
|
# Adapted from RFC 1867.
|
348
514
|
input = <<EOF
|
@@ -443,6 +609,24 @@ EOF
|
|
443
609
|
lambda { req.POST }.should.raise(EOFError)
|
444
610
|
end
|
445
611
|
|
612
|
+
should "correctly parse the part name from Content-Id header" do
|
613
|
+
input = <<EOF
|
614
|
+
--AaB03x\r
|
615
|
+
Content-Type: text/xml; charset=utf-8\r
|
616
|
+
Content-Id: <soap-start>\r
|
617
|
+
Content-Transfer-Encoding: 7bit\r
|
618
|
+
\r
|
619
|
+
foo\r
|
620
|
+
--AaB03x--\r
|
621
|
+
EOF
|
622
|
+
req = Rack::Request.new Rack::MockRequest.env_for("/",
|
623
|
+
"CONTENT_TYPE" => "multipart/related, boundary=AaB03x",
|
624
|
+
"CONTENT_LENGTH" => input.size,
|
625
|
+
:input => input)
|
626
|
+
|
627
|
+
req.params.keys.should.equal ["<soap-start>"]
|
628
|
+
end
|
629
|
+
|
446
630
|
should "not try to interpret binary as utf8" do
|
447
631
|
if /regexp/.respond_to?(:kcode) # < 1.9
|
448
632
|
begin
|
data/test/spec_response.rb
CHANGED
@@ -23,7 +23,7 @@ describe Rack::Response do
|
|
23
23
|
it "can be written to" do
|
24
24
|
response = Rack::Response.new
|
25
25
|
|
26
|
-
|
26
|
+
_, _, body = response.finish do
|
27
27
|
response.write "foo"
|
28
28
|
response.write "bar"
|
29
29
|
response.write "baz"
|
@@ -42,6 +42,11 @@ describe Rack::Response do
|
|
42
42
|
response["Content-Type"].should.equal "text/plain"
|
43
43
|
end
|
44
44
|
|
45
|
+
it "can override the initial Content-Type with a different case" do
|
46
|
+
response = Rack::Response.new("", 200, "content-type" => "text/plain")
|
47
|
+
response["Content-Type"].should.equal "text/plain"
|
48
|
+
end
|
49
|
+
|
45
50
|
it "can set cookies" do
|
46
51
|
response = Rack::Response.new
|
47
52
|
|
@@ -147,7 +152,7 @@ describe Rack::Response do
|
|
147
152
|
res.status = 404
|
148
153
|
res.write "foo"
|
149
154
|
}
|
150
|
-
status,
|
155
|
+
status, _, body = r.finish
|
151
156
|
str = ""; body.each { |part| str << part }
|
152
157
|
str.should.equal "foo"
|
153
158
|
status.should.equal 404
|
@@ -155,10 +160,11 @@ describe Rack::Response do
|
|
155
160
|
|
156
161
|
it "doesn't return invalid responses" do
|
157
162
|
r = Rack::Response.new(["foo", "bar"], 204)
|
158
|
-
|
163
|
+
_, header, body = r.finish
|
159
164
|
str = ""; body.each { |part| str << part }
|
160
165
|
str.should.be.empty
|
161
166
|
header["Content-Type"].should.equal nil
|
167
|
+
header['Content-Length'].should.equal nil
|
162
168
|
|
163
169
|
lambda {
|
164
170
|
Rack::Response.new(Object.new)
|
data/test/spec_server.rb
ADDED
@@ -0,0 +1,74 @@
|
|
1
|
+
require 'rack'
|
2
|
+
require 'rack/server'
|
3
|
+
require 'tempfile'
|
4
|
+
require 'socket'
|
5
|
+
require 'open-uri'
|
6
|
+
|
7
|
+
describe Rack::Server do
|
8
|
+
|
9
|
+
def app
|
10
|
+
lambda { |env| [200, {'Content-Type' => 'text/plain'}, ['success']] }
|
11
|
+
end
|
12
|
+
|
13
|
+
it "overrides :config if :app is passed in" do
|
14
|
+
server = Rack::Server.new(:app => "FOO")
|
15
|
+
server.app.should == "FOO"
|
16
|
+
end
|
17
|
+
|
18
|
+
should "not include Rack::Lint in deployment or none environments" do
|
19
|
+
server = Rack::Server.new(:app => 'foo')
|
20
|
+
server.middleware['deployment'].flatten.should.not.include(Rack::Lint)
|
21
|
+
server.middleware['none'].flatten.should.not.include(Rack::Lint)
|
22
|
+
end
|
23
|
+
|
24
|
+
should "not include Rack::ShowExceptions in deployment or none environments" do
|
25
|
+
server = Rack::Server.new(:app => 'foo')
|
26
|
+
server.middleware['deployment'].flatten.should.not.include(Rack::ShowExceptions)
|
27
|
+
server.middleware['none'].flatten.should.not.include(Rack::ShowExceptions)
|
28
|
+
end
|
29
|
+
|
30
|
+
should "support CGI" do
|
31
|
+
begin
|
32
|
+
o, ENV["REQUEST_METHOD"] = ENV["REQUEST_METHOD"], 'foo'
|
33
|
+
server = Rack::Server.new(:app => 'foo')
|
34
|
+
server.server.name =~ /CGI/
|
35
|
+
Rack::Server.logging_middleware.call(server).should.eql(nil)
|
36
|
+
ensure
|
37
|
+
ENV['REQUEST_METHOD'] = o
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
should "not force any middleware under the none configuration" do
|
42
|
+
server = Rack::Server.new(:app => 'foo')
|
43
|
+
server.middleware['none'].should.be.empty
|
44
|
+
end
|
45
|
+
|
46
|
+
should "use a full path to the pidfile" do
|
47
|
+
# avoids issues with daemonize chdir
|
48
|
+
opts = Rack::Server.new.send(:parse_options, %w[--pid testing.pid])
|
49
|
+
opts[:pid].should.eql(::File.expand_path('testing.pid'))
|
50
|
+
end
|
51
|
+
|
52
|
+
should "run a server" do
|
53
|
+
pidfile = Tempfile.open('pidfile') { |f| break f }.path
|
54
|
+
FileUtils.rm pidfile
|
55
|
+
server = Rack::Server.new(
|
56
|
+
:app => app,
|
57
|
+
:environment => 'none',
|
58
|
+
:pid => pidfile,
|
59
|
+
:Port => TCPServer.open('127.0.0.1', 0){|s| s.addr[1] },
|
60
|
+
:Host => '127.0.0.1',
|
61
|
+
:daemonize => false,
|
62
|
+
:server => 'webrick'
|
63
|
+
)
|
64
|
+
t = Thread.new { server.start }
|
65
|
+
until t.status == 'sleep'; t.join(0.01) end
|
66
|
+
body = open("http://127.0.0.1:#{server.options[:Port]}/") { |f| f.read }
|
67
|
+
body.should.eql('success')
|
68
|
+
|
69
|
+
Process.kill(:INT, $$)
|
70
|
+
t.join
|
71
|
+
open(pidfile) { |f| f.read.should.eql $$.to_s }
|
72
|
+
end
|
73
|
+
|
74
|
+
end
|