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.

Files changed (81) hide show
  1. data/COPYING +1 -1
  2. data/KNOWN-ISSUES +9 -0
  3. data/README.rdoc +72 -7
  4. data/Rakefile +18 -11
  5. data/SPEC +3 -1
  6. data/contrib/rack.png +0 -0
  7. data/contrib/rack.svg +150 -0
  8. data/contrib/rdoc.css +412 -0
  9. data/lib/rack/auth/basic.rb +1 -1
  10. data/lib/rack/auth/digest/nonce.rb +1 -1
  11. data/lib/rack/backports/uri/common_18.rb +14 -28
  12. data/lib/rack/backports/uri/common_192.rb +14 -17
  13. data/lib/rack/backports/uri/common_193.rb +29 -0
  14. data/lib/rack/body_proxy.rb +10 -0
  15. data/lib/rack/builder.rb +1 -1
  16. data/lib/rack/cascade.rb +11 -0
  17. data/lib/rack/commonlogger.rb +18 -5
  18. data/lib/rack/deflater.rb +5 -1
  19. data/lib/rack/directory.rb +1 -1
  20. data/lib/rack/etag.rb +6 -3
  21. data/lib/rack/file.rb +13 -4
  22. data/lib/rack/head.rb +1 -0
  23. data/lib/rack/lint.rb +3 -1
  24. data/lib/rack/lock.rb +3 -4
  25. data/lib/rack/mime.rb +1 -1
  26. data/lib/rack/mock.rb +3 -2
  27. data/lib/rack/multipart.rb +2 -2
  28. data/lib/rack/multipart/parser.rb +6 -4
  29. data/lib/rack/reloader.rb +1 -1
  30. data/lib/rack/request.rb +2 -4
  31. data/lib/rack/response.rb +2 -1
  32. data/lib/rack/server.rb +28 -2
  33. data/lib/rack/session/abstract/id.rb +5 -0
  34. data/lib/rack/session/cookie.rb +9 -0
  35. data/lib/rack/static.rb +90 -8
  36. data/lib/rack/utils.rb +17 -10
  37. data/rack.gemspec +3 -3
  38. data/test/builder/line.ru +1 -0
  39. data/test/cgi/assets/folder/test.js +1 -0
  40. data/test/cgi/assets/fonts/font.eot +1 -0
  41. data/test/cgi/assets/images/image.png +1 -0
  42. data/test/cgi/assets/index.html +1 -0
  43. data/test/cgi/assets/javascripts/app.js +1 -0
  44. data/test/cgi/assets/stylesheets/app.css +1 -0
  45. data/test/spec_auth_basic.rb +8 -0
  46. data/test/spec_auth_digest.rb +14 -0
  47. data/test/spec_body_proxy.rb +4 -0
  48. data/test/spec_builder.rb +7 -1
  49. data/test/spec_cascade.rb +8 -0
  50. data/test/spec_chunked.rb +6 -6
  51. data/test/spec_config.rb +0 -1
  52. data/test/spec_content_length.rb +26 -13
  53. data/test/spec_content_type.rb +15 -5
  54. data/test/spec_deflater.rb +35 -17
  55. data/test/spec_directory.rb +20 -1
  56. data/test/spec_etag.rb +29 -13
  57. data/test/spec_file.rb +42 -25
  58. data/test/spec_head.rb +25 -7
  59. data/test/spec_lobster.rb +20 -5
  60. data/test/spec_lock.rb +46 -21
  61. data/test/spec_logger.rb +2 -7
  62. data/test/spec_methodoverride.rb +21 -22
  63. data/test/spec_mock.rb +12 -7
  64. data/test/spec_multipart.rb +29 -0
  65. data/test/spec_nulllogger.rb +13 -2
  66. data/test/spec_recursive.rb +12 -9
  67. data/test/spec_request.rb +2 -2
  68. data/test/spec_response.rb +30 -0
  69. data/test/spec_runtime.rb +15 -5
  70. data/test/spec_sendfile.rb +11 -8
  71. data/test/spec_server.rb +47 -0
  72. data/test/spec_session_cookie.rb +68 -1
  73. data/test/spec_session_memcache.rb +10 -8
  74. data/test/spec_session_pool.rb +13 -10
  75. data/test/spec_showexceptions.rb +9 -4
  76. data/test/spec_showstatus.rb +10 -5
  77. data/test/spec_static.rb +85 -9
  78. data/test/spec_urlmap.rb +10 -10
  79. data/test/spec_utils.rb +14 -1
  80. data/test/static/another/index.html +1 -0
  81. metadata +21 -8
@@ -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 defined?(Enumerator)
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).tap do |response|
12
- # we want to use body like an array, but it only has #each
13
- response[2] = Enumerator.new(response[2]).to_a
14
- end
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 == "ASCII-8BIT"
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
 
@@ -8,7 +8,6 @@ describe Rack::Config do
8
8
  should "accept a block that modifies the environment" do
9
9
  app = Rack::Builder.new do
10
10
  use Rack::Lint
11
- use Rack::ContentLength
12
11
  use Rack::Config do |env|
13
12
  env['greeting'] = 'hello'
14
13
  end
@@ -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 = Rack::ContentLength.new(app).call({})
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 = Rack::ContentLength.new(app).call({})
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 = Rack::ContentLength.new(app).call({})
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, {'Content-Type' => 'text/plain'}, []] }
27
- response = Rack::ContentLength.new(app).call({})
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 = Rack::ContentLength.new(app).call({})
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 = Rack::ContentLength.new(app).call({})
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
- Rack::ContentLength.new(app).call({})
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 = Rack::ContentLength.new(app).call({})
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
@@ -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 = Rack::ContentType.new(app).call({})[1]
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
- Rack::ContentType.new(app, 'application/octet-stream').call({})[1]
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 = Rack::ContentType.new(app).call({})[1]
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 = Rack::ContentType.new(app).call({})[1]
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 = Rack::ContentType.new(app, "text/html").call({})
42
+ response = content_type(app, "text/html").call(request)
33
43
  response[1]['Content-Type'].should.equal nil
34
44
  end
35
45
  end
@@ -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 { |env| [status, {}, body] }
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 = Rack::Deflater.new(app).call(request)
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 = Rack::Deflater.new(app).call(request)
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 = Rack::Deflater.new(app).call(request)
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
@@ -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 DOCROOT, FILE_CATCH
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
@@ -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 = Rack::ETag.new(app).call({})
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 = Rack::ETag.new(app).call({})
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 = Rack::ETag.new(app).call({})
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 = Rack::ETag.new(app, nil, 'public').call({})
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 = Rack::ETag.new(app, 'no-cache').call({})
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 = Rack::ETag.new(app).call({})
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 = Rack::ETag.new(app).call({})
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 = Rack::ETag.new(app).call({})
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 = Rack::ETag.new(app).call({})
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 = Rack::ETag.new(app).call({})
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 = Rack::ETag.new(app).call({})
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 = Rack::ETag.new(app).call({})
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