rack 1.4.0 → 1.4.5
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/COPYING +1 -1
- data/KNOWN-ISSUES +9 -0
- data/README.rdoc +118 -4
- data/Rakefile +18 -11
- data/SPEC +3 -1
- data/contrib/rack.png +0 -0
- data/contrib/rack.svg +150 -0
- data/contrib/rdoc.css +412 -0
- data/lib/rack/auth/abstract/request.rb +5 -1
- data/lib/rack/auth/basic.rb +1 -1
- data/lib/rack/auth/digest/nonce.rb +1 -1
- data/lib/rack/backports/uri/common_18.rb +14 -28
- data/lib/rack/backports/uri/common_192.rb +14 -17
- data/lib/rack/backports/uri/common_193.rb +29 -0
- data/lib/rack/body_proxy.rb +15 -2
- data/lib/rack/builder.rb +1 -1
- data/lib/rack/cascade.rb +12 -1
- data/lib/rack/commonlogger.rb +18 -5
- data/lib/rack/deflater.rb +5 -1
- data/lib/rack/directory.rb +1 -1
- data/lib/rack/etag.rb +6 -3
- data/lib/rack/file.rb +20 -16
- data/lib/rack/head.rb +1 -0
- data/lib/rack/lint.rb +3 -1
- data/lib/rack/lock.rb +3 -4
- data/lib/rack/mime.rb +1 -1
- data/lib/rack/mock.rb +3 -2
- data/lib/rack/multipart/parser.rb +22 -20
- data/lib/rack/multipart.rb +2 -2
- data/lib/rack/reloader.rb +1 -1
- data/lib/rack/request.rb +4 -6
- data/lib/rack/response.rb +19 -17
- data/lib/rack/server.rb +28 -2
- data/lib/rack/session/abstract/id.rb +8 -3
- data/lib/rack/session/cookie.rb +20 -7
- data/lib/rack/showstatus.rb +2 -2
- data/lib/rack/static.rb +91 -9
- data/lib/rack/utils.rb +74 -36
- data/lib/rack.rb +13 -1
- data/rack.gemspec +3 -3
- data/test/builder/line.ru +1 -0
- data/test/cgi/assets/folder/test.js +1 -0
- data/test/cgi/assets/fonts/font.eot +1 -0
- data/test/cgi/assets/images/image.png +1 -0
- data/test/cgi/assets/index.html +1 -0
- data/test/cgi/assets/javascripts/app.js +1 -0
- data/test/cgi/assets/stylesheets/app.css +1 -0
- data/test/multipart/filename_with_unescaped_percentages +6 -0
- data/test/multipart/filename_with_unescaped_percentages2 +6 -0
- data/test/multipart/filename_with_unescaped_percentages3 +6 -0
- data/test/spec_auth.rb +57 -0
- data/test/spec_auth_basic.rb +8 -0
- data/test/spec_auth_digest.rb +14 -0
- data/test/spec_body_proxy.rb +21 -0
- data/test/spec_builder.rb +7 -1
- data/test/spec_cascade.rb +14 -3
- data/test/spec_chunked.rb +6 -6
- data/test/spec_config.rb +0 -1
- data/test/spec_content_length.rb +26 -13
- data/test/spec_content_type.rb +15 -5
- data/test/spec_deflater.rb +35 -17
- data/test/spec_directory.rb +20 -1
- data/test/spec_etag.rb +29 -13
- data/test/spec_file.rb +58 -30
- data/test/spec_head.rb +25 -7
- data/test/spec_lobster.rb +20 -5
- data/test/spec_lock.rb +46 -21
- data/test/spec_logger.rb +2 -7
- data/test/spec_methodoverride.rb +21 -22
- data/test/spec_mock.rb +12 -7
- data/test/spec_multipart.rb +129 -2
- data/test/spec_nulllogger.rb +13 -2
- data/test/spec_recursive.rb +12 -9
- data/test/spec_request.rb +15 -2
- data/test/spec_response.rb +41 -3
- data/test/spec_runtime.rb +15 -5
- data/test/spec_sendfile.rb +13 -9
- data/test/spec_server.rb +47 -0
- data/test/spec_session_cookie.rb +93 -3
- data/test/spec_session_memcache.rb +10 -8
- data/test/spec_session_pool.rb +13 -10
- data/test/spec_showexceptions.rb +9 -4
- data/test/spec_showstatus.rb +10 -5
- data/test/spec_static.rb +89 -8
- data/test/spec_urlmap.rb +10 -10
- data/test/spec_utils.rb +34 -7
- data/test/static/another/index.html +1 -0
- metadata +26 -8
data/test/spec_request.rb
CHANGED
|
@@ -137,6 +137,19 @@ describe Rack::Request do
|
|
|
137
137
|
end
|
|
138
138
|
end
|
|
139
139
|
|
|
140
|
+
should "limit the key size per nested params hash" do
|
|
141
|
+
nested_query = Rack::MockRequest.env_for("/?foo[bar][baz][qux]=1")
|
|
142
|
+
plain_query = Rack::MockRequest.env_for("/?foo_bar__baz__qux_=1")
|
|
143
|
+
|
|
144
|
+
old, Rack::Utils.key_space_limit = Rack::Utils.key_space_limit, 3
|
|
145
|
+
begin
|
|
146
|
+
lambda { Rack::Request.new(nested_query).GET }.should.not.raise(RangeError)
|
|
147
|
+
lambda { Rack::Request.new(plain_query).GET }.should.raise(RangeError)
|
|
148
|
+
ensure
|
|
149
|
+
Rack::Utils.key_space_limit = old
|
|
150
|
+
end
|
|
151
|
+
end
|
|
152
|
+
|
|
140
153
|
should "not unify GET and POST when calling params" do
|
|
141
154
|
mr = Rack::MockRequest.env_for("/?foo=quux",
|
|
142
155
|
"REQUEST_METHOD" => 'POST',
|
|
@@ -398,9 +411,9 @@ describe Rack::Request do
|
|
|
398
411
|
req.cookies.should.equal 'foo' => 'bar'
|
|
399
412
|
end
|
|
400
413
|
|
|
401
|
-
should "
|
|
414
|
+
should "pass through non-uri escaped cookies as-is" do
|
|
402
415
|
req = Rack::Request.new Rack::MockRequest.env_for("", "HTTP_COOKIE" => "foo=%")
|
|
403
|
-
|
|
416
|
+
req.cookies["foo"].should == "%"
|
|
404
417
|
end
|
|
405
418
|
|
|
406
419
|
should "parse cookies according to RFC 2109" do
|
data/test/spec_response.rb
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
require 'set'
|
|
2
1
|
require 'rack/response'
|
|
3
2
|
require 'stringio'
|
|
4
3
|
|
|
@@ -125,7 +124,6 @@ describe Rack::Response do
|
|
|
125
124
|
response = Rack::Response.new
|
|
126
125
|
response.redirect "/foo"
|
|
127
126
|
status, header, body = response.finish
|
|
128
|
-
|
|
129
127
|
status.should.equal 302
|
|
130
128
|
header["Location"].should.equal "/foo"
|
|
131
129
|
|
|
@@ -147,7 +145,12 @@ describe Rack::Response do
|
|
|
147
145
|
str = ""; body.each { |part| str << part }
|
|
148
146
|
str.should.equal "foobar"
|
|
149
147
|
|
|
150
|
-
|
|
148
|
+
object_with_each = Object.new
|
|
149
|
+
def object_with_each.each
|
|
150
|
+
yield "foo"
|
|
151
|
+
yield "bar"
|
|
152
|
+
end
|
|
153
|
+
r = Rack::Response.new(object_with_each)
|
|
151
154
|
r.write "foo"
|
|
152
155
|
status, header, body = r.finish
|
|
153
156
|
str = ""; body.each { |part| str << part }
|
|
@@ -218,6 +221,11 @@ describe Rack::Response do
|
|
|
218
221
|
res.should.be.client_error
|
|
219
222
|
res.should.be.not_found
|
|
220
223
|
|
|
224
|
+
res.status = 405
|
|
225
|
+
res.should.not.be.successful
|
|
226
|
+
res.should.be.client_error
|
|
227
|
+
res.should.be.method_not_allowed
|
|
228
|
+
|
|
221
229
|
res.status = 422
|
|
222
230
|
res.should.not.be.successful
|
|
223
231
|
res.should.be.client_error
|
|
@@ -272,4 +280,34 @@ describe Rack::Response do
|
|
|
272
280
|
res.close
|
|
273
281
|
res.body.should.be.closed
|
|
274
282
|
end
|
|
283
|
+
|
|
284
|
+
it "calls close on #body when 204, 205, or 304" do
|
|
285
|
+
res = Rack::Response.new
|
|
286
|
+
res.body = StringIO.new
|
|
287
|
+
res.finish
|
|
288
|
+
res.body.should.not.be.closed
|
|
289
|
+
|
|
290
|
+
res.status = 204
|
|
291
|
+
_, _, b = res.finish
|
|
292
|
+
res.body.should.be.closed
|
|
293
|
+
b.should.not == res.body
|
|
294
|
+
|
|
295
|
+
res.body = StringIO.new
|
|
296
|
+
res.status = 205
|
|
297
|
+
_, _, b = res.finish
|
|
298
|
+
res.body.should.be.closed
|
|
299
|
+
b.should.not == res.body
|
|
300
|
+
|
|
301
|
+
res.body = StringIO.new
|
|
302
|
+
res.status = 304
|
|
303
|
+
_, _, b = res.finish
|
|
304
|
+
res.body.should.be.closed
|
|
305
|
+
b.should.not == res.body
|
|
306
|
+
end
|
|
307
|
+
|
|
308
|
+
it "wraps the body from #to_ary to prevent infinite loops" do
|
|
309
|
+
res = Rack::Response.new
|
|
310
|
+
res.finish.last.should.not.respond_to?(:to_ary)
|
|
311
|
+
lambda { res.finish.last.to_ary }.should.raise(NoMethodError)
|
|
312
|
+
end
|
|
275
313
|
end
|
data/test/spec_runtime.rb
CHANGED
|
@@ -1,27 +1,37 @@
|
|
|
1
|
+
require 'rack/lint'
|
|
2
|
+
require 'rack/mock'
|
|
1
3
|
require 'rack/runtime'
|
|
2
4
|
|
|
3
5
|
describe Rack::Runtime do
|
|
6
|
+
def runtime_app(app, *args)
|
|
7
|
+
Rack::Lint.new Rack::Runtime.new(app, *args)
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def request
|
|
11
|
+
Rack::MockRequest.env_for
|
|
12
|
+
end
|
|
13
|
+
|
|
4
14
|
it "sets X-Runtime is none is set" do
|
|
5
15
|
app = lambda { |env| [200, {'Content-Type' => 'text/plain'}, "Hello, World!"] }
|
|
6
|
-
response =
|
|
16
|
+
response = runtime_app(app).call(request)
|
|
7
17
|
response[1]['X-Runtime'].should =~ /[\d\.]+/
|
|
8
18
|
end
|
|
9
19
|
|
|
10
20
|
it "doesn't set the X-Runtime if it is already set" do
|
|
11
21
|
app = lambda { |env| [200, {'Content-Type' => 'text/plain', "X-Runtime" => "foobar"}, "Hello, World!"] }
|
|
12
|
-
response =
|
|
22
|
+
response = runtime_app(app).call(request)
|
|
13
23
|
response[1]['X-Runtime'].should == "foobar"
|
|
14
24
|
end
|
|
15
25
|
|
|
16
26
|
should "allow a suffix to be set" do
|
|
17
27
|
app = lambda { |env| [200, {'Content-Type' => 'text/plain'}, "Hello, World!"] }
|
|
18
|
-
response =
|
|
28
|
+
response = runtime_app(app, "Test").call(request)
|
|
19
29
|
response[1]['X-Runtime-Test'].should =~ /[\d\.]+/
|
|
20
30
|
end
|
|
21
31
|
|
|
22
32
|
should "allow multiple timers to be set" do
|
|
23
33
|
app = lambda { |env| sleep 0.1; [200, {'Content-Type' => 'text/plain'}, "Hello, World!"] }
|
|
24
|
-
runtime =
|
|
34
|
+
runtime = runtime_app(app, "App")
|
|
25
35
|
|
|
26
36
|
# wrap many times to guarantee a measurable difference
|
|
27
37
|
100.times do |i|
|
|
@@ -29,7 +39,7 @@ describe Rack::Runtime do
|
|
|
29
39
|
end
|
|
30
40
|
runtime = Rack::Runtime.new(runtime, "All")
|
|
31
41
|
|
|
32
|
-
response = runtime.call(
|
|
42
|
+
response = runtime.call(request)
|
|
33
43
|
|
|
34
44
|
response[1]['X-Runtime-App'].should =~ /[\d\.]+/
|
|
35
45
|
response[1]['X-Runtime-All'].should =~ /[\d\.]+/
|
data/test/spec_sendfile.rb
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
|
+
require 'fileutils'
|
|
2
|
+
require 'rack/lint'
|
|
1
3
|
require 'rack/sendfile'
|
|
2
4
|
require 'rack/mock'
|
|
5
|
+
require 'tmpdir'
|
|
3
6
|
|
|
4
7
|
describe Rack::File do
|
|
5
8
|
should "respond to #to_path" do
|
|
@@ -9,8 +12,9 @@ end
|
|
|
9
12
|
|
|
10
13
|
describe Rack::Sendfile do
|
|
11
14
|
def sendfile_body
|
|
15
|
+
FileUtils.touch File.join(Dir.tmpdir, "rack_sendfile")
|
|
12
16
|
res = ['Hello World']
|
|
13
|
-
def res.to_path ;
|
|
17
|
+
def res.to_path ; File.join(Dir.tmpdir, "rack_sendfile") ; end
|
|
14
18
|
res
|
|
15
19
|
end
|
|
16
20
|
|
|
@@ -19,7 +23,7 @@ describe Rack::Sendfile do
|
|
|
19
23
|
end
|
|
20
24
|
|
|
21
25
|
def sendfile_app(body=sendfile_body)
|
|
22
|
-
Rack::Sendfile.new(simple_app(body))
|
|
26
|
+
Rack::Lint.new Rack::Sendfile.new(simple_app(body))
|
|
23
27
|
end
|
|
24
28
|
|
|
25
29
|
@request = Rack::MockRequest.new(sendfile_app)
|
|
@@ -40,8 +44,8 @@ describe Rack::Sendfile do
|
|
|
40
44
|
request 'HTTP_X_SENDFILE_TYPE' => 'X-Sendfile' do |response|
|
|
41
45
|
response.should.be.ok
|
|
42
46
|
response.body.should.be.empty
|
|
43
|
-
response.headers['Content-Length'].should
|
|
44
|
-
response.headers['X-Sendfile'].should.equal
|
|
47
|
+
response.headers['Content-Length'].should.equal '0'
|
|
48
|
+
response.headers['X-Sendfile'].should.equal File.join(Dir.tmpdir, "rack_sendfile")
|
|
45
49
|
end
|
|
46
50
|
end
|
|
47
51
|
|
|
@@ -49,21 +53,21 @@ describe Rack::Sendfile do
|
|
|
49
53
|
request 'HTTP_X_SENDFILE_TYPE' => 'X-Lighttpd-Send-File' do |response|
|
|
50
54
|
response.should.be.ok
|
|
51
55
|
response.body.should.be.empty
|
|
52
|
-
response.headers['Content-Length'].should
|
|
53
|
-
response.headers['X-Lighttpd-Send-File'].should.equal
|
|
56
|
+
response.headers['Content-Length'].should.equal '0'
|
|
57
|
+
response.headers['X-Lighttpd-Send-File'].should.equal File.join(Dir.tmpdir, "rack_sendfile")
|
|
54
58
|
end
|
|
55
59
|
end
|
|
56
60
|
|
|
57
61
|
it "sets X-Accel-Redirect response header and discards body" do
|
|
58
62
|
headers = {
|
|
59
63
|
'HTTP_X_SENDFILE_TYPE' => 'X-Accel-Redirect',
|
|
60
|
-
'HTTP_X_ACCEL_MAPPING' =>
|
|
64
|
+
'HTTP_X_ACCEL_MAPPING' => "#{Dir.tmpdir}/=/foo/bar/"
|
|
61
65
|
}
|
|
62
66
|
request headers do |response|
|
|
63
67
|
response.should.be.ok
|
|
64
68
|
response.body.should.be.empty
|
|
65
|
-
response.headers['Content-Length'].should
|
|
66
|
-
response.headers['X-Accel-Redirect'].should.equal '/foo/bar/
|
|
69
|
+
response.headers['Content-Length'].should.equal '0'
|
|
70
|
+
response.headers['X-Accel-Redirect'].should.equal '/foo/bar/rack_sendfile'
|
|
67
71
|
end
|
|
68
72
|
end
|
|
69
73
|
|
data/test/spec_server.rb
CHANGED
|
@@ -10,6 +10,13 @@ describe Rack::Server do
|
|
|
10
10
|
lambda { |env| [200, {'Content-Type' => 'text/plain'}, ['success']] }
|
|
11
11
|
end
|
|
12
12
|
|
|
13
|
+
def with_stderr
|
|
14
|
+
old, $stderr = $stderr, StringIO.new
|
|
15
|
+
yield $stderr
|
|
16
|
+
ensure
|
|
17
|
+
$stderr = old
|
|
18
|
+
end
|
|
19
|
+
|
|
13
20
|
it "overrides :config if :app is passed in" do
|
|
14
21
|
server = Rack::Server.new(:app => "FOO")
|
|
15
22
|
server.app.should == "FOO"
|
|
@@ -71,4 +78,44 @@ describe Rack::Server do
|
|
|
71
78
|
open(pidfile) { |f| f.read.should.eql $$.to_s }
|
|
72
79
|
end
|
|
73
80
|
|
|
81
|
+
should "check pid file presence and running process" do
|
|
82
|
+
pidfile = Tempfile.open('pidfile') { |f| f.write($$); break f }.path
|
|
83
|
+
server = Rack::Server.new(:pid => pidfile)
|
|
84
|
+
server.send(:pidfile_process_status).should.eql :running
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
should "check pid file presence and dead process" do
|
|
88
|
+
dead_pid = `echo $$`.to_i
|
|
89
|
+
pidfile = Tempfile.open('pidfile') { |f| f.write(dead_pid); break f }.path
|
|
90
|
+
server = Rack::Server.new(:pid => pidfile)
|
|
91
|
+
server.send(:pidfile_process_status).should.eql :dead
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
should "check pid file presence and exited process" do
|
|
95
|
+
pidfile = Tempfile.open('pidfile') { |f| break f }.path
|
|
96
|
+
::File.delete(pidfile)
|
|
97
|
+
server = Rack::Server.new(:pid => pidfile)
|
|
98
|
+
server.send(:pidfile_process_status).should.eql :exited
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
should "check pid file presence and not owned process" do
|
|
102
|
+
pidfile = Tempfile.open('pidfile') { |f| f.write(1); break f }.path
|
|
103
|
+
server = Rack::Server.new(:pid => pidfile)
|
|
104
|
+
server.send(:pidfile_process_status).should.eql :not_owned
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
should "inform the user about existing pidfiles with running processes" do
|
|
108
|
+
pidfile = Tempfile.open('pidfile') { |f| f.write(1); break f }.path
|
|
109
|
+
server = Rack::Server.new(:pid => pidfile)
|
|
110
|
+
with_stderr do |err|
|
|
111
|
+
should.raise(SystemExit) do
|
|
112
|
+
server.start
|
|
113
|
+
end
|
|
114
|
+
err.rewind
|
|
115
|
+
output = err.read
|
|
116
|
+
output.should.match(/already running/)
|
|
117
|
+
output.should.include? pidfile
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
|
|
74
121
|
end
|
data/test/spec_session_cookie.rb
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
require 'rack/session/cookie'
|
|
2
|
+
require 'rack/lint'
|
|
2
3
|
require 'rack/mock'
|
|
3
4
|
|
|
4
5
|
describe Rack::Session::Cookie do
|
|
@@ -9,7 +10,7 @@ describe Rack::Session::Cookie do
|
|
|
9
10
|
hash.delete("session_id")
|
|
10
11
|
Rack::Response.new(hash.inspect).to_a
|
|
11
12
|
end
|
|
12
|
-
|
|
13
|
+
|
|
13
14
|
session_id = lambda do |env|
|
|
14
15
|
Rack::Response.new(env["rack.session"].to_hash.inspect).to_a
|
|
15
16
|
end
|
|
@@ -24,6 +25,50 @@ describe Rack::Session::Cookie do
|
|
|
24
25
|
Rack::Response.new("Nothing").to_a
|
|
25
26
|
end
|
|
26
27
|
|
|
28
|
+
renewer = lambda do |env|
|
|
29
|
+
env["rack.session.options"][:renew] = true
|
|
30
|
+
Rack::Response.new("Nothing").to_a
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
only_session_id = lambda do |env|
|
|
34
|
+
Rack::Response.new(env["rack.session"]["session_id"].to_s).to_a
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
bigcookie = lambda do |env|
|
|
38
|
+
env["rack.session"]["cookie"] = "big" * 3000
|
|
39
|
+
Rack::Response.new(env["rack.session"].inspect).to_a
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
destroy_session = lambda do |env|
|
|
43
|
+
env["rack.session"].destroy
|
|
44
|
+
Rack::Response.new("Nothing").to_a
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def response_for(options={})
|
|
48
|
+
request_options = options.fetch(:request, {})
|
|
49
|
+
cookie = if options[:cookie].is_a?(Rack::Response)
|
|
50
|
+
options[:cookie]["Set-Cookie"]
|
|
51
|
+
else
|
|
52
|
+
options[:cookie]
|
|
53
|
+
end
|
|
54
|
+
request_options["HTTP_COOKIE"] = cookie || ""
|
|
55
|
+
|
|
56
|
+
app_with_cookie = Rack::Session::Cookie.new(*options[:app])
|
|
57
|
+
app_with_cookie = Rack::Lint.new(app_with_cookie)
|
|
58
|
+
Rack::MockRequest.new(app_with_cookie).get("/", request_options)
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
before do
|
|
62
|
+
@warnings = warnings = []
|
|
63
|
+
Rack::Session::Cookie.class_eval do
|
|
64
|
+
define_method(:warn) { |m| warnings << m }
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
after do
|
|
69
|
+
Rack::Session::Cookie.class_eval { remove_method :warn }
|
|
70
|
+
end
|
|
71
|
+
|
|
27
72
|
describe 'Base64' do
|
|
28
73
|
it 'uses base64 to encode' do
|
|
29
74
|
coder = Rack::Session::Cookie::Base64.new
|
|
@@ -57,6 +102,14 @@ describe Rack::Session::Cookie do
|
|
|
57
102
|
end
|
|
58
103
|
end
|
|
59
104
|
|
|
105
|
+
it "warns if no secret is given" do
|
|
106
|
+
cookie = Rack::Session::Cookie.new(incrementor)
|
|
107
|
+
@warnings.first.should =~ /no secret/i
|
|
108
|
+
@warnings.clear
|
|
109
|
+
cookie = Rack::Session::Cookie.new(incrementor, :secret => 'abc')
|
|
110
|
+
@warnings.should.be.empty?
|
|
111
|
+
end
|
|
112
|
+
|
|
60
113
|
it 'uses a coder' do
|
|
61
114
|
identity = Class.new {
|
|
62
115
|
attr_reader :calls
|
|
@@ -123,6 +176,10 @@ describe Rack::Session::Cookie do
|
|
|
123
176
|
res = Rack::MockRequest.new(Rack::Session::Cookie.new(incrementor)).
|
|
124
177
|
get("/", "HTTP_COOKIE" => "rack.session=blarghfasel")
|
|
125
178
|
res.body.should.equal '{"counter"=>1}'
|
|
179
|
+
|
|
180
|
+
app = Rack::Session::Cookie.new(incrementor, :secret => 'test')
|
|
181
|
+
res = Rack::MockRequest.new(app).get("/", "HTTP_COOKIE" => "rack.session=")
|
|
182
|
+
res.body.should.equal '{"counter"=>1}'
|
|
126
183
|
end
|
|
127
184
|
|
|
128
185
|
bigcookie = lambda do |env|
|
|
@@ -137,7 +194,7 @@ describe Rack::Session::Cookie do
|
|
|
137
194
|
}.should.raise(Rack::MockRequest::FatalWarning)
|
|
138
195
|
end
|
|
139
196
|
|
|
140
|
-
it "loads from a cookie
|
|
197
|
+
it "loads from a cookie with integrity hash" do
|
|
141
198
|
res = Rack::MockRequest.new(Rack::Session::Cookie.new(incrementor, :secret => 'test')).get("/")
|
|
142
199
|
cookie = res["Set-Cookie"]
|
|
143
200
|
res = Rack::MockRequest.new(Rack::Session::Cookie.new(incrementor, :secret => 'test')).
|
|
@@ -147,6 +204,9 @@ describe Rack::Session::Cookie do
|
|
|
147
204
|
res = Rack::MockRequest.new(Rack::Session::Cookie.new(incrementor, :secret => 'test')).
|
|
148
205
|
get("/", "HTTP_COOKIE" => cookie)
|
|
149
206
|
res.body.should.equal '{"counter"=>3}'
|
|
207
|
+
res = Rack::MockRequest.new(Rack::Session::Cookie.new(incrementor, :secret => 'other')).
|
|
208
|
+
get("/", "HTTP_COOKIE" => cookie)
|
|
209
|
+
res.body.should.equal '{"counter"=>1}'
|
|
150
210
|
end
|
|
151
211
|
|
|
152
212
|
it "loads from a cookie wih accept-only integrity hash for graceful key rotation" do
|
|
@@ -165,16 +225,31 @@ describe Rack::Session::Cookie do
|
|
|
165
225
|
app = Rack::Session::Cookie.new(incrementor, :secret => 'test')
|
|
166
226
|
response1 = Rack::MockRequest.new(app).get("/")
|
|
167
227
|
response1.body.should.equal '{"counter"=>1}'
|
|
228
|
+
response1 = Rack::MockRequest.new(app).get("/", "HTTP_COOKIE" => response1["Set-Cookie"])
|
|
229
|
+
response1.body.should.equal '{"counter"=>2}'
|
|
168
230
|
|
|
169
231
|
_, digest = response1["Set-Cookie"].split("--")
|
|
170
232
|
tampered_with_cookie = "hackerman-was-here" + "--" + digest
|
|
171
233
|
response2 = Rack::MockRequest.new(app).get("/", "HTTP_COOKIE" =>
|
|
172
234
|
tampered_with_cookie)
|
|
173
235
|
|
|
174
|
-
#
|
|
236
|
+
# Tampered cookie was ignored. Counter is back to 1.
|
|
175
237
|
response2.body.should.equal '{"counter"=>1}'
|
|
176
238
|
end
|
|
177
239
|
|
|
240
|
+
it "supports either of secret or old_secret" do
|
|
241
|
+
app = Rack::Session::Cookie.new(incrementor, :secret => 'test')
|
|
242
|
+
res = Rack::MockRequest.new(app).get("/")
|
|
243
|
+
res.body.should.equal '{"counter"=>1}'
|
|
244
|
+
res = Rack::MockRequest.new(app).get("/", "HTTP_COOKIE" => res["Set-Cookie"])
|
|
245
|
+
res.body.should.equal '{"counter"=>2}'
|
|
246
|
+
app = Rack::Session::Cookie.new(incrementor, :old_secret => 'test')
|
|
247
|
+
res = Rack::MockRequest.new(app).get("/")
|
|
248
|
+
res.body.should.equal '{"counter"=>1}'
|
|
249
|
+
res = Rack::MockRequest.new(app).get("/", "HTTP_COOKIE" => res["Set-Cookie"])
|
|
250
|
+
res.body.should.equal '{"counter"=>2}'
|
|
251
|
+
end
|
|
252
|
+
|
|
178
253
|
describe "1.9 bugs relating to inspecting yet-to-be-loaded from cookie data: Rack::Session::Abstract::SessionHash" do
|
|
179
254
|
|
|
180
255
|
it "can handle Rack::Lint middleware" do
|
|
@@ -225,6 +300,7 @@ describe Rack::Session::Cookie do
|
|
|
225
300
|
|
|
226
301
|
res = Rack::MockRequest.new(app).get("/", "HTTPS" => "on")
|
|
227
302
|
res["Set-Cookie"].should.not.be.nil
|
|
303
|
+
res["Set-Cookie"].should.match(/secure/)
|
|
228
304
|
end
|
|
229
305
|
|
|
230
306
|
it "does not return a cookie if cookie was not read/written" do
|
|
@@ -268,4 +344,18 @@ describe Rack::Session::Cookie do
|
|
|
268
344
|
res = Rack::MockRequest.new(app).get("/", 'rack.session' => {:foo => 'bar'})
|
|
269
345
|
res.body.should.match(/foo/)
|
|
270
346
|
end
|
|
347
|
+
|
|
348
|
+
it "allows modifying session data with session data from middleware in front" do
|
|
349
|
+
request = { 'rack.session' => { :foo => 'bar' }}
|
|
350
|
+
response = response_for(:app => incrementor, :request => request)
|
|
351
|
+
response.body.should.match(/counter/)
|
|
352
|
+
response.body.should.match(/foo/)
|
|
353
|
+
end
|
|
354
|
+
|
|
355
|
+
it "allows modifying session data with session data from middleware in front" do
|
|
356
|
+
request = { 'rack.session' => { :foo => 'bar' }}
|
|
357
|
+
response = response_for(:app => incrementor, :request => request)
|
|
358
|
+
response.body.should.match(/counter/)
|
|
359
|
+
response.body.should.match(/foo/)
|
|
360
|
+
end
|
|
271
361
|
end
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
begin
|
|
2
2
|
require 'rack/session/memcache'
|
|
3
|
+
require 'rack/lint'
|
|
3
4
|
require 'rack/mock'
|
|
4
5
|
require 'thread'
|
|
5
6
|
|
|
@@ -11,22 +12,23 @@ begin
|
|
|
11
12
|
env["rack.session"]["counter"] += 1
|
|
12
13
|
Rack::Response.new(env["rack.session"].inspect).to_a
|
|
13
14
|
end
|
|
14
|
-
drop_session = proc do |env|
|
|
15
|
+
drop_session = Rack::Lint.new(proc do |env|
|
|
15
16
|
env['rack.session.options'][:drop] = true
|
|
16
17
|
incrementor.call(env)
|
|
17
|
-
end
|
|
18
|
-
renew_session = proc do |env|
|
|
18
|
+
end)
|
|
19
|
+
renew_session = Rack::Lint.new(proc do |env|
|
|
19
20
|
env['rack.session.options'][:renew] = true
|
|
20
21
|
incrementor.call(env)
|
|
21
|
-
end
|
|
22
|
-
defer_session = proc do |env|
|
|
22
|
+
end)
|
|
23
|
+
defer_session = Rack::Lint.new(proc do |env|
|
|
23
24
|
env['rack.session.options'][:defer] = true
|
|
24
25
|
incrementor.call(env)
|
|
25
|
-
end
|
|
26
|
-
skip_session = proc do |env|
|
|
26
|
+
end)
|
|
27
|
+
skip_session = Rack::Lint.new(proc do |env|
|
|
27
28
|
env['rack.session.options'][:skip] = true
|
|
28
29
|
incrementor.call(env)
|
|
29
|
-
end
|
|
30
|
+
end)
|
|
31
|
+
incrementor = Rack::Lint.new(incrementor)
|
|
30
32
|
|
|
31
33
|
# test memcache connection
|
|
32
34
|
Rack::Session::Memcache.new(incrementor)
|
data/test/spec_session_pool.rb
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
require 'thread'
|
|
2
|
+
require 'rack/lint'
|
|
2
3
|
require 'rack/mock'
|
|
3
4
|
require 'rack/session/pool'
|
|
4
5
|
|
|
@@ -12,28 +13,30 @@ describe Rack::Session::Pool do
|
|
|
12
13
|
Rack::Response.new(env["rack.session"].inspect).to_a
|
|
13
14
|
end
|
|
14
15
|
|
|
15
|
-
session_id = lambda do |env|
|
|
16
|
+
session_id = Rack::Lint.new(lambda do |env|
|
|
16
17
|
Rack::Response.new(env["rack.session"].inspect).to_a
|
|
17
|
-
end
|
|
18
|
+
end)
|
|
18
19
|
|
|
19
|
-
nothing = lambda do |env|
|
|
20
|
+
nothing = Rack::Lint.new(lambda do |env|
|
|
20
21
|
Rack::Response.new("Nothing").to_a
|
|
21
|
-
end
|
|
22
|
+
end)
|
|
22
23
|
|
|
23
|
-
drop_session = lambda do |env|
|
|
24
|
+
drop_session = Rack::Lint.new(lambda do |env|
|
|
24
25
|
env['rack.session.options'][:drop] = true
|
|
25
26
|
incrementor.call(env)
|
|
26
|
-
end
|
|
27
|
+
end)
|
|
27
28
|
|
|
28
|
-
renew_session = lambda do |env|
|
|
29
|
+
renew_session = Rack::Lint.new(lambda do |env|
|
|
29
30
|
env['rack.session.options'][:renew] = true
|
|
30
31
|
incrementor.call(env)
|
|
31
|
-
end
|
|
32
|
+
end)
|
|
32
33
|
|
|
33
|
-
defer_session = lambda do |env|
|
|
34
|
+
defer_session = Rack::Lint.new(lambda do |env|
|
|
34
35
|
env['rack.session.options'][:defer] = true
|
|
35
36
|
incrementor.call(env)
|
|
36
|
-
end
|
|
37
|
+
end)
|
|
38
|
+
|
|
39
|
+
incrementor = Rack::Lint.new(incrementor)
|
|
37
40
|
|
|
38
41
|
it "creates a new cookie" do
|
|
39
42
|
pool = Rack::Session::Pool.new(incrementor)
|
data/test/spec_showexceptions.rb
CHANGED
|
@@ -1,12 +1,17 @@
|
|
|
1
1
|
require 'rack/showexceptions'
|
|
2
|
+
require 'rack/lint'
|
|
2
3
|
require 'rack/mock'
|
|
3
4
|
|
|
4
5
|
describe Rack::ShowExceptions do
|
|
6
|
+
def show_exceptions(app)
|
|
7
|
+
Rack::Lint.new Rack::ShowExceptions.new(app)
|
|
8
|
+
end
|
|
9
|
+
|
|
5
10
|
it "catches exceptions" do
|
|
6
11
|
res = nil
|
|
7
12
|
|
|
8
13
|
req = Rack::MockRequest.new(
|
|
9
|
-
|
|
14
|
+
show_exceptions(
|
|
10
15
|
lambda{|env| raise RuntimeError }
|
|
11
16
|
))
|
|
12
17
|
|
|
@@ -25,7 +30,7 @@ describe Rack::ShowExceptions do
|
|
|
25
30
|
res = nil
|
|
26
31
|
|
|
27
32
|
req = Rack::MockRequest.new(
|
|
28
|
-
|
|
33
|
+
show_exceptions(
|
|
29
34
|
lambda{|env| raise RuntimeError, "It was never supposed to work" }
|
|
30
35
|
))
|
|
31
36
|
|
|
@@ -46,7 +51,7 @@ describe Rack::ShowExceptions do
|
|
|
46
51
|
res = nil
|
|
47
52
|
|
|
48
53
|
req = Rack::MockRequest.new(
|
|
49
|
-
|
|
54
|
+
show_exceptions(
|
|
50
55
|
lambda{|env| raise RuntimeError, "It was never supposed to work" }
|
|
51
56
|
))
|
|
52
57
|
|
|
@@ -68,7 +73,7 @@ describe Rack::ShowExceptions do
|
|
|
68
73
|
res = nil
|
|
69
74
|
|
|
70
75
|
req = Rack::MockRequest.new(
|
|
71
|
-
|
|
76
|
+
show_exceptions(
|
|
72
77
|
lambda{|env| raise RuntimeError, "", [] }
|
|
73
78
|
)
|
|
74
79
|
)
|
data/test/spec_showstatus.rb
CHANGED
|
@@ -1,10 +1,15 @@
|
|
|
1
1
|
require 'rack/showstatus'
|
|
2
|
+
require 'rack/lint'
|
|
2
3
|
require 'rack/mock'
|
|
3
4
|
|
|
4
5
|
describe Rack::ShowStatus do
|
|
6
|
+
def show_status(app)
|
|
7
|
+
Rack::Lint.new Rack::ShowStatus.new(app)
|
|
8
|
+
end
|
|
9
|
+
|
|
5
10
|
should "provide a default status message" do
|
|
6
11
|
req = Rack::MockRequest.new(
|
|
7
|
-
|
|
12
|
+
show_status(lambda{|env|
|
|
8
13
|
[404, {"Content-Type" => "text/plain", "Content-Length" => "0"}, []]
|
|
9
14
|
}))
|
|
10
15
|
|
|
@@ -19,7 +24,7 @@ describe Rack::ShowStatus do
|
|
|
19
24
|
|
|
20
25
|
should "let the app provide additional information" do
|
|
21
26
|
req = Rack::MockRequest.new(
|
|
22
|
-
|
|
27
|
+
show_status(
|
|
23
28
|
lambda{|env|
|
|
24
29
|
env["rack.showstatus.detail"] = "gone too meta."
|
|
25
30
|
[404, {"Content-Type" => "text/plain", "Content-Length" => "0"}, []]
|
|
@@ -37,7 +42,7 @@ describe Rack::ShowStatus do
|
|
|
37
42
|
|
|
38
43
|
should "not replace existing messages" do
|
|
39
44
|
req = Rack::MockRequest.new(
|
|
40
|
-
|
|
45
|
+
show_status(
|
|
41
46
|
lambda{|env|
|
|
42
47
|
[404, {"Content-Type" => "text/plain", "Content-Length" => "4"}, ["foo!"]]
|
|
43
48
|
}))
|
|
@@ -52,7 +57,7 @@ describe Rack::ShowStatus do
|
|
|
52
57
|
headers = {"WWW-Authenticate" => "Basic blah"}
|
|
53
58
|
|
|
54
59
|
req = Rack::MockRequest.new(
|
|
55
|
-
|
|
60
|
+
show_status(lambda{|env| [401, headers, []] }))
|
|
56
61
|
res = req.get("/", :lint => true)
|
|
57
62
|
|
|
58
63
|
res["WWW-Authenticate"].should.equal("Basic blah")
|
|
@@ -60,7 +65,7 @@ describe Rack::ShowStatus do
|
|
|
60
65
|
|
|
61
66
|
should "replace existing messages if there is detail" do
|
|
62
67
|
req = Rack::MockRequest.new(
|
|
63
|
-
|
|
68
|
+
show_status(
|
|
64
69
|
lambda{|env|
|
|
65
70
|
env["rack.showstatus.detail"] = "gone too meta."
|
|
66
71
|
[404, {"Content-Type" => "text/plain", "Content-Length" => "4"}, ["foo!"]]
|