rack 1.6.13 → 2.0.9
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.
- checksums.yaml +4 -4
- data/COPYING +1 -1
- data/HISTORY.md +138 -8
- data/README.rdoc +18 -28
- data/Rakefile +6 -14
- data/SPEC +3 -3
- data/contrib/rack_logo.svg +164 -111
- data/example/protectedlobster.rb +1 -1
- data/example/protectedlobster.ru +1 -1
- data/lib/rack/auth/abstract/request.rb +5 -1
- data/lib/rack/auth/digest/params.rb +2 -3
- data/lib/rack/auth/digest/request.rb +1 -1
- data/lib/rack/body_proxy.rb +14 -9
- data/lib/rack/builder.rb +3 -3
- data/lib/rack/chunked.rb +5 -5
- data/lib/rack/{commonlogger.rb → common_logger.rb} +3 -3
- data/lib/rack/content_length.rb +2 -2
- data/lib/rack/deflater.rb +4 -39
- data/lib/rack/directory.rb +66 -54
- data/lib/rack/etag.rb +5 -4
- data/lib/rack/events.rb +154 -0
- data/lib/rack/file.rb +64 -40
- data/lib/rack/handler/cgi.rb +15 -16
- data/lib/rack/handler/fastcgi.rb +13 -14
- data/lib/rack/handler/lsws.rb +11 -11
- data/lib/rack/handler/scgi.rb +15 -15
- data/lib/rack/handler/thin.rb +3 -0
- data/lib/rack/handler/webrick.rb +24 -26
- data/lib/rack/handler.rb +3 -25
- data/lib/rack/head.rb +15 -17
- data/lib/rack/lint.rb +40 -40
- data/lib/rack/lobster.rb +1 -1
- data/lib/rack/lock.rb +15 -10
- data/lib/rack/logger.rb +2 -2
- data/lib/rack/media_type.rb +38 -0
- data/lib/rack/{methodoverride.rb → method_override.rb} +6 -6
- data/lib/rack/mime.rb +18 -5
- data/lib/rack/mock.rb +36 -54
- data/lib/rack/multipart/generator.rb +5 -5
- data/lib/rack/multipart/parser.rb +270 -157
- data/lib/rack/multipart/uploaded_file.rb +1 -2
- data/lib/rack/multipart.rb +35 -6
- data/lib/rack/{nulllogger.rb → null_logger.rb} +1 -1
- data/lib/rack/query_parser.rb +192 -0
- data/lib/rack/recursive.rb +8 -8
- data/lib/rack/request.rb +394 -305
- data/lib/rack/response.rb +130 -57
- data/lib/rack/rewindable_input.rb +1 -12
- data/lib/rack/runtime.rb +10 -18
- data/lib/rack/sendfile.rb +5 -7
- data/lib/rack/server.rb +30 -23
- data/lib/rack/session/abstract/id.rb +110 -75
- data/lib/rack/session/cookie.rb +24 -17
- data/lib/rack/session/memcache.rb +9 -9
- data/lib/rack/session/pool.rb +8 -8
- data/lib/rack/show_exceptions.rb +386 -0
- data/lib/rack/{showstatus.rb → show_status.rb} +3 -3
- data/lib/rack/static.rb +30 -5
- data/lib/rack/tempfile_reaper.rb +2 -2
- data/lib/rack/urlmap.rb +15 -14
- data/lib/rack/utils.rb +138 -211
- data/lib/rack.rb +70 -21
- data/rack.gemspec +10 -9
- data/test/builder/an_underscore_app.rb +5 -0
- data/test/builder/options.ru +1 -1
- data/test/cgi/test.fcgi +1 -0
- data/test/cgi/test.gz +0 -0
- data/test/helper.rb +34 -0
- data/test/multipart/filename_with_encoded_words +7 -0
- data/test/multipart/filename_with_single_quote +7 -0
- data/test/multipart/quoted +15 -0
- data/test/multipart/rack-logo.png +0 -0
- data/test/multipart/unity3d_wwwform +11 -0
- data/test/registering_handler/rack/handler/registering_myself.rb +1 -1
- data/test/spec_auth_basic.rb +27 -19
- data/test/spec_auth_digest.rb +47 -46
- data/test/spec_body_proxy.rb +27 -27
- data/test/spec_builder.rb +51 -41
- data/test/spec_cascade.rb +24 -22
- data/test/spec_cgi.rb +49 -67
- data/test/spec_chunked.rb +37 -35
- data/test/{spec_commonlogger.rb → spec_common_logger.rb} +23 -21
- data/test/{spec_conditionalget.rb → spec_conditional_get.rb} +29 -28
- data/test/spec_config.rb +3 -2
- data/test/spec_content_length.rb +18 -17
- data/test/spec_content_type.rb +13 -12
- data/test/spec_deflater.rb +85 -49
- data/test/spec_directory.rb +87 -27
- data/test/spec_etag.rb +32 -31
- data/test/spec_events.rb +133 -0
- data/test/spec_fastcgi.rb +50 -72
- data/test/spec_file.rb +120 -77
- data/test/spec_handler.rb +19 -34
- data/test/spec_head.rb +15 -14
- data/test/spec_lint.rb +164 -199
- data/test/spec_lobster.rb +24 -23
- data/test/spec_lock.rb +79 -39
- data/test/spec_logger.rb +4 -3
- data/test/spec_media_type.rb +42 -0
- data/test/{spec_methodoverride.rb → spec_method_override.rb} +34 -35
- data/test/spec_mime.rb +19 -19
- data/test/spec_mock.rb +206 -144
- data/test/spec_multipart.rb +322 -200
- data/test/{spec_nulllogger.rb → spec_null_logger.rb} +5 -4
- data/test/spec_recursive.rb +17 -14
- data/test/spec_request.rb +780 -605
- data/test/spec_response.rb +233 -112
- data/test/spec_rewindable_input.rb +50 -40
- data/test/spec_runtime.rb +11 -10
- data/test/spec_sendfile.rb +30 -35
- data/test/spec_server.rb +78 -52
- data/test/spec_session_abstract_id.rb +11 -33
- data/test/spec_session_abstract_session_hash.rb +45 -0
- data/test/spec_session_cookie.rb +99 -67
- data/test/spec_session_memcache.rb +67 -68
- data/test/spec_session_pool.rb +52 -51
- data/test/{spec_showexceptions.rb → spec_show_exceptions.rb} +23 -28
- data/test/{spec_showstatus.rb → spec_show_status.rb} +36 -35
- data/test/spec_static.rb +71 -32
- data/test/spec_tempfile_reaper.rb +11 -10
- data/test/spec_thin.rb +55 -50
- data/test/spec_urlmap.rb +79 -78
- data/test/spec_utils.rb +441 -346
- data/test/spec_version.rb +2 -8
- data/test/spec_webrick.rb +93 -71
- data/test/static/foo.html +1 -0
- data/test/testrequest.rb +1 -1
- data/test/unregistered_handler/rack/handler/unregistered.rb +1 -1
- data/test/unregistered_handler/rack/handler/unregistered_long_one.rb +1 -1
- metadata +57 -36
- data/KNOWN-ISSUES +0 -44
- data/lib/rack/backports/uri/common_18.rb +0 -56
- data/lib/rack/backports/uri/common_192.rb +0 -52
- data/lib/rack/backports/uri/common_193.rb +0 -29
- data/lib/rack/handler/evented_mongrel.rb +0 -8
- data/lib/rack/handler/mongrel.rb +0 -106
- data/lib/rack/handler/swiftiplied_mongrel.rb +0 -8
- data/lib/rack/showexceptions.rb +0 -387
- data/lib/rack/utils/okjson.rb +0 -600
- data/test/spec_mongrel.rb +0 -182
- /data/lib/rack/{conditionalget.rb → conditional_get.rb} +0 -0
@@ -1,4 +1,5 @@
|
|
1
|
-
require '
|
1
|
+
require 'minitest/autorun'
|
2
|
+
require 'rack/common_logger'
|
2
3
|
require 'rack/lint'
|
3
4
|
require 'rack/mock'
|
4
5
|
|
@@ -21,66 +22,67 @@ describe Rack::CommonLogger do
|
|
21
22
|
{"Content-Type" => "text/html", "Content-Length" => "0"},
|
22
23
|
[]]}
|
23
24
|
|
24
|
-
|
25
|
+
it "log to rack.errors by default" do
|
25
26
|
res = Rack::MockRequest.new(Rack::CommonLogger.new(app)).get("/")
|
26
27
|
|
27
|
-
res.errors.
|
28
|
-
res.errors.
|
28
|
+
res.errors.wont_be :empty?
|
29
|
+
res.errors.must_match(/"GET \/ " 200 #{length} /)
|
29
30
|
end
|
30
31
|
|
31
|
-
|
32
|
+
it "log to anything with +write+" do
|
32
33
|
log = StringIO.new
|
33
34
|
Rack::MockRequest.new(Rack::CommonLogger.new(app, log)).get("/")
|
34
35
|
|
35
|
-
log.string.
|
36
|
+
log.string.must_match(/"GET \/ " 200 #{length} /)
|
36
37
|
end
|
37
38
|
|
38
|
-
|
39
|
+
it "work with standartd library logger" do
|
39
40
|
logdev = StringIO.new
|
40
41
|
log = Logger.new(logdev)
|
41
42
|
Rack::MockRequest.new(Rack::CommonLogger.new(app, log)).get("/")
|
42
43
|
|
43
|
-
logdev.string.
|
44
|
+
logdev.string.must_match(/"GET \/ " 200 #{length} /)
|
44
45
|
end
|
45
46
|
|
46
|
-
|
47
|
+
it "log - content length if header is missing" do
|
47
48
|
res = Rack::MockRequest.new(Rack::CommonLogger.new(app_without_length)).get("/")
|
48
49
|
|
49
|
-
res.errors.
|
50
|
-
res.errors.
|
50
|
+
res.errors.wont_be :empty?
|
51
|
+
res.errors.must_match(/"GET \/ " 200 - /)
|
51
52
|
end
|
52
53
|
|
53
|
-
|
54
|
+
it "log - content length if header is zero" do
|
54
55
|
res = Rack::MockRequest.new(Rack::CommonLogger.new(app_with_zero_length)).get("/")
|
55
56
|
|
56
|
-
res.errors.
|
57
|
-
res.errors.
|
57
|
+
res.errors.wont_be :empty?
|
58
|
+
res.errors.must_match(/"GET \/ " 200 - /)
|
58
59
|
end
|
59
60
|
|
60
61
|
def with_mock_time(t = 0)
|
61
|
-
mc = class <<Time; self; end
|
62
|
+
mc = class << Time; self; end
|
62
63
|
mc.send :alias_method, :old_now, :now
|
63
64
|
mc.send :define_method, :now do
|
64
65
|
at(t)
|
65
66
|
end
|
66
67
|
yield
|
67
68
|
ensure
|
69
|
+
mc.send :undef_method, :now
|
68
70
|
mc.send :alias_method, :now, :old_now
|
69
71
|
end
|
70
72
|
|
71
|
-
|
73
|
+
it "log in common log format" do
|
72
74
|
log = StringIO.new
|
73
75
|
with_mock_time do
|
74
76
|
Rack::MockRequest.new(Rack::CommonLogger.new(app, log)).get("/")
|
75
77
|
end
|
76
78
|
|
77
79
|
md = /- - - \[([^\]]+)\] "(\w+) \/ " (\d{3}) \d+ ([\d\.]+)/.match(log.string)
|
78
|
-
md.
|
80
|
+
md.wont_equal nil
|
79
81
|
time, method, status, duration = *md.captures
|
80
|
-
time.
|
81
|
-
method.
|
82
|
-
status.
|
83
|
-
(0..1).
|
82
|
+
time.must_equal Time.at(0).strftime("%d/%b/%Y:%H:%M:%S %z")
|
83
|
+
method.must_equal "GET"
|
84
|
+
status.must_equal "200"
|
85
|
+
(0..1).must_include duration.to_f
|
84
86
|
end
|
85
87
|
|
86
88
|
def length
|
@@ -1,13 +1,14 @@
|
|
1
|
+
require 'minitest/autorun'
|
1
2
|
require 'time'
|
2
|
-
require 'rack/
|
3
|
+
require 'rack/conditional_get'
|
3
4
|
require 'rack/mock'
|
4
5
|
|
5
6
|
describe Rack::ConditionalGet do
|
6
7
|
def conditional_get(app)
|
7
8
|
Rack::Lint.new Rack::ConditionalGet.new(app)
|
8
9
|
end
|
9
|
-
|
10
|
-
|
10
|
+
|
11
|
+
it "set a 304 status and truncate body when If-Modified-Since hits" do
|
11
12
|
timestamp = Time.now.httpdate
|
12
13
|
app = conditional_get(lambda { |env|
|
13
14
|
[200, {'Last-Modified'=>timestamp}, ['TEST']] })
|
@@ -15,33 +16,33 @@ describe Rack::ConditionalGet do
|
|
15
16
|
response = Rack::MockRequest.new(app).
|
16
17
|
get("/", 'HTTP_IF_MODIFIED_SINCE' => timestamp)
|
17
18
|
|
18
|
-
response.status.
|
19
|
-
response.body.
|
19
|
+
response.status.must_equal 304
|
20
|
+
response.body.must_be :empty?
|
20
21
|
end
|
21
22
|
|
22
|
-
|
23
|
+
it "set a 304 status and truncate body when If-Modified-Since hits and is higher than current time" do
|
23
24
|
app = conditional_get(lambda { |env|
|
24
25
|
[200, {'Last-Modified'=>(Time.now - 3600).httpdate}, ['TEST']] })
|
25
26
|
|
26
27
|
response = Rack::MockRequest.new(app).
|
27
28
|
get("/", 'HTTP_IF_MODIFIED_SINCE' => Time.now.httpdate)
|
28
29
|
|
29
|
-
response.status.
|
30
|
-
response.body.
|
30
|
+
response.status.must_equal 304
|
31
|
+
response.body.must_be :empty?
|
31
32
|
end
|
32
33
|
|
33
|
-
|
34
|
+
it "set a 304 status and truncate body when If-None-Match hits" do
|
34
35
|
app = conditional_get(lambda { |env|
|
35
|
-
[200, {'
|
36
|
+
[200, {'ETag'=>'1234'}, ['TEST']] })
|
36
37
|
|
37
38
|
response = Rack::MockRequest.new(app).
|
38
39
|
get("/", 'HTTP_IF_NONE_MATCH' => '1234')
|
39
40
|
|
40
|
-
response.status.
|
41
|
-
response.body.
|
41
|
+
response.status.must_equal 304
|
42
|
+
response.body.must_be :empty?
|
42
43
|
end
|
43
44
|
|
44
|
-
|
45
|
+
it "not set a 304 status if If-Modified-Since hits but Etag does not" do
|
45
46
|
timestamp = Time.now.httpdate
|
46
47
|
app = conditional_get(lambda { |env|
|
47
48
|
[200, {'Last-Modified'=>timestamp, 'Etag'=>'1234', 'Content-Type' => 'text/plain'}, ['TEST']] })
|
@@ -49,45 +50,45 @@ describe Rack::ConditionalGet do
|
|
49
50
|
response = Rack::MockRequest.new(app).
|
50
51
|
get("/", 'HTTP_IF_MODIFIED_SINCE' => timestamp, 'HTTP_IF_NONE_MATCH' => '4321')
|
51
52
|
|
52
|
-
response.status.
|
53
|
-
response.body.
|
53
|
+
response.status.must_equal 200
|
54
|
+
response.body.must_equal 'TEST'
|
54
55
|
end
|
55
56
|
|
56
|
-
|
57
|
+
it "set a 304 status and truncate body when both If-None-Match and If-Modified-Since hits" do
|
57
58
|
timestamp = Time.now.httpdate
|
58
59
|
app = conditional_get(lambda { |env|
|
59
|
-
[200, {'Last-Modified'=>timestamp, '
|
60
|
+
[200, {'Last-Modified'=>timestamp, 'ETag'=>'1234'}, ['TEST']] })
|
60
61
|
|
61
62
|
response = Rack::MockRequest.new(app).
|
62
63
|
get("/", 'HTTP_IF_MODIFIED_SINCE' => timestamp, 'HTTP_IF_NONE_MATCH' => '1234')
|
63
64
|
|
64
|
-
response.status.
|
65
|
-
response.body.
|
65
|
+
response.status.must_equal 304
|
66
|
+
response.body.must_be :empty?
|
66
67
|
end
|
67
68
|
|
68
|
-
|
69
|
+
it "not affect non-GET/HEAD requests" do
|
69
70
|
app = conditional_get(lambda { |env|
|
70
71
|
[200, {'Etag'=>'1234', 'Content-Type' => 'text/plain'}, ['TEST']] })
|
71
72
|
|
72
73
|
response = Rack::MockRequest.new(app).
|
73
74
|
post("/", 'HTTP_IF_NONE_MATCH' => '1234')
|
74
75
|
|
75
|
-
response.status.
|
76
|
-
response.body.
|
76
|
+
response.status.must_equal 200
|
77
|
+
response.body.must_equal 'TEST'
|
77
78
|
end
|
78
79
|
|
79
|
-
|
80
|
+
it "not affect non-200 requests" do
|
80
81
|
app = conditional_get(lambda { |env|
|
81
82
|
[302, {'Etag'=>'1234', 'Content-Type' => 'text/plain'}, ['TEST']] })
|
82
83
|
|
83
84
|
response = Rack::MockRequest.new(app).
|
84
85
|
get("/", 'HTTP_IF_NONE_MATCH' => '1234')
|
85
86
|
|
86
|
-
response.status.
|
87
|
-
response.body.
|
87
|
+
response.status.must_equal 302
|
88
|
+
response.body.must_equal 'TEST'
|
88
89
|
end
|
89
90
|
|
90
|
-
|
91
|
+
it "not affect requests with malformed HTTP_IF_NONE_MATCH" do
|
91
92
|
bad_timestamp = Time.now.strftime('%Y-%m-%d %H:%M:%S %z')
|
92
93
|
app = conditional_get(lambda { |env|
|
93
94
|
[200,{'Last-Modified'=>(Time.now - 3600).httpdate, 'Content-Type' => 'text/plain'}, ['TEST']] })
|
@@ -95,8 +96,8 @@ describe Rack::ConditionalGet do
|
|
95
96
|
response = Rack::MockRequest.new(app).
|
96
97
|
get("/", 'HTTP_IF_MODIFIED_SINCE' => bad_timestamp)
|
97
98
|
|
98
|
-
response.status.
|
99
|
-
response.body.
|
99
|
+
response.status.must_equal 200
|
100
|
+
response.body.must_equal 'TEST'
|
100
101
|
end
|
101
102
|
|
102
103
|
end
|
data/test/spec_config.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
require 'minitest/autorun'
|
1
2
|
require 'rack/builder'
|
2
3
|
require 'rack/config'
|
3
4
|
require 'rack/content_length'
|
@@ -5,7 +6,7 @@ require 'rack/lint'
|
|
5
6
|
require 'rack/mock'
|
6
7
|
|
7
8
|
describe Rack::Config do
|
8
|
-
|
9
|
+
it "accept a block that modifies the environment" do
|
9
10
|
app = Rack::Builder.new do
|
10
11
|
use Rack::Lint
|
11
12
|
use Rack::Config do |env|
|
@@ -17,6 +18,6 @@ describe Rack::Config do
|
|
17
18
|
end
|
18
19
|
|
19
20
|
response = Rack::MockRequest.new(app).get('/')
|
20
|
-
response.body.
|
21
|
+
response.body.must_equal 'hello'
|
21
22
|
end
|
22
23
|
end
|
data/test/spec_content_length.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
require 'minitest/autorun'
|
1
2
|
require 'rack/content_length'
|
2
3
|
require 'rack/lint'
|
3
4
|
require 'rack/mock'
|
@@ -11,37 +12,37 @@ describe Rack::ContentLength do
|
|
11
12
|
Rack::MockRequest.env_for
|
12
13
|
end
|
13
14
|
|
14
|
-
|
15
|
+
it "set Content-Length on Array bodies if none is set" do
|
15
16
|
app = lambda { |env| [200, {'Content-Type' => 'text/plain'}, ["Hello, World!"]] }
|
16
17
|
response = content_length(app).call(request)
|
17
|
-
response[1]['Content-Length'].
|
18
|
+
response[1]['Content-Length'].must_equal '13'
|
18
19
|
end
|
19
20
|
|
20
|
-
|
21
|
+
it "not set Content-Length on variable length bodies" do
|
21
22
|
body = lambda { "Hello World!" }
|
22
23
|
def body.each ; yield call ; end
|
23
24
|
|
24
25
|
app = lambda { |env| [200, {'Content-Type' => 'text/plain'}, body] }
|
25
26
|
response = content_length(app).call(request)
|
26
|
-
response[1]['Content-Length'].
|
27
|
+
response[1]['Content-Length'].must_be_nil
|
27
28
|
end
|
28
29
|
|
29
|
-
|
30
|
+
it "not change Content-Length if it is already set" do
|
30
31
|
app = lambda { |env| [200, {'Content-Type' => 'text/plain', 'Content-Length' => '1'}, "Hello, World!"] }
|
31
32
|
response = content_length(app).call(request)
|
32
|
-
response[1]['Content-Length'].
|
33
|
+
response[1]['Content-Length'].must_equal '1'
|
33
34
|
end
|
34
35
|
|
35
|
-
|
36
|
+
it "not set Content-Length on 304 responses" do
|
36
37
|
app = lambda { |env| [304, {}, []] }
|
37
38
|
response = content_length(app).call(request)
|
38
|
-
response[1]['Content-Length'].
|
39
|
+
response[1]['Content-Length'].must_be_nil
|
39
40
|
end
|
40
41
|
|
41
|
-
|
42
|
+
it "not set Content-Length when Transfer-Encoding is chunked" do
|
42
43
|
app = lambda { |env| [200, {'Content-Type' => 'text/plain', 'Transfer-Encoding' => 'chunked'}, []] }
|
43
44
|
response = content_length(app).call(request)
|
44
|
-
response[1]['Content-Length'].
|
45
|
+
response[1]['Content-Length'].must_be_nil
|
45
46
|
end
|
46
47
|
|
47
48
|
# Using "Connection: close" for this is fairly contended. It might be useful
|
@@ -50,10 +51,10 @@ describe Rack::ContentLength do
|
|
50
51
|
# should "not force a Content-Length when Connection:close" do
|
51
52
|
# app = lambda { |env| [200, {'Connection' => 'close'}, []] }
|
52
53
|
# response = content_length(app).call({})
|
53
|
-
# response[1]['Content-Length'].
|
54
|
+
# response[1]['Content-Length'].must_be_nil
|
54
55
|
# end
|
55
56
|
|
56
|
-
|
57
|
+
it "close bodies that need to be closed" do
|
57
58
|
body = Struct.new(:body) do
|
58
59
|
attr_reader :closed
|
59
60
|
def each; body.join; end
|
@@ -63,12 +64,12 @@ describe Rack::ContentLength do
|
|
63
64
|
|
64
65
|
app = lambda { |env| [200, {'Content-Type' => 'text/plain'}, body] }
|
65
66
|
response = content_length(app).call(request)
|
66
|
-
body.closed.
|
67
|
+
body.closed.must_be_nil
|
67
68
|
response[2].close
|
68
|
-
body.closed.
|
69
|
+
body.closed.must_equal true
|
69
70
|
end
|
70
71
|
|
71
|
-
|
72
|
+
it "support single-execute bodies" do
|
72
73
|
body = Struct.new(:body) do
|
73
74
|
def each
|
74
75
|
yield body.shift until body.empty?
|
@@ -79,7 +80,7 @@ describe Rack::ContentLength do
|
|
79
80
|
app = lambda { |env| [200, {'Content-Type' => 'text/plain'}, body] }
|
80
81
|
response = content_length(app).call(request)
|
81
82
|
expected = %w[one two three]
|
82
|
-
response[1]['Content-Length'].
|
83
|
-
response[2].to_enum.to_a.
|
83
|
+
response[1]['Content-Length'].must_equal expected.join.size.to_s
|
84
|
+
response[2].to_enum.to_a.must_equal expected
|
84
85
|
end
|
85
86
|
end
|
data/test/spec_content_type.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
require 'minitest/autorun'
|
1
2
|
require 'rack/content_type'
|
2
3
|
require 'rack/lint'
|
3
4
|
require 'rack/mock'
|
@@ -6,40 +7,40 @@ describe Rack::ContentType do
|
|
6
7
|
def content_type(app, *args)
|
7
8
|
Rack::Lint.new Rack::ContentType.new(app, *args)
|
8
9
|
end
|
9
|
-
|
10
|
+
|
10
11
|
def request
|
11
12
|
Rack::MockRequest.env_for
|
12
13
|
end
|
13
|
-
|
14
|
-
|
14
|
+
|
15
|
+
it "set Content-Type to default text/html if none is set" do
|
15
16
|
app = lambda { |env| [200, {}, "Hello, World!"] }
|
16
17
|
headers = content_type(app).call(request)[1]
|
17
|
-
headers['Content-Type'].
|
18
|
+
headers['Content-Type'].must_equal 'text/html'
|
18
19
|
end
|
19
20
|
|
20
|
-
|
21
|
+
it "set Content-Type to chosen default if none is set" do
|
21
22
|
app = lambda { |env| [200, {}, "Hello, World!"] }
|
22
23
|
headers =
|
23
24
|
content_type(app, 'application/octet-stream').call(request)[1]
|
24
|
-
headers['Content-Type'].
|
25
|
+
headers['Content-Type'].must_equal 'application/octet-stream'
|
25
26
|
end
|
26
27
|
|
27
|
-
|
28
|
+
it "not change Content-Type if it is already set" do
|
28
29
|
app = lambda { |env| [200, {'Content-Type' => 'foo/bar'}, "Hello, World!"] }
|
29
30
|
headers = content_type(app).call(request)[1]
|
30
|
-
headers['Content-Type'].
|
31
|
+
headers['Content-Type'].must_equal 'foo/bar'
|
31
32
|
end
|
32
33
|
|
33
|
-
|
34
|
+
it "detect Content-Type case insensitive" do
|
34
35
|
app = lambda { |env| [200, {'CONTENT-Type' => 'foo/bar'}, "Hello, World!"] }
|
35
36
|
headers = content_type(app).call(request)[1]
|
36
37
|
headers.to_a.select { |k,v| k.downcase == "content-type" }.
|
37
|
-
|
38
|
+
must_equal [["CONTENT-Type","foo/bar"]]
|
38
39
|
end
|
39
40
|
|
40
|
-
|
41
|
+
it "not set Content-Type on 304 responses" do
|
41
42
|
app = lambda { |env| [304, {}, []] }
|
42
43
|
response = content_type(app, "text/html").call(request)
|
43
|
-
response[1]['Content-Type'].
|
44
|
+
response[1]['Content-Type'].must_be_nil
|
44
45
|
end
|
45
46
|
end
|