rack 1.1.6 → 1.6.9

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 (212) hide show
  1. checksums.yaml +7 -0
  2. data/COPYING +1 -1
  3. data/HISTORY.md +375 -0
  4. data/KNOWN-ISSUES +23 -0
  5. data/README.rdoc +312 -0
  6. data/Rakefile +124 -0
  7. data/SPEC +125 -32
  8. data/contrib/rack.png +0 -0
  9. data/contrib/rack.svg +150 -0
  10. data/contrib/rack_logo.svg +1 -1
  11. data/contrib/rdoc.css +412 -0
  12. data/example/protectedlobster.rb +1 -1
  13. data/lib/rack/auth/abstract/handler.rb +4 -4
  14. data/lib/rack/auth/abstract/request.rb +7 -5
  15. data/lib/rack/auth/basic.rb +1 -1
  16. data/lib/rack/auth/digest/md5.rb +7 -3
  17. data/lib/rack/auth/digest/nonce.rb +1 -1
  18. data/lib/rack/auth/digest/params.rb +7 -9
  19. data/lib/rack/auth/digest/request.rb +10 -9
  20. data/lib/rack/backports/uri/common_18.rb +56 -0
  21. data/lib/rack/backports/uri/common_192.rb +52 -0
  22. data/lib/rack/backports/uri/common_193.rb +29 -0
  23. data/lib/rack/body_proxy.rb +39 -0
  24. data/lib/rack/builder.rb +106 -22
  25. data/lib/rack/cascade.rb +17 -6
  26. data/lib/rack/chunked.rb +44 -24
  27. data/lib/rack/commonlogger.rb +36 -13
  28. data/lib/rack/conditionalget.rb +49 -17
  29. data/lib/rack/config.rb +5 -0
  30. data/lib/rack/content_length.rb +14 -6
  31. data/lib/rack/content_type.rb +7 -1
  32. data/lib/rack/deflater.rb +73 -15
  33. data/lib/rack/directory.rb +18 -8
  34. data/lib/rack/etag.rb +59 -9
  35. data/lib/rack/file.rb +106 -44
  36. data/lib/rack/handler/cgi.rb +11 -11
  37. data/lib/rack/handler/fastcgi.rb +18 -6
  38. data/lib/rack/handler/lsws.rb +2 -4
  39. data/lib/rack/handler/mongrel.rb +22 -6
  40. data/lib/rack/handler/scgi.rb +16 -8
  41. data/lib/rack/handler/thin.rb +19 -4
  42. data/lib/rack/handler/webrick.rb +72 -19
  43. data/lib/rack/handler.rb +47 -14
  44. data/lib/rack/head.rb +10 -2
  45. data/lib/rack/lint.rb +260 -75
  46. data/lib/rack/lobster.rb +13 -8
  47. data/lib/rack/lock.rb +13 -3
  48. data/lib/rack/logger.rb +0 -2
  49. data/lib/rack/methodoverride.rb +27 -8
  50. data/lib/rack/mime.rb +625 -167
  51. data/lib/rack/mock.rb +78 -53
  52. data/lib/rack/multipart/generator.rb +93 -0
  53. data/lib/rack/multipart/parser.rb +253 -0
  54. data/lib/rack/multipart/uploaded_file.rb +34 -0
  55. data/lib/rack/multipart.rb +34 -0
  56. data/lib/rack/nulllogger.rb +21 -2
  57. data/lib/rack/recursive.rb +10 -5
  58. data/lib/rack/reloader.rb +3 -2
  59. data/lib/rack/request.rb +201 -74
  60. data/lib/rack/response.rb +41 -28
  61. data/lib/rack/rewindable_input.rb +15 -11
  62. data/lib/rack/runtime.rb +16 -3
  63. data/lib/rack/sendfile.rb +47 -29
  64. data/lib/rack/server.rb +223 -47
  65. data/lib/rack/session/abstract/id.rb +289 -30
  66. data/lib/rack/session/cookie.rb +133 -44
  67. data/lib/rack/session/memcache.rb +30 -56
  68. data/lib/rack/session/pool.rb +19 -43
  69. data/lib/rack/showexceptions.rb +53 -15
  70. data/lib/rack/showstatus.rb +14 -7
  71. data/lib/rack/static.rb +124 -12
  72. data/lib/rack/tempfile_reaper.rb +22 -0
  73. data/lib/rack/urlmap.rb +49 -15
  74. data/lib/rack/utils/okjson.rb +600 -0
  75. data/lib/rack/utils.rb +363 -361
  76. data/lib/rack.rb +17 -23
  77. data/rack.gemspec +11 -20
  78. data/test/builder/anything.rb +5 -0
  79. data/test/builder/comment.ru +4 -0
  80. data/test/builder/end.ru +5 -0
  81. data/test/builder/line.ru +1 -0
  82. data/test/builder/options.ru +2 -0
  83. data/test/cgi/assets/folder/test.js +1 -0
  84. data/test/cgi/assets/fonts/font.eot +1 -0
  85. data/test/cgi/assets/images/image.png +1 -0
  86. data/test/cgi/assets/index.html +1 -0
  87. data/test/cgi/assets/javascripts/app.js +1 -0
  88. data/test/cgi/assets/stylesheets/app.css +1 -0
  89. data/test/cgi/lighttpd.conf +26 -0
  90. data/test/cgi/rackup_stub.rb +6 -0
  91. data/test/cgi/sample_rackup.ru +5 -0
  92. data/test/cgi/test +9 -0
  93. data/test/cgi/test+directory/test+file +1 -0
  94. data/test/cgi/test.fcgi +8 -0
  95. data/test/cgi/test.ru +5 -0
  96. data/test/gemloader.rb +10 -0
  97. data/test/multipart/bad_robots +259 -0
  98. data/test/multipart/binary +0 -0
  99. data/test/multipart/content_type_and_no_filename +6 -0
  100. data/test/multipart/empty +10 -0
  101. data/test/multipart/fail_16384_nofile +814 -0
  102. data/test/multipart/file1.txt +1 -0
  103. data/test/multipart/filename_and_modification_param +7 -0
  104. data/test/multipart/filename_and_no_name +6 -0
  105. data/test/multipart/filename_with_escaped_quotes +6 -0
  106. data/test/multipart/filename_with_escaped_quotes_and_modification_param +7 -0
  107. data/test/multipart/filename_with_null_byte +7 -0
  108. data/test/multipart/filename_with_percent_escaped_quotes +6 -0
  109. data/test/multipart/filename_with_unescaped_percentages +6 -0
  110. data/test/multipart/filename_with_unescaped_percentages2 +6 -0
  111. data/test/multipart/filename_with_unescaped_percentages3 +6 -0
  112. data/test/multipart/filename_with_unescaped_quotes +6 -0
  113. data/test/multipart/ie +6 -0
  114. data/test/multipart/invalid_character +6 -0
  115. data/test/multipart/mixed_files +21 -0
  116. data/test/multipart/nested +10 -0
  117. data/test/multipart/none +9 -0
  118. data/test/multipart/semicolon +6 -0
  119. data/test/multipart/text +15 -0
  120. data/test/multipart/three_files_three_fields +31 -0
  121. data/test/multipart/webkit +32 -0
  122. data/test/rackup/config.ru +31 -0
  123. data/test/registering_handler/rack/handler/registering_myself.rb +8 -0
  124. data/test/{spec_rack_auth_basic.rb → spec_auth_basic.rb} +23 -15
  125. data/test/{spec_rack_auth_digest.rb → spec_auth_digest.rb} +56 -29
  126. data/test/spec_body_proxy.rb +85 -0
  127. data/test/spec_builder.rb +223 -0
  128. data/test/{spec_rack_cascade.rb → spec_cascade.rb} +28 -15
  129. data/test/{spec_rack_cgi.rb → spec_cgi.rb} +44 -31
  130. data/test/spec_chunked.rb +101 -0
  131. data/test/spec_commonlogger.rb +93 -0
  132. data/test/spec_conditionalget.rb +102 -0
  133. data/test/{spec_rack_config.rb → spec_config.rb} +6 -8
  134. data/test/spec_content_length.rb +85 -0
  135. data/test/spec_content_type.rb +45 -0
  136. data/test/spec_deflater.rb +339 -0
  137. data/test/{spec_rack_directory.rb → spec_directory.rb} +37 -10
  138. data/test/spec_etag.rb +107 -0
  139. data/test/{spec_rack_fastcgi.rb → spec_fastcgi.rb} +47 -29
  140. data/test/spec_file.rb +221 -0
  141. data/test/spec_handler.rb +72 -0
  142. data/test/spec_head.rb +45 -0
  143. data/test/{spec_rack_lint.rb → spec_lint.rb} +82 -60
  144. data/test/spec_lobster.rb +58 -0
  145. data/test/spec_lock.rb +164 -0
  146. data/test/spec_logger.rb +23 -0
  147. data/test/spec_methodoverride.rb +95 -0
  148. data/test/spec_mime.rb +51 -0
  149. data/test/{spec_rack_mock.rb → spec_mock.rb} +92 -38
  150. data/test/{spec_rack_mongrel.rb → spec_mongrel.rb} +46 -53
  151. data/test/spec_multipart.rb +600 -0
  152. data/test/spec_nulllogger.rb +20 -0
  153. data/test/spec_recursive.rb +72 -0
  154. data/test/spec_request.rb +1227 -0
  155. data/test/spec_response.rb +407 -0
  156. data/test/spec_rewindable_input.rb +118 -0
  157. data/test/spec_runtime.rb +49 -0
  158. data/test/spec_sendfile.rb +130 -0
  159. data/test/spec_server.rb +167 -0
  160. data/test/spec_session_abstract_id.rb +53 -0
  161. data/test/spec_session_cookie.rb +410 -0
  162. data/test/{spec_rack_session_memcache.rb → spec_session_memcache.rb} +119 -71
  163. data/test/{spec_rack_session_pool.rb → spec_session_pool.rb} +106 -69
  164. data/test/spec_showexceptions.rb +85 -0
  165. data/test/spec_showstatus.rb +103 -0
  166. data/test/spec_static.rb +145 -0
  167. data/test/spec_tempfile_reaper.rb +63 -0
  168. data/test/{spec_rack_thin.rb → spec_thin.rb} +35 -35
  169. data/test/{spec_rack_urlmap.rb → spec_urlmap.rb} +40 -19
  170. data/test/spec_utils.rb +647 -0
  171. data/test/spec_version.rb +17 -0
  172. data/test/spec_webrick.rb +184 -0
  173. data/test/static/another/index.html +1 -0
  174. data/test/static/index.html +1 -0
  175. data/test/testrequest.rb +78 -0
  176. data/test/unregistered_handler/rack/handler/unregistered.rb +7 -0
  177. data/test/unregistered_handler/rack/handler/unregistered_long_one.rb +7 -0
  178. metadata +220 -239
  179. data/RDOX +0 -0
  180. data/README +0 -592
  181. data/lib/rack/adapter/camping.rb +0 -22
  182. data/test/spec_auth.rb +0 -57
  183. data/test/spec_rack_builder.rb +0 -84
  184. data/test/spec_rack_camping.rb +0 -55
  185. data/test/spec_rack_chunked.rb +0 -62
  186. data/test/spec_rack_commonlogger.rb +0 -61
  187. data/test/spec_rack_conditionalget.rb +0 -41
  188. data/test/spec_rack_content_length.rb +0 -43
  189. data/test/spec_rack_content_type.rb +0 -30
  190. data/test/spec_rack_deflater.rb +0 -127
  191. data/test/spec_rack_etag.rb +0 -17
  192. data/test/spec_rack_file.rb +0 -75
  193. data/test/spec_rack_handler.rb +0 -43
  194. data/test/spec_rack_head.rb +0 -30
  195. data/test/spec_rack_lobster.rb +0 -45
  196. data/test/spec_rack_lock.rb +0 -38
  197. data/test/spec_rack_logger.rb +0 -21
  198. data/test/spec_rack_methodoverride.rb +0 -60
  199. data/test/spec_rack_nulllogger.rb +0 -13
  200. data/test/spec_rack_recursive.rb +0 -77
  201. data/test/spec_rack_request.rb +0 -594
  202. data/test/spec_rack_response.rb +0 -221
  203. data/test/spec_rack_rewindable_input.rb +0 -118
  204. data/test/spec_rack_runtime.rb +0 -35
  205. data/test/spec_rack_sendfile.rb +0 -86
  206. data/test/spec_rack_session_cookie.rb +0 -92
  207. data/test/spec_rack_showexceptions.rb +0 -21
  208. data/test/spec_rack_showstatus.rb +0 -72
  209. data/test/spec_rack_static.rb +0 -37
  210. data/test/spec_rack_utils.rb +0 -557
  211. data/test/spec_rack_webrick.rb +0 -130
  212. data/test/spec_rackup.rb +0 -164
@@ -1,84 +0,0 @@
1
- require 'test/spec'
2
-
3
- require 'rack/builder'
4
- require 'rack/mock'
5
- require 'rack/showexceptions'
6
- require 'rack/auth/basic'
7
-
8
- context "Rack::Builder" do
9
- specify "chains apps by default" do
10
- app = Rack::Builder.new do
11
- use Rack::ShowExceptions
12
- run lambda { |env| raise "bzzzt" }
13
- end.to_app
14
-
15
- Rack::MockRequest.new(app).get("/").should.be.server_error
16
- Rack::MockRequest.new(app).get("/").should.be.server_error
17
- Rack::MockRequest.new(app).get("/").should.be.server_error
18
- end
19
-
20
- specify "has implicit #to_app" do
21
- app = Rack::Builder.new do
22
- use Rack::ShowExceptions
23
- run lambda { |env| raise "bzzzt" }
24
- end
25
-
26
- Rack::MockRequest.new(app).get("/").should.be.server_error
27
- Rack::MockRequest.new(app).get("/").should.be.server_error
28
- Rack::MockRequest.new(app).get("/").should.be.server_error
29
- end
30
-
31
- specify "supports blocks on use" do
32
- app = Rack::Builder.new do
33
- use Rack::ShowExceptions
34
- use Rack::Auth::Basic do |username, password|
35
- 'secret' == password
36
- end
37
-
38
- run lambda { |env| [200, {}, ['Hi Boss']] }
39
- end
40
-
41
- response = Rack::MockRequest.new(app).get("/")
42
- response.should.be.client_error
43
- response.status.should.equal 401
44
-
45
- # with auth...
46
- response = Rack::MockRequest.new(app).get("/",
47
- 'HTTP_AUTHORIZATION' => 'Basic ' + ["joe:secret"].pack("m*"))
48
- response.status.should.equal 200
49
- response.body.to_s.should.equal 'Hi Boss'
50
- end
51
-
52
- specify "has explicit #to_app" do
53
- app = Rack::Builder.app do
54
- use Rack::ShowExceptions
55
- run lambda { |env| raise "bzzzt" }
56
- end
57
-
58
- Rack::MockRequest.new(app).get("/").should.be.server_error
59
- Rack::MockRequest.new(app).get("/").should.be.server_error
60
- Rack::MockRequest.new(app).get("/").should.be.server_error
61
- end
62
-
63
- specify "apps are initialized once" do
64
- app = Rack::Builder.new do
65
- class AppClass
66
- def initialize
67
- @called = 0
68
- end
69
- def call(env)
70
- raise "bzzzt" if @called > 0
71
- @called += 1
72
- [200, {'Content-Type' => 'text/plain'}, ['OK']]
73
- end
74
- end
75
-
76
- use Rack::ShowExceptions
77
- run AppClass.new
78
- end
79
-
80
- Rack::MockRequest.new(app).get("/").status.should.equal 200
81
- Rack::MockRequest.new(app).get("/").should.be.server_error
82
- end
83
-
84
- end
@@ -1,55 +0,0 @@
1
- require 'test/spec'
2
- require 'stringio'
3
- require 'uri'
4
-
5
- begin
6
- require 'rack/mock'
7
-
8
- $-w, w = nil, $-w # yuck
9
-
10
- # campings dependencies also don't pull this in anymore:
11
- class Object;def meta_def m,&b;(class<<self;self;end).send:define_method,m,&b end end
12
-
13
- require 'camping'
14
- require 'rack/adapter/camping'
15
-
16
- Camping.goes :CampApp
17
- module CampApp
18
- module Controllers
19
- class HW < R('/')
20
- def get
21
- @headers["X-Served-By"] = URI("http://rack.rubyforge.org")
22
- "Camping works!"
23
- end
24
-
25
- def post
26
- "Data: #{input.foo}"
27
- end
28
- end
29
- end
30
- end
31
- $-w = w
32
-
33
- context "Rack::Adapter::Camping" do
34
- specify "works with GET" do
35
- res = Rack::MockRequest.new(Rack::Adapter::Camping.new(CampApp)).
36
- get("/")
37
-
38
- res.should.be.ok
39
- res["Content-Type"].should.equal "text/html"
40
- res["X-Served-By"].should.equal "http://rack.rubyforge.org"
41
-
42
- res.body.should.equal "Camping works!"
43
- end
44
-
45
- specify "works with POST" do
46
- res = Rack::MockRequest.new(Rack::Adapter::Camping.new(CampApp)).
47
- post("/", :input => "foo=bar")
48
-
49
- res.should.be.ok
50
- res.body.should.equal "Data: bar"
51
- end
52
- end
53
- rescue LoadError
54
- $stderr.puts "Skipping Rack::Adapter::Camping tests (Camping is required). `gem install camping` and try again."
55
- end
@@ -1,62 +0,0 @@
1
- require 'rack/mock'
2
- require 'rack/chunked'
3
- require 'rack/utils'
4
-
5
- context "Rack::Chunked" do
6
-
7
- before do
8
- @env = Rack::MockRequest.
9
- env_for('/', 'HTTP_VERSION' => '1.1', 'REQUEST_METHOD' => 'GET')
10
- end
11
-
12
- specify 'chunks responses with no Content-Length' do
13
- app = lambda { |env| [200, {}, ['Hello', ' ', 'World!']] }
14
- response = Rack::MockResponse.new(*Rack::Chunked.new(app).call(@env))
15
- response.headers.should.not.include 'Content-Length'
16
- response.headers['Transfer-Encoding'].should.equal 'chunked'
17
- response.body.should.equal "5\r\nHello\r\n1\r\n \r\n6\r\nWorld!\r\n0\r\n\r\n"
18
- end
19
-
20
- specify 'chunks empty bodies properly' do
21
- app = lambda { |env| [200, {}, []] }
22
- response = Rack::MockResponse.new(*Rack::Chunked.new(app).call(@env))
23
- response.headers.should.not.include 'Content-Length'
24
- response.headers['Transfer-Encoding'].should.equal 'chunked'
25
- response.body.should.equal "0\r\n\r\n"
26
- end
27
-
28
- specify 'does not modify response when Content-Length header present' do
29
- app = lambda { |env| [200, {'Content-Length'=>'12'}, ['Hello', ' ', 'World!']] }
30
- status, headers, body = Rack::Chunked.new(app).call(@env)
31
- status.should.equal 200
32
- headers.should.not.include 'Transfer-Encoding'
33
- headers.should.include 'Content-Length'
34
- body.join.should.equal 'Hello World!'
35
- end
36
-
37
- specify 'does not modify response when client is HTTP/1.0' do
38
- app = lambda { |env| [200, {}, ['Hello', ' ', 'World!']] }
39
- @env['HTTP_VERSION'] = 'HTTP/1.0'
40
- status, headers, body = Rack::Chunked.new(app).call(@env)
41
- status.should.equal 200
42
- headers.should.not.include 'Transfer-Encoding'
43
- body.join.should.equal 'Hello World!'
44
- end
45
-
46
- specify 'does not modify response when Transfer-Encoding header already present' do
47
- app = lambda { |env| [200, {'Transfer-Encoding' => 'identity'}, ['Hello', ' ', 'World!']] }
48
- status, headers, body = Rack::Chunked.new(app).call(@env)
49
- status.should.equal 200
50
- headers['Transfer-Encoding'].should.equal 'identity'
51
- body.join.should.equal 'Hello World!'
52
- end
53
-
54
- [100, 204, 304].each do |status_code|
55
- specify "does not modify response when status code is #{status_code}" do
56
- app = lambda { |env| [status_code, {}, []] }
57
- status, headers, body = Rack::Chunked.new(app).call(@env)
58
- status.should.equal status_code
59
- headers.should.not.include 'Transfer-Encoding'
60
- end
61
- end
62
- end
@@ -1,61 +0,0 @@
1
- require 'test/spec'
2
- require 'stringio'
3
-
4
- require 'rack/commonlogger'
5
- require 'rack/lobster'
6
- require 'rack/mock'
7
-
8
- context "Rack::CommonLogger" do
9
- app = lambda { |env|
10
- [200,
11
- {"Content-Type" => "text/html", "Content-Length" => length.to_s},
12
- [obj]]}
13
- app_without_length = lambda { |env|
14
- [200,
15
- {"Content-Type" => "text/html"},
16
- []]}
17
- app_with_zero_length = lambda { |env|
18
- [200,
19
- {"Content-Type" => "text/html", "Content-Length" => "0"},
20
- []]}
21
-
22
- specify "should log to rack.errors by default" do
23
- res = Rack::MockRequest.new(Rack::CommonLogger.new(app)).get("/")
24
-
25
- res.errors.should.not.be.empty
26
- res.errors.should =~ /"GET \/ " 200 #{length} /
27
- end
28
-
29
- specify "should log to anything with +write+" do
30
- log = StringIO.new
31
- res = Rack::MockRequest.new(Rack::CommonLogger.new(app, log)).get("/")
32
-
33
- log.string.should =~ /"GET \/ " 200 #{length} /
34
- end
35
-
36
- specify "should log - content length if header is missing" do
37
- res = Rack::MockRequest.new(Rack::CommonLogger.new(app_without_length)).get("/")
38
-
39
- res.errors.should.not.be.empty
40
- res.errors.should =~ /"GET \/ " 200 - /
41
- end
42
-
43
- specify "should log - content length if header is zero" do
44
- res = Rack::MockRequest.new(Rack::CommonLogger.new(app_with_zero_length)).get("/")
45
-
46
- res.errors.should.not.be.empty
47
- res.errors.should =~ /"GET \/ " 200 - /
48
- end
49
-
50
- def length
51
- self.class.length
52
- end
53
-
54
- def self.length
55
- 123
56
- end
57
-
58
- def self.obj
59
- "hello world"
60
- end
61
- end
@@ -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,17 +0,0 @@
1
- require 'test/spec'
2
- require 'rack/mock'
3
- require 'rack/etag'
4
-
5
- context "Rack::ETag" do
6
- specify "sets ETag if none is set" do
7
- app = lambda { |env| [200, {'Content-Type' => 'text/plain'}, ["Hello, World!"]] }
8
- response = Rack::ETag.new(app).call({})
9
- response[1]['ETag'].should.equal "\"65a8e27d8879283831b664bd8b7f0ad4\""
10
- end
11
-
12
- specify "does not change ETag if it is already set" do
13
- app = lambda { |env| [200, {'Content-Type' => 'text/plain', 'ETag' => '"abc"'}, ["Hello, World!"]] }
14
- response = Rack::ETag.new(app).call({})
15
- response[1]['ETag'].should.equal "\"abc\""
16
- end
17
- 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__)) unless defined? DOCROOT
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