rack 1.1.6 → 1.2.0
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 -205
- data/SPEC +3 -3
- data/lib/rack.rb +1 -24
- data/lib/rack/auth/abstract/request.rb +1 -5
- data/lib/rack/auth/digest/md5.rb +1 -2
- data/lib/rack/auth/digest/params.rb +1 -1
- data/lib/rack/content_length.rb +1 -1
- data/lib/rack/etag.rb +15 -6
- data/lib/rack/file.rb +3 -1
- data/lib/rack/handler/cgi.rb +8 -7
- data/lib/rack/handler/fastcgi.rb +1 -1
- data/lib/rack/handler/lsws.rb +1 -1
- data/lib/rack/handler/mongrel.rb +1 -1
- data/lib/rack/handler/scgi.rb +1 -4
- data/lib/rack/handler/webrick.rb +10 -6
- data/lib/rack/lint.rb +29 -37
- data/lib/rack/mime.rb +2 -0
- data/lib/rack/mock.rb +2 -1
- data/lib/rack/recursive.rb +4 -0
- data/lib/rack/request.rb +8 -6
- data/lib/rack/response.rb +1 -0
- data/lib/rack/rewindable_input.rb +13 -10
- data/lib/rack/sendfile.rb +8 -6
- data/lib/rack/server.rb +68 -9
- data/lib/rack/session/cookie.rb +1 -10
- data/lib/rack/session/memcache.rb +1 -1
- data/lib/rack/urlmap.rb +6 -7
- data/lib/rack/utils.rb +40 -71
- data/rack.gemspec +7 -11
- data/spec/cgi/lighttpd.conf +25 -0
- data/spec/cgi/rackup_stub.rb +6 -0
- data/spec/cgi/sample_rackup.ru +5 -0
- data/spec/cgi/test +9 -0
- data/spec/cgi/test.fcgi +8 -0
- data/spec/cgi/test.ru +5 -0
- data/spec/multipart/bad_robots +259 -0
- data/spec/multipart/binary +0 -0
- data/spec/multipart/empty +10 -0
- data/spec/multipart/fail_16384_nofile +814 -0
- data/spec/multipart/file1.txt +1 -0
- data/spec/multipart/filename_and_modification_param +7 -0
- data/spec/multipart/filename_with_escaped_quotes +6 -0
- data/spec/multipart/filename_with_escaped_quotes_and_modification_param +7 -0
- data/spec/multipart/filename_with_percent_escaped_quotes +6 -0
- data/spec/multipart/filename_with_unescaped_quotes +6 -0
- data/spec/multipart/ie +6 -0
- data/spec/multipart/nested +10 -0
- data/spec/multipart/none +9 -0
- data/spec/multipart/semicolon +6 -0
- data/spec/multipart/text +10 -0
- data/spec/rackup/config.ru +31 -0
- data/{test/spec_rack_auth_basic.rb → spec/spec_auth_basic.rb} +11 -14
- data/{test/spec_rack_auth_digest.rb → spec/spec_auth_digest.rb} +18 -27
- data/{test/spec_rack_builder.rb → spec/spec_builder.rb} +49 -10
- data/{test/spec_rack_cascade.rb → spec/spec_cascade.rb} +7 -10
- data/{test/spec_rack_cgi.rb → spec/spec_cgi.rb} +34 -32
- data/{test/spec_rack_chunked.rb → spec/spec_chunked.rb} +8 -10
- data/{test/spec_rack_commonlogger.rb → spec/spec_commonlogger.rb} +10 -15
- data/{test/spec_rack_conditionalget.rb → spec/spec_conditionalget.rb} +5 -7
- data/{test/spec_rack_config.rb → spec/spec_config.rb} +6 -7
- data/{test/spec_rack_content_length.rb → spec/spec_content_length.rb} +7 -8
- data/{test/spec_rack_content_type.rb → spec/spec_content_type.rb} +5 -6
- data/{test/spec_rack_deflater.rb → spec/spec_deflater.rb} +11 -13
- data/{test/spec_rack_directory.rb → spec/spec_directory.rb} +6 -10
- data/{test/spec_rack_etag.rb → spec/spec_etag.rb} +3 -5
- data/{test/spec_rack_fastcgi.rb → spec/spec_fastcgi.rb} +36 -29
- data/{test/spec_rack_file.rb → spec/spec_file.rb} +9 -13
- data/{test/spec_rack_handler.rb → spec/spec_handler.rb} +10 -12
- data/{test/spec_rack_head.rb → spec/spec_head.rb} +3 -3
- data/{test/spec_rack_lint.rb → spec/spec_lint.rb} +19 -32
- data/{test/spec_rack_lobster.rb → spec/spec_lobster.rb} +9 -11
- data/{test/spec_rack_lock.rb → spec/spec_lock.rb} +15 -17
- data/{test/spec_rack_logger.rb → spec/spec_logger.rb} +6 -7
- data/{test/spec_rack_methodoverride.rb → spec/spec_methodoverride.rb} +15 -17
- data/{test/spec_rack_mock.rb → spec/spec_mock.rb} +30 -32
- data/{test/spec_rack_mongrel.rb → spec/spec_mongrel.rb} +40 -46
- data/{test/spec_rack_nulllogger.rb → spec/spec_nulllogger.rb} +4 -5
- data/{test/spec_rack_recursive.rb → spec/spec_recursive.rb} +28 -36
- data/{test/spec_rack_request.rb → spec/spec_request.rb} +84 -98
- data/{test/spec_rack_response.rb → spec/spec_response.rb} +46 -27
- data/spec/spec_rewindable_input.rb +118 -0
- data/{test/spec_rack_runtime.rb → spec/spec_runtime.rb} +15 -11
- data/{test/spec_rack_sendfile.rb → spec/spec_sendfile.rb} +11 -14
- data/{test/spec_rack_session_cookie.rb → spec/spec_session_cookie.rb} +14 -36
- data/{test/spec_rack_session_memcache.rb → spec/spec_session_memcache.rb} +32 -26
- data/{test/spec_rack_session_pool.rb → spec/spec_session_pool.rb} +36 -31
- data/spec/spec_showexceptions.rb +23 -0
- data/spec/spec_showstatus.rb +79 -0
- data/{test/spec_rack_static.rb → spec/spec_static.rb} +5 -9
- data/{test/spec_rack_thin.rb → spec/spec_thin.rb} +30 -35
- data/{test/spec_rack_urlmap.rb → spec/spec_urlmap.rb} +6 -8
- data/{test/spec_rack_utils.rb → spec/spec_utils.rb} +134 -74
- data/{test/spec_rack_webrick.rb → spec/spec_webrick.rb} +28 -36
- data/spec/testrequest.rb +77 -0
- data/spec/unregistered_handler/rack/handler/unregistered.rb +7 -0
- data/spec/unregistered_handler/rack/handler/unregistered_long_one.rb +7 -0
- metadata +176 -191
- data/RDOX +0 -0
- data/lib/rack/adapter/camping.rb +0 -22
- data/test/spec_auth.rb +0 -57
- data/test/spec_rack_camping.rb +0 -55
- data/test/spec_rack_rewindable_input.rb +0 -118
- data/test/spec_rack_showexceptions.rb +0 -21
- data/test/spec_rack_showstatus.rb +0 -72
- data/test/spec_rackup.rb +0 -164
@@ -1,10 +1,8 @@
|
|
1
|
-
require 'test/spec'
|
2
1
|
require 'set'
|
3
|
-
|
4
2
|
require 'rack/response'
|
5
3
|
|
6
|
-
|
7
|
-
|
4
|
+
describe Rack::Response do
|
5
|
+
should "have sensible default values" do
|
8
6
|
response = Rack::Response.new
|
9
7
|
status, header, body = response.finish
|
10
8
|
status.should.equal 200
|
@@ -22,7 +20,7 @@ context "Rack::Response" do
|
|
22
20
|
}
|
23
21
|
end
|
24
22
|
|
25
|
-
|
23
|
+
it "can be written to" do
|
26
24
|
response = Rack::Response.new
|
27
25
|
|
28
26
|
status, header, body = response.finish do
|
@@ -30,23 +28,23 @@ context "Rack::Response" do
|
|
30
28
|
response.write "bar"
|
31
29
|
response.write "baz"
|
32
30
|
end
|
33
|
-
|
31
|
+
|
34
32
|
parts = []
|
35
33
|
body.each { |part| parts << part }
|
36
|
-
|
34
|
+
|
37
35
|
parts.should.equal ["foo", "bar", "baz"]
|
38
36
|
end
|
39
37
|
|
40
|
-
|
38
|
+
it "can set and read headers" do
|
41
39
|
response = Rack::Response.new
|
42
40
|
response["Content-Type"].should.equal "text/html"
|
43
41
|
response["Content-Type"] = "text/plain"
|
44
42
|
response["Content-Type"].should.equal "text/plain"
|
45
43
|
end
|
46
44
|
|
47
|
-
|
45
|
+
it "can set cookies" do
|
48
46
|
response = Rack::Response.new
|
49
|
-
|
47
|
+
|
50
48
|
response.set_cookie "foo", "bar"
|
51
49
|
response["Set-Cookie"].should.equal "foo=bar"
|
52
50
|
response.set_cookie "foo2", "bar2"
|
@@ -55,36 +53,57 @@ context "Rack::Response" do
|
|
55
53
|
response["Set-Cookie"].should.equal ["foo=bar", "foo2=bar2", "foo3=bar3"].join("\n")
|
56
54
|
end
|
57
55
|
|
58
|
-
|
56
|
+
it "can set cookies with the same name for multiple domains" do
|
57
|
+
response = Rack::Response.new
|
58
|
+
response.set_cookie "foo", {:value => "bar", :domain => "sample.example.com"}
|
59
|
+
response.set_cookie "foo", {:value => "bar", :domain => ".example.com"}
|
60
|
+
response["Set-Cookie"].should.equal ["foo=bar; domain=sample.example.com", "foo=bar; domain=.example.com"].join("\n")
|
61
|
+
end
|
62
|
+
|
63
|
+
it "formats the Cookie expiration date accordingly to RFC 2109" do
|
59
64
|
response = Rack::Response.new
|
60
|
-
|
65
|
+
|
61
66
|
response.set_cookie "foo", {:value => "bar", :expires => Time.now+10}
|
62
67
|
response["Set-Cookie"].should.match(
|
63
68
|
/expires=..., \d\d-...-\d\d\d\d \d\d:\d\d:\d\d .../)
|
64
69
|
end
|
65
70
|
|
66
|
-
|
71
|
+
it "can set secure cookies" do
|
67
72
|
response = Rack::Response.new
|
68
73
|
response.set_cookie "foo", {:value => "bar", :secure => true}
|
69
74
|
response["Set-Cookie"].should.equal "foo=bar; secure"
|
70
75
|
end
|
71
76
|
|
72
|
-
|
77
|
+
it "can set http only cookies" do
|
73
78
|
response = Rack::Response.new
|
74
79
|
response.set_cookie "foo", {:value => "bar", :httponly => true}
|
75
80
|
response["Set-Cookie"].should.equal "foo=bar; HttpOnly"
|
76
81
|
end
|
77
82
|
|
78
|
-
|
83
|
+
it "can delete cookies" do
|
79
84
|
response = Rack::Response.new
|
80
85
|
response.set_cookie "foo", "bar"
|
81
86
|
response.set_cookie "foo2", "bar2"
|
82
87
|
response.delete_cookie "foo"
|
83
|
-
response["Set-Cookie"].should.equal [
|
84
|
-
|
88
|
+
response["Set-Cookie"].should.equal [
|
89
|
+
"foo2=bar2",
|
90
|
+
"foo=; expires=Thu, 01-Jan-1970 00:00:00 GMT"
|
91
|
+
].join("\n")
|
92
|
+
end
|
93
|
+
|
94
|
+
it "can delete cookies with the same name from multiple domains" do
|
95
|
+
response = Rack::Response.new
|
96
|
+
response.set_cookie "foo", {:value => "bar", :domain => "sample.example.com"}
|
97
|
+
response.set_cookie "foo", {:value => "bar", :domain => ".example.com"}
|
98
|
+
response["Set-Cookie"].should.equal ["foo=bar; domain=sample.example.com", "foo=bar; domain=.example.com"].join("\n")
|
99
|
+
response.delete_cookie "foo", :domain => ".example.com"
|
100
|
+
response["Set-Cookie"].should.equal ["foo=bar; domain=sample.example.com", "foo=; domain=.example.com; expires=Thu, 01-Jan-1970 00:00:00 GMT"].join("\n")
|
101
|
+
response.delete_cookie "foo", :domain => "sample.example.com"
|
102
|
+
response["Set-Cookie"].should.equal ["foo=; domain=.example.com; expires=Thu, 01-Jan-1970 00:00:00 GMT",
|
103
|
+
"foo=; domain=sample.example.com; expires=Thu, 01-Jan-1970 00:00:00 GMT"].join("\n")
|
85
104
|
end
|
86
105
|
|
87
|
-
|
106
|
+
it "can do redirects" do
|
88
107
|
response = Rack::Response.new
|
89
108
|
response.redirect "/foo"
|
90
109
|
status, header, body = response.finish
|
@@ -99,7 +118,7 @@ context "Rack::Response" do
|
|
99
118
|
status.should.equal 307
|
100
119
|
end
|
101
120
|
|
102
|
-
|
121
|
+
it "has a useful constructor" do
|
103
122
|
r = Rack::Response.new("foo")
|
104
123
|
status, header, body = r.finish
|
105
124
|
str = ""; body.each { |part| str << part }
|
@@ -123,7 +142,7 @@ context "Rack::Response" do
|
|
123
142
|
r.status.should.equal 200
|
124
143
|
end
|
125
144
|
|
126
|
-
|
145
|
+
it "has a constructor that can take a block" do
|
127
146
|
r = Rack::Response.new { |res|
|
128
147
|
res.status = 404
|
129
148
|
res.write "foo"
|
@@ -133,8 +152,8 @@ context "Rack::Response" do
|
|
133
152
|
str.should.equal "foo"
|
134
153
|
status.should.equal 404
|
135
154
|
end
|
136
|
-
|
137
|
-
|
155
|
+
|
156
|
+
it "doesn't return invalid responses" do
|
138
157
|
r = Rack::Response.new(["foo", "bar"], 204)
|
139
158
|
status, header, body = r.finish
|
140
159
|
str = ""; body.each { |part| str << part }
|
@@ -147,7 +166,7 @@ context "Rack::Response" do
|
|
147
166
|
message.should =~ /stringable or iterable required/
|
148
167
|
end
|
149
168
|
|
150
|
-
|
169
|
+
it "knows if it's empty" do
|
151
170
|
r = Rack::Response.new
|
152
171
|
r.should.be.empty
|
153
172
|
r.write "foo"
|
@@ -164,7 +183,7 @@ context "Rack::Response" do
|
|
164
183
|
r.should.not.be.empty
|
165
184
|
end
|
166
185
|
|
167
|
-
|
186
|
+
should "provide access to the HTTP status" do
|
168
187
|
res = Rack::Response.new
|
169
188
|
res.status = 200
|
170
189
|
res.should.be.successful
|
@@ -183,7 +202,7 @@ context "Rack::Response" do
|
|
183
202
|
res.should.be.redirect
|
184
203
|
end
|
185
204
|
|
186
|
-
|
205
|
+
should "provide access to the HTTP headers" do
|
187
206
|
res = Rack::Response.new
|
188
207
|
res["Content-Type"] = "text/yaml"
|
189
208
|
|
@@ -195,7 +214,7 @@ context "Rack::Response" do
|
|
195
214
|
res.location.should.be.nil
|
196
215
|
end
|
197
216
|
|
198
|
-
|
217
|
+
it "does not add or change Content-Length when #finish()ing" do
|
199
218
|
res = Rack::Response.new
|
200
219
|
res.status = 200
|
201
220
|
res.finish
|
@@ -208,7 +227,7 @@ context "Rack::Response" do
|
|
208
227
|
res.headers["Content-Length"].should.equal "10"
|
209
228
|
end
|
210
229
|
|
211
|
-
|
230
|
+
it "updates Content-Length when body appended to using #write" do
|
212
231
|
res = Rack::Response.new
|
213
232
|
res.status = 200
|
214
233
|
res.headers["Content-Length"].should.be.nil
|
@@ -0,0 +1,118 @@
|
|
1
|
+
require 'stringio'
|
2
|
+
require 'rack/rewindable_input'
|
3
|
+
|
4
|
+
shared "a rewindable IO object" do
|
5
|
+
before do
|
6
|
+
@rio = Rack::RewindableInput.new(@io)
|
7
|
+
end
|
8
|
+
|
9
|
+
should "be able to handle to read()" do
|
10
|
+
@rio.read.should.equal "hello world"
|
11
|
+
end
|
12
|
+
|
13
|
+
should "be able to handle to read(nil)" do
|
14
|
+
@rio.read(nil).should.equal "hello world"
|
15
|
+
end
|
16
|
+
|
17
|
+
should "be able to handle to read(length)" do
|
18
|
+
@rio.read(1).should.equal "h"
|
19
|
+
end
|
20
|
+
|
21
|
+
should "be able to handle to read(length, buffer)" do
|
22
|
+
buffer = ""
|
23
|
+
result = @rio.read(1, buffer)
|
24
|
+
result.should.equal "h"
|
25
|
+
result.object_id.should.equal buffer.object_id
|
26
|
+
end
|
27
|
+
|
28
|
+
should "be able to handle to read(nil, buffer)" do
|
29
|
+
buffer = ""
|
30
|
+
result = @rio.read(nil, buffer)
|
31
|
+
result.should.equal "hello world"
|
32
|
+
result.object_id.should.equal buffer.object_id
|
33
|
+
end
|
34
|
+
|
35
|
+
should "rewind to the beginning when #rewind is called" do
|
36
|
+
@rio.read(1)
|
37
|
+
@rio.rewind
|
38
|
+
@rio.read.should.equal "hello world"
|
39
|
+
end
|
40
|
+
|
41
|
+
should "be able to handle gets" do
|
42
|
+
@rio.gets.should == "hello world"
|
43
|
+
end
|
44
|
+
|
45
|
+
should "be able to handle each" do
|
46
|
+
array = []
|
47
|
+
@rio.each do |data|
|
48
|
+
array << data
|
49
|
+
end
|
50
|
+
array.should.equal(["hello world"])
|
51
|
+
end
|
52
|
+
|
53
|
+
should "not buffer into a Tempfile if no data has been read yet" do
|
54
|
+
@rio.instance_variable_get(:@rewindable_io).should.be.nil
|
55
|
+
end
|
56
|
+
|
57
|
+
should "buffer into a Tempfile when data has been consumed for the first time" do
|
58
|
+
@rio.read(1)
|
59
|
+
tempfile = @rio.instance_variable_get(:@rewindable_io)
|
60
|
+
tempfile.should.not.be.nil
|
61
|
+
@rio.read(1)
|
62
|
+
tempfile2 = @rio.instance_variable_get(:@rewindable_io)
|
63
|
+
tempfile2.path.should == tempfile.path
|
64
|
+
end
|
65
|
+
|
66
|
+
should "close the underlying tempfile upon calling #close" do
|
67
|
+
@rio.read(1)
|
68
|
+
tempfile = @rio.instance_variable_get(:@rewindable_io)
|
69
|
+
@rio.close
|
70
|
+
tempfile.should.be.closed
|
71
|
+
end
|
72
|
+
|
73
|
+
should "be possible to call #close when no data has been buffered yet" do
|
74
|
+
lambda{ @rio.close }.should.not.raise
|
75
|
+
end
|
76
|
+
|
77
|
+
should "be possible to call #close multiple times" do
|
78
|
+
lambda{
|
79
|
+
@rio.close
|
80
|
+
@rio.close
|
81
|
+
}.should.not.raise
|
82
|
+
end
|
83
|
+
|
84
|
+
@rio.close
|
85
|
+
@rio = nil
|
86
|
+
end
|
87
|
+
|
88
|
+
describe Rack::RewindableInput do
|
89
|
+
describe "given an IO object that is already rewindable" do
|
90
|
+
before do
|
91
|
+
@io = StringIO.new("hello world")
|
92
|
+
end
|
93
|
+
|
94
|
+
behaves_like "a rewindable IO object"
|
95
|
+
end
|
96
|
+
|
97
|
+
describe "given an IO object that is not rewindable" do
|
98
|
+
before do
|
99
|
+
@io = StringIO.new("hello world")
|
100
|
+
@io.instance_eval do
|
101
|
+
undef :rewind
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
behaves_like "a rewindable IO object"
|
106
|
+
end
|
107
|
+
|
108
|
+
describe "given an IO object whose rewind method raises Errno::ESPIPE" do
|
109
|
+
before do
|
110
|
+
@io = StringIO.new("hello world")
|
111
|
+
def @io.rewind
|
112
|
+
raise Errno::ESPIPE, "You can't rewind this!"
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
behaves_like "a rewindable IO object"
|
117
|
+
end
|
118
|
+
end
|
@@ -1,31 +1,35 @@
|
|
1
|
-
require 'test/spec'
|
2
|
-
require 'rack/mock'
|
3
1
|
require 'rack/runtime'
|
4
2
|
|
5
|
-
|
6
|
-
|
3
|
+
describe Rack::Runtime do
|
4
|
+
it "sets X-Runtime is none is set" do
|
7
5
|
app = lambda { |env| [200, {'Content-Type' => 'text/plain'}, "Hello, World!"] }
|
8
6
|
response = Rack::Runtime.new(app).call({})
|
9
7
|
response[1]['X-Runtime'].should =~ /[\d\.]+/
|
10
8
|
end
|
11
9
|
|
12
|
-
|
10
|
+
it "doesn't set the X-Runtime if it is already set" do
|
13
11
|
app = lambda { |env| [200, {'Content-Type' => 'text/plain', "X-Runtime" => "foobar"}, "Hello, World!"] }
|
14
12
|
response = Rack::Runtime.new(app).call({})
|
15
13
|
response[1]['X-Runtime'].should == "foobar"
|
16
14
|
end
|
17
15
|
|
18
|
-
|
16
|
+
should "allow a suffix to be set" do
|
19
17
|
app = lambda { |env| [200, {'Content-Type' => 'text/plain'}, "Hello, World!"] }
|
20
18
|
response = Rack::Runtime.new(app, "Test").call({})
|
21
19
|
response[1]['X-Runtime-Test'].should =~ /[\d\.]+/
|
22
20
|
end
|
23
21
|
|
24
|
-
|
25
|
-
app = lambda { |env| [200, {'Content-Type' => 'text/plain'}, "Hello, World!"] }
|
26
|
-
|
27
|
-
|
28
|
-
|
22
|
+
should "allow multiple timers to be set" do
|
23
|
+
app = lambda { |env| sleep 0.1; [200, {'Content-Type' => 'text/plain'}, "Hello, World!"] }
|
24
|
+
runtime = Rack::Runtime.new(app, "App")
|
25
|
+
|
26
|
+
# wrap many times to guarantee a measurable difference
|
27
|
+
100.times do |i|
|
28
|
+
runtime = Rack::Runtime.new(runtime, i.to_s)
|
29
|
+
end
|
30
|
+
runtime = Rack::Runtime.new(runtime, "All")
|
31
|
+
|
32
|
+
response = runtime.call({})
|
29
33
|
|
30
34
|
response[1]['X-Runtime-App'].should =~ /[\d\.]+/
|
31
35
|
response[1]['X-Runtime-All'].should =~ /[\d\.]+/
|
@@ -1,14 +1,13 @@
|
|
1
|
-
require 'test/spec'
|
2
|
-
require 'rack/mock'
|
3
1
|
require 'rack/sendfile'
|
2
|
+
require 'rack/mock'
|
4
3
|
|
5
|
-
|
6
|
-
|
4
|
+
describe Rack::File do
|
5
|
+
should "respond to #to_path" do
|
7
6
|
Rack::File.new(Dir.pwd).should.respond_to :to_path
|
8
7
|
end
|
9
8
|
end
|
10
9
|
|
11
|
-
|
10
|
+
describe Rack::Sendfile do
|
12
11
|
def sendfile_body
|
13
12
|
res = ['Hello World']
|
14
13
|
def res.to_path ; "/tmp/hello.txt" ; end
|
@@ -23,15 +22,13 @@ context "Rack::Sendfile" do
|
|
23
22
|
Rack::Sendfile.new(simple_app(body))
|
24
23
|
end
|
25
24
|
|
26
|
-
|
27
|
-
@request = Rack::MockRequest.new(sendfile_app)
|
28
|
-
end
|
25
|
+
@request = Rack::MockRequest.new(sendfile_app)
|
29
26
|
|
30
27
|
def request(headers={})
|
31
28
|
yield @request.get('/', headers)
|
32
29
|
end
|
33
30
|
|
34
|
-
|
31
|
+
it "does nothing when no X-Sendfile-Type header present" do
|
35
32
|
request do |response|
|
36
33
|
response.should.be.ok
|
37
34
|
response.body.should.equal 'Hello World'
|
@@ -39,7 +36,7 @@ context "Rack::Sendfile" do
|
|
39
36
|
end
|
40
37
|
end
|
41
38
|
|
42
|
-
|
39
|
+
it "sets X-Sendfile response header and discards body" do
|
43
40
|
request 'HTTP_X_SENDFILE_TYPE' => 'X-Sendfile' do |response|
|
44
41
|
response.should.be.ok
|
45
42
|
response.body.should.be.empty
|
@@ -47,7 +44,7 @@ context "Rack::Sendfile" do
|
|
47
44
|
end
|
48
45
|
end
|
49
46
|
|
50
|
-
|
47
|
+
it "sets X-Lighttpd-Send-File response header and discards body" do
|
51
48
|
request 'HTTP_X_SENDFILE_TYPE' => 'X-Lighttpd-Send-File' do |response|
|
52
49
|
response.should.be.ok
|
53
50
|
response.body.should.be.empty
|
@@ -55,7 +52,7 @@ context "Rack::Sendfile" do
|
|
55
52
|
end
|
56
53
|
end
|
57
54
|
|
58
|
-
|
55
|
+
it "sets X-Accel-Redirect response header and discards body" do
|
59
56
|
headers = {
|
60
57
|
'HTTP_X_SENDFILE_TYPE' => 'X-Accel-Redirect',
|
61
58
|
'HTTP_X_ACCEL_MAPPING' => '/tmp/=/foo/bar/'
|
@@ -67,7 +64,7 @@ context "Rack::Sendfile" do
|
|
67
64
|
end
|
68
65
|
end
|
69
66
|
|
70
|
-
|
67
|
+
it 'writes to rack.error when no X-Accel-Mapping is specified' do
|
71
68
|
request 'HTTP_X_SENDFILE_TYPE' => 'X-Accel-Redirect' do |response|
|
72
69
|
response.should.be.ok
|
73
70
|
response.body.should.equal 'Hello World'
|
@@ -76,7 +73,7 @@ context "Rack::Sendfile" do
|
|
76
73
|
end
|
77
74
|
end
|
78
75
|
|
79
|
-
|
76
|
+
it 'does nothing when body does not respond to #to_path' do
|
80
77
|
@request = Rack::MockRequest.new(sendfile_app(['Not a file...']))
|
81
78
|
request 'HTTP_X_SENDFILE_TYPE' => 'X-Sendfile' do |response|
|
82
79
|
response.body.should.equal 'Not a file...'
|
@@ -1,42 +1,20 @@
|
|
1
|
-
require 'test/spec'
|
2
|
-
|
3
1
|
require 'rack/session/cookie'
|
4
2
|
require 'rack/mock'
|
5
|
-
require 'rack/response'
|
6
3
|
|
7
|
-
|
8
|
-
incrementor = lambda
|
4
|
+
describe Rack::Session::Cookie do
|
5
|
+
incrementor = lambda do |env|
|
9
6
|
env["rack.session"]["counter"] ||= 0
|
10
7
|
env["rack.session"]["counter"] += 1
|
11
8
|
Rack::Response.new(env["rack.session"].inspect).to_a
|
12
|
-
}
|
13
|
-
|
14
|
-
before do
|
15
|
-
@warnings = warnings = []
|
16
|
-
Rack::Session::Cookie.class_eval do
|
17
|
-
define_method(:warn) { |m| warnings << m }
|
18
|
-
end
|
19
9
|
end
|
20
10
|
|
21
|
-
|
22
|
-
Rack::Session::Cookie.class_eval { remove_method :warn }
|
23
|
-
end
|
24
|
-
|
25
|
-
specify "warns if no secret is given" do
|
26
|
-
cookie = Rack::Session::Cookie.new(incrementor)
|
27
|
-
@warnings.first.should =~ /no secret/i
|
28
|
-
@warnings.clear
|
29
|
-
cookie = Rack::Session::Cookie.new(incrementor, :secret => 'abc')
|
30
|
-
@warnings.should.be.empty?
|
31
|
-
end
|
32
|
-
|
33
|
-
specify "creates a new cookie" do
|
11
|
+
it "creates a new cookie" do
|
34
12
|
res = Rack::MockRequest.new(Rack::Session::Cookie.new(incrementor)).get("/")
|
35
|
-
res["Set-Cookie"].should.
|
13
|
+
res["Set-Cookie"].should.include("rack.session=")
|
36
14
|
res.body.should.equal '{"counter"=>1}'
|
37
15
|
end
|
38
16
|
|
39
|
-
|
17
|
+
it "loads from a cookie" do
|
40
18
|
res = Rack::MockRequest.new(Rack::Session::Cookie.new(incrementor)).get("/")
|
41
19
|
cookie = res["Set-Cookie"]
|
42
20
|
res = Rack::MockRequest.new(Rack::Session::Cookie.new(incrementor)).
|
@@ -48,25 +26,25 @@ context "Rack::Session::Cookie" do
|
|
48
26
|
res.body.should.equal '{"counter"=>3}'
|
49
27
|
end
|
50
28
|
|
51
|
-
|
29
|
+
it "survives broken cookies" do
|
52
30
|
res = Rack::MockRequest.new(Rack::Session::Cookie.new(incrementor)).
|
53
31
|
get("/", "HTTP_COOKIE" => "rack.session=blarghfasel")
|
54
32
|
res.body.should.equal '{"counter"=>1}'
|
55
33
|
end
|
56
34
|
|
57
|
-
bigcookie = lambda
|
35
|
+
bigcookie = lambda do |env|
|
58
36
|
env["rack.session"]["cookie"] = "big" * 3000
|
59
37
|
Rack::Response.new(env["rack.session"].inspect).to_a
|
60
|
-
|
38
|
+
end
|
61
39
|
|
62
|
-
|
63
|
-
lambda
|
40
|
+
it "barks on too big cookies" do
|
41
|
+
lambda{
|
64
42
|
Rack::MockRequest.new(Rack::Session::Cookie.new(bigcookie)).
|
65
43
|
get("/", :fatal => true)
|
66
44
|
}.should.raise(Rack::MockRequest::FatalWarning)
|
67
45
|
end
|
68
46
|
|
69
|
-
|
47
|
+
it "loads from a cookie wih integrity hash" do
|
70
48
|
res = Rack::MockRequest.new(Rack::Session::Cookie.new(incrementor, :secret => 'test')).get("/")
|
71
49
|
cookie = res["Set-Cookie"]
|
72
50
|
res = Rack::MockRequest.new(Rack::Session::Cookie.new(incrementor, :secret => 'test')).
|
@@ -77,15 +55,15 @@ context "Rack::Session::Cookie" do
|
|
77
55
|
get("/", "HTTP_COOKIE" => cookie)
|
78
56
|
res.body.should.equal '{"counter"=>3}'
|
79
57
|
end
|
80
|
-
|
81
|
-
|
58
|
+
|
59
|
+
it "ignores tampered with session cookies" do
|
82
60
|
app = Rack::Session::Cookie.new(incrementor, :secret => 'test')
|
83
61
|
response1 = Rack::MockRequest.new(app).get("/")
|
84
62
|
_, digest = response1["Set-Cookie"].split("--")
|
85
63
|
tampered_with_cookie = "hackerman-was-here" + "--" + digest
|
86
64
|
response2 = Rack::MockRequest.new(app).get("/", "HTTP_COOKIE" =>
|
87
65
|
tampered_with_cookie)
|
88
|
-
|
66
|
+
|
89
67
|
# The tampered-with cookie is ignored, so we get back an identical Set-Cookie
|
90
68
|
response2["Set-Cookie"].should.equal(response1["Set-Cookie"])
|
91
69
|
end
|