rack 1.6.13 → 2.0.0.alpha
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 +5 -5
- data/HISTORY.md +139 -18
- data/README.rdoc +17 -25
- data/Rakefile +6 -14
- data/SPEC +8 -9
- data/contrib/rack_logo.svg +164 -111
- data/lib/rack.rb +70 -21
- 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} +2 -2
- data/lib/rack/{conditionalget.rb → conditional_get.rb} +0 -0
- data/lib/rack/content_length.rb +2 -2
- data/lib/rack/deflater.rb +4 -4
- data/lib/rack/directory.rb +49 -55
- data/lib/rack/etag.rb +2 -1
- data/lib/rack/events.rb +154 -0
- data/lib/rack/file.rb +55 -40
- data/lib/rack/handler.rb +2 -24
- 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 +22 -24
- data/lib/rack/head.rb +15 -17
- data/lib/rack/lint.rb +38 -38
- data/lib/rack/lobster.rb +1 -1
- data/lib/rack/lock.rb +6 -10
- data/lib/rack/logger.rb +2 -2
- data/lib/rack/media_type.rb +38 -0
- data/lib/rack/{methodoverride.rb → method_override.rb} +4 -11
- data/lib/rack/mime.rb +18 -5
- data/lib/rack/mock.rb +35 -52
- data/lib/rack/multipart.rb +35 -6
- data/lib/rack/multipart/generator.rb +4 -4
- data/lib/rack/multipart/parser.rb +273 -158
- data/lib/rack/multipart/uploaded_file.rb +1 -2
- data/lib/rack/{nulllogger.rb → null_logger.rb} +1 -1
- data/lib/rack/query_parser.rb +174 -0
- data/lib/rack/recursive.rb +8 -8
- data/lib/rack/reloader.rb +1 -2
- data/lib/rack/request.rb +370 -304
- data/lib/rack/response.rb +129 -56
- 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 +31 -25
- data/lib/rack/session/abstract/id.rb +93 -135
- data/lib/rack/session/cookie.rb +26 -28
- data/lib/rack/session/memcache.rb +8 -14
- data/lib/rack/session/pool.rb +14 -21
- 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 +13 -14
- data/lib/rack/utils.rb +128 -221
- data/rack.gemspec +9 -5
- 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 +31 -0
- data/test/multipart/filename_with_encoded_words +7 -0
- data/test/multipart/{filename_with_null_byte → filename_with_single_quote} +1 -1
- data/test/multipart/quoted +15 -0
- data/test/multipart/rack-logo.png +0 -0
- data/test/registering_handler/rack/handler/registering_myself.rb +1 -1
- data/test/spec_auth_basic.rb +20 -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 +36 -34
- 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 +66 -40
- data/test/spec_directory.rb +72 -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 +96 -77
- data/test/spec_handler.rb +19 -34
- data/test/spec_head.rb +15 -14
- data/test/spec_lint.rb +162 -197
- data/test/spec_lobster.rb +24 -23
- data/test/spec_lock.rb +69 -39
- data/test/spec_logger.rb +4 -3
- data/test/spec_media_type.rb +42 -0
- data/test/spec_method_override.rb +83 -0
- data/test/spec_mime.rb +19 -19
- data/test/spec_mock.rb +196 -151
- data/test/spec_multipart.rb +310 -202
- data/test/{spec_nulllogger.rb → spec_null_logger.rb} +5 -4
- data/test/spec_recursive.rb +17 -14
- data/test/spec_request.rb +763 -607
- data/test/spec_response.rb +209 -156
- 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_cookie.rb +97 -65
- data/test/spec_session_memcache.rb +63 -101
- data/test/spec_session_pool.rb +48 -84
- data/test/spec_show_exceptions.rb +80 -0
- 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 +417 -345
- data/test/spec_version.rb +2 -8
- data/test/spec_webrick.rb +77 -67
- 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 +116 -71
- 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_methodoverride.rb +0 -111
- data/test/spec_mongrel.rb +0 -182
- data/test/spec_session_persisted_secure_secure_session_hash.rb +0 -73
- data/test/spec_showexceptions.rb +0 -98
data/test/spec_chunked.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
require 'minitest/autorun'
|
1
2
|
require 'rack/chunked'
|
2
3
|
require 'rack/lint'
|
3
4
|
require 'rack/mock'
|
@@ -18,59 +19,60 @@ describe Rack::Chunked do
|
|
18
19
|
env_for('/', 'HTTP_VERSION' => '1.1', 'REQUEST_METHOD' => 'GET')
|
19
20
|
end
|
20
21
|
|
21
|
-
|
22
|
+
it 'chunk responses with no Content-Length' do
|
22
23
|
app = lambda { |env| [200, {"Content-Type" => "text/plain"}, ['Hello', ' ', 'World!']] }
|
23
24
|
response = Rack::MockResponse.new(*chunked(app).call(@env))
|
24
|
-
response.headers.
|
25
|
-
response.headers['Transfer-Encoding'].
|
26
|
-
response.body.
|
25
|
+
response.headers.wont_include 'Content-Length'
|
26
|
+
response.headers['Transfer-Encoding'].must_equal 'chunked'
|
27
|
+
response.body.must_equal "5\r\nHello\r\n1\r\n \r\n6\r\nWorld!\r\n0\r\n\r\n"
|
27
28
|
end
|
28
29
|
|
29
|
-
|
30
|
+
it 'chunks empty bodies properly' do
|
30
31
|
app = lambda { |env| [200, {"Content-Type" => "text/plain"}, []] }
|
31
32
|
response = Rack::MockResponse.new(*chunked(app).call(@env))
|
32
|
-
response.headers.
|
33
|
-
response.headers['Transfer-Encoding'].
|
34
|
-
response.body.
|
33
|
+
response.headers.wont_include 'Content-Length'
|
34
|
+
response.headers['Transfer-Encoding'].must_equal 'chunked'
|
35
|
+
response.body.must_equal "0\r\n\r\n"
|
35
36
|
end
|
36
37
|
|
37
|
-
|
38
|
+
it 'chunks encoded bodies properly' do
|
38
39
|
body = ["\uFFFEHello", " ", "World"].map {|t| t.encode("UTF-16LE") }
|
39
40
|
app = lambda { |env| [200, {"Content-Type" => "text/plain"}, body] }
|
40
41
|
response = Rack::MockResponse.new(*chunked(app).call(@env))
|
41
|
-
response.headers.
|
42
|
-
response.headers['Transfer-Encoding'].
|
43
|
-
response.body.encoding.to_s.
|
44
|
-
response.body.
|
45
|
-
|
42
|
+
response.headers.wont_include 'Content-Length'
|
43
|
+
response.headers['Transfer-Encoding'].must_equal 'chunked'
|
44
|
+
response.body.encoding.to_s.must_equal "ASCII-8BIT"
|
45
|
+
response.body.must_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".force_encoding("BINARY")
|
46
|
+
response.body.must_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".force_encoding(Encoding::BINARY)
|
47
|
+
end
|
46
48
|
|
47
|
-
|
49
|
+
it 'not modify response when Content-Length header present' do
|
48
50
|
app = lambda { |env|
|
49
51
|
[200, {"Content-Type" => "text/plain", 'Content-Length'=>'12'}, ['Hello', ' ', 'World!']]
|
50
52
|
}
|
51
53
|
status, headers, body = chunked(app).call(@env)
|
52
|
-
status.
|
53
|
-
headers.
|
54
|
-
headers.
|
55
|
-
body.join.
|
54
|
+
status.must_equal 200
|
55
|
+
headers.wont_include 'Transfer-Encoding'
|
56
|
+
headers.must_include 'Content-Length'
|
57
|
+
body.join.must_equal 'Hello World!'
|
56
58
|
end
|
57
59
|
|
58
|
-
|
60
|
+
it 'not modify response when client is HTTP/1.0' do
|
59
61
|
app = lambda { |env| [200, {"Content-Type" => "text/plain"}, ['Hello', ' ', 'World!']] }
|
60
62
|
@env['HTTP_VERSION'] = 'HTTP/1.0'
|
61
63
|
status, headers, body = chunked(app).call(@env)
|
62
|
-
status.
|
63
|
-
headers.
|
64
|
-
body.join.
|
64
|
+
status.must_equal 200
|
65
|
+
headers.wont_include 'Transfer-Encoding'
|
66
|
+
body.join.must_equal 'Hello World!'
|
65
67
|
end
|
66
68
|
|
67
|
-
|
69
|
+
it 'not modify response when client is ancient, pre-HTTP/1.0' do
|
68
70
|
app = lambda { |env| [200, {"Content-Type" => "text/plain"}, ['Hello', ' ', 'World!']] }
|
69
71
|
check = lambda do
|
70
72
|
status, headers, body = chunked(app).call(@env.dup)
|
71
|
-
status.
|
72
|
-
headers.
|
73
|
-
body.join.
|
73
|
+
status.must_equal 200
|
74
|
+
headers.wont_include 'Transfer-Encoding'
|
75
|
+
body.join.must_equal 'Hello World!'
|
74
76
|
end
|
75
77
|
|
76
78
|
@env.delete('HTTP_VERSION') # unicorn will do this on pre-HTTP/1.0 requests
|
@@ -80,22 +82,22 @@ describe Rack::Chunked do
|
|
80
82
|
check.call
|
81
83
|
end
|
82
84
|
|
83
|
-
|
85
|
+
it 'not modify response when Transfer-Encoding header already present' do
|
84
86
|
app = lambda { |env|
|
85
87
|
[200, {"Content-Type" => "text/plain", 'Transfer-Encoding' => 'identity'}, ['Hello', ' ', 'World!']]
|
86
88
|
}
|
87
89
|
status, headers, body = chunked(app).call(@env)
|
88
|
-
status.
|
89
|
-
headers['Transfer-Encoding'].
|
90
|
-
body.join.
|
90
|
+
status.must_equal 200
|
91
|
+
headers['Transfer-Encoding'].must_equal 'identity'
|
92
|
+
body.join.must_equal 'Hello World!'
|
91
93
|
end
|
92
94
|
|
93
95
|
[100, 204, 205, 304].each do |status_code|
|
94
|
-
|
96
|
+
it "not modify response when status code is #{status_code}" do
|
95
97
|
app = lambda { |env| [status_code, {}, []] }
|
96
98
|
status, headers, _ = chunked(app).call(@env)
|
97
|
-
status.
|
98
|
-
headers.
|
99
|
+
status.must_equal status_code
|
100
|
+
headers.wont_include 'Transfer-Encoding'
|
99
101
|
end
|
100
102
|
end
|
101
103
|
end
|
@@ -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_equal 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_equal 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_equal 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_equal 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
|