rack 1.0.1 → 2.2.21

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.
Files changed (147) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +829 -0
  3. data/CONTRIBUTING.md +136 -0
  4. data/{COPYING → MIT-LICENSE} +4 -2
  5. data/README.rdoc +355 -0
  6. data/Rakefile +64 -98
  7. data/SPEC.rdoc +292 -0
  8. data/bin/rackup +3 -174
  9. data/contrib/rack.png +0 -0
  10. data/contrib/rack.svg +150 -0
  11. data/contrib/rack_logo.svg +164 -111
  12. data/contrib/rdoc.css +412 -0
  13. data/example/lobster.ru +2 -0
  14. data/example/protectedlobster.rb +4 -2
  15. data/example/protectedlobster.ru +3 -1
  16. data/lib/rack/auth/abstract/handler.rb +7 -5
  17. data/lib/rack/auth/abstract/request.rb +12 -2
  18. data/lib/rack/auth/basic.rb +6 -4
  19. data/lib/rack/auth/digest/md5.rb +20 -13
  20. data/lib/rack/auth/digest/nonce.rb +6 -4
  21. data/lib/rack/auth/digest/params.rb +11 -12
  22. data/lib/rack/auth/digest/request.rb +15 -12
  23. data/lib/rack/body_proxy.rb +45 -0
  24. data/lib/rack/builder.rb +213 -19
  25. data/lib/rack/cascade.rb +50 -18
  26. data/lib/rack/chunked.rb +95 -27
  27. data/lib/rack/common_logger.rb +84 -0
  28. data/lib/rack/conditional_get.rb +83 -0
  29. data/lib/rack/config.rb +22 -0
  30. data/lib/rack/content_length.rb +19 -10
  31. data/lib/rack/content_type.rb +12 -5
  32. data/lib/rack/core_ext/regexp.rb +14 -0
  33. data/lib/rack/deflater.rb +90 -42
  34. data/lib/rack/directory.rb +118 -72
  35. data/lib/rack/etag.rb +77 -0
  36. data/lib/rack/events.rb +153 -0
  37. data/lib/rack/file.rb +4 -85
  38. data/lib/rack/files.rb +218 -0
  39. data/lib/rack/handler/cgi.rb +22 -24
  40. data/lib/rack/handler/fastcgi.rb +34 -24
  41. data/lib/rack/handler/lsws.rb +16 -15
  42. data/lib/rack/handler/scgi.rb +38 -29
  43. data/lib/rack/handler/thin.rb +23 -7
  44. data/lib/rack/handler/webrick.rb +95 -37
  45. data/lib/rack/handler.rb +49 -14
  46. data/lib/rack/head.rb +19 -13
  47. data/lib/rack/lint.rb +466 -217
  48. data/lib/rack/lobster.rb +19 -14
  49. data/lib/rack/lock.rb +24 -8
  50. data/lib/rack/logger.rb +20 -0
  51. data/lib/rack/media_type.rb +53 -0
  52. data/lib/rack/method_override.rb +52 -0
  53. data/lib/rack/mime.rb +652 -171
  54. data/lib/rack/mock.rb +203 -64
  55. data/lib/rack/multipart/generator.rb +97 -0
  56. data/lib/rack/multipart/parser.rb +440 -0
  57. data/lib/rack/multipart/uploaded_file.rb +41 -0
  58. data/lib/rack/multipart.rb +64 -0
  59. data/lib/rack/null_logger.rb +39 -0
  60. data/lib/rack/query_parser.rb +266 -0
  61. data/lib/rack/recursive.rb +18 -11
  62. data/lib/rack/reloader.rb +13 -5
  63. data/lib/rack/request.rb +607 -191
  64. data/lib/rack/response.rb +245 -110
  65. data/lib/rack/rewindable_input.rb +15 -21
  66. data/lib/rack/runtime.rb +34 -0
  67. data/lib/rack/sendfile.rb +192 -0
  68. data/lib/rack/server.rb +466 -0
  69. data/lib/rack/session/abstract/id.rb +449 -68
  70. data/lib/rack/session/cookie.rb +159 -47
  71. data/lib/rack/session/memcache.rb +4 -103
  72. data/lib/rack/session/pool.rb +39 -49
  73. data/lib/rack/show_exceptions.rb +390 -0
  74. data/lib/rack/{showstatus.rb → show_status.rb} +21 -14
  75. data/lib/rack/static.rb +164 -14
  76. data/lib/rack/tempfile_reaper.rb +22 -0
  77. data/lib/rack/urlmap.rb +60 -18
  78. data/lib/rack/utils.rb +508 -277
  79. data/lib/rack/version.rb +29 -0
  80. data/lib/rack.rb +85 -34
  81. data/rack.gemspec +43 -51
  82. metadata +119 -207
  83. data/KNOWN-ISSUES +0 -18
  84. data/RDOX +0 -428
  85. data/README +0 -364
  86. data/SPEC +0 -164
  87. data/lib/rack/adapter/camping.rb +0 -22
  88. data/lib/rack/auth/openid.rb +0 -480
  89. data/lib/rack/commonlogger.rb +0 -61
  90. data/lib/rack/conditionalget.rb +0 -47
  91. data/lib/rack/handler/evented_mongrel.rb +0 -8
  92. data/lib/rack/handler/mongrel.rb +0 -87
  93. data/lib/rack/handler/swiftiplied_mongrel.rb +0 -8
  94. data/lib/rack/methodoverride.rb +0 -27
  95. data/lib/rack/showexceptions.rb +0 -349
  96. data/test/cgi/lighttpd.conf +0 -20
  97. data/test/cgi/test +0 -9
  98. data/test/cgi/test.fcgi +0 -8
  99. data/test/cgi/test.ru +0 -7
  100. data/test/multipart/binary +0 -0
  101. data/test/multipart/empty +0 -10
  102. data/test/multipart/ie +0 -6
  103. data/test/multipart/nested +0 -10
  104. data/test/multipart/none +0 -9
  105. data/test/multipart/semicolon +0 -6
  106. data/test/multipart/text +0 -10
  107. data/test/spec_rack_auth_basic.rb +0 -73
  108. data/test/spec_rack_auth_digest.rb +0 -226
  109. data/test/spec_rack_auth_openid.rb +0 -84
  110. data/test/spec_rack_builder.rb +0 -84
  111. data/test/spec_rack_camping.rb +0 -51
  112. data/test/spec_rack_cascade.rb +0 -50
  113. data/test/spec_rack_cgi.rb +0 -89
  114. data/test/spec_rack_chunked.rb +0 -62
  115. data/test/spec_rack_commonlogger.rb +0 -32
  116. data/test/spec_rack_conditionalget.rb +0 -41
  117. data/test/spec_rack_content_length.rb +0 -43
  118. data/test/spec_rack_content_type.rb +0 -30
  119. data/test/spec_rack_deflater.rb +0 -127
  120. data/test/spec_rack_directory.rb +0 -61
  121. data/test/spec_rack_fastcgi.rb +0 -89
  122. data/test/spec_rack_file.rb +0 -75
  123. data/test/spec_rack_handler.rb +0 -43
  124. data/test/spec_rack_head.rb +0 -30
  125. data/test/spec_rack_lint.rb +0 -521
  126. data/test/spec_rack_lobster.rb +0 -45
  127. data/test/spec_rack_lock.rb +0 -38
  128. data/test/spec_rack_methodoverride.rb +0 -60
  129. data/test/spec_rack_mock.rb +0 -157
  130. data/test/spec_rack_mongrel.rb +0 -189
  131. data/test/spec_rack_recursive.rb +0 -77
  132. data/test/spec_rack_request.rb +0 -504
  133. data/test/spec_rack_response.rb +0 -218
  134. data/test/spec_rack_rewindable_input.rb +0 -118
  135. data/test/spec_rack_session_cookie.rb +0 -82
  136. data/test/spec_rack_session_memcache.rb +0 -240
  137. data/test/spec_rack_session_pool.rb +0 -172
  138. data/test/spec_rack_showexceptions.rb +0 -21
  139. data/test/spec_rack_showstatus.rb +0 -72
  140. data/test/spec_rack_static.rb +0 -37
  141. data/test/spec_rack_thin.rb +0 -91
  142. data/test/spec_rack_urlmap.rb +0 -185
  143. data/test/spec_rack_utils.rb +0 -387
  144. data/test/spec_rack_webrick.rb +0 -130
  145. data/test/testrequest.rb +0 -57
  146. data/test/unregistered_handler/rack/handler/unregistered.rb +0 -7
  147. data/test/unregistered_handler/rack/handler/unregistered_long_one.rb +0 -7
@@ -1,41 +0,0 @@
1
- require 'test/spec'
2
- require 'time'
3
-
4
- require 'rack/mock'
5
- require 'rack/conditionalget'
6
-
7
- context "Rack::ConditionalGet" do
8
- specify "should set a 304 status and truncate body when If-Modified-Since hits" do
9
- timestamp = Time.now.httpdate
10
- app = Rack::ConditionalGet.new(lambda { |env|
11
- [200, {'Last-Modified'=>timestamp}, ['TEST']] })
12
-
13
- response = Rack::MockRequest.new(app).
14
- get("/", 'HTTP_IF_MODIFIED_SINCE' => timestamp)
15
-
16
- response.status.should.equal 304
17
- response.body.should.be.empty
18
- end
19
-
20
- specify "should set a 304 status and truncate body when If-None-Match hits" do
21
- app = Rack::ConditionalGet.new(lambda { |env|
22
- [200, {'Etag'=>'1234'}, ['TEST']] })
23
-
24
- response = Rack::MockRequest.new(app).
25
- get("/", 'HTTP_IF_NONE_MATCH' => '1234')
26
-
27
- response.status.should.equal 304
28
- response.body.should.be.empty
29
- end
30
-
31
- specify "should not affect non-GET/HEAD requests" do
32
- app = Rack::ConditionalGet.new(lambda { |env|
33
- [200, {'Etag'=>'1234'}, ['TEST']] })
34
-
35
- response = Rack::MockRequest.new(app).
36
- post("/", 'HTTP_IF_NONE_MATCH' => '1234')
37
-
38
- response.status.should.equal 200
39
- response.body.should.equal 'TEST'
40
- end
41
- end
@@ -1,43 +0,0 @@
1
- require 'rack/mock'
2
- require 'rack/content_length'
3
-
4
- context "Rack::ContentLength" do
5
- specify "sets Content-Length on String bodies if none is set" do
6
- app = lambda { |env| [200, {'Content-Type' => 'text/plain'}, "Hello, World!"] }
7
- response = Rack::ContentLength.new(app).call({})
8
- response[1]['Content-Length'].should.equal '13'
9
- end
10
-
11
- specify "sets Content-Length on Array bodies if none is set" do
12
- app = lambda { |env| [200, {'Content-Type' => 'text/plain'}, ["Hello, World!"]] }
13
- response = Rack::ContentLength.new(app).call({})
14
- response[1]['Content-Length'].should.equal '13'
15
- end
16
-
17
- specify "does not set Content-Length on variable length bodies" do
18
- body = lambda { "Hello World!" }
19
- def body.each ; yield call ; end
20
-
21
- app = lambda { |env| [200, {'Content-Type' => 'text/plain'}, body] }
22
- response = Rack::ContentLength.new(app).call({})
23
- response[1]['Content-Length'].should.be.nil
24
- end
25
-
26
- specify "does not change Content-Length if it is already set" do
27
- app = lambda { |env| [200, {'Content-Type' => 'text/plain', 'Content-Length' => '1'}, "Hello, World!"] }
28
- response = Rack::ContentLength.new(app).call({})
29
- response[1]['Content-Length'].should.equal '1'
30
- end
31
-
32
- specify "does not set Content-Length on 304 responses" do
33
- app = lambda { |env| [304, {'Content-Type' => 'text/plain'}, []] }
34
- response = Rack::ContentLength.new(app).call({})
35
- response[1]['Content-Length'].should.equal nil
36
- end
37
-
38
- specify "does not set Content-Length when Transfer-Encoding is chunked" do
39
- app = lambda { |env| [200, {'Transfer-Encoding' => 'chunked'}, []] }
40
- response = Rack::ContentLength.new(app).call({})
41
- response[1]['Content-Length'].should.equal nil
42
- end
43
- end
@@ -1,30 +0,0 @@
1
- require 'rack/mock'
2
- require 'rack/content_type'
3
-
4
- context "Rack::ContentType" do
5
- specify "sets Content-Type to default text/html if none is set" do
6
- app = lambda { |env| [200, {}, "Hello, World!"] }
7
- status, headers, body = Rack::ContentType.new(app).call({})
8
- headers['Content-Type'].should.equal 'text/html'
9
- end
10
-
11
- specify "sets Content-Type to chosen default if none is set" do
12
- app = lambda { |env| [200, {}, "Hello, World!"] }
13
- status, headers, body =
14
- Rack::ContentType.new(app, 'application/octet-stream').call({})
15
- headers['Content-Type'].should.equal 'application/octet-stream'
16
- end
17
-
18
- specify "does not change Content-Type if it is already set" do
19
- app = lambda { |env| [200, {'Content-Type' => 'foo/bar'}, "Hello, World!"] }
20
- status, headers, body = Rack::ContentType.new(app).call({})
21
- headers['Content-Type'].should.equal 'foo/bar'
22
- end
23
-
24
- specify "case insensitive detection of Content-Type" do
25
- app = lambda { |env| [200, {'CONTENT-Type' => 'foo/bar'}, "Hello, World!"] }
26
- status, headers, body = Rack::ContentType.new(app).call({})
27
- headers.to_a.select { |k,v| k.downcase == "content-type" }.
28
- should.equal [["CONTENT-Type","foo/bar"]]
29
- end
30
- end
@@ -1,127 +0,0 @@
1
- require 'test/spec'
2
-
3
- require 'rack/mock'
4
- require 'rack/deflater'
5
- require 'stringio'
6
- require 'time' # for Time#httpdate
7
-
8
- context "Rack::Deflater" do
9
- def build_response(status, body, accept_encoding, headers = {})
10
- body = [body] if body.respond_to? :to_str
11
- app = lambda { |env| [status, {}, body] }
12
- request = Rack::MockRequest.env_for("", headers.merge("HTTP_ACCEPT_ENCODING" => accept_encoding))
13
- response = Rack::Deflater.new(app).call(request)
14
-
15
- return response
16
- end
17
-
18
- specify "should be able to deflate bodies that respond to each" do
19
- body = Object.new
20
- class << body; def each; yield("foo"); yield("bar"); end; end
21
-
22
- response = build_response(200, body, "deflate")
23
-
24
- response[0].should.equal(200)
25
- response[1].should.equal({
26
- "Content-Encoding" => "deflate",
27
- "Vary" => "Accept-Encoding"
28
- })
29
- buf = ''
30
- response[2].each { |part| buf << part }
31
- buf.should.equal("K\313\317OJ,\002\000")
32
- end
33
-
34
- # TODO: This is really just a special case of the above...
35
- specify "should be able to deflate String bodies" do
36
- response = build_response(200, "Hello world!", "deflate")
37
-
38
- response[0].should.equal(200)
39
- response[1].should.equal({
40
- "Content-Encoding" => "deflate",
41
- "Vary" => "Accept-Encoding"
42
- })
43
- buf = ''
44
- response[2].each { |part| buf << part }
45
- buf.should.equal("\363H\315\311\311W(\317/\312IQ\004\000")
46
- end
47
-
48
- specify "should be able to gzip bodies that respond to each" do
49
- body = Object.new
50
- class << body; def each; yield("foo"); yield("bar"); end; end
51
-
52
- response = build_response(200, body, "gzip")
53
-
54
- response[0].should.equal(200)
55
- response[1].should.equal({
56
- "Content-Encoding" => "gzip",
57
- "Vary" => "Accept-Encoding",
58
- })
59
-
60
- buf = ''
61
- response[2].each { |part| buf << part }
62
- io = StringIO.new(buf)
63
- gz = Zlib::GzipReader.new(io)
64
- gz.read.should.equal("foobar")
65
- gz.close
66
- end
67
-
68
- specify "should be able to fallback to no deflation" do
69
- response = build_response(200, "Hello world!", "superzip")
70
-
71
- response[0].should.equal(200)
72
- response[1].should.equal({ "Vary" => "Accept-Encoding" })
73
- response[2].should.equal(["Hello world!"])
74
- end
75
-
76
- specify "should be able to skip when there is no response entity body" do
77
- response = build_response(304, [], "gzip")
78
-
79
- response[0].should.equal(304)
80
- response[1].should.equal({})
81
- response[2].should.equal([])
82
- end
83
-
84
- specify "should handle the lack of an acceptable encoding" do
85
- response1 = build_response(200, "Hello world!", "identity;q=0", "PATH_INFO" => "/")
86
- response1[0].should.equal(406)
87
- response1[1].should.equal({"Content-Type" => "text/plain", "Content-Length" => "71"})
88
- response1[2].should.equal(["An acceptable encoding for the requested resource / could not be found."])
89
-
90
- response2 = build_response(200, "Hello world!", "identity;q=0", "SCRIPT_NAME" => "/foo", "PATH_INFO" => "/bar")
91
- response2[0].should.equal(406)
92
- response2[1].should.equal({"Content-Type" => "text/plain", "Content-Length" => "78"})
93
- response2[2].should.equal(["An acceptable encoding for the requested resource /foo/bar could not be found."])
94
- end
95
-
96
- specify "should handle gzip response with Last-Modified header" do
97
- last_modified = Time.now.httpdate
98
-
99
- app = lambda { |env| [200, { "Last-Modified" => last_modified }, ["Hello World!"]] }
100
- request = Rack::MockRequest.env_for("", "HTTP_ACCEPT_ENCODING" => "gzip")
101
- response = Rack::Deflater.new(app).call(request)
102
-
103
- response[0].should.equal(200)
104
- response[1].should.equal({
105
- "Content-Encoding" => "gzip",
106
- "Vary" => "Accept-Encoding",
107
- "Last-Modified" => last_modified
108
- })
109
-
110
- buf = ''
111
- response[2].each { |part| buf << part }
112
- io = StringIO.new(buf)
113
- gz = Zlib::GzipReader.new(io)
114
- gz.read.should.equal("Hello World!")
115
- gz.close
116
- end
117
-
118
- specify "should do nothing when no-transform Cache-Control directive present" do
119
- app = lambda { |env| [200, {'Cache-Control' => 'no-transform'}, ['Hello World!']] }
120
- request = Rack::MockRequest.env_for("", "HTTP_ACCEPT_ENCODING" => "gzip")
121
- response = Rack::Deflater.new(app).call(request)
122
-
123
- response[0].should.equal(200)
124
- response[1].should.not.include "Content-Encoding"
125
- response[2].join.should.equal("Hello World!")
126
- end
127
- end
@@ -1,61 +0,0 @@
1
- require 'test/spec'
2
-
3
- require 'rack/directory'
4
- require 'rack/lint'
5
-
6
- require 'rack/mock'
7
-
8
- context "Rack::Directory" do
9
- DOCROOT = File.expand_path(File.dirname(__FILE__))
10
- FILE_CATCH = proc{|env| [200, {'Content-Type'=>'text/plain', "Content-Length" => "7"}, ['passed!']] }
11
- app = Rack::Directory.new DOCROOT, FILE_CATCH
12
-
13
- specify "serves directory indices" do
14
- res = Rack::MockRequest.new(Rack::Lint.new(app)).
15
- get("/cgi/")
16
-
17
- res.should.be.ok
18
- res.should =~ /<html><head>/
19
- end
20
-
21
- specify "passes to app if file found" do
22
- res = Rack::MockRequest.new(Rack::Lint.new(app)).
23
- get("/cgi/test")
24
-
25
- res.should.be.ok
26
- res.should =~ /passed!/
27
- end
28
-
29
- specify "serves uri with URL encoded filenames" do
30
- res = Rack::MockRequest.new(Rack::Lint.new(app)).
31
- get("/%63%67%69/") # "/cgi/test"
32
-
33
- res.should.be.ok
34
- res.should =~ /<html><head>/
35
-
36
- res = Rack::MockRequest.new(Rack::Lint.new(app)).
37
- get("/cgi/%74%65%73%74") # "/cgi/test"
38
-
39
- res.should.be.ok
40
- res.should =~ /passed!/
41
- end
42
-
43
- specify "does not allow directory traversal" do
44
- res = Rack::MockRequest.new(Rack::Lint.new(app)).
45
- get("/cgi/../test")
46
-
47
- res.should.be.forbidden
48
-
49
- res = Rack::MockRequest.new(Rack::Lint.new(app)).
50
- get("/cgi/%2E%2E/test")
51
-
52
- res.should.be.forbidden
53
- end
54
-
55
- specify "404s if it can't find the file" do
56
- res = Rack::MockRequest.new(Rack::Lint.new(app)).
57
- get("/cgi/blubb")
58
-
59
- res.should.be.not_found
60
- end
61
- end
@@ -1,89 +0,0 @@
1
- require 'test/spec'
2
- require 'testrequest'
3
-
4
- context "Rack::Handler::FastCGI" do
5
- include TestRequest::Helpers
6
-
7
- setup do
8
- @host = '0.0.0.0'
9
- @port = 9203
10
- end
11
-
12
- # Keep this first.
13
- specify "startup" do
14
- $pid = fork {
15
- Dir.chdir(File.join(File.dirname(__FILE__), "..", "test", "cgi"))
16
- exec "lighttpd -D -f lighttpd.conf"
17
- }
18
- end
19
-
20
- specify "should respond" do
21
- sleep 1
22
- lambda {
23
- GET("/test.fcgi")
24
- }.should.not.raise
25
- end
26
-
27
- specify "should be a lighttpd" do
28
- GET("/test.fcgi")
29
- status.should.be 200
30
- response["SERVER_SOFTWARE"].should =~ /lighttpd/
31
- response["HTTP_VERSION"].should.equal "HTTP/1.1"
32
- response["SERVER_PROTOCOL"].should.equal "HTTP/1.1"
33
- response["SERVER_PORT"].should.equal @port.to_s
34
- response["SERVER_NAME"].should =~ @host
35
- end
36
-
37
- specify "should have rack headers" do
38
- GET("/test.fcgi")
39
- response["rack.version"].should.equal [1,0]
40
- response["rack.multithread"].should.be false
41
- response["rack.multiprocess"].should.be true
42
- response["rack.run_once"].should.be false
43
- end
44
-
45
- specify "should have CGI headers on GET" do
46
- GET("/test.fcgi")
47
- response["REQUEST_METHOD"].should.equal "GET"
48
- response["SCRIPT_NAME"].should.equal "/test.fcgi"
49
- response["REQUEST_PATH"].should.equal "/"
50
- response["PATH_INFO"].should.be.nil
51
- response["QUERY_STRING"].should.equal ""
52
- response["test.postdata"].should.equal ""
53
-
54
- GET("/test.fcgi/foo?quux=1")
55
- response["REQUEST_METHOD"].should.equal "GET"
56
- response["SCRIPT_NAME"].should.equal "/test.fcgi"
57
- response["REQUEST_PATH"].should.equal "/"
58
- response["PATH_INFO"].should.equal "/foo"
59
- response["QUERY_STRING"].should.equal "quux=1"
60
- end
61
-
62
- specify "should have CGI headers on POST" do
63
- POST("/test.fcgi", {"rack-form-data" => "23"}, {'X-test-header' => '42'})
64
- status.should.equal 200
65
- response["REQUEST_METHOD"].should.equal "POST"
66
- response["SCRIPT_NAME"].should.equal "/test.fcgi"
67
- response["REQUEST_PATH"].should.equal "/"
68
- response["QUERY_STRING"].should.equal ""
69
- response["HTTP_X_TEST_HEADER"].should.equal "42"
70
- response["test.postdata"].should.equal "rack-form-data=23"
71
- end
72
-
73
- specify "should support HTTP auth" do
74
- GET("/test.fcgi", {:user => "ruth", :passwd => "secret"})
75
- response["HTTP_AUTHORIZATION"].should.equal "Basic cnV0aDpzZWNyZXQ="
76
- end
77
-
78
- specify "should set status" do
79
- GET("/test.fcgi?secret")
80
- status.should.equal 403
81
- response["rack.url_scheme"].should.equal "http"
82
- end
83
-
84
- # Keep this last.
85
- specify "shutdown" do
86
- Process.kill 15, $pid
87
- Process.wait($pid).should.equal $pid
88
- end
89
- end
@@ -1,75 +0,0 @@
1
- require 'test/spec'
2
-
3
- require 'rack/file'
4
- require 'rack/lint'
5
-
6
- require 'rack/mock'
7
-
8
- context "Rack::File" do
9
- DOCROOT = File.expand_path(File.dirname(__FILE__))
10
-
11
- specify "serves files" do
12
- res = Rack::MockRequest.new(Rack::Lint.new(Rack::File.new(DOCROOT))).
13
- get("/cgi/test")
14
-
15
- res.should.be.ok
16
- res.should =~ /ruby/
17
- end
18
-
19
- specify "sets Last-Modified header" do
20
- res = Rack::MockRequest.new(Rack::Lint.new(Rack::File.new(DOCROOT))).
21
- get("/cgi/test")
22
-
23
- path = File.join(DOCROOT, "/cgi/test")
24
-
25
- res.should.be.ok
26
- res["Last-Modified"].should.equal File.mtime(path).httpdate
27
- end
28
-
29
- specify "serves files with URL encoded filenames" do
30
- res = Rack::MockRequest.new(Rack::Lint.new(Rack::File.new(DOCROOT))).
31
- get("/cgi/%74%65%73%74") # "/cgi/test"
32
-
33
- res.should.be.ok
34
- res.should =~ /ruby/
35
- end
36
-
37
- specify "does not allow directory traversal" do
38
- res = Rack::MockRequest.new(Rack::Lint.new(Rack::File.new(DOCROOT))).
39
- get("/cgi/../test")
40
-
41
- res.should.be.forbidden
42
- end
43
-
44
- specify "does not allow directory traversal with encoded periods" do
45
- res = Rack::MockRequest.new(Rack::Lint.new(Rack::File.new(DOCROOT))).
46
- get("/%2E%2E/README")
47
-
48
- res.should.be.forbidden
49
- end
50
-
51
- specify "404s if it can't find the file" do
52
- res = Rack::MockRequest.new(Rack::Lint.new(Rack::File.new(DOCROOT))).
53
- get("/cgi/blubb")
54
-
55
- res.should.be.not_found
56
- end
57
-
58
- specify "detects SystemCallErrors" do
59
- res = Rack::MockRequest.new(Rack::Lint.new(Rack::File.new(DOCROOT))).
60
- get("/cgi")
61
-
62
- res.should.be.not_found
63
- end
64
-
65
- specify "returns bodies that respond to #to_path" do
66
- env = Rack::MockRequest.env_for("/cgi/test")
67
- status, headers, body = Rack::File.new(DOCROOT).call(env)
68
-
69
- path = File.join(DOCROOT, "/cgi/test")
70
-
71
- status.should.equal 200
72
- body.should.respond_to :to_path
73
- body.to_path.should.equal path
74
- end
75
- end
@@ -1,43 +0,0 @@
1
- require 'test/spec'
2
-
3
- require 'rack/handler'
4
-
5
- class Rack::Handler::Lobster; end
6
- class RockLobster; end
7
-
8
- context "Rack::Handler" do
9
- specify "has registered default handlers" do
10
- Rack::Handler.get('cgi').should.equal Rack::Handler::CGI
11
- Rack::Handler.get('fastcgi').should.equal Rack::Handler::FastCGI
12
- Rack::Handler.get('mongrel').should.equal Rack::Handler::Mongrel
13
- Rack::Handler.get('webrick').should.equal Rack::Handler::WEBrick
14
- end
15
-
16
- specify "handler that doesn't exist should raise a NameError" do
17
- lambda {
18
- Rack::Handler.get('boom')
19
- }.should.raise(NameError)
20
- end
21
-
22
- specify "should get unregistered, but already required, handler by name" do
23
- Rack::Handler.get('Lobster').should.equal Rack::Handler::Lobster
24
- end
25
-
26
- specify "should register custom handler" do
27
- Rack::Handler.register('rock_lobster', 'RockLobster')
28
- Rack::Handler.get('rock_lobster').should.equal RockLobster
29
- end
30
-
31
- specify "should not need registration for properly coded handlers even if not already required" do
32
- begin
33
- $:.push "test/unregistered_handler"
34
- Rack::Handler.get('Unregistered').should.equal Rack::Handler::Unregistered
35
- lambda {
36
- Rack::Handler.get('UnRegistered')
37
- }.should.raise(NameError)
38
- Rack::Handler.get('UnregisteredLongOne').should.equal Rack::Handler::UnregisteredLongOne
39
- ensure
40
- $:.delete "test/unregistered_handler"
41
- end
42
- end
43
- end
@@ -1,30 +0,0 @@
1
- require 'rack/head'
2
- require 'rack/mock'
3
-
4
- context "Rack::Head" do
5
- def test_response(headers = {})
6
- app = lambda { |env| [200, {"Content-type" => "test/plain", "Content-length" => "3"}, ["foo"]] }
7
- request = Rack::MockRequest.env_for("/", headers)
8
- response = Rack::Head.new(app).call(request)
9
-
10
- return response
11
- end
12
-
13
- specify "passes GET, POST, PUT, DELETE, OPTIONS, TRACE requests" do
14
- %w[GET POST PUT DELETE OPTIONS TRACE].each do |type|
15
- resp = test_response("REQUEST_METHOD" => type)
16
-
17
- resp[0].should.equal(200)
18
- resp[1].should.equal({"Content-type" => "test/plain", "Content-length" => "3"})
19
- resp[2].should.equal(["foo"])
20
- end
21
- end
22
-
23
- specify "removes body from HEAD requests" do
24
- resp = test_response("REQUEST_METHOD" => "HEAD")
25
-
26
- resp[0].should.equal(200)
27
- resp[1].should.equal({"Content-type" => "test/plain", "Content-length" => "3"})
28
- resp[2].should.equal([])
29
- end
30
- end