rack 2.0.6 → 2.1.0

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 (187) hide show
  1. checksums.yaml +4 -4
  2. data/{HISTORY.md → CHANGELOG.md} +220 -155
  3. data/{COPYING → MIT-LICENSE} +4 -2
  4. data/README.rdoc +77 -117
  5. data/Rakefile +25 -18
  6. data/SPEC +3 -4
  7. data/bin/rackup +1 -0
  8. data/example/lobster.ru +2 -0
  9. data/example/protectedlobster.rb +3 -1
  10. data/example/protectedlobster.ru +2 -0
  11. data/lib/rack/auth/abstract/handler.rb +3 -1
  12. data/lib/rack/auth/abstract/request.rb +2 -0
  13. data/lib/rack/auth/basic.rb +4 -1
  14. data/lib/rack/auth/digest/md5.rb +9 -7
  15. data/lib/rack/auth/digest/nonce.rb +6 -3
  16. data/lib/rack/auth/digest/params.rb +4 -2
  17. data/lib/rack/auth/digest/request.rb +2 -0
  18. data/lib/rack/body_proxy.rb +3 -6
  19. data/lib/rack/builder.rb +38 -15
  20. data/lib/rack/cascade.rb +6 -5
  21. data/lib/rack/chunked.rb +29 -6
  22. data/lib/rack/common_logger.rb +9 -8
  23. data/lib/rack/conditional_get.rb +3 -1
  24. data/lib/rack/config.rb +2 -0
  25. data/lib/rack/content_length.rb +3 -1
  26. data/lib/rack/content_type.rb +3 -1
  27. data/lib/rack/core_ext/regexp.rb +14 -0
  28. data/lib/rack/deflater.rb +28 -17
  29. data/lib/rack/directory.rb +17 -14
  30. data/lib/rack/etag.rb +3 -1
  31. data/lib/rack/events.rb +5 -3
  32. data/lib/rack/file.rb +5 -173
  33. data/lib/rack/files.rb +178 -0
  34. data/lib/rack/handler/cgi.rb +3 -1
  35. data/lib/rack/handler/fastcgi.rb +4 -2
  36. data/lib/rack/handler/lsws.rb +3 -1
  37. data/lib/rack/handler/scgi.rb +9 -6
  38. data/lib/rack/handler/thin.rb +3 -1
  39. data/lib/rack/handler/webrick.rb +4 -2
  40. data/lib/rack/handler.rb +7 -2
  41. data/lib/rack/head.rb +2 -0
  42. data/lib/rack/lint.rb +14 -11
  43. data/lib/rack/lobster.rb +7 -5
  44. data/lib/rack/lock.rb +2 -0
  45. data/lib/rack/logger.rb +2 -0
  46. data/lib/rack/media_type.rb +10 -5
  47. data/lib/rack/method_override.rb +4 -2
  48. data/lib/rack/mime.rb +9 -1
  49. data/lib/rack/mock.rb +74 -15
  50. data/lib/rack/multipart/generator.rb +6 -7
  51. data/lib/rack/multipart/parser.rb +55 -52
  52. data/lib/rack/multipart/uploaded_file.rb +2 -0
  53. data/lib/rack/multipart.rb +5 -3
  54. data/lib/rack/null_logger.rb +2 -0
  55. data/lib/rack/query_parser.rb +51 -25
  56. data/lib/rack/recursive.rb +7 -5
  57. data/lib/rack/reloader.rb +10 -4
  58. data/lib/rack/request.rb +80 -27
  59. data/lib/rack/response.rb +71 -31
  60. data/lib/rack/rewindable_input.rb +4 -2
  61. data/lib/rack/runtime.rb +4 -2
  62. data/lib/rack/sendfile.rb +15 -8
  63. data/lib/rack/server.rb +88 -16
  64. data/lib/rack/session/abstract/id.rb +104 -21
  65. data/lib/rack/session/cookie.rb +21 -11
  66. data/lib/rack/session/memcache.rb +4 -87
  67. data/lib/rack/session/pool.rb +17 -8
  68. data/lib/rack/show_exceptions.rb +15 -9
  69. data/lib/rack/show_status.rb +4 -2
  70. data/lib/rack/static.rb +15 -10
  71. data/lib/rack/tempfile_reaper.rb +2 -0
  72. data/lib/rack/urlmap.rb +11 -2
  73. data/lib/rack/utils.rb +55 -70
  74. data/lib/rack.rb +63 -60
  75. data/rack.gemspec +17 -7
  76. metadata +30 -171
  77. data/test/builder/an_underscore_app.rb +0 -5
  78. data/test/builder/anything.rb +0 -5
  79. data/test/builder/comment.ru +0 -4
  80. data/test/builder/end.ru +0 -5
  81. data/test/builder/line.ru +0 -1
  82. data/test/builder/options.ru +0 -2
  83. data/test/cgi/assets/folder/test.js +0 -1
  84. data/test/cgi/assets/fonts/font.eot +0 -1
  85. data/test/cgi/assets/images/image.png +0 -1
  86. data/test/cgi/assets/index.html +0 -1
  87. data/test/cgi/assets/javascripts/app.js +0 -1
  88. data/test/cgi/assets/stylesheets/app.css +0 -1
  89. data/test/cgi/lighttpd.conf +0 -26
  90. data/test/cgi/rackup_stub.rb +0 -6
  91. data/test/cgi/sample_rackup.ru +0 -5
  92. data/test/cgi/test +0 -9
  93. data/test/cgi/test+directory/test+file +0 -1
  94. data/test/cgi/test.fcgi +0 -9
  95. data/test/cgi/test.gz +0 -0
  96. data/test/cgi/test.ru +0 -5
  97. data/test/gemloader.rb +0 -10
  98. data/test/helper.rb +0 -34
  99. data/test/multipart/bad_robots +0 -259
  100. data/test/multipart/binary +0 -0
  101. data/test/multipart/content_type_and_no_filename +0 -6
  102. data/test/multipart/empty +0 -10
  103. data/test/multipart/fail_16384_nofile +0 -814
  104. data/test/multipart/file1.txt +0 -1
  105. data/test/multipart/filename_and_modification_param +0 -7
  106. data/test/multipart/filename_and_no_name +0 -6
  107. data/test/multipart/filename_with_encoded_words +0 -7
  108. data/test/multipart/filename_with_escaped_quotes +0 -6
  109. data/test/multipart/filename_with_escaped_quotes_and_modification_param +0 -7
  110. data/test/multipart/filename_with_null_byte +0 -7
  111. data/test/multipart/filename_with_percent_escaped_quotes +0 -6
  112. data/test/multipart/filename_with_single_quote +0 -7
  113. data/test/multipart/filename_with_unescaped_percentages +0 -6
  114. data/test/multipart/filename_with_unescaped_percentages2 +0 -6
  115. data/test/multipart/filename_with_unescaped_percentages3 +0 -6
  116. data/test/multipart/filename_with_unescaped_quotes +0 -6
  117. data/test/multipart/ie +0 -6
  118. data/test/multipart/invalid_character +0 -6
  119. data/test/multipart/mixed_files +0 -21
  120. data/test/multipart/nested +0 -10
  121. data/test/multipart/none +0 -9
  122. data/test/multipart/quoted +0 -15
  123. data/test/multipart/rack-logo.png +0 -0
  124. data/test/multipart/semicolon +0 -6
  125. data/test/multipart/text +0 -15
  126. data/test/multipart/three_files_three_fields +0 -31
  127. data/test/multipart/unity3d_wwwform +0 -11
  128. data/test/multipart/webkit +0 -32
  129. data/test/rackup/config.ru +0 -31
  130. data/test/registering_handler/rack/handler/registering_myself.rb +0 -8
  131. data/test/spec_auth_basic.rb +0 -89
  132. data/test/spec_auth_digest.rb +0 -260
  133. data/test/spec_body_proxy.rb +0 -85
  134. data/test/spec_builder.rb +0 -233
  135. data/test/spec_cascade.rb +0 -63
  136. data/test/spec_cgi.rb +0 -84
  137. data/test/spec_chunked.rb +0 -103
  138. data/test/spec_common_logger.rb +0 -95
  139. data/test/spec_conditional_get.rb +0 -103
  140. data/test/spec_config.rb +0 -23
  141. data/test/spec_content_length.rb +0 -86
  142. data/test/spec_content_type.rb +0 -46
  143. data/test/spec_deflater.rb +0 -375
  144. data/test/spec_directory.rb +0 -148
  145. data/test/spec_etag.rb +0 -108
  146. data/test/spec_events.rb +0 -133
  147. data/test/spec_fastcgi.rb +0 -85
  148. data/test/spec_file.rb +0 -264
  149. data/test/spec_handler.rb +0 -57
  150. data/test/spec_head.rb +0 -46
  151. data/test/spec_lint.rb +0 -515
  152. data/test/spec_lobster.rb +0 -59
  153. data/test/spec_lock.rb +0 -204
  154. data/test/spec_logger.rb +0 -24
  155. data/test/spec_media_type.rb +0 -42
  156. data/test/spec_method_override.rb +0 -110
  157. data/test/spec_mime.rb +0 -51
  158. data/test/spec_mock.rb +0 -359
  159. data/test/spec_multipart.rb +0 -722
  160. data/test/spec_null_logger.rb +0 -21
  161. data/test/spec_recursive.rb +0 -75
  162. data/test/spec_request.rb +0 -1398
  163. data/test/spec_response.rb +0 -510
  164. data/test/spec_rewindable_input.rb +0 -128
  165. data/test/spec_runtime.rb +0 -50
  166. data/test/spec_sendfile.rb +0 -125
  167. data/test/spec_server.rb +0 -193
  168. data/test/spec_session_abstract_id.rb +0 -31
  169. data/test/spec_session_abstract_session_hash.rb +0 -45
  170. data/test/spec_session_cookie.rb +0 -442
  171. data/test/spec_session_memcache.rb +0 -320
  172. data/test/spec_session_pool.rb +0 -210
  173. data/test/spec_show_exceptions.rb +0 -93
  174. data/test/spec_show_status.rb +0 -104
  175. data/test/spec_static.rb +0 -184
  176. data/test/spec_tempfile_reaper.rb +0 -64
  177. data/test/spec_thin.rb +0 -96
  178. data/test/spec_urlmap.rb +0 -237
  179. data/test/spec_utils.rb +0 -742
  180. data/test/spec_version.rb +0 -11
  181. data/test/spec_webrick.rb +0 -206
  182. data/test/static/another/index.html +0 -1
  183. data/test/static/foo.html +0 -1
  184. data/test/static/index.html +0 -1
  185. data/test/testrequest.rb +0 -78
  186. data/test/unregistered_handler/rack/handler/unregistered.rb +0 -7
  187. data/test/unregistered_handler/rack/handler/unregistered_long_one.rb +0 -7
@@ -1,320 +0,0 @@
1
- require 'minitest/autorun'
2
- begin
3
- require 'rack/session/memcache'
4
- require 'rack/lint'
5
- require 'rack/mock'
6
- require 'thread'
7
-
8
- describe Rack::Session::Memcache do
9
- session_key = Rack::Session::Memcache::DEFAULT_OPTIONS[:key]
10
- session_match = /#{session_key}=([0-9a-fA-F]+);/
11
- incrementor = lambda do |env|
12
- env["rack.session"]["counter"] ||= 0
13
- env["rack.session"]["counter"] += 1
14
- Rack::Response.new(env["rack.session"].inspect).to_a
15
- end
16
- drop_session = Rack::Lint.new(proc do |env|
17
- env['rack.session.options'][:drop] = true
18
- incrementor.call(env)
19
- end)
20
- renew_session = Rack::Lint.new(proc do |env|
21
- env['rack.session.options'][:renew] = true
22
- incrementor.call(env)
23
- end)
24
- defer_session = Rack::Lint.new(proc do |env|
25
- env['rack.session.options'][:defer] = true
26
- incrementor.call(env)
27
- end)
28
- skip_session = Rack::Lint.new(proc do |env|
29
- env['rack.session.options'][:skip] = true
30
- incrementor.call(env)
31
- end)
32
- incrementor = Rack::Lint.new(incrementor)
33
-
34
- # test memcache connection
35
- Rack::Session::Memcache.new(incrementor)
36
-
37
- it "faults on no connection" do
38
- lambda {
39
- Rack::Session::Memcache.new(incrementor, :memcache_server => 'nosuchserver')
40
- }.must_raise(RuntimeError).message.must_equal 'No memcache servers'
41
- end
42
-
43
- it "connects to existing server" do
44
- test_pool = MemCache.new(incrementor, :namespace => 'test:rack:session')
45
- test_pool.namespace.must_equal 'test:rack:session'
46
- end
47
-
48
- it "passes options to MemCache" do
49
- pool = Rack::Session::Memcache.new(incrementor, :namespace => 'test:rack:session')
50
- pool.pool.namespace.must_equal 'test:rack:session'
51
- end
52
-
53
- it "creates a new cookie" do
54
- pool = Rack::Session::Memcache.new(incrementor)
55
- res = Rack::MockRequest.new(pool).get("/")
56
- res["Set-Cookie"].must_include "#{session_key}="
57
- res.body.must_equal '{"counter"=>1}'
58
- end
59
-
60
- it "determines session from a cookie" do
61
- pool = Rack::Session::Memcache.new(incrementor)
62
- req = Rack::MockRequest.new(pool)
63
- res = req.get("/")
64
- cookie = res["Set-Cookie"]
65
- req.get("/", "HTTP_COOKIE" => cookie).
66
- body.must_equal '{"counter"=>2}'
67
- req.get("/", "HTTP_COOKIE" => cookie).
68
- body.must_equal '{"counter"=>3}'
69
- end
70
-
71
- it "determines session only from a cookie by default" do
72
- pool = Rack::Session::Memcache.new(incrementor)
73
- req = Rack::MockRequest.new(pool)
74
- res = req.get("/")
75
- sid = res["Set-Cookie"][session_match, 1]
76
- req.get("/?rack.session=#{sid}").
77
- body.must_equal '{"counter"=>1}'
78
- req.get("/?rack.session=#{sid}").
79
- body.must_equal '{"counter"=>1}'
80
- end
81
-
82
- it "determines session from params" do
83
- pool = Rack::Session::Memcache.new(incrementor, :cookie_only => false)
84
- req = Rack::MockRequest.new(pool)
85
- res = req.get("/")
86
- sid = res["Set-Cookie"][session_match, 1]
87
- req.get("/?rack.session=#{sid}").
88
- body.must_equal '{"counter"=>2}'
89
- req.get("/?rack.session=#{sid}").
90
- body.must_equal '{"counter"=>3}'
91
- end
92
-
93
- it "survives nonexistant cookies" do
94
- bad_cookie = "rack.session=blarghfasel"
95
- pool = Rack::Session::Memcache.new(incrementor)
96
- res = Rack::MockRequest.new(pool).
97
- get("/", "HTTP_COOKIE" => bad_cookie)
98
- res.body.must_equal '{"counter"=>1}'
99
- cookie = res["Set-Cookie"][session_match]
100
- cookie.wont_match(/#{bad_cookie}/)
101
- end
102
-
103
- it "maintains freshness" do
104
- pool = Rack::Session::Memcache.new(incrementor, :expire_after => 3)
105
- res = Rack::MockRequest.new(pool).get('/')
106
- res.body.must_include '"counter"=>1'
107
- cookie = res["Set-Cookie"]
108
- res = Rack::MockRequest.new(pool).get('/', "HTTP_COOKIE" => cookie)
109
- res["Set-Cookie"].must_equal cookie
110
- res.body.must_include '"counter"=>2'
111
- puts 'Sleeping to expire session' if $DEBUG
112
- sleep 4
113
- res = Rack::MockRequest.new(pool).get('/', "HTTP_COOKIE" => cookie)
114
- res["Set-Cookie"].wont_equal cookie
115
- res.body.must_include '"counter"=>1'
116
- end
117
-
118
- it "does not send the same session id if it did not change" do
119
- pool = Rack::Session::Memcache.new(incrementor)
120
- req = Rack::MockRequest.new(pool)
121
-
122
- res0 = req.get("/")
123
- cookie = res0["Set-Cookie"][session_match]
124
- res0.body.must_equal '{"counter"=>1}'
125
-
126
- res1 = req.get("/", "HTTP_COOKIE" => cookie)
127
- res1["Set-Cookie"].must_be_nil
128
- res1.body.must_equal '{"counter"=>2}'
129
-
130
- res2 = req.get("/", "HTTP_COOKIE" => cookie)
131
- res2["Set-Cookie"].must_be_nil
132
- res2.body.must_equal '{"counter"=>3}'
133
- end
134
-
135
- it "deletes cookies with :drop option" do
136
- pool = Rack::Session::Memcache.new(incrementor)
137
- req = Rack::MockRequest.new(pool)
138
- drop = Rack::Utils::Context.new(pool, drop_session)
139
- dreq = Rack::MockRequest.new(drop)
140
-
141
- res1 = req.get("/")
142
- session = (cookie = res1["Set-Cookie"])[session_match]
143
- res1.body.must_equal '{"counter"=>1}'
144
-
145
- res2 = dreq.get("/", "HTTP_COOKIE" => cookie)
146
- res2["Set-Cookie"].must_be_nil
147
- res2.body.must_equal '{"counter"=>2}'
148
-
149
- res3 = req.get("/", "HTTP_COOKIE" => cookie)
150
- res3["Set-Cookie"][session_match].wont_equal session
151
- res3.body.must_equal '{"counter"=>1}'
152
- end
153
-
154
- it "provides new session id with :renew option" do
155
- pool = Rack::Session::Memcache.new(incrementor)
156
- req = Rack::MockRequest.new(pool)
157
- renew = Rack::Utils::Context.new(pool, renew_session)
158
- rreq = Rack::MockRequest.new(renew)
159
-
160
- res1 = req.get("/")
161
- session = (cookie = res1["Set-Cookie"])[session_match]
162
- res1.body.must_equal '{"counter"=>1}'
163
-
164
- res2 = rreq.get("/", "HTTP_COOKIE" => cookie)
165
- new_cookie = res2["Set-Cookie"]
166
- new_session = new_cookie[session_match]
167
- new_session.wont_equal session
168
- res2.body.must_equal '{"counter"=>2}'
169
-
170
- res3 = req.get("/", "HTTP_COOKIE" => new_cookie)
171
- res3.body.must_equal '{"counter"=>3}'
172
-
173
- # Old cookie was deleted
174
- res4 = req.get("/", "HTTP_COOKIE" => cookie)
175
- res4.body.must_equal '{"counter"=>1}'
176
- end
177
-
178
- it "omits cookie with :defer option but still updates the state" do
179
- pool = Rack::Session::Memcache.new(incrementor)
180
- count = Rack::Utils::Context.new(pool, incrementor)
181
- defer = Rack::Utils::Context.new(pool, defer_session)
182
- dreq = Rack::MockRequest.new(defer)
183
- creq = Rack::MockRequest.new(count)
184
-
185
- res0 = dreq.get("/")
186
- res0["Set-Cookie"].must_be_nil
187
- res0.body.must_equal '{"counter"=>1}'
188
-
189
- res0 = creq.get("/")
190
- res1 = dreq.get("/", "HTTP_COOKIE" => res0["Set-Cookie"])
191
- res1.body.must_equal '{"counter"=>2}'
192
- res2 = dreq.get("/", "HTTP_COOKIE" => res0["Set-Cookie"])
193
- res2.body.must_equal '{"counter"=>3}'
194
- end
195
-
196
- it "omits cookie and state update with :skip option" do
197
- pool = Rack::Session::Memcache.new(incrementor)
198
- count = Rack::Utils::Context.new(pool, incrementor)
199
- skip = Rack::Utils::Context.new(pool, skip_session)
200
- sreq = Rack::MockRequest.new(skip)
201
- creq = Rack::MockRequest.new(count)
202
-
203
- res0 = sreq.get("/")
204
- res0["Set-Cookie"].must_be_nil
205
- res0.body.must_equal '{"counter"=>1}'
206
-
207
- res0 = creq.get("/")
208
- res1 = sreq.get("/", "HTTP_COOKIE" => res0["Set-Cookie"])
209
- res1.body.must_equal '{"counter"=>2}'
210
- res2 = sreq.get("/", "HTTP_COOKIE" => res0["Set-Cookie"])
211
- res2.body.must_equal '{"counter"=>2}'
212
- end
213
-
214
- it "updates deep hashes correctly" do
215
- hash_check = proc do |env|
216
- session = env['rack.session']
217
- unless session.include? 'test'
218
- session.update :a => :b, :c => { :d => :e },
219
- :f => { :g => { :h => :i} }, 'test' => true
220
- else
221
- session[:f][:g][:h] = :j
222
- end
223
- [200, {}, [session.inspect]]
224
- end
225
- pool = Rack::Session::Memcache.new(hash_check)
226
- req = Rack::MockRequest.new(pool)
227
-
228
- res0 = req.get("/")
229
- session_id = (cookie = res0["Set-Cookie"])[session_match, 1]
230
- ses0 = pool.pool.get(session_id, true)
231
-
232
- req.get("/", "HTTP_COOKIE" => cookie)
233
- ses1 = pool.pool.get(session_id, true)
234
-
235
- ses1.wont_equal ses0
236
- end
237
-
238
- # anyone know how to do this better?
239
- it "cleanly merges sessions when multithreaded" do
240
- skip unless $DEBUG
241
-
242
- warn 'Running multithread test for Session::Memcache'
243
- pool = Rack::Session::Memcache.new(incrementor)
244
- req = Rack::MockRequest.new(pool)
245
-
246
- res = req.get('/')
247
- res.body.must_equal '{"counter"=>1}'
248
- cookie = res["Set-Cookie"]
249
- session_id = cookie[session_match, 1]
250
-
251
- delta_incrementor = lambda do |env|
252
- # emulate disconjoinment of threading
253
- env['rack.session'] = env['rack.session'].dup
254
- Thread.stop
255
- env['rack.session'][(Time.now.usec*rand).to_i] = true
256
- incrementor.call(env)
257
- end
258
- tses = Rack::Utils::Context.new pool, delta_incrementor
259
- treq = Rack::MockRequest.new(tses)
260
- tnum = rand(7).to_i+5
261
- r = Array.new(tnum) do
262
- Thread.new(treq) do |run|
263
- run.get('/', "HTTP_COOKIE" => cookie, 'rack.multithread' => true)
264
- end
265
- end.reverse.map{|t| t.run.join.value }
266
- r.each do |request|
267
- request['Set-Cookie'].must_equal cookie
268
- request.body.must_include '"counter"=>2'
269
- end
270
-
271
- session = pool.pool.get(session_id)
272
- session.size.must_equal tnum+1 # counter
273
- session['counter'].must_equal 2 # meeeh
274
-
275
- tnum = rand(7).to_i+5
276
- r = Array.new(tnum) do
277
- app = Rack::Utils::Context.new pool, time_delta
278
- req = Rack::MockRequest.new app
279
- Thread.new(req) do |run|
280
- run.get('/', "HTTP_COOKIE" => cookie, 'rack.multithread' => true)
281
- end
282
- end.reverse.map{|t| t.run.join.value }
283
- r.each do |request|
284
- request['Set-Cookie'].must_equal cookie
285
- request.body.must_include '"counter"=>3'
286
- end
287
-
288
- session = pool.pool.get(session_id)
289
- session.size.must_equal tnum+1
290
- session['counter'].must_equal 3
291
-
292
- drop_counter = proc do |env|
293
- env['rack.session'].delete 'counter'
294
- env['rack.session']['foo'] = 'bar'
295
- [200, {'Content-Type'=>'text/plain'}, env['rack.session'].inspect]
296
- end
297
- tses = Rack::Utils::Context.new pool, drop_counter
298
- treq = Rack::MockRequest.new(tses)
299
- tnum = rand(7).to_i+5
300
- r = Array.new(tnum) do
301
- Thread.new(treq) do |run|
302
- run.get('/', "HTTP_COOKIE" => cookie, 'rack.multithread' => true)
303
- end
304
- end.reverse.map{|t| t.run.join.value }
305
- r.each do |request|
306
- request['Set-Cookie'].must_equal cookie
307
- request.body.must_include '"foo"=>"bar"'
308
- end
309
-
310
- session = pool.pool.get(session_id)
311
- session.size.must_equal r.size+1
312
- session['counter'].must_be_nil?
313
- session['foo'].must_equal 'bar'
314
- end
315
- end
316
- rescue RuntimeError
317
- $stderr.puts "Skipping Rack::Session::Memcache tests. Start memcached and try again."
318
- rescue LoadError
319
- $stderr.puts "Skipping Rack::Session::Memcache tests (Memcache is required). `gem install memcache-client` and try again."
320
- end
@@ -1,210 +0,0 @@
1
- require 'minitest/autorun'
2
- require 'thread'
3
- require 'rack/lint'
4
- require 'rack/mock'
5
- require 'rack/session/pool'
6
-
7
- describe Rack::Session::Pool do
8
- session_key = Rack::Session::Pool::DEFAULT_OPTIONS[:key]
9
- session_match = /#{session_key}=[0-9a-fA-F]+;/
10
-
11
- incrementor = lambda do |env|
12
- env["rack.session"]["counter"] ||= 0
13
- env["rack.session"]["counter"] += 1
14
- Rack::Response.new(env["rack.session"].inspect).to_a
15
- end
16
-
17
- session_id = Rack::Lint.new(lambda do |env|
18
- Rack::Response.new(env["rack.session"].inspect).to_a
19
- end)
20
-
21
- nothing = Rack::Lint.new(lambda do |env|
22
- Rack::Response.new("Nothing").to_a
23
- end)
24
-
25
- drop_session = Rack::Lint.new(lambda do |env|
26
- env['rack.session.options'][:drop] = true
27
- incrementor.call(env)
28
- end)
29
-
30
- renew_session = Rack::Lint.new(lambda do |env|
31
- env['rack.session.options'][:renew] = true
32
- incrementor.call(env)
33
- end)
34
-
35
- defer_session = Rack::Lint.new(lambda do |env|
36
- env['rack.session.options'][:defer] = true
37
- incrementor.call(env)
38
- end)
39
-
40
- incrementor = Rack::Lint.new(incrementor)
41
-
42
- it "creates a new cookie" do
43
- pool = Rack::Session::Pool.new(incrementor)
44
- res = Rack::MockRequest.new(pool).get("/")
45
- res["Set-Cookie"].must_match(session_match)
46
- res.body.must_equal '{"counter"=>1}'
47
- end
48
-
49
- it "determines session from a cookie" do
50
- pool = Rack::Session::Pool.new(incrementor)
51
- req = Rack::MockRequest.new(pool)
52
- cookie = req.get("/")["Set-Cookie"]
53
- req.get("/", "HTTP_COOKIE" => cookie).
54
- body.must_equal '{"counter"=>2}'
55
- req.get("/", "HTTP_COOKIE" => cookie).
56
- body.must_equal '{"counter"=>3}'
57
- end
58
-
59
- it "survives nonexistant cookies" do
60
- pool = Rack::Session::Pool.new(incrementor)
61
- res = Rack::MockRequest.new(pool).
62
- get("/", "HTTP_COOKIE" => "#{session_key}=blarghfasel")
63
- res.body.must_equal '{"counter"=>1}'
64
- end
65
-
66
- it "does not send the same session id if it did not change" do
67
- pool = Rack::Session::Pool.new(incrementor)
68
- req = Rack::MockRequest.new(pool)
69
-
70
- res0 = req.get("/")
71
- cookie = res0["Set-Cookie"][session_match]
72
- res0.body.must_equal '{"counter"=>1}'
73
- pool.pool.size.must_equal 1
74
-
75
- res1 = req.get("/", "HTTP_COOKIE" => cookie)
76
- res1["Set-Cookie"].must_be_nil
77
- res1.body.must_equal '{"counter"=>2}'
78
- pool.pool.size.must_equal 1
79
-
80
- res2 = req.get("/", "HTTP_COOKIE" => cookie)
81
- res2["Set-Cookie"].must_be_nil
82
- res2.body.must_equal '{"counter"=>3}'
83
- pool.pool.size.must_equal 1
84
- end
85
-
86
- it "deletes cookies with :drop option" do
87
- pool = Rack::Session::Pool.new(incrementor)
88
- req = Rack::MockRequest.new(pool)
89
- drop = Rack::Utils::Context.new(pool, drop_session)
90
- dreq = Rack::MockRequest.new(drop)
91
-
92
- res1 = req.get("/")
93
- session = (cookie = res1["Set-Cookie"])[session_match]
94
- res1.body.must_equal '{"counter"=>1}'
95
- pool.pool.size.must_equal 1
96
-
97
- res2 = dreq.get("/", "HTTP_COOKIE" => cookie)
98
- res2["Set-Cookie"].must_be_nil
99
- res2.body.must_equal '{"counter"=>2}'
100
- pool.pool.size.must_equal 0
101
-
102
- res3 = req.get("/", "HTTP_COOKIE" => cookie)
103
- res3["Set-Cookie"][session_match].wont_equal session
104
- res3.body.must_equal '{"counter"=>1}'
105
- pool.pool.size.must_equal 1
106
- end
107
-
108
- it "provides new session id with :renew option" do
109
- pool = Rack::Session::Pool.new(incrementor)
110
- req = Rack::MockRequest.new(pool)
111
- renew = Rack::Utils::Context.new(pool, renew_session)
112
- rreq = Rack::MockRequest.new(renew)
113
-
114
- res1 = req.get("/")
115
- session = (cookie = res1["Set-Cookie"])[session_match]
116
- res1.body.must_equal '{"counter"=>1}'
117
- pool.pool.size.must_equal 1
118
-
119
- res2 = rreq.get("/", "HTTP_COOKIE" => cookie)
120
- new_cookie = res2["Set-Cookie"]
121
- new_session = new_cookie[session_match]
122
- new_session.wont_equal session
123
- res2.body.must_equal '{"counter"=>2}'
124
- pool.pool.size.must_equal 1
125
-
126
- res3 = req.get("/", "HTTP_COOKIE" => new_cookie)
127
- res3.body.must_equal '{"counter"=>3}'
128
- pool.pool.size.must_equal 1
129
-
130
- res4 = req.get("/", "HTTP_COOKIE" => cookie)
131
- res4.body.must_equal '{"counter"=>1}'
132
- pool.pool.size.must_equal 2
133
- end
134
-
135
- it "omits cookie with :defer option" do
136
- pool = Rack::Session::Pool.new(incrementor)
137
- defer = Rack::Utils::Context.new(pool, defer_session)
138
- dreq = Rack::MockRequest.new(defer)
139
-
140
- res1 = dreq.get("/")
141
- res1["Set-Cookie"].must_be_nil
142
- res1.body.must_equal '{"counter"=>1}'
143
- pool.pool.size.must_equal 1
144
- end
145
-
146
- # anyone know how to do this better?
147
- it "should merge sessions when multithreaded" do
148
- unless $DEBUG
149
- 1.must_equal 1
150
- next
151
- end
152
-
153
- warn 'Running multithread tests for Session::Pool'
154
- pool = Rack::Session::Pool.new(incrementor)
155
- req = Rack::MockRequest.new(pool)
156
-
157
- res = req.get('/')
158
- res.body.must_equal '{"counter"=>1}'
159
- cookie = res["Set-Cookie"]
160
- sess_id = cookie[/#{pool.key}=([^,;]+)/,1]
161
-
162
- delta_incrementor = lambda do |env|
163
- # emulate disconjoinment of threading
164
- env['rack.session'] = env['rack.session'].dup
165
- Thread.stop
166
- env['rack.session'][(Time.now.usec*rand).to_i] = true
167
- incrementor.call(env)
168
- end
169
- tses = Rack::Utils::Context.new pool, delta_incrementor
170
- treq = Rack::MockRequest.new(tses)
171
- tnum = rand(7).to_i+5
172
- r = Array.new(tnum) do
173
- Thread.new(treq) do |run|
174
- run.get('/', "HTTP_COOKIE" => cookie, 'rack.multithread' => true)
175
- end
176
- end.reverse.map{|t| t.run.join.value }
177
- r.each do |resp|
178
- resp['Set-Cookie'].must_equal cookie
179
- resp.body.must_include '"counter"=>2'
180
- end
181
-
182
- session = pool.pool[sess_id]
183
- session.size.must_equal tnum+1 # counter
184
- session['counter'].must_equal 2 # meeeh
185
- end
186
-
187
- it "does not return a cookie if cookie was not read/written" do
188
- app = Rack::Session::Pool.new(nothing)
189
- res = Rack::MockRequest.new(app).get("/")
190
- res["Set-Cookie"].must_be_nil
191
- end
192
-
193
- it "does not return a cookie if cookie was not written (only read)" do
194
- app = Rack::Session::Pool.new(session_id)
195
- res = Rack::MockRequest.new(app).get("/")
196
- res["Set-Cookie"].must_be_nil
197
- end
198
-
199
- it "returns even if not read/written if :expire_after is set" do
200
- app = Rack::Session::Pool.new(nothing, :expire_after => 3600)
201
- res = Rack::MockRequest.new(app).get("/", 'rack.session' => {'not' => 'empty'})
202
- res["Set-Cookie"].wont_be :nil?
203
- end
204
-
205
- it "returns no cookie if no data was written and no session was created previously, even if :expire_after is set" do
206
- app = Rack::Session::Pool.new(nothing, :expire_after => 3600)
207
- res = Rack::MockRequest.new(app).get("/")
208
- res["Set-Cookie"].must_be_nil
209
- end
210
- end
@@ -1,93 +0,0 @@
1
- require 'minitest/autorun'
2
- require 'rack/show_exceptions'
3
- require 'rack/lint'
4
- require 'rack/mock'
5
-
6
- describe Rack::ShowExceptions do
7
- def show_exceptions(app)
8
- Rack::Lint.new Rack::ShowExceptions.new(app)
9
- end
10
-
11
- it "catches exceptions" do
12
- res = nil
13
-
14
- req = Rack::MockRequest.new(
15
- show_exceptions(
16
- lambda{|env| raise RuntimeError }
17
- ))
18
-
19
- res = req.get("/", "HTTP_ACCEPT" => "text/html")
20
-
21
- res.must_be :server_error?
22
- res.status.must_equal 500
23
-
24
- assert_match(res, /RuntimeError/)
25
- assert_match(res, /ShowExceptions/)
26
- end
27
-
28
- it "responds with HTML only to requests accepting HTML" do
29
- res = nil
30
-
31
- req = Rack::MockRequest.new(
32
- show_exceptions(
33
- lambda{|env| raise RuntimeError, "It was never supposed to work" }
34
- ))
35
-
36
- [
37
- # Serve text/html when the client accepts text/html
38
- ["text/html", ["/", {"HTTP_ACCEPT" => "text/html"}]],
39
- ["text/html", ["/", {"HTTP_ACCEPT" => "*/*"}]],
40
- # Serve text/plain when the client does not accept text/html
41
- ["text/plain", ["/"]],
42
- ["text/plain", ["/", {"HTTP_ACCEPT" => "application/json"}]]
43
- ].each do |exmime, rargs|
44
- res = req.get(*rargs)
45
-
46
- res.must_be :server_error?
47
- res.status.must_equal 500
48
-
49
- res.content_type.must_equal exmime
50
-
51
- res.body.must_include "RuntimeError"
52
- res.body.must_include "It was never supposed to work"
53
-
54
- if exmime == "text/html"
55
- res.body.must_include '</html>'
56
- else
57
- res.body.wont_include '</html>'
58
- end
59
- end
60
- end
61
-
62
- it "handles exceptions without a backtrace" do
63
- res = nil
64
-
65
- req = Rack::MockRequest.new(
66
- show_exceptions(
67
- lambda{|env| raise RuntimeError, "", [] }
68
- )
69
- )
70
-
71
- res = req.get("/", "HTTP_ACCEPT" => "text/html")
72
-
73
- res.must_be :server_error?
74
- res.status.must_equal 500
75
-
76
- assert_match(res, /RuntimeError/)
77
- assert_match(res, /ShowExceptions/)
78
- assert_match(res, /unknown location/)
79
- end
80
-
81
- it "knows to prefer plaintext for non-html" do
82
- # We don't need an app for this
83
- exc = Rack::ShowExceptions.new(nil)
84
-
85
- [
86
- [{ "HTTP_ACCEPT" => "text/plain" }, true],
87
- [{ "HTTP_ACCEPT" => "text/foo" }, true],
88
- [{ "HTTP_ACCEPT" => "text/html" }, false]
89
- ].each do |env, expected|
90
- assert_equal(expected, exc.prefers_plaintext?(env))
91
- end
92
- end
93
- end