rack 1.4.7 → 2.1.4

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.

Files changed (183) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +77 -0
  3. data/{COPYING → MIT-LICENSE} +4 -2
  4. data/README.rdoc +122 -456
  5. data/Rakefile +32 -31
  6. data/SPEC +119 -29
  7. data/bin/rackup +1 -0
  8. data/contrib/rack_logo.svg +164 -111
  9. data/example/lobster.ru +2 -0
  10. data/example/protectedlobster.rb +4 -2
  11. data/example/protectedlobster.ru +3 -1
  12. data/lib/rack/auth/abstract/handler.rb +7 -5
  13. data/lib/rack/auth/abstract/request.rb +8 -6
  14. data/lib/rack/auth/basic.rb +5 -2
  15. data/lib/rack/auth/digest/md5.rb +10 -8
  16. data/lib/rack/auth/digest/nonce.rb +6 -3
  17. data/lib/rack/auth/digest/params.rb +5 -4
  18. data/lib/rack/auth/digest/request.rb +4 -2
  19. data/lib/rack/body_proxy.rb +11 -9
  20. data/lib/rack/builder.rb +63 -20
  21. data/lib/rack/cascade.rb +10 -9
  22. data/lib/rack/chunked.rb +45 -11
  23. data/lib/rack/{commonlogger.rb → common_logger.rb} +24 -15
  24. data/lib/rack/{conditionalget.rb → conditional_get.rb} +20 -6
  25. data/lib/rack/config.rb +7 -0
  26. data/lib/rack/content_length.rb +12 -6
  27. data/lib/rack/content_type.rb +4 -2
  28. data/lib/rack/core_ext/regexp.rb +14 -0
  29. data/lib/rack/deflater.rb +73 -42
  30. data/lib/rack/directory.rb +77 -56
  31. data/lib/rack/etag.rb +25 -13
  32. data/lib/rack/events.rb +156 -0
  33. data/lib/rack/file.rb +4 -143
  34. data/lib/rack/files.rb +178 -0
  35. data/lib/rack/handler/cgi.rb +18 -17
  36. data/lib/rack/handler/fastcgi.rb +21 -17
  37. data/lib/rack/handler/lsws.rb +14 -12
  38. data/lib/rack/handler/scgi.rb +27 -21
  39. data/lib/rack/handler/thin.rb +19 -5
  40. data/lib/rack/handler/webrick.rb +66 -24
  41. data/lib/rack/handler.rb +29 -19
  42. data/lib/rack/head.rb +21 -14
  43. data/lib/rack/lint.rb +259 -65
  44. data/lib/rack/lobster.rb +17 -10
  45. data/lib/rack/lock.rb +19 -10
  46. data/lib/rack/logger.rb +4 -2
  47. data/lib/rack/media_type.rb +43 -0
  48. data/lib/rack/method_override.rb +52 -0
  49. data/lib/rack/mime.rb +43 -6
  50. data/lib/rack/mock.rb +109 -44
  51. data/lib/rack/multipart/generator.rb +11 -12
  52. data/lib/rack/multipart/parser.rb +302 -115
  53. data/lib/rack/multipart/uploaded_file.rb +4 -3
  54. data/lib/rack/multipart.rb +40 -9
  55. data/lib/rack/null_logger.rb +39 -0
  56. data/lib/rack/query_parser.rb +218 -0
  57. data/lib/rack/recursive.rb +14 -11
  58. data/lib/rack/reloader.rb +12 -5
  59. data/lib/rack/request.rb +484 -270
  60. data/lib/rack/response.rb +196 -77
  61. data/lib/rack/rewindable_input.rb +5 -14
  62. data/lib/rack/runtime.rb +13 -6
  63. data/lib/rack/sendfile.rb +44 -20
  64. data/lib/rack/server.rb +175 -61
  65. data/lib/rack/session/abstract/id.rb +276 -133
  66. data/lib/rack/session/cookie.rb +75 -40
  67. data/lib/rack/session/memcache.rb +4 -87
  68. data/lib/rack/session/pool.rb +24 -18
  69. data/lib/rack/show_exceptions.rb +392 -0
  70. data/lib/rack/{showstatus.rb → show_status.rb} +11 -9
  71. data/lib/rack/static.rb +65 -38
  72. data/lib/rack/tempfile_reaper.rb +24 -0
  73. data/lib/rack/urlmap.rb +40 -15
  74. data/lib/rack/utils.rb +316 -285
  75. data/lib/rack.rb +78 -23
  76. data/rack.gemspec +26 -19
  77. metadata +44 -209
  78. data/KNOWN-ISSUES +0 -30
  79. data/lib/rack/backports/uri/common_18.rb +0 -56
  80. data/lib/rack/backports/uri/common_192.rb +0 -52
  81. data/lib/rack/backports/uri/common_193.rb +0 -29
  82. data/lib/rack/handler/evented_mongrel.rb +0 -8
  83. data/lib/rack/handler/mongrel.rb +0 -100
  84. data/lib/rack/handler/swiftiplied_mongrel.rb +0 -8
  85. data/lib/rack/methodoverride.rb +0 -33
  86. data/lib/rack/nulllogger.rb +0 -18
  87. data/lib/rack/showexceptions.rb +0 -378
  88. data/test/builder/anything.rb +0 -5
  89. data/test/builder/comment.ru +0 -4
  90. data/test/builder/end.ru +0 -5
  91. data/test/builder/line.ru +0 -1
  92. data/test/builder/options.ru +0 -2
  93. data/test/cgi/assets/folder/test.js +0 -1
  94. data/test/cgi/assets/fonts/font.eot +0 -1
  95. data/test/cgi/assets/images/image.png +0 -1
  96. data/test/cgi/assets/index.html +0 -1
  97. data/test/cgi/assets/javascripts/app.js +0 -1
  98. data/test/cgi/assets/stylesheets/app.css +0 -1
  99. data/test/cgi/lighttpd.conf +0 -26
  100. data/test/cgi/lighttpd.errors +0 -1
  101. data/test/cgi/rackup_stub.rb +0 -6
  102. data/test/cgi/sample_rackup.ru +0 -5
  103. data/test/cgi/test +0 -9
  104. data/test/cgi/test+directory/test+file +0 -1
  105. data/test/cgi/test.fcgi +0 -8
  106. data/test/cgi/test.ru +0 -5
  107. data/test/gemloader.rb +0 -10
  108. data/test/multipart/bad_robots +0 -259
  109. data/test/multipart/binary +0 -0
  110. data/test/multipart/content_type_and_no_filename +0 -6
  111. data/test/multipart/empty +0 -10
  112. data/test/multipart/fail_16384_nofile +0 -814
  113. data/test/multipart/file1.txt +0 -1
  114. data/test/multipart/filename_and_modification_param +0 -7
  115. data/test/multipart/filename_with_escaped_quotes +0 -6
  116. data/test/multipart/filename_with_escaped_quotes_and_modification_param +0 -7
  117. data/test/multipart/filename_with_percent_escaped_quotes +0 -6
  118. data/test/multipart/filename_with_unescaped_percentages +0 -6
  119. data/test/multipart/filename_with_unescaped_percentages2 +0 -6
  120. data/test/multipart/filename_with_unescaped_percentages3 +0 -6
  121. data/test/multipart/filename_with_unescaped_quotes +0 -6
  122. data/test/multipart/ie +0 -6
  123. data/test/multipart/mixed_files +0 -21
  124. data/test/multipart/nested +0 -10
  125. data/test/multipart/none +0 -9
  126. data/test/multipart/semicolon +0 -6
  127. data/test/multipart/text +0 -15
  128. data/test/multipart/three_files_three_fields +0 -31
  129. data/test/multipart/webkit +0 -32
  130. data/test/rackup/config.ru +0 -31
  131. data/test/registering_handler/rack/handler/registering_myself.rb +0 -8
  132. data/test/spec_auth.rb +0 -57
  133. data/test/spec_auth_basic.rb +0 -81
  134. data/test/spec_auth_digest.rb +0 -259
  135. data/test/spec_body_proxy.rb +0 -69
  136. data/test/spec_builder.rb +0 -207
  137. data/test/spec_cascade.rb +0 -61
  138. data/test/spec_cgi.rb +0 -102
  139. data/test/spec_chunked.rb +0 -87
  140. data/test/spec_commonlogger.rb +0 -57
  141. data/test/spec_conditionalget.rb +0 -102
  142. data/test/spec_config.rb +0 -22
  143. data/test/spec_content_length.rb +0 -86
  144. data/test/spec_content_type.rb +0 -45
  145. data/test/spec_deflater.rb +0 -187
  146. data/test/spec_directory.rb +0 -88
  147. data/test/spec_etag.rb +0 -98
  148. data/test/spec_fastcgi.rb +0 -107
  149. data/test/spec_file.rb +0 -200
  150. data/test/spec_handler.rb +0 -59
  151. data/test/spec_head.rb +0 -48
  152. data/test/spec_lint.rb +0 -515
  153. data/test/spec_lobster.rb +0 -58
  154. data/test/spec_lock.rb +0 -167
  155. data/test/spec_logger.rb +0 -23
  156. data/test/spec_methodoverride.rb +0 -72
  157. data/test/spec_mock.rb +0 -269
  158. data/test/spec_mongrel.rb +0 -182
  159. data/test/spec_multipart.rb +0 -479
  160. data/test/spec_nulllogger.rb +0 -23
  161. data/test/spec_recursive.rb +0 -72
  162. data/test/spec_request.rb +0 -955
  163. data/test/spec_response.rb +0 -313
  164. data/test/spec_rewindable_input.rb +0 -118
  165. data/test/spec_runtime.rb +0 -49
  166. data/test/spec_sendfile.rb +0 -90
  167. data/test/spec_server.rb +0 -121
  168. data/test/spec_session_abstract_id.rb +0 -43
  169. data/test/spec_session_cookie.rb +0 -361
  170. data/test/spec_session_memcache.rb +0 -321
  171. data/test/spec_session_pool.rb +0 -209
  172. data/test/spec_showexceptions.rb +0 -92
  173. data/test/spec_showstatus.rb +0 -84
  174. data/test/spec_static.rb +0 -145
  175. data/test/spec_thin.rb +0 -86
  176. data/test/spec_urlmap.rb +0 -213
  177. data/test/spec_utils.rb +0 -554
  178. data/test/spec_webrick.rb +0 -143
  179. data/test/static/another/index.html +0 -1
  180. data/test/static/index.html +0 -1
  181. data/test/testrequest.rb +0 -78
  182. data/test/unregistered_handler/rack/handler/unregistered.rb +0 -7
  183. data/test/unregistered_handler/rack/handler/unregistered_long_one.rb +0 -7
@@ -1,69 +0,0 @@
1
- require 'rack/body_proxy'
2
- require 'stringio'
3
-
4
- describe Rack::BodyProxy do
5
- should 'call each on the wrapped body' do
6
- called = false
7
- proxy = Rack::BodyProxy.new(['foo']) { }
8
- proxy.each do |str|
9
- called = true
10
- str.should.equal 'foo'
11
- end
12
- called.should.equal true
13
- end
14
-
15
- should 'call close on the wrapped body' do
16
- body = StringIO.new
17
- proxy = Rack::BodyProxy.new(body) { }
18
- proxy.close
19
- body.should.be.closed
20
- end
21
-
22
- should 'only call close on the wrapped body if it responds to close' do
23
- body = []
24
- proxy = Rack::BodyProxy.new(body) { }
25
- proc { proxy.close }.should.not.raise
26
- end
27
-
28
- should 'call the passed block on close' do
29
- called = false
30
- proxy = Rack::BodyProxy.new([]) { called = true }
31
- called.should.equal false
32
- proxy.close
33
- called.should.equal true
34
- end
35
-
36
- should 'call the passed block on close even if there is an exception' do
37
- object = Object.new
38
- def object.close() raise "No!" end
39
- called = false
40
-
41
- begin
42
- proxy = Rack::BodyProxy.new(object) { called = true }
43
- called.should.equal false
44
- proxy.close
45
- rescue RuntimeError => e
46
- end
47
-
48
- raise "Expected exception to have been raised" unless e
49
- called.should.equal true
50
- end
51
-
52
- should 'not close more than one time' do
53
- count = 0
54
- proxy = Rack::BodyProxy.new([]) { count += 1; raise "Block invoked more than 1 time!" if count > 1 }
55
- 2.times { proxy.close }
56
- count.should.equal 1
57
- end
58
-
59
- should 'be closed when the callback is triggered' do
60
- closed = false
61
- proxy = Rack::BodyProxy.new([]) { closed = proxy.closed? }
62
- proxy.close
63
- closed.should.equal true
64
- end
65
-
66
- should 'provide an #each method' do
67
- Rack::BodyProxy.method_defined?(:each).should.equal true
68
- end
69
- end
data/test/spec_builder.rb DELETED
@@ -1,207 +0,0 @@
1
- require 'rack/builder'
2
- require 'rack/lint'
3
- require 'rack/mock'
4
- require 'rack/showexceptions'
5
- require 'rack/urlmap'
6
-
7
- class NothingMiddleware
8
- def initialize(app)
9
- @app = app
10
- end
11
- def call(env)
12
- @@env = env
13
- response = @app.call(env)
14
- response
15
- end
16
- def self.env
17
- @@env
18
- end
19
- end
20
-
21
- describe Rack::Builder do
22
- def builder(&block)
23
- Rack::Lint.new Rack::Builder.new(&block)
24
- end
25
-
26
- def builder_to_app(&block)
27
- Rack::Lint.new Rack::Builder.new(&block).to_app
28
- end
29
-
30
- it "supports mapping" do
31
- app = builder_to_app do
32
- map '/' do |outer_env|
33
- run lambda { |inner_env| [200, {"Content-Type" => "text/plain"}, ['root']] }
34
- end
35
- map '/sub' do
36
- run lambda { |inner_env| [200, {"Content-Type" => "text/plain"}, ['sub']] }
37
- end
38
- end
39
- Rack::MockRequest.new(app).get("/").body.to_s.should.equal 'root'
40
- Rack::MockRequest.new(app).get("/sub").body.to_s.should.equal 'sub'
41
- end
42
-
43
- it "doesn't dupe env even when mapping" do
44
- app = builder_to_app do
45
- use NothingMiddleware
46
- map '/' do |outer_env|
47
- run lambda { |inner_env|
48
- inner_env['new_key'] = 'new_value'
49
- [200, {"Content-Type" => "text/plain"}, ['root']]
50
- }
51
- end
52
- end
53
- Rack::MockRequest.new(app).get("/").body.to_s.should.equal 'root'
54
- NothingMiddleware.env['new_key'].should.equal 'new_value'
55
- end
56
-
57
- it "chains apps by default" do
58
- app = builder_to_app do
59
- use Rack::ShowExceptions
60
- run lambda { |env| raise "bzzzt" }
61
- end
62
-
63
- Rack::MockRequest.new(app).get("/").should.be.server_error
64
- Rack::MockRequest.new(app).get("/").should.be.server_error
65
- Rack::MockRequest.new(app).get("/").should.be.server_error
66
- end
67
-
68
- it "has implicit #to_app" do
69
- app = builder do
70
- use Rack::ShowExceptions
71
- run lambda { |env| raise "bzzzt" }
72
- end
73
-
74
- Rack::MockRequest.new(app).get("/").should.be.server_error
75
- Rack::MockRequest.new(app).get("/").should.be.server_error
76
- Rack::MockRequest.new(app).get("/").should.be.server_error
77
- end
78
-
79
- it "supports blocks on use" do
80
- app = builder do
81
- use Rack::ShowExceptions
82
- use Rack::Auth::Basic do |username, password|
83
- 'secret' == password
84
- end
85
-
86
- run lambda { |env| [200, {"Content-Type" => "text/plain"}, ['Hi Boss']] }
87
- end
88
-
89
- response = Rack::MockRequest.new(app).get("/")
90
- response.should.be.client_error
91
- response.status.should.equal 401
92
-
93
- # with auth...
94
- response = Rack::MockRequest.new(app).get("/",
95
- 'HTTP_AUTHORIZATION' => 'Basic ' + ["joe:secret"].pack("m*"))
96
- response.status.should.equal 200
97
- response.body.to_s.should.equal 'Hi Boss'
98
- end
99
-
100
- it "has explicit #to_app" do
101
- app = builder do
102
- use Rack::ShowExceptions
103
- run lambda { |env| raise "bzzzt" }
104
- end
105
-
106
- Rack::MockRequest.new(app).get("/").should.be.server_error
107
- Rack::MockRequest.new(app).get("/").should.be.server_error
108
- Rack::MockRequest.new(app).get("/").should.be.server_error
109
- end
110
-
111
- it "can mix map and run for endpoints" do
112
- app = builder do
113
- map '/sub' do
114
- run lambda { |inner_env| [200, {"Content-Type" => "text/plain"}, ['sub']] }
115
- end
116
- run lambda { |inner_env| [200, {"Content-Type" => "text/plain"}, ['root']] }
117
- end
118
-
119
- Rack::MockRequest.new(app).get("/").body.to_s.should.equal 'root'
120
- Rack::MockRequest.new(app).get("/sub").body.to_s.should.equal 'sub'
121
- end
122
-
123
- it "accepts middleware-only map blocks" do
124
- app = builder do
125
- map('/foo') { use Rack::ShowExceptions }
126
- run lambda { |env| raise "bzzzt" }
127
- end
128
-
129
- proc { Rack::MockRequest.new(app).get("/") }.should.raise(RuntimeError)
130
- Rack::MockRequest.new(app).get("/foo").should.be.server_error
131
- end
132
-
133
- should "initialize apps once" do
134
- app = builder do
135
- class AppClass
136
- def initialize
137
- @called = 0
138
- end
139
- def call(env)
140
- raise "bzzzt" if @called > 0
141
- @called += 1
142
- [200, {'Content-Type' => 'text/plain'}, ['OK']]
143
- end
144
- end
145
-
146
- use Rack::ShowExceptions
147
- run AppClass.new
148
- end
149
-
150
- Rack::MockRequest.new(app).get("/").status.should.equal 200
151
- Rack::MockRequest.new(app).get("/").should.be.server_error
152
- end
153
-
154
- it "allows use after run" do
155
- app = builder do
156
- run lambda { |env| raise "bzzzt" }
157
- use Rack::ShowExceptions
158
- end
159
-
160
- Rack::MockRequest.new(app).get("/").should.be.server_error
161
- Rack::MockRequest.new(app).get("/").should.be.server_error
162
- Rack::MockRequest.new(app).get("/").should.be.server_error
163
- end
164
-
165
- it 'complains about a missing run' do
166
- proc do
167
- Rack::Lint.new Rack::Builder.app { use Rack::ShowExceptions }
168
- end.should.raise(RuntimeError)
169
- end
170
-
171
- describe "parse_file" do
172
- def config_file(name)
173
- File.join(File.dirname(__FILE__), 'builder', name)
174
- end
175
-
176
- it "parses commented options" do
177
- app, options = Rack::Builder.parse_file config_file('options.ru')
178
- options[:debug].should.be.true
179
- Rack::MockRequest.new(app).get("/").body.to_s.should.equal 'OK'
180
- end
181
-
182
- it "removes __END__ before evaluating app" do
183
- app, options = Rack::Builder.parse_file config_file('end.ru')
184
- options = nil # ignored, prevents warning
185
- Rack::MockRequest.new(app).get("/").body.to_s.should.equal 'OK'
186
- end
187
-
188
- it "supports multi-line comments" do
189
- lambda {
190
- Rack::Builder.parse_file config_file('comment.ru')
191
- }.should.not.raise(SyntaxError)
192
- end
193
-
194
- it "requires anything not ending in .ru" do
195
- $: << File.dirname(__FILE__)
196
- app, * = Rack::Builder.parse_file 'builder/anything'
197
- Rack::MockRequest.new(app).get("/").body.to_s.should.equal 'OK'
198
- $:.pop
199
- end
200
-
201
- it "sets __LINE__ correctly" do
202
- app, options = Rack::Builder.parse_file config_file('line.ru')
203
- options = nil # ignored, prevents warning
204
- Rack::MockRequest.new(app).get("/").body.to_s.should.equal '1'
205
- end
206
- end
207
- end
data/test/spec_cascade.rb DELETED
@@ -1,61 +0,0 @@
1
- require 'rack/cascade'
2
- require 'rack/file'
3
- require 'rack/lint'
4
- require 'rack/urlmap'
5
- require 'rack/mock'
6
-
7
- describe Rack::Cascade do
8
- def cascade(*args)
9
- Rack::Lint.new Rack::Cascade.new(*args)
10
- end
11
-
12
- docroot = File.expand_path(File.dirname(__FILE__))
13
- app1 = Rack::File.new(docroot)
14
-
15
- app2 = Rack::URLMap.new("/crash" => lambda { |env| raise "boom" })
16
-
17
- app3 = Rack::URLMap.new("/foo" => lambda { |env|
18
- [200, { "Content-Type" => "text/plain"}, [""]]})
19
-
20
- should "dispatch onward on 404 and 405 by default" do
21
- cascade = cascade([app1, app2, app3])
22
- Rack::MockRequest.new(cascade).get("/cgi/test").should.be.ok
23
- Rack::MockRequest.new(cascade).get("/foo").should.be.ok
24
- Rack::MockRequest.new(cascade).get("/toobad").should.be.not_found
25
- Rack::MockRequest.new(cascade).get("/cgi/../..").should.be.client_error
26
-
27
- # Put is not allowed by Rack::File so it'll 405.
28
- Rack::MockRequest.new(cascade).put("/foo").should.be.ok
29
- end
30
-
31
- should "dispatch onward on whatever is passed" do
32
- cascade = cascade([app1, app2, app3], [404, 403])
33
- Rack::MockRequest.new(cascade).get("/cgi/../bla").should.be.not_found
34
- end
35
-
36
- should "return 404 if empty" do
37
- Rack::MockRequest.new(cascade([])).get('/').should.be.not_found
38
- end
39
-
40
- should "append new app" do
41
- cascade = Rack::Cascade.new([], [404, 403])
42
- Rack::MockRequest.new(cascade).get('/').should.be.not_found
43
- cascade << app2
44
- Rack::MockRequest.new(cascade).get('/cgi/test').should.be.not_found
45
- Rack::MockRequest.new(cascade).get('/cgi/../bla').should.be.not_found
46
- cascade << app1
47
- Rack::MockRequest.new(cascade).get('/cgi/test').should.be.ok
48
- Rack::MockRequest.new(cascade).get('/cgi/../..').should.be.client_error
49
- Rack::MockRequest.new(cascade).get('/foo').should.be.not_found
50
- cascade << app3
51
- Rack::MockRequest.new(cascade).get('/foo').should.be.ok
52
- end
53
-
54
- should "close the body on cascade" do
55
- body = StringIO.new
56
- closer = lambda { |env| [404, {}, body] }
57
- cascade = Rack::Cascade.new([closer, app3], [404])
58
- Rack::MockRequest.new(cascade).get("/foo").should.be.ok
59
- body.should.be.closed
60
- end
61
- end
data/test/spec_cgi.rb DELETED
@@ -1,102 +0,0 @@
1
- begin
2
- require File.expand_path('../testrequest', __FILE__)
3
- require 'rack/handler/cgi'
4
-
5
- describe Rack::Handler::CGI do
6
- extend TestRequest::Helpers
7
-
8
- @host = '127.0.0.1'
9
- @port = 9203
10
-
11
- if `which lighttpd` && !$?.success?
12
- raise "lighttpd not found"
13
- end
14
-
15
- # Keep this first.
16
- $pid = fork {
17
- ENV['RACK_ENV'] = 'deployment'
18
- ENV['RUBYLIB'] = [
19
- File.expand_path('../../lib', __FILE__),
20
- ENV['RUBYLIB'],
21
- ].compact.join(':')
22
-
23
- Dir.chdir(File.expand_path("../cgi", __FILE__)) do
24
- exec "lighttpd -D -f lighttpd.conf"
25
- end
26
- }
27
-
28
- should "respond" do
29
- sleep 1
30
- GET("/test")
31
- response.should.not.be.nil
32
- end
33
-
34
- should "be a lighttpd" do
35
- GET("/test")
36
- status.should.equal 200
37
- response["SERVER_SOFTWARE"].should =~ /lighttpd/
38
- response["HTTP_VERSION"].should.equal "HTTP/1.1"
39
- response["SERVER_PROTOCOL"].should.equal "HTTP/1.1"
40
- response["SERVER_PORT"].should.equal @port.to_s
41
- response["SERVER_NAME"].should.equal @host
42
- end
43
-
44
- should "have rack headers" do
45
- GET("/test")
46
- response["rack.version"].should.equal([1,1])
47
- response["rack.multithread"].should.be.false
48
- response["rack.multiprocess"].should.be.true
49
- response["rack.run_once"].should.be.true
50
- end
51
-
52
- should "have CGI headers on GET" do
53
- GET("/test")
54
- response["REQUEST_METHOD"].should.equal "GET"
55
- response["SCRIPT_NAME"].should.equal "/test"
56
- response["REQUEST_PATH"].should.equal "/"
57
- response["PATH_INFO"].should.be.nil
58
- response["QUERY_STRING"].should.equal ""
59
- response["test.postdata"].should.equal ""
60
-
61
- GET("/test/foo?quux=1")
62
- response["REQUEST_METHOD"].should.equal "GET"
63
- response["SCRIPT_NAME"].should.equal "/test"
64
- response["REQUEST_PATH"].should.equal "/"
65
- response["PATH_INFO"].should.equal "/foo"
66
- response["QUERY_STRING"].should.equal "quux=1"
67
- end
68
-
69
- should "have CGI headers on POST" do
70
- POST("/test", {"rack-form-data" => "23"}, {'X-test-header' => '42'})
71
- status.should.equal 200
72
- response["REQUEST_METHOD"].should.equal "POST"
73
- response["SCRIPT_NAME"].should.equal "/test"
74
- response["REQUEST_PATH"].should.equal "/"
75
- response["QUERY_STRING"].should.equal ""
76
- response["HTTP_X_TEST_HEADER"].should.equal "42"
77
- response["test.postdata"].should.equal "rack-form-data=23"
78
- end
79
-
80
- should "support HTTP auth" do
81
- GET("/test", {:user => "ruth", :passwd => "secret"})
82
- response["HTTP_AUTHORIZATION"].should.equal "Basic cnV0aDpzZWNyZXQ="
83
- end
84
-
85
- should "set status" do
86
- GET("/test?secret")
87
- status.should.equal 403
88
- response["rack.url_scheme"].should.equal "http"
89
- end
90
-
91
- # Keep this last.
92
- should "shutdown" do
93
- Process.kill 15, $pid
94
- Process.wait($pid).should == $pid
95
- end
96
- end
97
-
98
- rescue RuntimeError
99
- $stderr.puts "Skipping Rack::Handler::CGI tests (lighttpd is required). Install lighttpd and try again."
100
- rescue NotImplementedError
101
- $stderr.puts "Your Ruby implemenation or platform does not support fork. Skipping Rack::Handler::CGI tests."
102
- end
data/test/spec_chunked.rb DELETED
@@ -1,87 +0,0 @@
1
- require 'rack/chunked'
2
- require 'rack/lint'
3
- require 'rack/mock'
4
-
5
- describe Rack::Chunked do
6
- ::Enumerator = ::Enumerable::Enumerator unless Object.const_defined?(:Enumerator)
7
-
8
- def chunked(app)
9
- proc do |env|
10
- app = Rack::Chunked.new(app)
11
- response = Rack::Lint.new(app).call(env)
12
- # we want to use body like an array, but it only has #each
13
- response[2] = Enumerator.new(response[2]).to_a
14
- response
15
- end
16
- end
17
-
18
- before do
19
- @env = Rack::MockRequest.
20
- env_for('/', 'HTTP_VERSION' => '1.1', 'REQUEST_METHOD' => 'GET')
21
- end
22
-
23
- should 'chunk responses with no Content-Length' do
24
- app = lambda { |env| [200, {"Content-Type" => "text/plain"}, ['Hello', ' ', 'World!']] }
25
- response = Rack::MockResponse.new(*chunked(app).call(@env))
26
- response.headers.should.not.include 'Content-Length'
27
- response.headers['Transfer-Encoding'].should.equal 'chunked'
28
- response.body.should.equal "5\r\nHello\r\n1\r\n \r\n6\r\nWorld!\r\n0\r\n\r\n"
29
- end
30
-
31
- should 'chunks empty bodies properly' do
32
- app = lambda { |env| [200, {"Content-Type" => "text/plain"}, []] }
33
- response = Rack::MockResponse.new(*chunked(app).call(@env))
34
- response.headers.should.not.include 'Content-Length'
35
- response.headers['Transfer-Encoding'].should.equal 'chunked'
36
- response.body.should.equal "0\r\n\r\n"
37
- end
38
-
39
- should 'chunks encoded bodies properly' do
40
- body = ["\uFFFEHello", " ", "World"].map {|t| t.encode("UTF-16LE") }
41
- app = lambda { |env| [200, {"Content-Type" => "text/plain"}, body] }
42
- response = Rack::MockResponse.new(*chunked(app).call(@env))
43
- response.headers.should.not.include 'Content-Length'
44
- response.headers['Transfer-Encoding'].should.equal 'chunked'
45
- response.body.encoding.to_s.should.equal "ASCII-8BIT"
46
- response.body.should.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"
47
- end if RUBY_VERSION >= "1.9"
48
-
49
- should '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.should.equal 200
55
- headers.should.not.include 'Transfer-Encoding'
56
- headers.should.include 'Content-Length'
57
- body.join.should.equal 'Hello World!'
58
- end
59
-
60
- should '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.should.equal 200
65
- headers.should.not.include 'Transfer-Encoding'
66
- body.join.should.equal 'Hello World!'
67
- end
68
-
69
- should 'not modify response when Transfer-Encoding header already present' do
70
- app = lambda { |env|
71
- [200, {"Content-Type" => "text/plain", 'Transfer-Encoding' => 'identity'}, ['Hello', ' ', 'World!']]
72
- }
73
- status, headers, body = chunked(app).call(@env)
74
- status.should.equal 200
75
- headers['Transfer-Encoding'].should.equal 'identity'
76
- body.join.should.equal 'Hello World!'
77
- end
78
-
79
- [100, 204, 205, 304].each do |status_code|
80
- should "not modify response when status code is #{status_code}" do
81
- app = lambda { |env| [status_code, {}, []] }
82
- status, headers, _ = chunked(app).call(@env)
83
- status.should.equal status_code
84
- headers.should.not.include 'Transfer-Encoding'
85
- end
86
- end
87
- end
@@ -1,57 +0,0 @@
1
- require 'rack/commonlogger'
2
- require 'rack/lint'
3
- require 'rack/mock'
4
-
5
- describe Rack::CommonLogger do
6
- obj = 'foobar'
7
- length = obj.size
8
-
9
- app = Rack::Lint.new lambda { |env|
10
- [200,
11
- {"Content-Type" => "text/html", "Content-Length" => length.to_s},
12
- [obj]]}
13
- app_without_length = Rack::Lint.new lambda { |env|
14
- [200,
15
- {"Content-Type" => "text/html"},
16
- []]}
17
- app_with_zero_length = Rack::Lint.new lambda { |env|
18
- [200,
19
- {"Content-Type" => "text/html", "Content-Length" => "0"},
20
- []]}
21
-
22
- 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
- should "log to anything with +write+" do
30
- log = StringIO.new
31
- Rack::MockRequest.new(Rack::CommonLogger.new(app, log)).get("/")
32
-
33
- log.string.should =~ /"GET \/ " 200 #{length} /
34
- end
35
-
36
- 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
- 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
- 123
52
- end
53
-
54
- def self.obj
55
- "hello world"
56
- end
57
- end
@@ -1,102 +0,0 @@
1
- require 'time'
2
- require 'rack/conditionalget'
3
- require 'rack/mock'
4
-
5
- describe Rack::ConditionalGet do
6
- def conditional_get(app)
7
- Rack::Lint.new Rack::ConditionalGet.new(app)
8
- end
9
-
10
- should "set a 304 status and truncate body when If-Modified-Since hits" do
11
- timestamp = Time.now.httpdate
12
- app = conditional_get(lambda { |env|
13
- [200, {'Last-Modified'=>timestamp}, ['TEST']] })
14
-
15
- response = Rack::MockRequest.new(app).
16
- get("/", 'HTTP_IF_MODIFIED_SINCE' => timestamp)
17
-
18
- response.status.should.equal 304
19
- response.body.should.be.empty
20
- end
21
-
22
- should "set a 304 status and truncate body when If-Modified-Since hits and is higher than current time" do
23
- app = conditional_get(lambda { |env|
24
- [200, {'Last-Modified'=>(Time.now - 3600).httpdate}, ['TEST']] })
25
-
26
- response = Rack::MockRequest.new(app).
27
- get("/", 'HTTP_IF_MODIFIED_SINCE' => Time.now.httpdate)
28
-
29
- response.status.should.equal 304
30
- response.body.should.be.empty
31
- end
32
-
33
- should "set a 304 status and truncate body when If-None-Match hits" do
34
- app = conditional_get(lambda { |env|
35
- [200, {'Etag'=>'1234'}, ['TEST']] })
36
-
37
- response = Rack::MockRequest.new(app).
38
- get("/", 'HTTP_IF_NONE_MATCH' => '1234')
39
-
40
- response.status.should.equal 304
41
- response.body.should.be.empty
42
- end
43
-
44
- should "not set a 304 status if If-Modified-Since hits but Etag does not" do
45
- timestamp = Time.now.httpdate
46
- app = conditional_get(lambda { |env|
47
- [200, {'Last-Modified'=>timestamp, 'Etag'=>'1234', 'Content-Type' => 'text/plain'}, ['TEST']] })
48
-
49
- response = Rack::MockRequest.new(app).
50
- get("/", 'HTTP_IF_MODIFIED_SINCE' => timestamp, 'HTTP_IF_NONE_MATCH' => '4321')
51
-
52
- response.status.should.equal 200
53
- response.body.should.equal 'TEST'
54
- end
55
-
56
- should "set a 304 status and truncate body when both If-None-Match and If-Modified-Since hits" do
57
- timestamp = Time.now.httpdate
58
- app = conditional_get(lambda { |env|
59
- [200, {'Last-Modified'=>timestamp, 'Etag'=>'1234'}, ['TEST']] })
60
-
61
- response = Rack::MockRequest.new(app).
62
- get("/", 'HTTP_IF_MODIFIED_SINCE' => timestamp, 'HTTP_IF_NONE_MATCH' => '1234')
63
-
64
- response.status.should.equal 304
65
- response.body.should.be.empty
66
- end
67
-
68
- should "not affect non-GET/HEAD requests" do
69
- app = conditional_get(lambda { |env|
70
- [200, {'Etag'=>'1234', 'Content-Type' => 'text/plain'}, ['TEST']] })
71
-
72
- response = Rack::MockRequest.new(app).
73
- post("/", 'HTTP_IF_NONE_MATCH' => '1234')
74
-
75
- response.status.should.equal 200
76
- response.body.should.equal 'TEST'
77
- end
78
-
79
- should "not affect non-200 requests" do
80
- app = conditional_get(lambda { |env|
81
- [302, {'Etag'=>'1234', 'Content-Type' => 'text/plain'}, ['TEST']] })
82
-
83
- response = Rack::MockRequest.new(app).
84
- get("/", 'HTTP_IF_NONE_MATCH' => '1234')
85
-
86
- response.status.should.equal 302
87
- response.body.should.equal 'TEST'
88
- end
89
-
90
- should "not affect requests with malformed HTTP_IF_NONE_MATCH" do
91
- bad_timestamp = Time.now.strftime('%Y-%m-%d %H:%M:%S %z')
92
- app = conditional_get(lambda { |env|
93
- [200,{'Last-Modified'=>(Time.now - 3600).httpdate, 'Content-Type' => 'text/plain'}, ['TEST']] })
94
-
95
- response = Rack::MockRequest.new(app).
96
- get("/", 'HTTP_IF_MODIFIED_SINCE' => bad_timestamp)
97
-
98
- response.status.should.equal 200
99
- response.body.should.equal 'TEST'
100
- end
101
-
102
- end