rack 2.0.6 → 2.2.3
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/CHANGELOG.md +694 -0
- data/CONTRIBUTING.md +136 -0
- data/{COPYING → MIT-LICENSE} +4 -2
- data/README.rdoc +152 -148
- data/Rakefile +37 -23
- data/{SPEC → SPEC.rdoc} +38 -10
- data/bin/rackup +1 -0
- data/example/lobster.ru +2 -0
- data/example/protectedlobster.rb +3 -1
- data/example/protectedlobster.ru +2 -0
- data/lib/rack.rb +67 -73
- data/lib/rack/auth/abstract/handler.rb +3 -1
- data/lib/rack/auth/abstract/request.rb +1 -1
- data/lib/rack/auth/basic.rb +7 -4
- data/lib/rack/auth/digest/md5.rb +13 -11
- data/lib/rack/auth/digest/nonce.rb +6 -3
- data/lib/rack/auth/digest/params.rb +4 -2
- data/lib/rack/auth/digest/request.rb +5 -3
- data/lib/rack/body_proxy.rb +15 -14
- data/lib/rack/builder.rb +116 -23
- data/lib/rack/cascade.rb +28 -12
- data/lib/rack/chunked.rb +68 -20
- data/lib/rack/common_logger.rb +33 -25
- data/lib/rack/conditional_get.rb +20 -16
- data/lib/rack/config.rb +2 -0
- data/lib/rack/content_length.rb +8 -7
- data/lib/rack/content_type.rb +5 -4
- data/lib/rack/core_ext/regexp.rb +14 -0
- data/lib/rack/deflater.rb +59 -34
- data/lib/rack/directory.rb +84 -64
- data/lib/rack/etag.rb +5 -4
- data/lib/rack/events.rb +19 -20
- data/lib/rack/file.rb +4 -173
- data/lib/rack/files.rb +218 -0
- data/lib/rack/handler.rb +7 -2
- data/lib/rack/handler/cgi.rb +2 -3
- data/lib/rack/handler/fastcgi.rb +4 -4
- data/lib/rack/handler/lsws.rb +3 -3
- data/lib/rack/handler/scgi.rb +9 -8
- data/lib/rack/handler/thin.rb +3 -3
- data/lib/rack/handler/webrick.rb +15 -6
- data/lib/rack/head.rb +1 -1
- data/lib/rack/lint.rb +71 -25
- data/lib/rack/lobster.rb +10 -10
- data/lib/rack/lock.rb +2 -1
- data/lib/rack/logger.rb +2 -0
- data/lib/rack/media_type.rb +10 -5
- data/lib/rack/method_override.rb +4 -2
- data/lib/rack/mime.rb +9 -1
- data/lib/rack/mock.rb +97 -20
- data/lib/rack/multipart.rb +6 -4
- data/lib/rack/multipart/generator.rb +17 -13
- data/lib/rack/multipart/parser.rb +57 -62
- data/lib/rack/multipart/uploaded_file.rb +15 -7
- data/lib/rack/null_logger.rb +2 -0
- data/lib/rack/query_parser.rb +53 -28
- data/lib/rack/recursive.rb +7 -5
- data/lib/rack/reloader.rb +8 -4
- data/lib/rack/request.rb +220 -61
- data/lib/rack/response.rb +127 -44
- data/lib/rack/rewindable_input.rb +4 -3
- data/lib/rack/runtime.rb +6 -4
- data/lib/rack/sendfile.rb +13 -9
- data/lib/rack/server.rb +95 -24
- data/lib/rack/session/abstract/id.rb +100 -22
- data/lib/rack/session/cookie.rb +22 -14
- data/lib/rack/session/memcache.rb +4 -87
- data/lib/rack/session/pool.rb +18 -9
- data/lib/rack/show_exceptions.rb +21 -17
- data/lib/rack/show_status.rb +9 -9
- data/lib/rack/static.rb +23 -11
- data/lib/rack/tempfile_reaper.rb +1 -1
- data/lib/rack/urlmap.rb +12 -6
- data/lib/rack/utils.rb +102 -109
- data/lib/rack/version.rb +29 -0
- data/rack.gemspec +40 -28
- metadata +39 -181
- data/HISTORY.md +0 -505
- data/test/builder/an_underscore_app.rb +0 -5
- data/test/builder/anything.rb +0 -5
- data/test/builder/comment.ru +0 -4
- data/test/builder/end.ru +0 -5
- data/test/builder/line.ru +0 -1
- data/test/builder/options.ru +0 -2
- data/test/cgi/assets/folder/test.js +0 -1
- data/test/cgi/assets/fonts/font.eot +0 -1
- data/test/cgi/assets/images/image.png +0 -1
- data/test/cgi/assets/index.html +0 -1
- data/test/cgi/assets/javascripts/app.js +0 -1
- data/test/cgi/assets/stylesheets/app.css +0 -1
- data/test/cgi/lighttpd.conf +0 -26
- data/test/cgi/rackup_stub.rb +0 -6
- data/test/cgi/sample_rackup.ru +0 -5
- data/test/cgi/test +0 -9
- data/test/cgi/test+directory/test+file +0 -1
- data/test/cgi/test.fcgi +0 -9
- data/test/cgi/test.gz +0 -0
- data/test/cgi/test.ru +0 -5
- data/test/gemloader.rb +0 -10
- data/test/helper.rb +0 -34
- data/test/multipart/bad_robots +0 -259
- data/test/multipart/binary +0 -0
- data/test/multipart/content_type_and_no_filename +0 -6
- data/test/multipart/empty +0 -10
- data/test/multipart/fail_16384_nofile +0 -814
- data/test/multipart/file1.txt +0 -1
- data/test/multipart/filename_and_modification_param +0 -7
- data/test/multipart/filename_and_no_name +0 -6
- data/test/multipart/filename_with_encoded_words +0 -7
- data/test/multipart/filename_with_escaped_quotes +0 -6
- data/test/multipart/filename_with_escaped_quotes_and_modification_param +0 -7
- data/test/multipart/filename_with_null_byte +0 -7
- data/test/multipart/filename_with_percent_escaped_quotes +0 -6
- data/test/multipart/filename_with_single_quote +0 -7
- data/test/multipart/filename_with_unescaped_percentages +0 -6
- data/test/multipart/filename_with_unescaped_percentages2 +0 -6
- data/test/multipart/filename_with_unescaped_percentages3 +0 -6
- data/test/multipart/filename_with_unescaped_quotes +0 -6
- data/test/multipart/ie +0 -6
- data/test/multipart/invalid_character +0 -6
- data/test/multipart/mixed_files +0 -21
- data/test/multipart/nested +0 -10
- data/test/multipart/none +0 -9
- data/test/multipart/quoted +0 -15
- data/test/multipart/rack-logo.png +0 -0
- data/test/multipart/semicolon +0 -6
- data/test/multipart/text +0 -15
- data/test/multipart/three_files_three_fields +0 -31
- data/test/multipart/unity3d_wwwform +0 -11
- data/test/multipart/webkit +0 -32
- data/test/rackup/config.ru +0 -31
- data/test/registering_handler/rack/handler/registering_myself.rb +0 -8
- data/test/spec_auth_basic.rb +0 -89
- data/test/spec_auth_digest.rb +0 -260
- data/test/spec_body_proxy.rb +0 -85
- data/test/spec_builder.rb +0 -233
- data/test/spec_cascade.rb +0 -63
- data/test/spec_cgi.rb +0 -84
- data/test/spec_chunked.rb +0 -103
- data/test/spec_common_logger.rb +0 -95
- data/test/spec_conditional_get.rb +0 -103
- data/test/spec_config.rb +0 -23
- data/test/spec_content_length.rb +0 -86
- data/test/spec_content_type.rb +0 -46
- data/test/spec_deflater.rb +0 -375
- data/test/spec_directory.rb +0 -148
- data/test/spec_etag.rb +0 -108
- data/test/spec_events.rb +0 -133
- data/test/spec_fastcgi.rb +0 -85
- data/test/spec_file.rb +0 -264
- data/test/spec_handler.rb +0 -57
- data/test/spec_head.rb +0 -46
- data/test/spec_lint.rb +0 -515
- data/test/spec_lobster.rb +0 -59
- data/test/spec_lock.rb +0 -204
- data/test/spec_logger.rb +0 -24
- data/test/spec_media_type.rb +0 -42
- data/test/spec_method_override.rb +0 -110
- data/test/spec_mime.rb +0 -51
- data/test/spec_mock.rb +0 -359
- data/test/spec_multipart.rb +0 -722
- data/test/spec_null_logger.rb +0 -21
- data/test/spec_recursive.rb +0 -75
- data/test/spec_request.rb +0 -1398
- data/test/spec_response.rb +0 -510
- data/test/spec_rewindable_input.rb +0 -128
- data/test/spec_runtime.rb +0 -50
- data/test/spec_sendfile.rb +0 -125
- data/test/spec_server.rb +0 -193
- data/test/spec_session_abstract_id.rb +0 -31
- data/test/spec_session_abstract_session_hash.rb +0 -45
- data/test/spec_session_cookie.rb +0 -442
- data/test/spec_session_memcache.rb +0 -320
- data/test/spec_session_pool.rb +0 -210
- data/test/spec_show_exceptions.rb +0 -93
- data/test/spec_show_status.rb +0 -104
- data/test/spec_static.rb +0 -184
- data/test/spec_tempfile_reaper.rb +0 -64
- data/test/spec_thin.rb +0 -96
- data/test/spec_urlmap.rb +0 -237
- data/test/spec_utils.rb +0 -742
- data/test/spec_version.rb +0 -11
- data/test/spec_webrick.rb +0 -206
- data/test/static/another/index.html +0 -1
- data/test/static/foo.html +0 -1
- data/test/static/index.html +0 -1
- data/test/testrequest.rb +0 -78
- data/test/unregistered_handler/rack/handler/unregistered.rb +0 -7
- data/test/unregistered_handler/rack/handler/unregistered_long_one.rb +0 -7
data/test/spec_chunked.rb
DELETED
@@ -1,103 +0,0 @@
|
|
1
|
-
require 'minitest/autorun'
|
2
|
-
require 'rack/chunked'
|
3
|
-
require 'rack/lint'
|
4
|
-
require 'rack/mock'
|
5
|
-
|
6
|
-
describe Rack::Chunked do
|
7
|
-
def chunked(app)
|
8
|
-
proc do |env|
|
9
|
-
app = Rack::Chunked.new(app)
|
10
|
-
response = Rack::Lint.new(app).call(env)
|
11
|
-
# we want to use body like an array, but it only has #each
|
12
|
-
response[2] = response[2].to_enum.to_a
|
13
|
-
response
|
14
|
-
end
|
15
|
-
end
|
16
|
-
|
17
|
-
before do
|
18
|
-
@env = Rack::MockRequest.
|
19
|
-
env_for('/', 'HTTP_VERSION' => '1.1', 'REQUEST_METHOD' => 'GET')
|
20
|
-
end
|
21
|
-
|
22
|
-
it 'chunk responses with no Content-Length' do
|
23
|
-
app = lambda { |env| [200, {"Content-Type" => "text/plain"}, ['Hello', ' ', 'World!']] }
|
24
|
-
response = Rack::MockResponse.new(*chunked(app).call(@env))
|
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"
|
28
|
-
end
|
29
|
-
|
30
|
-
it 'chunks empty bodies properly' do
|
31
|
-
app = lambda { |env| [200, {"Content-Type" => "text/plain"}, []] }
|
32
|
-
response = Rack::MockResponse.new(*chunked(app).call(@env))
|
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"
|
36
|
-
end
|
37
|
-
|
38
|
-
it 'chunks encoded bodies properly' do
|
39
|
-
body = ["\uFFFEHello", " ", "World"].map {|t| t.encode("UTF-16LE") }
|
40
|
-
app = lambda { |env| [200, {"Content-Type" => "text/plain"}, body] }
|
41
|
-
response = Rack::MockResponse.new(*chunked(app).call(@env))
|
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
|
48
|
-
|
49
|
-
it 'not modify response when Content-Length header present' do
|
50
|
-
app = lambda { |env|
|
51
|
-
[200, {"Content-Type" => "text/plain", 'Content-Length'=>'12'}, ['Hello', ' ', 'World!']]
|
52
|
-
}
|
53
|
-
status, headers, body = chunked(app).call(@env)
|
54
|
-
status.must_equal 200
|
55
|
-
headers.wont_include 'Transfer-Encoding'
|
56
|
-
headers.must_include 'Content-Length'
|
57
|
-
body.join.must_equal 'Hello World!'
|
58
|
-
end
|
59
|
-
|
60
|
-
it 'not modify response when client is HTTP/1.0' do
|
61
|
-
app = lambda { |env| [200, {"Content-Type" => "text/plain"}, ['Hello', ' ', 'World!']] }
|
62
|
-
@env['HTTP_VERSION'] = 'HTTP/1.0'
|
63
|
-
status, headers, body = chunked(app).call(@env)
|
64
|
-
status.must_equal 200
|
65
|
-
headers.wont_include 'Transfer-Encoding'
|
66
|
-
body.join.must_equal 'Hello World!'
|
67
|
-
end
|
68
|
-
|
69
|
-
it 'not modify response when client is ancient, pre-HTTP/1.0' do
|
70
|
-
app = lambda { |env| [200, {"Content-Type" => "text/plain"}, ['Hello', ' ', 'World!']] }
|
71
|
-
check = lambda do
|
72
|
-
status, headers, body = chunked(app).call(@env.dup)
|
73
|
-
status.must_equal 200
|
74
|
-
headers.wont_include 'Transfer-Encoding'
|
75
|
-
body.join.must_equal 'Hello World!'
|
76
|
-
end
|
77
|
-
|
78
|
-
@env.delete('HTTP_VERSION') # unicorn will do this on pre-HTTP/1.0 requests
|
79
|
-
check.call
|
80
|
-
|
81
|
-
@env['HTTP_VERSION'] = 'HTTP/0.9' # not sure if this happens in practice
|
82
|
-
check.call
|
83
|
-
end
|
84
|
-
|
85
|
-
it 'not modify response when Transfer-Encoding header already present' do
|
86
|
-
app = lambda { |env|
|
87
|
-
[200, {"Content-Type" => "text/plain", 'Transfer-Encoding' => 'identity'}, ['Hello', ' ', 'World!']]
|
88
|
-
}
|
89
|
-
status, headers, body = chunked(app).call(@env)
|
90
|
-
status.must_equal 200
|
91
|
-
headers['Transfer-Encoding'].must_equal 'identity'
|
92
|
-
body.join.must_equal 'Hello World!'
|
93
|
-
end
|
94
|
-
|
95
|
-
[100, 204, 304].each do |status_code|
|
96
|
-
it "not modify response when status code is #{status_code}" do
|
97
|
-
app = lambda { |env| [status_code, {}, []] }
|
98
|
-
status, headers, _ = chunked(app).call(@env)
|
99
|
-
status.must_equal status_code
|
100
|
-
headers.wont_include 'Transfer-Encoding'
|
101
|
-
end
|
102
|
-
end
|
103
|
-
end
|
data/test/spec_common_logger.rb
DELETED
@@ -1,95 +0,0 @@
|
|
1
|
-
require 'minitest/autorun'
|
2
|
-
require 'rack/common_logger'
|
3
|
-
require 'rack/lint'
|
4
|
-
require 'rack/mock'
|
5
|
-
|
6
|
-
require 'logger'
|
7
|
-
|
8
|
-
describe Rack::CommonLogger do
|
9
|
-
obj = 'foobar'
|
10
|
-
length = obj.size
|
11
|
-
|
12
|
-
app = Rack::Lint.new lambda { |env|
|
13
|
-
[200,
|
14
|
-
{"Content-Type" => "text/html", "Content-Length" => length.to_s},
|
15
|
-
[obj]]}
|
16
|
-
app_without_length = Rack::Lint.new lambda { |env|
|
17
|
-
[200,
|
18
|
-
{"Content-Type" => "text/html"},
|
19
|
-
[]]}
|
20
|
-
app_with_zero_length = Rack::Lint.new lambda { |env|
|
21
|
-
[200,
|
22
|
-
{"Content-Type" => "text/html", "Content-Length" => "0"},
|
23
|
-
[]]}
|
24
|
-
|
25
|
-
it "log to rack.errors by default" do
|
26
|
-
res = Rack::MockRequest.new(Rack::CommonLogger.new(app)).get("/")
|
27
|
-
|
28
|
-
res.errors.wont_be :empty?
|
29
|
-
res.errors.must_match(/"GET \/ " 200 #{length} /)
|
30
|
-
end
|
31
|
-
|
32
|
-
it "log to anything with +write+" do
|
33
|
-
log = StringIO.new
|
34
|
-
Rack::MockRequest.new(Rack::CommonLogger.new(app, log)).get("/")
|
35
|
-
|
36
|
-
log.string.must_match(/"GET \/ " 200 #{length} /)
|
37
|
-
end
|
38
|
-
|
39
|
-
it "work with standartd library logger" do
|
40
|
-
logdev = StringIO.new
|
41
|
-
log = Logger.new(logdev)
|
42
|
-
Rack::MockRequest.new(Rack::CommonLogger.new(app, log)).get("/")
|
43
|
-
|
44
|
-
logdev.string.must_match(/"GET \/ " 200 #{length} /)
|
45
|
-
end
|
46
|
-
|
47
|
-
it "log - content length if header is missing" do
|
48
|
-
res = Rack::MockRequest.new(Rack::CommonLogger.new(app_without_length)).get("/")
|
49
|
-
|
50
|
-
res.errors.wont_be :empty?
|
51
|
-
res.errors.must_match(/"GET \/ " 200 - /)
|
52
|
-
end
|
53
|
-
|
54
|
-
it "log - content length if header is zero" do
|
55
|
-
res = Rack::MockRequest.new(Rack::CommonLogger.new(app_with_zero_length)).get("/")
|
56
|
-
|
57
|
-
res.errors.wont_be :empty?
|
58
|
-
res.errors.must_match(/"GET \/ " 200 - /)
|
59
|
-
end
|
60
|
-
|
61
|
-
def with_mock_time(t = 0)
|
62
|
-
mc = class << Time; self; end
|
63
|
-
mc.send :alias_method, :old_now, :now
|
64
|
-
mc.send :define_method, :now do
|
65
|
-
at(t)
|
66
|
-
end
|
67
|
-
yield
|
68
|
-
ensure
|
69
|
-
mc.send :undef_method, :now
|
70
|
-
mc.send :alias_method, :now, :old_now
|
71
|
-
end
|
72
|
-
|
73
|
-
it "log in common log format" do
|
74
|
-
log = StringIO.new
|
75
|
-
with_mock_time do
|
76
|
-
Rack::MockRequest.new(Rack::CommonLogger.new(app, log)).get("/")
|
77
|
-
end
|
78
|
-
|
79
|
-
md = /- - - \[([^\]]+)\] "(\w+) \/ " (\d{3}) \d+ ([\d\.]+)/.match(log.string)
|
80
|
-
md.wont_equal nil
|
81
|
-
time, method, status, duration = *md.captures
|
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
|
86
|
-
end
|
87
|
-
|
88
|
-
def length
|
89
|
-
123
|
90
|
-
end
|
91
|
-
|
92
|
-
def self.obj
|
93
|
-
"hello world"
|
94
|
-
end
|
95
|
-
end
|
@@ -1,103 +0,0 @@
|
|
1
|
-
require 'minitest/autorun'
|
2
|
-
require 'time'
|
3
|
-
require 'rack/conditional_get'
|
4
|
-
require 'rack/mock'
|
5
|
-
|
6
|
-
describe Rack::ConditionalGet do
|
7
|
-
def conditional_get(app)
|
8
|
-
Rack::Lint.new Rack::ConditionalGet.new(app)
|
9
|
-
end
|
10
|
-
|
11
|
-
it "set a 304 status and truncate body when If-Modified-Since hits" do
|
12
|
-
timestamp = Time.now.httpdate
|
13
|
-
app = conditional_get(lambda { |env|
|
14
|
-
[200, {'Last-Modified'=>timestamp}, ['TEST']] })
|
15
|
-
|
16
|
-
response = Rack::MockRequest.new(app).
|
17
|
-
get("/", 'HTTP_IF_MODIFIED_SINCE' => timestamp)
|
18
|
-
|
19
|
-
response.status.must_equal 304
|
20
|
-
response.body.must_be :empty?
|
21
|
-
end
|
22
|
-
|
23
|
-
it "set a 304 status and truncate body when If-Modified-Since hits and is higher than current time" do
|
24
|
-
app = conditional_get(lambda { |env|
|
25
|
-
[200, {'Last-Modified'=>(Time.now - 3600).httpdate}, ['TEST']] })
|
26
|
-
|
27
|
-
response = Rack::MockRequest.new(app).
|
28
|
-
get("/", 'HTTP_IF_MODIFIED_SINCE' => Time.now.httpdate)
|
29
|
-
|
30
|
-
response.status.must_equal 304
|
31
|
-
response.body.must_be :empty?
|
32
|
-
end
|
33
|
-
|
34
|
-
it "set a 304 status and truncate body when If-None-Match hits" do
|
35
|
-
app = conditional_get(lambda { |env|
|
36
|
-
[200, {'ETag'=>'1234'}, ['TEST']] })
|
37
|
-
|
38
|
-
response = Rack::MockRequest.new(app).
|
39
|
-
get("/", 'HTTP_IF_NONE_MATCH' => '1234')
|
40
|
-
|
41
|
-
response.status.must_equal 304
|
42
|
-
response.body.must_be :empty?
|
43
|
-
end
|
44
|
-
|
45
|
-
it "not set a 304 status if If-Modified-Since hits but Etag does not" do
|
46
|
-
timestamp = Time.now.httpdate
|
47
|
-
app = conditional_get(lambda { |env|
|
48
|
-
[200, {'Last-Modified'=>timestamp, 'Etag'=>'1234', 'Content-Type' => 'text/plain'}, ['TEST']] })
|
49
|
-
|
50
|
-
response = Rack::MockRequest.new(app).
|
51
|
-
get("/", 'HTTP_IF_MODIFIED_SINCE' => timestamp, 'HTTP_IF_NONE_MATCH' => '4321')
|
52
|
-
|
53
|
-
response.status.must_equal 200
|
54
|
-
response.body.must_equal 'TEST'
|
55
|
-
end
|
56
|
-
|
57
|
-
it "set a 304 status and truncate body when both If-None-Match and If-Modified-Since hits" do
|
58
|
-
timestamp = Time.now.httpdate
|
59
|
-
app = conditional_get(lambda { |env|
|
60
|
-
[200, {'Last-Modified'=>timestamp, 'ETag'=>'1234'}, ['TEST']] })
|
61
|
-
|
62
|
-
response = Rack::MockRequest.new(app).
|
63
|
-
get("/", 'HTTP_IF_MODIFIED_SINCE' => timestamp, 'HTTP_IF_NONE_MATCH' => '1234')
|
64
|
-
|
65
|
-
response.status.must_equal 304
|
66
|
-
response.body.must_be :empty?
|
67
|
-
end
|
68
|
-
|
69
|
-
it "not affect non-GET/HEAD requests" do
|
70
|
-
app = conditional_get(lambda { |env|
|
71
|
-
[200, {'Etag'=>'1234', 'Content-Type' => 'text/plain'}, ['TEST']] })
|
72
|
-
|
73
|
-
response = Rack::MockRequest.new(app).
|
74
|
-
post("/", 'HTTP_IF_NONE_MATCH' => '1234')
|
75
|
-
|
76
|
-
response.status.must_equal 200
|
77
|
-
response.body.must_equal 'TEST'
|
78
|
-
end
|
79
|
-
|
80
|
-
it "not affect non-200 requests" do
|
81
|
-
app = conditional_get(lambda { |env|
|
82
|
-
[302, {'Etag'=>'1234', 'Content-Type' => 'text/plain'}, ['TEST']] })
|
83
|
-
|
84
|
-
response = Rack::MockRequest.new(app).
|
85
|
-
get("/", 'HTTP_IF_NONE_MATCH' => '1234')
|
86
|
-
|
87
|
-
response.status.must_equal 302
|
88
|
-
response.body.must_equal 'TEST'
|
89
|
-
end
|
90
|
-
|
91
|
-
it "not affect requests with malformed HTTP_IF_NONE_MATCH" do
|
92
|
-
bad_timestamp = Time.now.strftime('%Y-%m-%d %H:%M:%S %z')
|
93
|
-
app = conditional_get(lambda { |env|
|
94
|
-
[200,{'Last-Modified'=>(Time.now - 3600).httpdate, 'Content-Type' => 'text/plain'}, ['TEST']] })
|
95
|
-
|
96
|
-
response = Rack::MockRequest.new(app).
|
97
|
-
get("/", 'HTTP_IF_MODIFIED_SINCE' => bad_timestamp)
|
98
|
-
|
99
|
-
response.status.must_equal 200
|
100
|
-
response.body.must_equal 'TEST'
|
101
|
-
end
|
102
|
-
|
103
|
-
end
|
data/test/spec_config.rb
DELETED
@@ -1,23 +0,0 @@
|
|
1
|
-
require 'minitest/autorun'
|
2
|
-
require 'rack/builder'
|
3
|
-
require 'rack/config'
|
4
|
-
require 'rack/content_length'
|
5
|
-
require 'rack/lint'
|
6
|
-
require 'rack/mock'
|
7
|
-
|
8
|
-
describe Rack::Config do
|
9
|
-
it "accept a block that modifies the environment" do
|
10
|
-
app = Rack::Builder.new do
|
11
|
-
use Rack::Lint
|
12
|
-
use Rack::Config do |env|
|
13
|
-
env['greeting'] = 'hello'
|
14
|
-
end
|
15
|
-
run lambda { |env|
|
16
|
-
[200, {'Content-Type' => 'text/plain'}, [env['greeting'] || '']]
|
17
|
-
}
|
18
|
-
end
|
19
|
-
|
20
|
-
response = Rack::MockRequest.new(app).get('/')
|
21
|
-
response.body.must_equal 'hello'
|
22
|
-
end
|
23
|
-
end
|
data/test/spec_content_length.rb
DELETED
@@ -1,86 +0,0 @@
|
|
1
|
-
require 'minitest/autorun'
|
2
|
-
require 'rack/content_length'
|
3
|
-
require 'rack/lint'
|
4
|
-
require 'rack/mock'
|
5
|
-
|
6
|
-
describe Rack::ContentLength do
|
7
|
-
def content_length(app)
|
8
|
-
Rack::Lint.new Rack::ContentLength.new(app)
|
9
|
-
end
|
10
|
-
|
11
|
-
def request
|
12
|
-
Rack::MockRequest.env_for
|
13
|
-
end
|
14
|
-
|
15
|
-
it "set Content-Length on Array bodies if none is set" do
|
16
|
-
app = lambda { |env| [200, {'Content-Type' => 'text/plain'}, ["Hello, World!"]] }
|
17
|
-
response = content_length(app).call(request)
|
18
|
-
response[1]['Content-Length'].must_equal '13'
|
19
|
-
end
|
20
|
-
|
21
|
-
it "not set Content-Length on variable length bodies" do
|
22
|
-
body = lambda { "Hello World!" }
|
23
|
-
def body.each ; yield call ; end
|
24
|
-
|
25
|
-
app = lambda { |env| [200, {'Content-Type' => 'text/plain'}, body] }
|
26
|
-
response = content_length(app).call(request)
|
27
|
-
response[1]['Content-Length'].must_be_nil
|
28
|
-
end
|
29
|
-
|
30
|
-
it "not change Content-Length if it is already set" do
|
31
|
-
app = lambda { |env| [200, {'Content-Type' => 'text/plain', 'Content-Length' => '1'}, "Hello, World!"] }
|
32
|
-
response = content_length(app).call(request)
|
33
|
-
response[1]['Content-Length'].must_equal '1'
|
34
|
-
end
|
35
|
-
|
36
|
-
it "not set Content-Length on 304 responses" do
|
37
|
-
app = lambda { |env| [304, {}, []] }
|
38
|
-
response = content_length(app).call(request)
|
39
|
-
response[1]['Content-Length'].must_be_nil
|
40
|
-
end
|
41
|
-
|
42
|
-
it "not set Content-Length when Transfer-Encoding is chunked" do
|
43
|
-
app = lambda { |env| [200, {'Content-Type' => 'text/plain', 'Transfer-Encoding' => 'chunked'}, []] }
|
44
|
-
response = content_length(app).call(request)
|
45
|
-
response[1]['Content-Length'].must_be_nil
|
46
|
-
end
|
47
|
-
|
48
|
-
# Using "Connection: close" for this is fairly contended. It might be useful
|
49
|
-
# to have some other way to signal this.
|
50
|
-
#
|
51
|
-
# should "not force a Content-Length when Connection:close" do
|
52
|
-
# app = lambda { |env| [200, {'Connection' => 'close'}, []] }
|
53
|
-
# response = content_length(app).call({})
|
54
|
-
# response[1]['Content-Length'].must_be_nil
|
55
|
-
# end
|
56
|
-
|
57
|
-
it "close bodies that need to be closed" do
|
58
|
-
body = Struct.new(:body) do
|
59
|
-
attr_reader :closed
|
60
|
-
def each; body.join; end
|
61
|
-
def close; @closed = true; end
|
62
|
-
def to_ary; end
|
63
|
-
end.new(%w[one two three])
|
64
|
-
|
65
|
-
app = lambda { |env| [200, {'Content-Type' => 'text/plain'}, body] }
|
66
|
-
response = content_length(app).call(request)
|
67
|
-
body.closed.must_be_nil
|
68
|
-
response[2].close
|
69
|
-
body.closed.must_equal true
|
70
|
-
end
|
71
|
-
|
72
|
-
it "support single-execute bodies" do
|
73
|
-
body = Struct.new(:body) do
|
74
|
-
def each
|
75
|
-
yield body.shift until body.empty?
|
76
|
-
end
|
77
|
-
def to_ary; end
|
78
|
-
end.new(%w[one two three])
|
79
|
-
|
80
|
-
app = lambda { |env| [200, {'Content-Type' => 'text/plain'}, body] }
|
81
|
-
response = content_length(app).call(request)
|
82
|
-
expected = %w[one two three]
|
83
|
-
response[1]['Content-Length'].must_equal expected.join.size.to_s
|
84
|
-
response[2].to_enum.to_a.must_equal expected
|
85
|
-
end
|
86
|
-
end
|
data/test/spec_content_type.rb
DELETED
@@ -1,46 +0,0 @@
|
|
1
|
-
require 'minitest/autorun'
|
2
|
-
require 'rack/content_type'
|
3
|
-
require 'rack/lint'
|
4
|
-
require 'rack/mock'
|
5
|
-
|
6
|
-
describe Rack::ContentType do
|
7
|
-
def content_type(app, *args)
|
8
|
-
Rack::Lint.new Rack::ContentType.new(app, *args)
|
9
|
-
end
|
10
|
-
|
11
|
-
def request
|
12
|
-
Rack::MockRequest.env_for
|
13
|
-
end
|
14
|
-
|
15
|
-
it "set Content-Type to default text/html if none is set" do
|
16
|
-
app = lambda { |env| [200, {}, "Hello, World!"] }
|
17
|
-
headers = content_type(app).call(request)[1]
|
18
|
-
headers['Content-Type'].must_equal 'text/html'
|
19
|
-
end
|
20
|
-
|
21
|
-
it "set Content-Type to chosen default if none is set" do
|
22
|
-
app = lambda { |env| [200, {}, "Hello, World!"] }
|
23
|
-
headers =
|
24
|
-
content_type(app, 'application/octet-stream').call(request)[1]
|
25
|
-
headers['Content-Type'].must_equal 'application/octet-stream'
|
26
|
-
end
|
27
|
-
|
28
|
-
it "not change Content-Type if it is already set" do
|
29
|
-
app = lambda { |env| [200, {'Content-Type' => 'foo/bar'}, "Hello, World!"] }
|
30
|
-
headers = content_type(app).call(request)[1]
|
31
|
-
headers['Content-Type'].must_equal 'foo/bar'
|
32
|
-
end
|
33
|
-
|
34
|
-
it "detect Content-Type case insensitive" do
|
35
|
-
app = lambda { |env| [200, {'CONTENT-Type' => 'foo/bar'}, "Hello, World!"] }
|
36
|
-
headers = content_type(app).call(request)[1]
|
37
|
-
headers.to_a.select { |k,v| k.downcase == "content-type" }.
|
38
|
-
must_equal [["CONTENT-Type","foo/bar"]]
|
39
|
-
end
|
40
|
-
|
41
|
-
it "not set Content-Type on 304 responses" do
|
42
|
-
app = lambda { |env| [304, {}, []] }
|
43
|
-
response = content_type(app, "text/html").call(request)
|
44
|
-
response[1]['Content-Type'].must_be_nil
|
45
|
-
end
|
46
|
-
end
|