rack 1.4.1 → 1.4.2
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/COPYING +1 -1
- data/KNOWN-ISSUES +9 -0
- data/README.rdoc +72 -7
- 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/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 +10 -0
- data/lib/rack/builder.rb +1 -1
- data/lib/rack/cascade.rb +11 -0
- 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 +13 -4
- 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.rb +2 -2
- data/lib/rack/multipart/parser.rb +6 -4
- data/lib/rack/reloader.rb +1 -1
- data/lib/rack/request.rb +2 -4
- data/lib/rack/response.rb +2 -1
- data/lib/rack/server.rb +28 -2
- data/lib/rack/session/abstract/id.rb +5 -0
- data/lib/rack/session/cookie.rb +9 -0
- data/lib/rack/static.rb +90 -8
- data/lib/rack/utils.rb +17 -10
- 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/spec_auth_basic.rb +8 -0
- data/test/spec_auth_digest.rb +14 -0
- data/test/spec_body_proxy.rb +4 -0
- data/test/spec_builder.rb +7 -1
- data/test/spec_cascade.rb +8 -0
- 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 +42 -25
- 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 +29 -0
- data/test/spec_nulllogger.rb +13 -2
- data/test/spec_recursive.rb +12 -9
- data/test/spec_request.rb +2 -2
- data/test/spec_response.rb +30 -0
- data/test/spec_runtime.rb +15 -5
- data/test/spec_sendfile.rb +11 -8
- data/test/spec_server.rb +47 -0
- data/test/spec_session_cookie.rb +68 -1
- 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 +85 -9
- data/test/spec_urlmap.rb +10 -10
- data/test/spec_utils.rb +14 -1
- data/test/static/another/index.html +1 -0
- metadata +21 -8
data/test/spec_chunked.rb
CHANGED
@@ -3,15 +3,15 @@ require 'rack/lint'
|
|
3
3
|
require 'rack/mock'
|
4
4
|
|
5
5
|
describe Rack::Chunked do
|
6
|
-
Enumerator = ::Enumerable::Enumerator unless
|
6
|
+
::Enumerator = ::Enumerable::Enumerator unless Object.const_defined?(:Enumerator)
|
7
7
|
|
8
8
|
def chunked(app)
|
9
9
|
proc do |env|
|
10
10
|
app = Rack::Chunked.new(app)
|
11
|
-
Rack::Lint.new(app).call(env)
|
12
|
-
|
13
|
-
|
14
|
-
|
11
|
+
response = Rack::Lint.new(app).call(env)
|
12
|
+
# we want to use body like an array, but it only has #each
|
13
|
+
response[2] = Enumerator.new(response[2]).to_a
|
14
|
+
response
|
15
15
|
end
|
16
16
|
end
|
17
17
|
|
@@ -42,7 +42,7 @@ describe Rack::Chunked do
|
|
42
42
|
response = Rack::MockResponse.new(*chunked(app).call(@env))
|
43
43
|
response.headers.should.not.include 'Content-Length'
|
44
44
|
response.headers['Transfer-Encoding'].should.equal 'chunked'
|
45
|
-
response.body.encoding.to_s.should
|
45
|
+
response.body.encoding.to_s.should.equal "ASCII-8BIT"
|
46
46
|
response.body.should.equal "c\r\n\xFE\xFFH\x00e\x00l\x00l\x00o\x00\r\n2\r\n \x00\r\na\r\nW\x00o\x00r\x00l\x00d\x00\r\n0\r\n\r\n"
|
47
47
|
end if RUBY_VERSION >= "1.9"
|
48
48
|
|
data/test/spec_config.rb
CHANGED
data/test/spec_content_length.rb
CHANGED
@@ -1,9 +1,22 @@
|
|
1
|
+
require 'enumerator'
|
1
2
|
require 'rack/content_length'
|
3
|
+
require 'rack/lint'
|
4
|
+
require 'rack/mock'
|
2
5
|
|
3
6
|
describe Rack::ContentLength do
|
7
|
+
::Enumerator = ::Enumerable::Enumerator unless Object.const_defined?(:Enumerator)
|
8
|
+
|
9
|
+
def content_length(app)
|
10
|
+
Rack::Lint.new Rack::ContentLength.new(app)
|
11
|
+
end
|
12
|
+
|
13
|
+
def request
|
14
|
+
Rack::MockRequest.env_for
|
15
|
+
end
|
16
|
+
|
4
17
|
should "set Content-Length on Array bodies if none is set" do
|
5
18
|
app = lambda { |env| [200, {'Content-Type' => 'text/plain'}, ["Hello, World!"]] }
|
6
|
-
response =
|
19
|
+
response = content_length(app).call(request)
|
7
20
|
response[1]['Content-Length'].should.equal '13'
|
8
21
|
end
|
9
22
|
|
@@ -12,25 +25,25 @@ describe Rack::ContentLength do
|
|
12
25
|
def body.each ; yield call ; end
|
13
26
|
|
14
27
|
app = lambda { |env| [200, {'Content-Type' => 'text/plain'}, body] }
|
15
|
-
response =
|
28
|
+
response = content_length(app).call(request)
|
16
29
|
response[1]['Content-Length'].should.be.nil
|
17
30
|
end
|
18
31
|
|
19
32
|
should "not change Content-Length if it is already set" do
|
20
33
|
app = lambda { |env| [200, {'Content-Type' => 'text/plain', 'Content-Length' => '1'}, "Hello, World!"] }
|
21
|
-
response =
|
34
|
+
response = content_length(app).call(request)
|
22
35
|
response[1]['Content-Length'].should.equal '1'
|
23
36
|
end
|
24
37
|
|
25
38
|
should "not set Content-Length on 304 responses" do
|
26
|
-
app = lambda { |env| [304, {
|
27
|
-
response =
|
39
|
+
app = lambda { |env| [304, {}, []] }
|
40
|
+
response = content_length(app).call(request)
|
28
41
|
response[1]['Content-Length'].should.equal nil
|
29
42
|
end
|
30
43
|
|
31
44
|
should "not set Content-Length when Transfer-Encoding is chunked" do
|
32
|
-
app = lambda { |env| [200, {'Transfer-Encoding' => 'chunked'}, []] }
|
33
|
-
response =
|
45
|
+
app = lambda { |env| [200, {'Content-Type' => 'text/plain', 'Transfer-Encoding' => 'chunked'}, []] }
|
46
|
+
response = content_length(app).call(request)
|
34
47
|
response[1]['Content-Length'].should.equal nil
|
35
48
|
end
|
36
49
|
|
@@ -39,7 +52,7 @@ describe Rack::ContentLength do
|
|
39
52
|
#
|
40
53
|
# should "not force a Content-Length when Connection:close" do
|
41
54
|
# app = lambda { |env| [200, {'Connection' => 'close'}, []] }
|
42
|
-
# response =
|
55
|
+
# response = content_length(app).call({})
|
43
56
|
# response[1]['Content-Length'].should.equal nil
|
44
57
|
# end
|
45
58
|
|
@@ -51,8 +64,8 @@ describe Rack::ContentLength do
|
|
51
64
|
def to_ary; end
|
52
65
|
end.new(%w[one two three])
|
53
66
|
|
54
|
-
app = lambda { |env| [200, {}, body] }
|
55
|
-
|
67
|
+
app = lambda { |env| [200, {'Content-Type' => 'text/plain'}, body] }
|
68
|
+
content_length(app).call(request)
|
56
69
|
body.closed.should.equal true
|
57
70
|
end
|
58
71
|
|
@@ -64,10 +77,10 @@ describe Rack::ContentLength do
|
|
64
77
|
def to_ary; end
|
65
78
|
end.new(%w[one two three])
|
66
79
|
|
67
|
-
app = lambda { |env| [200, {}, body] }
|
68
|
-
response =
|
80
|
+
app = lambda { |env| [200, {'Content-Type' => 'text/plain'}, body] }
|
81
|
+
response = content_length(app).call(request)
|
69
82
|
expected = %w[one two three]
|
70
83
|
response[1]['Content-Length'].should.equal expected.join.size.to_s
|
71
|
-
response[2].should.equal expected
|
84
|
+
Enumerator.new(response[2]).to_a.should.equal expected
|
72
85
|
end
|
73
86
|
end
|
data/test/spec_content_type.rb
CHANGED
@@ -1,35 +1,45 @@
|
|
1
1
|
require 'rack/content_type'
|
2
|
+
require 'rack/lint'
|
3
|
+
require 'rack/mock'
|
2
4
|
|
3
5
|
describe Rack::ContentType do
|
6
|
+
def content_type(app, *args)
|
7
|
+
Rack::Lint.new Rack::ContentType.new(app, *args)
|
8
|
+
end
|
9
|
+
|
10
|
+
def request
|
11
|
+
Rack::MockRequest.env_for
|
12
|
+
end
|
13
|
+
|
4
14
|
should "set Content-Type to default text/html if none is set" do
|
5
15
|
app = lambda { |env| [200, {}, "Hello, World!"] }
|
6
|
-
headers =
|
16
|
+
headers = content_type(app).call(request)[1]
|
7
17
|
headers['Content-Type'].should.equal 'text/html'
|
8
18
|
end
|
9
19
|
|
10
20
|
should "set Content-Type to chosen default if none is set" do
|
11
21
|
app = lambda { |env| [200, {}, "Hello, World!"] }
|
12
22
|
headers =
|
13
|
-
|
23
|
+
content_type(app, 'application/octet-stream').call(request)[1]
|
14
24
|
headers['Content-Type'].should.equal 'application/octet-stream'
|
15
25
|
end
|
16
26
|
|
17
27
|
should "not change Content-Type if it is already set" do
|
18
28
|
app = lambda { |env| [200, {'Content-Type' => 'foo/bar'}, "Hello, World!"] }
|
19
|
-
headers =
|
29
|
+
headers = content_type(app).call(request)[1]
|
20
30
|
headers['Content-Type'].should.equal 'foo/bar'
|
21
31
|
end
|
22
32
|
|
23
33
|
should "detect Content-Type case insensitive" do
|
24
34
|
app = lambda { |env| [200, {'CONTENT-Type' => 'foo/bar'}, "Hello, World!"] }
|
25
|
-
headers =
|
35
|
+
headers = content_type(app).call(request)[1]
|
26
36
|
headers.to_a.select { |k,v| k.downcase == "content-type" }.
|
27
37
|
should.equal [["CONTENT-Type","foo/bar"]]
|
28
38
|
end
|
29
39
|
|
30
40
|
should "not set Content-Type on 304 responses" do
|
31
41
|
app = lambda { |env| [304, {}, []] }
|
32
|
-
response =
|
42
|
+
response = content_type(app, "text/html").call(request)
|
33
43
|
response[1]['Content-Type'].should.equal nil
|
34
44
|
end
|
35
45
|
end
|
data/test/spec_deflater.rb
CHANGED
@@ -1,15 +1,27 @@
|
|
1
|
+
require 'enumerator'
|
1
2
|
require 'stringio'
|
2
3
|
require 'time' # for Time#httpdate
|
3
4
|
require 'rack/deflater'
|
5
|
+
require 'rack/lint'
|
4
6
|
require 'rack/mock'
|
5
7
|
require 'zlib'
|
6
8
|
|
7
9
|
describe Rack::Deflater do
|
10
|
+
::Enumerator = ::Enumerable::Enumerator unless Object.const_defined?(:Enumerator)
|
11
|
+
|
12
|
+
def deflater(app)
|
13
|
+
Rack::Lint.new Rack::Deflater.new(app)
|
14
|
+
end
|
15
|
+
|
8
16
|
def build_response(status, body, accept_encoding, headers = {})
|
9
17
|
body = [body] if body.respond_to? :to_str
|
10
|
-
app = lambda
|
18
|
+
app = lambda do |env|
|
19
|
+
res = [status, {}, body]
|
20
|
+
res[1]["Content-Type"] = "text/plain" unless res[0] == 304
|
21
|
+
res
|
22
|
+
end
|
11
23
|
request = Rack::MockRequest.env_for("", headers.merge("HTTP_ACCEPT_ENCODING" => accept_encoding))
|
12
|
-
response =
|
24
|
+
response = deflater(app).call(request)
|
13
25
|
|
14
26
|
return response
|
15
27
|
end
|
@@ -28,7 +40,8 @@ describe Rack::Deflater do
|
|
28
40
|
response[0].should.equal(200)
|
29
41
|
response[1].should.equal({
|
30
42
|
"Content-Encoding" => "deflate",
|
31
|
-
"Vary" => "Accept-Encoding"
|
43
|
+
"Vary" => "Accept-Encoding",
|
44
|
+
"Content-Type" => "text/plain"
|
32
45
|
})
|
33
46
|
buf = ''
|
34
47
|
response[2].each { |part| buf << part }
|
@@ -44,7 +57,8 @@ describe Rack::Deflater do
|
|
44
57
|
response[0].should.equal(200)
|
45
58
|
response[1].should.equal({
|
46
59
|
"Content-Encoding" => "deflate",
|
47
|
-
"Vary" => "Accept-Encoding"
|
60
|
+
"Vary" => "Accept-Encoding",
|
61
|
+
"Content-Type" => "text/plain"
|
48
62
|
})
|
49
63
|
buf = []
|
50
64
|
inflater = Zlib::Inflate.new(-Zlib::MAX_WBITS)
|
@@ -61,7 +75,8 @@ describe Rack::Deflater do
|
|
61
75
|
response[0].should.equal(200)
|
62
76
|
response[1].should.equal({
|
63
77
|
"Content-Encoding" => "deflate",
|
64
|
-
"Vary" => "Accept-Encoding"
|
78
|
+
"Vary" => "Accept-Encoding",
|
79
|
+
"Content-Type" => "text/plain"
|
65
80
|
})
|
66
81
|
buf = ''
|
67
82
|
response[2].each { |part| buf << part }
|
@@ -78,6 +93,7 @@ describe Rack::Deflater do
|
|
78
93
|
response[1].should.equal({
|
79
94
|
"Content-Encoding" => "gzip",
|
80
95
|
"Vary" => "Accept-Encoding",
|
96
|
+
"Content-Type" => "text/plain"
|
81
97
|
})
|
82
98
|
|
83
99
|
buf = ''
|
@@ -97,7 +113,8 @@ describe Rack::Deflater do
|
|
97
113
|
response[0].should.equal(200)
|
98
114
|
response[1].should.equal({
|
99
115
|
"Content-Encoding" => "gzip",
|
100
|
-
"Vary" => "Accept-Encoding"
|
116
|
+
"Vary" => "Accept-Encoding",
|
117
|
+
"Content-Type" => "text/plain"
|
101
118
|
})
|
102
119
|
buf = []
|
103
120
|
inflater = Zlib::Inflate.new(Zlib::MAX_WBITS + 32)
|
@@ -111,8 +128,8 @@ describe Rack::Deflater do
|
|
111
128
|
response = build_response(200, "Hello world!", "superzip")
|
112
129
|
|
113
130
|
response[0].should.equal(200)
|
114
|
-
response[1].should.equal({ "Vary" => "Accept-Encoding" })
|
115
|
-
response[2].should.equal(["Hello world!"])
|
131
|
+
response[1].should.equal({ "Vary" => "Accept-Encoding", "Content-Type" => "text/plain" })
|
132
|
+
Enumerator.new(response[2]).to_a.should.equal(["Hello world!"])
|
116
133
|
end
|
117
134
|
|
118
135
|
should "be able to skip when there is no response entity body" do
|
@@ -120,33 +137,34 @@ describe Rack::Deflater do
|
|
120
137
|
|
121
138
|
response[0].should.equal(304)
|
122
139
|
response[1].should.equal({})
|
123
|
-
response[2].should.equal([])
|
140
|
+
Enumerator.new(response[2]).to_a.should.equal([])
|
124
141
|
end
|
125
142
|
|
126
143
|
should "handle the lack of an acceptable encoding" do
|
127
144
|
response1 = build_response(200, "Hello world!", "identity;q=0", "PATH_INFO" => "/")
|
128
145
|
response1[0].should.equal(406)
|
129
146
|
response1[1].should.equal({"Content-Type" => "text/plain", "Content-Length" => "71"})
|
130
|
-
response1[2].should.equal(["An acceptable encoding for the requested resource / could not be found."])
|
147
|
+
Enumerator.new(response1[2]).to_a.should.equal(["An acceptable encoding for the requested resource / could not be found."])
|
131
148
|
|
132
149
|
response2 = build_response(200, "Hello world!", "identity;q=0", "SCRIPT_NAME" => "/foo", "PATH_INFO" => "/bar")
|
133
150
|
response2[0].should.equal(406)
|
134
151
|
response2[1].should.equal({"Content-Type" => "text/plain", "Content-Length" => "78"})
|
135
|
-
response2[2].should.equal(["An acceptable encoding for the requested resource /foo/bar could not be found."])
|
152
|
+
Enumerator.new(response2[2]).to_a.should.equal(["An acceptable encoding for the requested resource /foo/bar could not be found."])
|
136
153
|
end
|
137
154
|
|
138
155
|
should "handle gzip response with Last-Modified header" do
|
139
156
|
last_modified = Time.now.httpdate
|
140
157
|
|
141
|
-
app = lambda { |env| [200, { "Last-Modified" => last_modified }, ["Hello World!"]] }
|
158
|
+
app = lambda { |env| [200, { "Content-Type" => "text/plain", "Last-Modified" => last_modified }, ["Hello World!"]] }
|
142
159
|
request = Rack::MockRequest.env_for("", "HTTP_ACCEPT_ENCODING" => "gzip")
|
143
|
-
response =
|
160
|
+
response = deflater(app).call(request)
|
144
161
|
|
145
162
|
response[0].should.equal(200)
|
146
163
|
response[1].should.equal({
|
147
164
|
"Content-Encoding" => "gzip",
|
148
165
|
"Vary" => "Accept-Encoding",
|
149
|
-
"Last-Modified" => last_modified
|
166
|
+
"Last-Modified" => last_modified,
|
167
|
+
"Content-Type" => "text/plain"
|
150
168
|
})
|
151
169
|
|
152
170
|
buf = ''
|
@@ -158,12 +176,12 @@ describe Rack::Deflater do
|
|
158
176
|
end
|
159
177
|
|
160
178
|
should "do nothing when no-transform Cache-Control directive present" do
|
161
|
-
app = lambda { |env| [200, {'Cache-Control' => 'no-transform'}, ['Hello World!']] }
|
179
|
+
app = lambda { |env| [200, {'Content-Type' => 'text/plain', 'Cache-Control' => 'no-transform'}, ['Hello World!']] }
|
162
180
|
request = Rack::MockRequest.env_for("", "HTTP_ACCEPT_ENCODING" => "gzip")
|
163
|
-
response =
|
181
|
+
response = deflater(app).call(request)
|
164
182
|
|
165
183
|
response[0].should.equal(200)
|
166
184
|
response[1].should.not.include "Content-Encoding"
|
167
|
-
response[2].join.should.equal("Hello World!")
|
185
|
+
Enumerator.new(response[2]).to_a.join.should.equal("Hello World!")
|
168
186
|
end
|
169
187
|
end
|
data/test/spec_directory.rb
CHANGED
@@ -1,10 +1,11 @@
|
|
1
1
|
require 'rack/directory'
|
2
|
+
require 'rack/lint'
|
2
3
|
require 'rack/mock'
|
3
4
|
|
4
5
|
describe Rack::Directory do
|
5
6
|
DOCROOT = File.expand_path(File.dirname(__FILE__)) unless defined? DOCROOT
|
6
7
|
FILE_CATCH = proc{|env| [200, {'Content-Type'=>'text/plain', "Content-Length" => "7"}, ['passed!']] }
|
7
|
-
app = Rack::Directory.new
|
8
|
+
app = Rack::Lint.new(Rack::Directory.new(DOCROOT, FILE_CATCH))
|
8
9
|
|
9
10
|
should "serve directory indices" do
|
10
11
|
res = Rack::MockRequest.new(Rack::Lint.new(app)).
|
@@ -66,4 +67,22 @@ describe Rack::Directory do
|
|
66
67
|
res = mr.get("/cgi/test%2bdirectory/test%2bfile")
|
67
68
|
res.should.be.ok
|
68
69
|
end
|
70
|
+
|
71
|
+
should "correctly escape script name" do
|
72
|
+
app2 = Rack::Builder.new do
|
73
|
+
map '/script-path' do
|
74
|
+
run app
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
mr = Rack::MockRequest.new(Rack::Lint.new(app2))
|
79
|
+
|
80
|
+
res = mr.get("/script-path/cgi/test%2bdirectory")
|
81
|
+
|
82
|
+
res.should.be.ok
|
83
|
+
res.body.should =~ %r[/script-path/cgi/test%2Bdirectory/test%2Bfile]
|
84
|
+
|
85
|
+
res = mr.get("/script-path/cgi/test%2bdirectory/test%2bfile")
|
86
|
+
res.should.be.ok
|
87
|
+
end
|
69
88
|
end
|
data/test/spec_etag.rb
CHANGED
@@ -1,7 +1,17 @@
|
|
1
1
|
require 'rack/etag'
|
2
|
+
require 'rack/lint'
|
3
|
+
require 'rack/mock'
|
2
4
|
require 'time'
|
3
5
|
|
4
6
|
describe Rack::ETag do
|
7
|
+
def etag(app, *args)
|
8
|
+
Rack::Lint.new Rack::ETag.new(app, *args)
|
9
|
+
end
|
10
|
+
|
11
|
+
def request
|
12
|
+
Rack::MockRequest.env_for
|
13
|
+
end
|
14
|
+
|
5
15
|
def sendfile_body
|
6
16
|
res = ['Hello World']
|
7
17
|
def res.to_path ; "/tmp/hello.txt" ; end
|
@@ -10,73 +20,79 @@ describe Rack::ETag do
|
|
10
20
|
|
11
21
|
should "set ETag if none is set if status is 200" do
|
12
22
|
app = lambda { |env| [200, {'Content-Type' => 'text/plain'}, ["Hello, World!"]] }
|
13
|
-
response =
|
23
|
+
response = etag(app).call(request)
|
14
24
|
response[1]['ETag'].should.equal "\"65a8e27d8879283831b664bd8b7f0ad4\""
|
15
25
|
end
|
16
26
|
|
17
27
|
should "set ETag if none is set if status is 201" do
|
18
28
|
app = lambda { |env| [201, {'Content-Type' => 'text/plain'}, ["Hello, World!"]] }
|
19
|
-
response =
|
29
|
+
response = etag(app).call(request)
|
20
30
|
response[1]['ETag'].should.equal "\"65a8e27d8879283831b664bd8b7f0ad4\""
|
21
31
|
end
|
22
32
|
|
23
33
|
should "set Cache-Control to 'max-age=0, private, must-revalidate' (default) if none is set" do
|
24
34
|
app = lambda { |env| [201, {'Content-Type' => 'text/plain'}, ["Hello, World!"]] }
|
25
|
-
response =
|
35
|
+
response = etag(app).call(request)
|
26
36
|
response[1]['Cache-Control'].should.equal 'max-age=0, private, must-revalidate'
|
27
37
|
end
|
28
38
|
|
29
39
|
should "set Cache-Control to chosen one if none is set" do
|
30
40
|
app = lambda { |env| [201, {'Content-Type' => 'text/plain'}, ["Hello, World!"]] }
|
31
|
-
response =
|
41
|
+
response = etag(app, nil, 'public').call(request)
|
32
42
|
response[1]['Cache-Control'].should.equal 'public'
|
33
43
|
end
|
34
44
|
|
35
45
|
should "set a given Cache-Control even if digest could not be calculated" do
|
36
46
|
app = lambda { |env| [200, {'Content-Type' => 'text/plain'}, []] }
|
37
|
-
response =
|
47
|
+
response = etag(app, 'no-cache').call(request)
|
38
48
|
response[1]['Cache-Control'].should.equal 'no-cache'
|
39
49
|
end
|
40
50
|
|
41
51
|
should "not set Cache-Control if it is already set" do
|
42
52
|
app = lambda { |env| [201, {'Content-Type' => 'text/plain', 'Cache-Control' => 'public'}, ["Hello, World!"]] }
|
43
|
-
response =
|
53
|
+
response = etag(app).call(request)
|
44
54
|
response[1]['Cache-Control'].should.equal 'public'
|
45
55
|
end
|
46
56
|
|
57
|
+
should "not set Cache-Control if directive isn't present" do
|
58
|
+
app = lambda { |env| [200, {'Content-Type' => 'text/plain'}, ["Hello, World!"]] }
|
59
|
+
response = etag(app, nil, nil).call(request)
|
60
|
+
response[1]['Cache-Control'].should.equal nil
|
61
|
+
end
|
62
|
+
|
47
63
|
should "not change ETag if it is already set" do
|
48
64
|
app = lambda { |env| [200, {'Content-Type' => 'text/plain', 'ETag' => '"abc"'}, ["Hello, World!"]] }
|
49
|
-
response =
|
65
|
+
response = etag(app).call(request)
|
50
66
|
response[1]['ETag'].should.equal "\"abc\""
|
51
67
|
end
|
52
68
|
|
53
69
|
should "not set ETag if body is empty" do
|
54
70
|
app = lambda { |env| [200, {'Content-Type' => 'text/plain', 'Last-Modified' => Time.now.httpdate}, []] }
|
55
|
-
response =
|
71
|
+
response = etag(app).call(request)
|
56
72
|
response[1]['ETag'].should.be.nil
|
57
73
|
end
|
58
74
|
|
59
75
|
should "not set ETag if Last-Modified is set" do
|
60
76
|
app = lambda { |env| [200, {'Content-Type' => 'text/plain', 'Last-Modified' => Time.now.httpdate}, ["Hello, World!"]] }
|
61
|
-
response =
|
77
|
+
response = etag(app).call(request)
|
62
78
|
response[1]['ETag'].should.be.nil
|
63
79
|
end
|
64
80
|
|
65
81
|
should "not set ETag if a sendfile_body is given" do
|
66
82
|
app = lambda { |env| [200, {'Content-Type' => 'text/plain'}, sendfile_body] }
|
67
|
-
response =
|
83
|
+
response = etag(app).call(request)
|
68
84
|
response[1]['ETag'].should.be.nil
|
69
85
|
end
|
70
86
|
|
71
87
|
should "not set ETag if a status is not 200 or 201" do
|
72
88
|
app = lambda { |env| [401, {'Content-Type' => 'text/plain'}, ['Access denied.']] }
|
73
|
-
response =
|
89
|
+
response = etag(app).call(request)
|
74
90
|
response[1]['ETag'].should.be.nil
|
75
91
|
end
|
76
92
|
|
77
93
|
should "not set ETag if no-cache is given" do
|
78
|
-
app = lambda { |env| [200, {'Cache-Control' => 'no-cache'}, ['Hello, World!']] }
|
79
|
-
response =
|
94
|
+
app = lambda { |env| [200, {'Content-Type' => 'text/plain', 'Cache-Control' => 'no-cache, must-revalidate'}, ['Hello, World!']] }
|
95
|
+
response = etag(app).call(request)
|
80
96
|
response[1]['ETag'].should.be.nil
|
81
97
|
end
|
82
98
|
end
|