rack 1.1.0 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README +23 -26
- data/SPEC +3 -3
- data/lib/rack/auth/digest/params.rb +1 -1
- data/lib/rack/content_length.rb +1 -1
- data/lib/rack/etag.rb +15 -6
- data/lib/rack/file.rb +3 -1
- data/lib/rack/handler/cgi.rb +8 -7
- data/lib/rack/handler/fastcgi.rb +1 -1
- data/lib/rack/handler/lsws.rb +1 -1
- data/lib/rack/handler/mongrel.rb +1 -1
- data/lib/rack/handler/scgi.rb +1 -4
- data/lib/rack/handler/webrick.rb +10 -6
- data/lib/rack/lint.rb +29 -37
- data/lib/rack/mime.rb +2 -0
- data/lib/rack/mock.rb +2 -1
- data/lib/rack/recursive.rb +4 -0
- data/lib/rack/request.rb +8 -6
- data/lib/rack/response.rb +1 -0
- data/lib/rack/rewindable_input.rb +13 -10
- data/lib/rack/sendfile.rb +8 -6
- data/lib/rack/server.rb +66 -7
- data/lib/rack/session/memcache.rb +1 -1
- data/lib/rack/urlmap.rb +6 -7
- data/lib/rack/utils.rb +64 -22
- data/lib/rack.rb +1 -12
- data/rack.gemspec +6 -6
- data/spec/cgi/lighttpd.conf +25 -0
- data/spec/cgi/rackup_stub.rb +6 -0
- data/spec/cgi/sample_rackup.ru +5 -0
- data/spec/cgi/test +9 -0
- data/spec/cgi/test.fcgi +8 -0
- data/spec/cgi/test.ru +5 -0
- data/spec/multipart/bad_robots +259 -0
- data/spec/multipart/binary +0 -0
- data/spec/multipart/empty +10 -0
- data/spec/multipart/fail_16384_nofile +814 -0
- data/spec/multipart/file1.txt +1 -0
- data/spec/multipart/filename_and_modification_param +7 -0
- data/spec/multipart/filename_with_escaped_quotes +6 -0
- data/spec/multipart/filename_with_escaped_quotes_and_modification_param +7 -0
- data/spec/multipart/filename_with_percent_escaped_quotes +6 -0
- data/spec/multipart/filename_with_unescaped_quotes +6 -0
- data/spec/multipart/ie +6 -0
- data/spec/multipart/nested +10 -0
- data/spec/multipart/none +9 -0
- data/spec/multipart/semicolon +6 -0
- data/spec/multipart/text +10 -0
- data/spec/rackup/config.ru +31 -0
- data/{test/spec_rack_auth_basic.rb → spec/spec_auth_basic.rb} +11 -14
- data/{test/spec_rack_auth_digest.rb → spec/spec_auth_digest.rb} +18 -21
- data/{test/spec_rack_builder.rb → spec/spec_builder.rb} +49 -10
- data/{test/spec_rack_cascade.rb → spec/spec_cascade.rb} +7 -10
- data/{test/spec_rack_cgi.rb → spec/spec_cgi.rb} +34 -32
- data/{test/spec_rack_chunked.rb → spec/spec_chunked.rb} +8 -10
- data/{test/spec_rack_commonlogger.rb → spec/spec_commonlogger.rb} +10 -15
- data/{test/spec_rack_conditionalget.rb → spec/spec_conditionalget.rb} +5 -7
- data/{test/spec_rack_config.rb → spec/spec_config.rb} +6 -7
- data/{test/spec_rack_content_length.rb → spec/spec_content_length.rb} +7 -8
- data/{test/spec_rack_content_type.rb → spec/spec_content_type.rb} +5 -6
- data/{test/spec_rack_deflater.rb → spec/spec_deflater.rb} +11 -13
- data/{test/spec_rack_directory.rb → spec/spec_directory.rb} +6 -10
- data/{test/spec_rack_etag.rb → spec/spec_etag.rb} +3 -5
- data/{test/spec_rack_fastcgi.rb → spec/spec_fastcgi.rb} +36 -29
- data/{test/spec_rack_file.rb → spec/spec_file.rb} +9 -13
- data/{test/spec_rack_handler.rb → spec/spec_handler.rb} +10 -12
- data/{test/spec_rack_head.rb → spec/spec_head.rb} +3 -3
- data/{test/spec_rack_lint.rb → spec/spec_lint.rb} +19 -32
- data/{test/spec_rack_lobster.rb → spec/spec_lobster.rb} +9 -11
- data/{test/spec_rack_lock.rb → spec/spec_lock.rb} +15 -17
- data/{test/spec_rack_logger.rb → spec/spec_logger.rb} +6 -7
- data/{test/spec_rack_methodoverride.rb → spec/spec_methodoverride.rb} +15 -17
- data/{test/spec_rack_mock.rb → spec/spec_mock.rb} +30 -32
- data/{test/spec_rack_mongrel.rb → spec/spec_mongrel.rb} +40 -46
- data/{test/spec_rack_nulllogger.rb → spec/spec_nulllogger.rb} +4 -5
- data/{test/spec_rack_recursive.rb → spec/spec_recursive.rb} +28 -36
- data/{test/spec_rack_request.rb → spec/spec_request.rb} +84 -49
- data/{test/spec_rack_response.rb → spec/spec_response.rb} +48 -29
- data/spec/spec_rewindable_input.rb +118 -0
- data/{test/spec_rack_runtime.rb → spec/spec_runtime.rb} +15 -11
- data/{test/spec_rack_sendfile.rb → spec/spec_sendfile.rb} +11 -14
- data/{test/spec_rack_session_cookie.rb → spec/spec_session_cookie.rb} +15 -18
- data/{test/spec_rack_session_memcache.rb → spec/spec_session_memcache.rb} +32 -26
- data/{test/spec_rack_session_pool.rb → spec/spec_session_pool.rb} +36 -31
- data/spec/spec_showexceptions.rb +23 -0
- data/spec/spec_showstatus.rb +79 -0
- data/{test/spec_rack_static.rb → spec/spec_static.rb} +5 -9
- data/{test/spec_rack_thin.rb → spec/spec_thin.rb} +30 -35
- data/{test/spec_rack_urlmap.rb → spec/spec_urlmap.rb} +6 -8
- data/{test/spec_rack_utils.rb → spec/spec_utils.rb} +136 -71
- data/{test/spec_rack_webrick.rb → spec/spec_webrick.rb} +28 -36
- data/spec/testrequest.rb +77 -0
- data/spec/unregistered_handler/rack/handler/unregistered.rb +7 -0
- data/spec/unregistered_handler/rack/handler/unregistered_long_one.rb +7 -0
- metadata +206 -124
- data/RDOX +0 -0
- data/lib/rack/adapter/camping.rb +0 -22
- data/test/spec_rack_camping.rb +0 -51
- data/test/spec_rack_rewindable_input.rb +0 -118
- data/test/spec_rack_showexceptions.rb +0 -21
- data/test/spec_rack_showstatus.rb +0 -72
- data/test/spec_rackup.rb +0 -154
|
@@ -1,11 +1,10 @@
|
|
|
1
|
-
require 'test/spec'
|
|
2
|
-
require 'stringio'
|
|
3
|
-
|
|
4
1
|
require 'rack/commonlogger'
|
|
5
|
-
require 'rack/lobster'
|
|
6
2
|
require 'rack/mock'
|
|
7
3
|
|
|
8
|
-
|
|
4
|
+
describe Rack::CommonLogger do
|
|
5
|
+
obj = 'foobar'
|
|
6
|
+
length = obj.size
|
|
7
|
+
|
|
9
8
|
app = lambda { |env|
|
|
10
9
|
[200,
|
|
11
10
|
{"Content-Type" => "text/html", "Content-Length" => length.to_s},
|
|
@@ -19,42 +18,38 @@ context "Rack::CommonLogger" do
|
|
|
19
18
|
{"Content-Type" => "text/html", "Content-Length" => "0"},
|
|
20
19
|
[]]}
|
|
21
20
|
|
|
22
|
-
|
|
21
|
+
should "log to rack.errors by default" do
|
|
23
22
|
res = Rack::MockRequest.new(Rack::CommonLogger.new(app)).get("/")
|
|
24
23
|
|
|
25
24
|
res.errors.should.not.be.empty
|
|
26
25
|
res.errors.should =~ /"GET \/ " 200 #{length} /
|
|
27
26
|
end
|
|
28
27
|
|
|
29
|
-
|
|
28
|
+
should "log to anything with +write+" do
|
|
30
29
|
log = StringIO.new
|
|
31
30
|
res = Rack::MockRequest.new(Rack::CommonLogger.new(app, log)).get("/")
|
|
32
31
|
|
|
33
32
|
log.string.should =~ /"GET \/ " 200 #{length} /
|
|
34
33
|
end
|
|
35
34
|
|
|
36
|
-
|
|
35
|
+
should "log - content length if header is missing" do
|
|
37
36
|
res = Rack::MockRequest.new(Rack::CommonLogger.new(app_without_length)).get("/")
|
|
38
37
|
|
|
39
38
|
res.errors.should.not.be.empty
|
|
40
39
|
res.errors.should =~ /"GET \/ " 200 - /
|
|
41
40
|
end
|
|
42
41
|
|
|
43
|
-
|
|
42
|
+
should "log - content length if header is zero" do
|
|
44
43
|
res = Rack::MockRequest.new(Rack::CommonLogger.new(app_with_zero_length)).get("/")
|
|
45
44
|
|
|
46
45
|
res.errors.should.not.be.empty
|
|
47
46
|
res.errors.should =~ /"GET \/ " 200 - /
|
|
48
47
|
end
|
|
49
|
-
|
|
48
|
+
|
|
50
49
|
def length
|
|
51
|
-
self.class.length
|
|
52
|
-
end
|
|
53
|
-
|
|
54
|
-
def self.length
|
|
55
50
|
123
|
|
56
51
|
end
|
|
57
|
-
|
|
52
|
+
|
|
58
53
|
def self.obj
|
|
59
54
|
"hello world"
|
|
60
55
|
end
|
|
@@ -1,11 +1,9 @@
|
|
|
1
|
-
require 'test/spec'
|
|
2
1
|
require 'time'
|
|
3
|
-
|
|
4
|
-
require 'rack/mock'
|
|
5
2
|
require 'rack/conditionalget'
|
|
3
|
+
require 'rack/mock'
|
|
6
4
|
|
|
7
|
-
|
|
8
|
-
|
|
5
|
+
describe Rack::ConditionalGet do
|
|
6
|
+
should "set a 304 status and truncate body when If-Modified-Since hits" do
|
|
9
7
|
timestamp = Time.now.httpdate
|
|
10
8
|
app = Rack::ConditionalGet.new(lambda { |env|
|
|
11
9
|
[200, {'Last-Modified'=>timestamp}, ['TEST']] })
|
|
@@ -17,7 +15,7 @@ context "Rack::ConditionalGet" do
|
|
|
17
15
|
response.body.should.be.empty
|
|
18
16
|
end
|
|
19
17
|
|
|
20
|
-
|
|
18
|
+
should "set a 304 status and truncate body when If-None-Match hits" do
|
|
21
19
|
app = Rack::ConditionalGet.new(lambda { |env|
|
|
22
20
|
[200, {'Etag'=>'1234'}, ['TEST']] })
|
|
23
21
|
|
|
@@ -28,7 +26,7 @@ context "Rack::ConditionalGet" do
|
|
|
28
26
|
response.body.should.be.empty
|
|
29
27
|
end
|
|
30
28
|
|
|
31
|
-
|
|
29
|
+
should "not affect non-GET/HEAD requests" do
|
|
32
30
|
app = Rack::ConditionalGet.new(lambda { |env|
|
|
33
31
|
[200, {'Etag'=>'1234'}, ['TEST']] })
|
|
34
32
|
|
|
@@ -1,12 +1,11 @@
|
|
|
1
|
-
require 'test/spec'
|
|
2
|
-
require 'rack/mock'
|
|
3
1
|
require 'rack/builder'
|
|
4
|
-
require 'rack/content_length'
|
|
5
2
|
require 'rack/config'
|
|
3
|
+
require 'rack/content_length'
|
|
4
|
+
require 'rack/lint'
|
|
5
|
+
require 'rack/mock'
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
specify "should accept a block that modifies the environment" do
|
|
7
|
+
describe Rack::Config do
|
|
8
|
+
should "accept a block that modifies the environment" do
|
|
10
9
|
app = Rack::Builder.new do
|
|
11
10
|
use Rack::Lint
|
|
12
11
|
use Rack::ContentLength
|
|
@@ -17,8 +16,8 @@ context "Rack::Config" do
|
|
|
17
16
|
[200, {'Content-Type' => 'text/plain'}, [env['greeting'] || '']]
|
|
18
17
|
}
|
|
19
18
|
end
|
|
19
|
+
|
|
20
20
|
response = Rack::MockRequest.new(app).get('/')
|
|
21
21
|
response.body.should.equal('hello')
|
|
22
22
|
end
|
|
23
|
-
|
|
24
23
|
end
|
|
@@ -1,20 +1,19 @@
|
|
|
1
|
-
require 'rack/mock'
|
|
2
1
|
require 'rack/content_length'
|
|
3
2
|
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
describe Rack::ContentLength do
|
|
4
|
+
should "set Content-Length on String bodies if none is set" do
|
|
6
5
|
app = lambda { |env| [200, {'Content-Type' => 'text/plain'}, "Hello, World!"] }
|
|
7
6
|
response = Rack::ContentLength.new(app).call({})
|
|
8
7
|
response[1]['Content-Length'].should.equal '13'
|
|
9
8
|
end
|
|
10
9
|
|
|
11
|
-
|
|
10
|
+
should "set Content-Length on Array bodies if none is set" do
|
|
12
11
|
app = lambda { |env| [200, {'Content-Type' => 'text/plain'}, ["Hello, World!"]] }
|
|
13
12
|
response = Rack::ContentLength.new(app).call({})
|
|
14
13
|
response[1]['Content-Length'].should.equal '13'
|
|
15
14
|
end
|
|
16
15
|
|
|
17
|
-
|
|
16
|
+
should "not set Content-Length on variable length bodies" do
|
|
18
17
|
body = lambda { "Hello World!" }
|
|
19
18
|
def body.each ; yield call ; end
|
|
20
19
|
|
|
@@ -23,19 +22,19 @@ context "Rack::ContentLength" do
|
|
|
23
22
|
response[1]['Content-Length'].should.be.nil
|
|
24
23
|
end
|
|
25
24
|
|
|
26
|
-
|
|
25
|
+
should "not change Content-Length if it is already set" do
|
|
27
26
|
app = lambda { |env| [200, {'Content-Type' => 'text/plain', 'Content-Length' => '1'}, "Hello, World!"] }
|
|
28
27
|
response = Rack::ContentLength.new(app).call({})
|
|
29
28
|
response[1]['Content-Length'].should.equal '1'
|
|
30
29
|
end
|
|
31
30
|
|
|
32
|
-
|
|
31
|
+
should "not set Content-Length on 304 responses" do
|
|
33
32
|
app = lambda { |env| [304, {'Content-Type' => 'text/plain'}, []] }
|
|
34
33
|
response = Rack::ContentLength.new(app).call({})
|
|
35
34
|
response[1]['Content-Length'].should.equal nil
|
|
36
35
|
end
|
|
37
36
|
|
|
38
|
-
|
|
37
|
+
should "not set Content-Length when Transfer-Encoding is chunked" do
|
|
39
38
|
app = lambda { |env| [200, {'Transfer-Encoding' => 'chunked'}, []] }
|
|
40
39
|
response = Rack::ContentLength.new(app).call({})
|
|
41
40
|
response[1]['Content-Length'].should.equal nil
|
|
@@ -1,27 +1,26 @@
|
|
|
1
|
-
require 'rack/mock'
|
|
2
1
|
require 'rack/content_type'
|
|
3
2
|
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
describe Rack::ContentType do
|
|
4
|
+
should "set Content-Type to default text/html if none is set" do
|
|
6
5
|
app = lambda { |env| [200, {}, "Hello, World!"] }
|
|
7
6
|
status, headers, body = Rack::ContentType.new(app).call({})
|
|
8
7
|
headers['Content-Type'].should.equal 'text/html'
|
|
9
8
|
end
|
|
10
9
|
|
|
11
|
-
|
|
10
|
+
should "set Content-Type to chosen default if none is set" do
|
|
12
11
|
app = lambda { |env| [200, {}, "Hello, World!"] }
|
|
13
12
|
status, headers, body =
|
|
14
13
|
Rack::ContentType.new(app, 'application/octet-stream').call({})
|
|
15
14
|
headers['Content-Type'].should.equal 'application/octet-stream'
|
|
16
15
|
end
|
|
17
16
|
|
|
18
|
-
|
|
17
|
+
should "not change Content-Type if it is already set" do
|
|
19
18
|
app = lambda { |env| [200, {'Content-Type' => 'foo/bar'}, "Hello, World!"] }
|
|
20
19
|
status, headers, body = Rack::ContentType.new(app).call({})
|
|
21
20
|
headers['Content-Type'].should.equal 'foo/bar'
|
|
22
21
|
end
|
|
23
22
|
|
|
24
|
-
|
|
23
|
+
should "detect Content-Type case insensitive" do
|
|
25
24
|
app = lambda { |env| [200, {'CONTENT-Type' => 'foo/bar'}, "Hello, World!"] }
|
|
26
25
|
status, headers, body = Rack::ContentType.new(app).call({})
|
|
27
26
|
headers.to_a.select { |k,v| k.downcase == "content-type" }.
|
|
@@ -1,11 +1,9 @@
|
|
|
1
|
-
require 'test/spec'
|
|
2
|
-
|
|
3
|
-
require 'rack/mock'
|
|
4
|
-
require 'rack/deflater'
|
|
5
1
|
require 'stringio'
|
|
6
2
|
require 'time' # for Time#httpdate
|
|
3
|
+
require 'rack/deflater'
|
|
4
|
+
require 'rack/mock'
|
|
7
5
|
|
|
8
|
-
|
|
6
|
+
describe Rack::Deflater do
|
|
9
7
|
def build_response(status, body, accept_encoding, headers = {})
|
|
10
8
|
body = [body] if body.respond_to? :to_str
|
|
11
9
|
app = lambda { |env| [status, {}, body] }
|
|
@@ -15,7 +13,7 @@ context "Rack::Deflater" do
|
|
|
15
13
|
return response
|
|
16
14
|
end
|
|
17
15
|
|
|
18
|
-
|
|
16
|
+
should "be able to deflate bodies that respond to each" do
|
|
19
17
|
body = Object.new
|
|
20
18
|
class << body; def each; yield("foo"); yield("bar"); end; end
|
|
21
19
|
|
|
@@ -32,7 +30,7 @@ context "Rack::Deflater" do
|
|
|
32
30
|
end
|
|
33
31
|
|
|
34
32
|
# TODO: This is really just a special case of the above...
|
|
35
|
-
|
|
33
|
+
should "be able to deflate String bodies" do
|
|
36
34
|
response = build_response(200, "Hello world!", "deflate")
|
|
37
35
|
|
|
38
36
|
response[0].should.equal(200)
|
|
@@ -45,7 +43,7 @@ context "Rack::Deflater" do
|
|
|
45
43
|
buf.should.equal("\363H\315\311\311W(\317/\312IQ\004\000")
|
|
46
44
|
end
|
|
47
45
|
|
|
48
|
-
|
|
46
|
+
should "be able to gzip bodies that respond to each" do
|
|
49
47
|
body = Object.new
|
|
50
48
|
class << body; def each; yield("foo"); yield("bar"); end; end
|
|
51
49
|
|
|
@@ -65,7 +63,7 @@ context "Rack::Deflater" do
|
|
|
65
63
|
gz.close
|
|
66
64
|
end
|
|
67
65
|
|
|
68
|
-
|
|
66
|
+
should "be able to fallback to no deflation" do
|
|
69
67
|
response = build_response(200, "Hello world!", "superzip")
|
|
70
68
|
|
|
71
69
|
response[0].should.equal(200)
|
|
@@ -73,7 +71,7 @@ context "Rack::Deflater" do
|
|
|
73
71
|
response[2].should.equal(["Hello world!"])
|
|
74
72
|
end
|
|
75
73
|
|
|
76
|
-
|
|
74
|
+
should "be able to skip when there is no response entity body" do
|
|
77
75
|
response = build_response(304, [], "gzip")
|
|
78
76
|
|
|
79
77
|
response[0].should.equal(304)
|
|
@@ -81,7 +79,7 @@ context "Rack::Deflater" do
|
|
|
81
79
|
response[2].should.equal([])
|
|
82
80
|
end
|
|
83
81
|
|
|
84
|
-
|
|
82
|
+
should "handle the lack of an acceptable encoding" do
|
|
85
83
|
response1 = build_response(200, "Hello world!", "identity;q=0", "PATH_INFO" => "/")
|
|
86
84
|
response1[0].should.equal(406)
|
|
87
85
|
response1[1].should.equal({"Content-Type" => "text/plain", "Content-Length" => "71"})
|
|
@@ -93,7 +91,7 @@ context "Rack::Deflater" do
|
|
|
93
91
|
response2[2].should.equal(["An acceptable encoding for the requested resource /foo/bar could not be found."])
|
|
94
92
|
end
|
|
95
93
|
|
|
96
|
-
|
|
94
|
+
should "handle gzip response with Last-Modified header" do
|
|
97
95
|
last_modified = Time.now.httpdate
|
|
98
96
|
|
|
99
97
|
app = lambda { |env| [200, { "Last-Modified" => last_modified }, ["Hello World!"]] }
|
|
@@ -115,7 +113,7 @@ context "Rack::Deflater" do
|
|
|
115
113
|
gz.close
|
|
116
114
|
end
|
|
117
115
|
|
|
118
|
-
|
|
116
|
+
should "do nothing when no-transform Cache-Control directive present" do
|
|
119
117
|
app = lambda { |env| [200, {'Cache-Control' => 'no-transform'}, ['Hello World!']] }
|
|
120
118
|
request = Rack::MockRequest.env_for("", "HTTP_ACCEPT_ENCODING" => "gzip")
|
|
121
119
|
response = Rack::Deflater.new(app).call(request)
|
|
@@ -1,16 +1,12 @@
|
|
|
1
|
-
require 'test/spec'
|
|
2
|
-
|
|
3
1
|
require 'rack/directory'
|
|
4
|
-
require 'rack/lint'
|
|
5
|
-
|
|
6
2
|
require 'rack/mock'
|
|
7
3
|
|
|
8
|
-
|
|
4
|
+
describe Rack::Directory do
|
|
9
5
|
DOCROOT = File.expand_path(File.dirname(__FILE__)) unless defined? DOCROOT
|
|
10
6
|
FILE_CATCH = proc{|env| [200, {'Content-Type'=>'text/plain', "Content-Length" => "7"}, ['passed!']] }
|
|
11
7
|
app = Rack::Directory.new DOCROOT, FILE_CATCH
|
|
12
8
|
|
|
13
|
-
|
|
9
|
+
should "serve directory indices" do
|
|
14
10
|
res = Rack::MockRequest.new(Rack::Lint.new(app)).
|
|
15
11
|
get("/cgi/")
|
|
16
12
|
|
|
@@ -18,7 +14,7 @@ context "Rack::Directory" do
|
|
|
18
14
|
res.should =~ /<html><head>/
|
|
19
15
|
end
|
|
20
16
|
|
|
21
|
-
|
|
17
|
+
should "pass to app if file found" do
|
|
22
18
|
res = Rack::MockRequest.new(Rack::Lint.new(app)).
|
|
23
19
|
get("/cgi/test")
|
|
24
20
|
|
|
@@ -26,7 +22,7 @@ context "Rack::Directory" do
|
|
|
26
22
|
res.should =~ /passed!/
|
|
27
23
|
end
|
|
28
24
|
|
|
29
|
-
|
|
25
|
+
should "serve uri with URL encoded filenames" do
|
|
30
26
|
res = Rack::MockRequest.new(Rack::Lint.new(app)).
|
|
31
27
|
get("/%63%67%69/") # "/cgi/test"
|
|
32
28
|
|
|
@@ -40,7 +36,7 @@ context "Rack::Directory" do
|
|
|
40
36
|
res.should =~ /passed!/
|
|
41
37
|
end
|
|
42
38
|
|
|
43
|
-
|
|
39
|
+
should "not allow directory traversal" do
|
|
44
40
|
res = Rack::MockRequest.new(Rack::Lint.new(app)).
|
|
45
41
|
get("/cgi/../test")
|
|
46
42
|
|
|
@@ -52,7 +48,7 @@ context "Rack::Directory" do
|
|
|
52
48
|
res.should.be.forbidden
|
|
53
49
|
end
|
|
54
50
|
|
|
55
|
-
|
|
51
|
+
should "404 if it can't find the file" do
|
|
56
52
|
res = Rack::MockRequest.new(Rack::Lint.new(app)).
|
|
57
53
|
get("/cgi/blubb")
|
|
58
54
|
|
|
@@ -1,15 +1,13 @@
|
|
|
1
|
-
require 'test/spec'
|
|
2
|
-
require 'rack/mock'
|
|
3
1
|
require 'rack/etag'
|
|
4
2
|
|
|
5
|
-
|
|
6
|
-
|
|
3
|
+
describe Rack::ETag do
|
|
4
|
+
should "set ETag if none is set" do
|
|
7
5
|
app = lambda { |env| [200, {'Content-Type' => 'text/plain'}, ["Hello, World!"]] }
|
|
8
6
|
response = Rack::ETag.new(app).call({})
|
|
9
7
|
response[1]['ETag'].should.equal "\"65a8e27d8879283831b664bd8b7f0ad4\""
|
|
10
8
|
end
|
|
11
9
|
|
|
12
|
-
|
|
10
|
+
should "not change ETag if it is already set" do
|
|
13
11
|
app = lambda { |env| [200, {'Content-Type' => 'text/plain', 'ETag' => '"abc"'}, ["Hello, World!"]] }
|
|
14
12
|
response = Rack::ETag.new(app).call({})
|
|
15
13
|
response[1]['ETag'].should.equal "\"abc\""
|
|
@@ -1,48 +1,55 @@
|
|
|
1
|
-
require '
|
|
2
|
-
require '
|
|
1
|
+
require File.expand_path('../testrequest', __FILE__)
|
|
2
|
+
require 'rack/handler/fastcgi'
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
|
|
4
|
+
describe Rack::Handler::FastCGI do
|
|
5
|
+
extend TestRequest::Helpers
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
@port = 9203
|
|
10
|
-
end
|
|
7
|
+
@host = '0.0.0.0'
|
|
8
|
+
@port = 9203
|
|
11
9
|
|
|
12
10
|
# Keep this first.
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
11
|
+
$pid = fork {
|
|
12
|
+
ENV['RACK_ENV'] = 'deployment'
|
|
13
|
+
ENV['RUBYLIB'] = [
|
|
14
|
+
File.expand_path('../../lib', __FILE__),
|
|
15
|
+
ENV['RUBYLIB'],
|
|
16
|
+
].compact.join(':')
|
|
17
|
+
|
|
18
|
+
Dir.chdir(File.expand_path("../cgi", __FILE__)) do
|
|
16
19
|
exec "lighttpd -D -f lighttpd.conf"
|
|
17
|
-
|
|
18
|
-
|
|
20
|
+
end
|
|
21
|
+
}
|
|
19
22
|
|
|
20
|
-
|
|
23
|
+
should "respond" do
|
|
21
24
|
sleep 1
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
}.should.not.raise
|
|
25
|
+
GET("/test")
|
|
26
|
+
response.should.not.be.nil
|
|
25
27
|
end
|
|
26
28
|
|
|
27
|
-
|
|
29
|
+
should "respond via rackup server" do
|
|
30
|
+
GET("/sample_rackup.ru")
|
|
31
|
+
status.should.equal 200
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
should "be a lighttpd" do
|
|
28
35
|
GET("/test.fcgi")
|
|
29
|
-
status.should.
|
|
36
|
+
status.should.equal 200
|
|
30
37
|
response["SERVER_SOFTWARE"].should =~ /lighttpd/
|
|
31
38
|
response["HTTP_VERSION"].should.equal "HTTP/1.1"
|
|
32
39
|
response["SERVER_PROTOCOL"].should.equal "HTTP/1.1"
|
|
33
40
|
response["SERVER_PORT"].should.equal @port.to_s
|
|
34
|
-
response["SERVER_NAME"].should
|
|
41
|
+
response["SERVER_NAME"].should.equal @host
|
|
35
42
|
end
|
|
36
43
|
|
|
37
|
-
|
|
44
|
+
should "have rack headers" do
|
|
38
45
|
GET("/test.fcgi")
|
|
39
46
|
response["rack.version"].should.equal [1,1]
|
|
40
|
-
response["rack.multithread"].should.be
|
|
41
|
-
response["rack.multiprocess"].should.be
|
|
42
|
-
response["rack.run_once"].should.be
|
|
47
|
+
response["rack.multithread"].should.be.false
|
|
48
|
+
response["rack.multiprocess"].should.be.true
|
|
49
|
+
response["rack.run_once"].should.be.false
|
|
43
50
|
end
|
|
44
51
|
|
|
45
|
-
|
|
52
|
+
should "have CGI headers on GET" do
|
|
46
53
|
GET("/test.fcgi")
|
|
47
54
|
response["REQUEST_METHOD"].should.equal "GET"
|
|
48
55
|
response["SCRIPT_NAME"].should.equal "/test.fcgi"
|
|
@@ -59,7 +66,7 @@ context "Rack::Handler::FastCGI" do
|
|
|
59
66
|
response["QUERY_STRING"].should.equal "quux=1"
|
|
60
67
|
end
|
|
61
68
|
|
|
62
|
-
|
|
69
|
+
should "have CGI headers on POST" do
|
|
63
70
|
POST("/test.fcgi", {"rack-form-data" => "23"}, {'X-test-header' => '42'})
|
|
64
71
|
status.should.equal 200
|
|
65
72
|
response["REQUEST_METHOD"].should.equal "POST"
|
|
@@ -70,19 +77,19 @@ context "Rack::Handler::FastCGI" do
|
|
|
70
77
|
response["test.postdata"].should.equal "rack-form-data=23"
|
|
71
78
|
end
|
|
72
79
|
|
|
73
|
-
|
|
80
|
+
should "support HTTP auth" do
|
|
74
81
|
GET("/test.fcgi", {:user => "ruth", :passwd => "secret"})
|
|
75
82
|
response["HTTP_AUTHORIZATION"].should.equal "Basic cnV0aDpzZWNyZXQ="
|
|
76
83
|
end
|
|
77
84
|
|
|
78
|
-
|
|
85
|
+
should "set status" do
|
|
79
86
|
GET("/test.fcgi?secret")
|
|
80
87
|
status.should.equal 403
|
|
81
88
|
response["rack.url_scheme"].should.equal "http"
|
|
82
89
|
end
|
|
83
90
|
|
|
84
91
|
# Keep this last.
|
|
85
|
-
|
|
92
|
+
should "shutdown" do
|
|
86
93
|
Process.kill 15, $pid
|
|
87
94
|
Process.wait($pid).should.equal $pid
|
|
88
95
|
end
|
|
@@ -1,14 +1,10 @@
|
|
|
1
|
-
require 'test/spec'
|
|
2
|
-
|
|
3
1
|
require 'rack/file'
|
|
4
|
-
require 'rack/lint'
|
|
5
|
-
|
|
6
2
|
require 'rack/mock'
|
|
7
3
|
|
|
8
|
-
|
|
4
|
+
describe Rack::File do
|
|
9
5
|
DOCROOT = File.expand_path(File.dirname(__FILE__)) unless defined? DOCROOT
|
|
10
6
|
|
|
11
|
-
|
|
7
|
+
should "serve files" do
|
|
12
8
|
res = Rack::MockRequest.new(Rack::Lint.new(Rack::File.new(DOCROOT))).
|
|
13
9
|
get("/cgi/test")
|
|
14
10
|
|
|
@@ -16,7 +12,7 @@ context "Rack::File" do
|
|
|
16
12
|
res.should =~ /ruby/
|
|
17
13
|
end
|
|
18
14
|
|
|
19
|
-
|
|
15
|
+
should "set Last-Modified header" do
|
|
20
16
|
res = Rack::MockRequest.new(Rack::Lint.new(Rack::File.new(DOCROOT))).
|
|
21
17
|
get("/cgi/test")
|
|
22
18
|
|
|
@@ -26,7 +22,7 @@ context "Rack::File" do
|
|
|
26
22
|
res["Last-Modified"].should.equal File.mtime(path).httpdate
|
|
27
23
|
end
|
|
28
24
|
|
|
29
|
-
|
|
25
|
+
should "serve files with URL encoded filenames" do
|
|
30
26
|
res = Rack::MockRequest.new(Rack::Lint.new(Rack::File.new(DOCROOT))).
|
|
31
27
|
get("/cgi/%74%65%73%74") # "/cgi/test"
|
|
32
28
|
|
|
@@ -34,35 +30,35 @@ context "Rack::File" do
|
|
|
34
30
|
res.should =~ /ruby/
|
|
35
31
|
end
|
|
36
32
|
|
|
37
|
-
|
|
33
|
+
should "not allow directory traversal" do
|
|
38
34
|
res = Rack::MockRequest.new(Rack::Lint.new(Rack::File.new(DOCROOT))).
|
|
39
35
|
get("/cgi/../test")
|
|
40
36
|
|
|
41
37
|
res.should.be.forbidden
|
|
42
38
|
end
|
|
43
39
|
|
|
44
|
-
|
|
40
|
+
should "not allow directory traversal with encoded periods" do
|
|
45
41
|
res = Rack::MockRequest.new(Rack::Lint.new(Rack::File.new(DOCROOT))).
|
|
46
42
|
get("/%2E%2E/README")
|
|
47
43
|
|
|
48
44
|
res.should.be.forbidden
|
|
49
45
|
end
|
|
50
46
|
|
|
51
|
-
|
|
47
|
+
should "404 if it can't find the file" do
|
|
52
48
|
res = Rack::MockRequest.new(Rack::Lint.new(Rack::File.new(DOCROOT))).
|
|
53
49
|
get("/cgi/blubb")
|
|
54
50
|
|
|
55
51
|
res.should.be.not_found
|
|
56
52
|
end
|
|
57
53
|
|
|
58
|
-
|
|
54
|
+
should "detect SystemCallErrors" do
|
|
59
55
|
res = Rack::MockRequest.new(Rack::Lint.new(Rack::File.new(DOCROOT))).
|
|
60
56
|
get("/cgi")
|
|
61
57
|
|
|
62
58
|
res.should.be.not_found
|
|
63
59
|
end
|
|
64
60
|
|
|
65
|
-
|
|
61
|
+
should "return bodies that respond to #to_path" do
|
|
66
62
|
env = Rack::MockRequest.env_for("/cgi/test")
|
|
67
63
|
status, headers, body = Rack::File.new(DOCROOT).call(env)
|
|
68
64
|
|
|
@@ -1,43 +1,41 @@
|
|
|
1
|
-
require 'test/spec'
|
|
2
|
-
|
|
3
1
|
require 'rack/handler'
|
|
4
2
|
|
|
5
3
|
class Rack::Handler::Lobster; end
|
|
6
4
|
class RockLobster; end
|
|
7
5
|
|
|
8
|
-
|
|
9
|
-
|
|
6
|
+
describe Rack::Handler do
|
|
7
|
+
it "has registered default handlers" do
|
|
10
8
|
Rack::Handler.get('cgi').should.equal Rack::Handler::CGI
|
|
11
9
|
Rack::Handler.get('fastcgi').should.equal Rack::Handler::FastCGI
|
|
12
10
|
Rack::Handler.get('mongrel').should.equal Rack::Handler::Mongrel
|
|
13
11
|
Rack::Handler.get('webrick').should.equal Rack::Handler::WEBrick
|
|
14
12
|
end
|
|
15
|
-
|
|
16
|
-
|
|
13
|
+
|
|
14
|
+
should "raise NameError if handler doesn't exist" do
|
|
17
15
|
lambda {
|
|
18
16
|
Rack::Handler.get('boom')
|
|
19
17
|
}.should.raise(NameError)
|
|
20
18
|
end
|
|
21
19
|
|
|
22
|
-
|
|
20
|
+
should "get unregistered, but already required, handler by name" do
|
|
23
21
|
Rack::Handler.get('Lobster').should.equal Rack::Handler::Lobster
|
|
24
22
|
end
|
|
25
23
|
|
|
26
|
-
|
|
24
|
+
should "register custom handler" do
|
|
27
25
|
Rack::Handler.register('rock_lobster', 'RockLobster')
|
|
28
26
|
Rack::Handler.get('rock_lobster').should.equal RockLobster
|
|
29
27
|
end
|
|
30
|
-
|
|
31
|
-
|
|
28
|
+
|
|
29
|
+
should "not need registration for properly coded handlers even if not already required" do
|
|
32
30
|
begin
|
|
33
|
-
|
|
31
|
+
$LOAD_PATH.push File.expand_path('../unregistered_handler', __FILE__)
|
|
34
32
|
Rack::Handler.get('Unregistered').should.equal Rack::Handler::Unregistered
|
|
35
33
|
lambda {
|
|
36
34
|
Rack::Handler.get('UnRegistered')
|
|
37
35
|
}.should.raise(NameError)
|
|
38
36
|
Rack::Handler.get('UnregisteredLongOne').should.equal Rack::Handler::UnregisteredLongOne
|
|
39
37
|
ensure
|
|
40
|
-
|
|
38
|
+
$LOAD_PATH.delete File.expand_path('../unregistered_handler', __FILE__)
|
|
41
39
|
end
|
|
42
40
|
end
|
|
43
41
|
end
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
require 'rack/head'
|
|
2
2
|
require 'rack/mock'
|
|
3
3
|
|
|
4
|
-
|
|
4
|
+
describe Rack::Head do
|
|
5
5
|
def test_response(headers = {})
|
|
6
6
|
app = lambda { |env| [200, {"Content-type" => "test/plain", "Content-length" => "3"}, ["foo"]] }
|
|
7
7
|
request = Rack::MockRequest.env_for("/", headers)
|
|
@@ -10,7 +10,7 @@ context "Rack::Head" do
|
|
|
10
10
|
return response
|
|
11
11
|
end
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
should "pass GET, POST, PUT, DELETE, OPTIONS, TRACE requests" do
|
|
14
14
|
%w[GET POST PUT DELETE OPTIONS TRACE].each do |type|
|
|
15
15
|
resp = test_response("REQUEST_METHOD" => type)
|
|
16
16
|
|
|
@@ -20,7 +20,7 @@ context "Rack::Head" do
|
|
|
20
20
|
end
|
|
21
21
|
end
|
|
22
22
|
|
|
23
|
-
|
|
23
|
+
should "remove body from HEAD requests" do
|
|
24
24
|
resp = test_response("REQUEST_METHOD" => "HEAD")
|
|
25
25
|
|
|
26
26
|
resp[0].should.equal(200)
|