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,12 +1,10 @@
1
- require 'test/spec'
2
-
3
1
  begin
4
2
  require 'rack/session/memcache'
3
+ require 'rack/lint'
5
4
  require 'rack/mock'
6
- require 'rack/response'
7
5
  require 'thread'
8
6
 
9
- context "Rack::Session::Memcache" do
7
+ describe Rack::Session::Memcache do
10
8
  session_key = Rack::Session::Memcache::DEFAULT_OPTIONS[:key]
11
9
  session_match = /#{session_key}=([0-9a-fA-F]+);/
12
10
  incrementor = lambda do |env|
@@ -14,43 +12,51 @@ begin
14
12
  env["rack.session"]["counter"] += 1
15
13
  Rack::Response.new(env["rack.session"].inspect).to_a
16
14
  end
17
- drop_session = proc do |env|
15
+ drop_session = Rack::Lint.new(proc do |env|
18
16
  env['rack.session.options'][:drop] = true
19
17
  incrementor.call(env)
20
- end
21
- renew_session = proc do |env|
18
+ end)
19
+ renew_session = Rack::Lint.new(proc do |env|
22
20
  env['rack.session.options'][:renew] = true
23
21
  incrementor.call(env)
24
- end
25
- defer_session = proc do |env|
22
+ end)
23
+ defer_session = Rack::Lint.new(proc do |env|
26
24
  env['rack.session.options'][:defer] = true
27
25
  incrementor.call(env)
26
+ end)
27
+ skip_session = Rack::Lint.new(proc do |env|
28
+ env['rack.session.options'][:skip] = true
29
+ incrementor.call(env)
30
+ end)
31
+ incrementor = Rack::Lint.new(incrementor)
32
+
33
+ # test memcache connection
34
+ Rack::Session::Memcache.new(incrementor)
35
+
36
+ it "faults on no connection" do
37
+ lambda{
38
+ Rack::Session::Memcache.new(incrementor, :memcache_server => 'nosuchserver')
39
+ }.should.raise
28
40
  end
29
41
 
30
- specify "faults on no connection" do
31
- if RUBY_VERSION < "1.9"
32
- lambda do
33
- Rack::Session::Memcache.new incrementor, :memcache_server => 'nosuchserver'
34
- end.should.raise
35
- else
36
- lambda do
37
- Rack::Session::Memcache.new incrementor, :memcache_server => 'nosuchserver'
38
- end.should.raise ArgumentError
39
- end
42
+ it "connects to existing server" do
43
+ test_pool = MemCache.new(incrementor, :namespace => 'test:rack:session')
44
+ test_pool.namespace.should.equal 'test:rack:session'
40
45
  end
41
46
 
42
- specify "connect to existing server" do
43
- test_pool = MemCache.new incrementor, :namespace => 'test:rack:session'
47
+ it "passes options to MemCache" do
48
+ pool = Rack::Session::Memcache.new(incrementor, :namespace => 'test:rack:session')
49
+ pool.pool.namespace.should.equal 'test:rack:session'
44
50
  end
45
51
 
46
- specify "creates a new cookie" do
52
+ it "creates a new cookie" do
47
53
  pool = Rack::Session::Memcache.new(incrementor)
48
54
  res = Rack::MockRequest.new(pool).get("/")
49
- res["Set-Cookie"].should.match("#{session_key}=")
55
+ res["Set-Cookie"].should.include("#{session_key}=")
50
56
  res.body.should.equal '{"counter"=>1}'
51
57
  end
52
58
 
53
- specify "determines session from a cookie" do
59
+ it "determines session from a cookie" do
54
60
  pool = Rack::Session::Memcache.new(incrementor)
55
61
  req = Rack::MockRequest.new(pool)
56
62
  res = req.get("/")
@@ -61,7 +67,29 @@ begin
61
67
  body.should.equal '{"counter"=>3}'
62
68
  end
63
69
 
64
- specify "survives nonexistant cookies" do
70
+ it "determines session only from a cookie by default" do
71
+ pool = Rack::Session::Memcache.new(incrementor)
72
+ req = Rack::MockRequest.new(pool)
73
+ res = req.get("/")
74
+ sid = res["Set-Cookie"][session_match, 1]
75
+ req.get("/?rack.session=#{sid}").
76
+ body.should.equal '{"counter"=>1}'
77
+ req.get("/?rack.session=#{sid}").
78
+ body.should.equal '{"counter"=>1}'
79
+ end
80
+
81
+ it "determines session from params" do
82
+ pool = Rack::Session::Memcache.new(incrementor, :cookie_only => false)
83
+ req = Rack::MockRequest.new(pool)
84
+ res = req.get("/")
85
+ sid = res["Set-Cookie"][session_match, 1]
86
+ req.get("/?rack.session=#{sid}").
87
+ body.should.equal '{"counter"=>2}'
88
+ req.get("/?rack.session=#{sid}").
89
+ body.should.equal '{"counter"=>3}'
90
+ end
91
+
92
+ it "survives nonexistant cookies" do
65
93
  bad_cookie = "rack.session=blarghfasel"
66
94
  pool = Rack::Session::Memcache.new(incrementor)
67
95
  res = Rack::MockRequest.new(pool).
@@ -71,7 +99,7 @@ begin
71
99
  cookie.should.not.match(/#{bad_cookie}/)
72
100
  end
73
101
 
74
- specify "maintains freshness" do
102
+ it "maintains freshness" do
75
103
  pool = Rack::Session::Memcache.new(incrementor, :expire_after => 3)
76
104
  res = Rack::MockRequest.new(pool).get('/')
77
105
  res.body.should.include '"counter"=>1'
@@ -86,79 +114,103 @@ begin
86
114
  res.body.should.include '"counter"=>1'
87
115
  end
88
116
 
89
- specify "deletes cookies with :drop option" do
117
+ it "does not send the same session id if it did not change" do
90
118
  pool = Rack::Session::Memcache.new(incrementor)
91
119
  req = Rack::MockRequest.new(pool)
92
- drop = Rack::Utils::Context.new(pool, drop_session)
93
- dreq = Rack::MockRequest.new(drop)
94
120
 
95
121
  res0 = req.get("/")
96
- session = (cookie = res0["Set-Cookie"])[session_match]
122
+ cookie = res0["Set-Cookie"][session_match]
97
123
  res0.body.should.equal '{"counter"=>1}'
98
124
 
99
125
  res1 = req.get("/", "HTTP_COOKIE" => cookie)
100
- res1["Set-Cookie"][session_match].should.equal session
126
+ res1["Set-Cookie"].should.be.nil
101
127
  res1.body.should.equal '{"counter"=>2}'
102
128
 
129
+ res2 = req.get("/", "HTTP_COOKIE" => cookie)
130
+ res2["Set-Cookie"].should.be.nil
131
+ res2.body.should.equal '{"counter"=>3}'
132
+ end
133
+
134
+ it "deletes cookies with :drop option" do
135
+ pool = Rack::Session::Memcache.new(incrementor)
136
+ req = Rack::MockRequest.new(pool)
137
+ drop = Rack::Utils::Context.new(pool, drop_session)
138
+ dreq = Rack::MockRequest.new(drop)
139
+
140
+ res1 = req.get("/")
141
+ session = (cookie = res1["Set-Cookie"])[session_match]
142
+ res1.body.should.equal '{"counter"=>1}'
143
+
103
144
  res2 = dreq.get("/", "HTTP_COOKIE" => cookie)
104
145
  res2["Set-Cookie"].should.equal nil
105
- res2.body.should.equal '{"counter"=>3}'
146
+ res2.body.should.equal '{"counter"=>2}'
106
147
 
107
148
  res3 = req.get("/", "HTTP_COOKIE" => cookie)
108
149
  res3["Set-Cookie"][session_match].should.not.equal session
109
150
  res3.body.should.equal '{"counter"=>1}'
110
151
  end
111
152
 
112
- specify "provides new session id with :renew option" do
153
+ it "provides new session id with :renew option" do
113
154
  pool = Rack::Session::Memcache.new(incrementor)
114
155
  req = Rack::MockRequest.new(pool)
115
156
  renew = Rack::Utils::Context.new(pool, renew_session)
116
157
  rreq = Rack::MockRequest.new(renew)
117
158
 
118
- res0 = req.get("/")
119
- session = (cookie = res0["Set-Cookie"])[session_match]
120
- res0.body.should.equal '{"counter"=>1}'
121
-
122
- res1 = req.get("/", "HTTP_COOKIE" => cookie)
123
- res1["Set-Cookie"][session_match].should.equal session
124
- res1.body.should.equal '{"counter"=>2}'
159
+ res1 = req.get("/")
160
+ session = (cookie = res1["Set-Cookie"])[session_match]
161
+ res1.body.should.equal '{"counter"=>1}'
125
162
 
126
163
  res2 = rreq.get("/", "HTTP_COOKIE" => cookie)
127
164
  new_cookie = res2["Set-Cookie"]
128
165
  new_session = new_cookie[session_match]
129
166
  new_session.should.not.equal session
130
- res2.body.should.equal '{"counter"=>3}'
167
+ res2.body.should.equal '{"counter"=>2}'
131
168
 
132
169
  res3 = req.get("/", "HTTP_COOKIE" => new_cookie)
133
- res3["Set-Cookie"][session_match].should.equal new_session
134
- res3.body.should.equal '{"counter"=>4}'
170
+ res3.body.should.equal '{"counter"=>3}'
171
+
172
+ # Old cookie was deleted
173
+ res4 = req.get("/", "HTTP_COOKIE" => cookie)
174
+ res4.body.should.equal '{"counter"=>1}'
135
175
  end
136
176
 
137
- specify "omits cookie with :defer option" do
177
+ it "omits cookie with :defer option but still updates the state" do
138
178
  pool = Rack::Session::Memcache.new(incrementor)
139
- req = Rack::MockRequest.new(pool)
179
+ count = Rack::Utils::Context.new(pool, incrementor)
140
180
  defer = Rack::Utils::Context.new(pool, defer_session)
141
181
  dreq = Rack::MockRequest.new(defer)
182
+ creq = Rack::MockRequest.new(count)
142
183
 
143
- res0 = req.get("/")
144
- session = (cookie = res0["Set-Cookie"])[session_match]
184
+ res0 = dreq.get("/")
185
+ res0["Set-Cookie"].should.equal nil
145
186
  res0.body.should.equal '{"counter"=>1}'
146
187
 
147
- res1 = req.get("/", "HTTP_COOKIE" => cookie)
148
- res1["Set-Cookie"][session_match].should.equal session
188
+ res0 = creq.get("/")
189
+ res1 = dreq.get("/", "HTTP_COOKIE" => res0["Set-Cookie"])
149
190
  res1.body.should.equal '{"counter"=>2}'
150
-
151
- res2 = dreq.get("/", "HTTP_COOKIE" => cookie)
152
- res2["Set-Cookie"].should.equal nil
191
+ res2 = dreq.get("/", "HTTP_COOKIE" => res0["Set-Cookie"])
153
192
  res2.body.should.equal '{"counter"=>3}'
193
+ end
154
194
 
155
- res3 = req.get("/", "HTTP_COOKIE" => cookie)
156
- res3["Set-Cookie"][session_match].should.equal session
157
- res3.body.should.equal '{"counter"=>4}'
195
+ it "omits cookie and state update with :skip option" do
196
+ pool = Rack::Session::Memcache.new(incrementor)
197
+ count = Rack::Utils::Context.new(pool, incrementor)
198
+ skip = Rack::Utils::Context.new(pool, skip_session)
199
+ sreq = Rack::MockRequest.new(skip)
200
+ creq = Rack::MockRequest.new(count)
201
+
202
+ res0 = sreq.get("/")
203
+ res0["Set-Cookie"].should.equal nil
204
+ res0.body.should.equal '{"counter"=>1}'
205
+
206
+ res0 = creq.get("/")
207
+ res1 = sreq.get("/", "HTTP_COOKIE" => res0["Set-Cookie"])
208
+ res1.body.should.equal '{"counter"=>2}'
209
+ res2 = sreq.get("/", "HTTP_COOKIE" => res0["Set-Cookie"])
210
+ res2.body.should.equal '{"counter"=>2}'
158
211
  end
159
212
 
160
- specify "deep hashes are correctly updated" do
161
- store = nil
213
+ it "updates deep hashes correctly" do
162
214
  hash_check = proc do |env|
163
215
  session = env['rack.session']
164
216
  unless session.include? 'test'
@@ -167,7 +219,7 @@ begin
167
219
  else
168
220
  session[:f][:g][:h] = :j
169
221
  end
170
- [200, {}, session.inspect]
222
+ [200, {}, [session.inspect]]
171
223
  end
172
224
  pool = Rack::Session::Memcache.new(hash_check)
173
225
  req = Rack::MockRequest.new(pool)
@@ -176,15 +228,18 @@ begin
176
228
  session_id = (cookie = res0["Set-Cookie"])[session_match, 1]
177
229
  ses0 = pool.pool.get(session_id, true)
178
230
 
179
- res1 = req.get("/", "HTTP_COOKIE" => cookie)
231
+ req.get("/", "HTTP_COOKIE" => cookie)
180
232
  ses1 = pool.pool.get(session_id, true)
181
233
 
182
234
  ses1.should.not.equal ses0
183
235
  end
184
236
 
185
237
  # anyone know how to do this better?
186
- specify "multithread: should cleanly merge sessions" do
187
- next unless $DEBUG
238
+ it "cleanly merges sessions when multithreaded" do
239
+ unless $DEBUG
240
+ 1.should.equal 1 # fake assertion to appease the mighty bacon
241
+ next
242
+ end
188
243
  warn 'Running multithread test for Session::Memcache'
189
244
  pool = Rack::Session::Memcache.new(incrementor)
190
245
  req = Rack::MockRequest.new(pool)
@@ -215,18 +270,11 @@ begin
215
270
  end
216
271
 
217
272
  session = pool.pool.get(session_id)
218
- session.size.should.be tnum+1 # counter
219
- session['counter'].should.be 2 # meeeh
273
+ session.size.should.equal tnum+1 # counter
274
+ session['counter'].should.equal 2 # meeeh
220
275
 
221
276
  tnum = rand(7).to_i+5
222
- r = Array.new(tnum) do |i|
223
- delta_time = proc do |env|
224
- env['rack.session'][i] = Time.now
225
- Thread.stop
226
- env['rack.session'] = env['rack.session'].dup
227
- env['rack.session'][i] -= Time.now
228
- incrementor.call(env)
229
- end
277
+ r = Array.new(tnum) do
230
278
  app = Rack::Utils::Context.new pool, time_delta
231
279
  req = Rack::MockRequest.new app
232
280
  Thread.new(req) do |run|
@@ -1,39 +1,51 @@
1
- require 'test/spec'
2
-
3
- require 'rack/session/pool'
4
- require 'rack/mock'
5
- require 'rack/response'
6
1
  require 'thread'
2
+ require 'rack/lint'
3
+ require 'rack/mock'
4
+ require 'rack/session/pool'
7
5
 
8
- context "Rack::Session::Pool" do
6
+ describe Rack::Session::Pool do
9
7
  session_key = Rack::Session::Pool::DEFAULT_OPTIONS[:key]
10
8
  session_match = /#{session_key}=[0-9a-fA-F]+;/
9
+
11
10
  incrementor = lambda do |env|
12
11
  env["rack.session"]["counter"] ||= 0
13
12
  env["rack.session"]["counter"] += 1
14
13
  Rack::Response.new(env["rack.session"].inspect).to_a
15
14
  end
16
- drop_session = proc do |env|
15
+
16
+ session_id = Rack::Lint.new(lambda do |env|
17
+ Rack::Response.new(env["rack.session"].inspect).to_a
18
+ end)
19
+
20
+ nothing = Rack::Lint.new(lambda do |env|
21
+ Rack::Response.new("Nothing").to_a
22
+ end)
23
+
24
+ drop_session = Rack::Lint.new(lambda do |env|
17
25
  env['rack.session.options'][:drop] = true
18
26
  incrementor.call(env)
19
- end
20
- renew_session = proc do |env|
27
+ end)
28
+
29
+ renew_session = Rack::Lint.new(lambda do |env|
21
30
  env['rack.session.options'][:renew] = true
22
31
  incrementor.call(env)
23
- end
24
- defer_session = proc do |env|
32
+ end)
33
+
34
+ defer_session = Rack::Lint.new(lambda do |env|
25
35
  env['rack.session.options'][:defer] = true
26
36
  incrementor.call(env)
27
- end
37
+ end)
38
+
39
+ incrementor = Rack::Lint.new(incrementor)
28
40
 
29
- specify "creates a new cookie" do
41
+ it "creates a new cookie" do
30
42
  pool = Rack::Session::Pool.new(incrementor)
31
43
  res = Rack::MockRequest.new(pool).get("/")
32
44
  res["Set-Cookie"].should.match session_match
33
45
  res.body.should.equal '{"counter"=>1}'
34
46
  end
35
47
 
36
- specify "determines session from a cookie" do
48
+ it "determines session from a cookie" do
37
49
  pool = Rack::Session::Pool.new(incrementor)
38
50
  req = Rack::MockRequest.new(pool)
39
51
  cookie = req.get("/")["Set-Cookie"]
@@ -43,99 +55,100 @@ context "Rack::Session::Pool" do
43
55
  body.should.equal '{"counter"=>3}'
44
56
  end
45
57
 
46
- specify "survives nonexistant cookies" do
58
+ it "survives nonexistant cookies" do
47
59
  pool = Rack::Session::Pool.new(incrementor)
48
60
  res = Rack::MockRequest.new(pool).
49
61
  get("/", "HTTP_COOKIE" => "#{session_key}=blarghfasel")
50
62
  res.body.should.equal '{"counter"=>1}'
51
63
  end
52
64
 
53
- specify "deletes cookies with :drop option" do
65
+ it "does not send the same session id if it did not change" do
54
66
  pool = Rack::Session::Pool.new(incrementor)
55
67
  req = Rack::MockRequest.new(pool)
56
- drop = Rack::Utils::Context.new(pool, drop_session)
57
- dreq = Rack::MockRequest.new(drop)
58
68
 
59
69
  res0 = req.get("/")
60
- session = (cookie = res0["Set-Cookie"])[session_match]
70
+ cookie = res0["Set-Cookie"][session_match]
61
71
  res0.body.should.equal '{"counter"=>1}'
62
- pool.pool.size.should.be 1
72
+ pool.pool.size.should.equal 1
63
73
 
64
74
  res1 = req.get("/", "HTTP_COOKIE" => cookie)
65
- res1["Set-Cookie"][session_match].should.equal session
75
+ res1["Set-Cookie"].should.be.nil
66
76
  res1.body.should.equal '{"counter"=>2}'
67
- pool.pool.size.should.be 1
77
+ pool.pool.size.should.equal 1
68
78
 
69
- res2 = dreq.get("/", "HTTP_COOKIE" => cookie)
70
- res2["Set-Cookie"].should.equal nil
79
+ res2 = req.get("/", "HTTP_COOKIE" => cookie)
80
+ res2["Set-Cookie"].should.be.nil
71
81
  res2.body.should.equal '{"counter"=>3}'
72
- pool.pool.size.should.be 0
82
+ pool.pool.size.should.equal 1
83
+ end
84
+
85
+ it "deletes cookies with :drop option" do
86
+ pool = Rack::Session::Pool.new(incrementor)
87
+ req = Rack::MockRequest.new(pool)
88
+ drop = Rack::Utils::Context.new(pool, drop_session)
89
+ dreq = Rack::MockRequest.new(drop)
90
+
91
+ res1 = req.get("/")
92
+ session = (cookie = res1["Set-Cookie"])[session_match]
93
+ res1.body.should.equal '{"counter"=>1}'
94
+ pool.pool.size.should.equal 1
95
+
96
+ res2 = dreq.get("/", "HTTP_COOKIE" => cookie)
97
+ res2["Set-Cookie"].should.be.nil
98
+ res2.body.should.equal '{"counter"=>2}'
99
+ pool.pool.size.should.equal 0
73
100
 
74
101
  res3 = req.get("/", "HTTP_COOKIE" => cookie)
75
102
  res3["Set-Cookie"][session_match].should.not.equal session
76
103
  res3.body.should.equal '{"counter"=>1}'
77
- pool.pool.size.should.be 1
104
+ pool.pool.size.should.equal 1
78
105
  end
79
106
 
80
- specify "provides new session id with :renew option" do
107
+ it "provides new session id with :renew option" do
81
108
  pool = Rack::Session::Pool.new(incrementor)
82
109
  req = Rack::MockRequest.new(pool)
83
110
  renew = Rack::Utils::Context.new(pool, renew_session)
84
111
  rreq = Rack::MockRequest.new(renew)
85
112
 
86
- res0 = req.get("/")
87
- session = (cookie = res0["Set-Cookie"])[session_match]
88
- res0.body.should.equal '{"counter"=>1}'
89
- pool.pool.size.should.be 1
90
-
91
- res1 = req.get("/", "HTTP_COOKIE" => cookie)
92
- res1["Set-Cookie"][session_match].should.equal session
93
- res1.body.should.equal '{"counter"=>2}'
94
- pool.pool.size.should.be 1
113
+ res1 = req.get("/")
114
+ session = (cookie = res1["Set-Cookie"])[session_match]
115
+ res1.body.should.equal '{"counter"=>1}'
116
+ pool.pool.size.should.equal 1
95
117
 
96
118
  res2 = rreq.get("/", "HTTP_COOKIE" => cookie)
97
119
  new_cookie = res2["Set-Cookie"]
98
120
  new_session = new_cookie[session_match]
99
121
  new_session.should.not.equal session
100
- res2.body.should.equal '{"counter"=>3}'
101
- pool.pool.size.should.be 1
122
+ res2.body.should.equal '{"counter"=>2}'
123
+ pool.pool.size.should.equal 1
102
124
 
103
125
  res3 = req.get("/", "HTTP_COOKIE" => new_cookie)
104
- res3["Set-Cookie"][session_match].should.equal new_session
105
- res3.body.should.equal '{"counter"=>4}'
106
- pool.pool.size.should.be 1
126
+ res3.body.should.equal '{"counter"=>3}'
127
+ pool.pool.size.should.equal 1
128
+
129
+ res4 = req.get("/", "HTTP_COOKIE" => cookie)
130
+ res4.body.should.equal '{"counter"=>1}'
131
+ pool.pool.size.should.equal 2
107
132
  end
108
133
 
109
- specify "omits cookie with :defer option" do
134
+ it "omits cookie with :defer option" do
110
135
  pool = Rack::Session::Pool.new(incrementor)
111
- req = Rack::MockRequest.new(pool)
112
136
  defer = Rack::Utils::Context.new(pool, defer_session)
113
137
  dreq = Rack::MockRequest.new(defer)
114
138
 
115
- res0 = req.get("/")
116
- session = (cookie = res0["Set-Cookie"])[session_match]
117
- res0.body.should.equal '{"counter"=>1}'
118
- pool.pool.size.should.be 1
119
-
120
- res1 = req.get("/", "HTTP_COOKIE" => cookie)
121
- res1["Set-Cookie"][session_match].should.equal session
122
- res1.body.should.equal '{"counter"=>2}'
123
- pool.pool.size.should.be 1
124
-
125
- res2 = dreq.get("/", "HTTP_COOKIE" => cookie)
126
- res2["Set-Cookie"].should.equal nil
127
- res2.body.should.equal '{"counter"=>3}'
128
- pool.pool.size.should.be 1
129
-
130
- res3 = req.get("/", "HTTP_COOKIE" => cookie)
131
- res3["Set-Cookie"][session_match].should.equal session
132
- res3.body.should.equal '{"counter"=>4}'
133
- pool.pool.size.should.be 1
139
+ res1 = dreq.get("/")
140
+ res1["Set-Cookie"].should.equal nil
141
+ res1.body.should.equal '{"counter"=>1}'
142
+ pool.pool.size.should.equal 1
134
143
  end
135
144
 
136
145
  # anyone know how to do this better?
137
- specify "multithread: should merge sessions" do
138
- next unless $DEBUG
146
+ it "should merge sessions when multithreaded" do
147
+ unless $DEBUG
148
+ 1.should.equal 1
149
+ next
150
+ end
151
+
139
152
  warn 'Running multithread tests for Session::Pool'
140
153
  pool = Rack::Session::Pool.new(incrementor)
141
154
  req = Rack::MockRequest.new(pool)
@@ -160,13 +173,37 @@ context "Rack::Session::Pool" do
160
173
  run.get('/', "HTTP_COOKIE" => cookie, 'rack.multithread' => true)
161
174
  end
162
175
  end.reverse.map{|t| t.run.join.value }
163
- r.each do |res|
164
- res['Set-Cookie'].should.equal cookie
165
- res.body.should.include '"counter"=>2'
176
+ r.each do |resp|
177
+ resp['Set-Cookie'].should.equal cookie
178
+ resp.body.should.include '"counter"=>2'
166
179
  end
167
180
 
168
181
  session = pool.pool[sess_id]
169
- session.size.should.be tnum+1 # counter
170
- session['counter'].should.be 2 # meeeh
182
+ session.size.should.equal tnum+1 # counter
183
+ session['counter'].should.equal 2 # meeeh
184
+ end
185
+
186
+ it "does not return a cookie if cookie was not read/written" do
187
+ app = Rack::Session::Pool.new(nothing)
188
+ res = Rack::MockRequest.new(app).get("/")
189
+ res["Set-Cookie"].should.be.nil
190
+ end
191
+
192
+ it "does not return a cookie if cookie was not written (only read)" do
193
+ app = Rack::Session::Pool.new(session_id)
194
+ res = Rack::MockRequest.new(app).get("/")
195
+ res["Set-Cookie"].should.be.nil
196
+ end
197
+
198
+ it "returns even if not read/written if :expire_after is set" do
199
+ app = Rack::Session::Pool.new(nothing, :expire_after => 3600)
200
+ res = Rack::MockRequest.new(app).get("/", 'rack.session' => {'not' => 'empty'})
201
+ res["Set-Cookie"].should.not.be.nil
202
+ end
203
+
204
+ it "returns no cookie if no data was written and no session was created previously, even if :expire_after is set" do
205
+ app = Rack::Session::Pool.new(nothing, :expire_after => 3600)
206
+ res = Rack::MockRequest.new(app).get("/")
207
+ res["Set-Cookie"].should.be.nil
171
208
  end
172
209
  end
@@ -0,0 +1,85 @@
1
+ require 'rack/showexceptions'
2
+ require 'rack/lint'
3
+ require 'rack/mock'
4
+
5
+ describe Rack::ShowExceptions do
6
+ def show_exceptions(app)
7
+ Rack::Lint.new Rack::ShowExceptions.new(app)
8
+ end
9
+
10
+ it "catches exceptions" do
11
+ res = nil
12
+
13
+ req = Rack::MockRequest.new(
14
+ show_exceptions(
15
+ lambda{|env| raise RuntimeError }
16
+ ))
17
+
18
+ lambda{
19
+ res = req.get("/", "HTTP_ACCEPT" => "text/html")
20
+ }.should.not.raise
21
+
22
+ res.should.be.a.server_error
23
+ res.status.should.equal 500
24
+
25
+ res.should =~ /RuntimeError/
26
+ res.should =~ /ShowExceptions/
27
+ end
28
+
29
+ it "responds with HTML only to requests accepting HTML" do
30
+ res = nil
31
+
32
+ req = Rack::MockRequest.new(
33
+ show_exceptions(
34
+ lambda{|env| raise RuntimeError, "It was never supposed to work" }
35
+ ))
36
+
37
+ [
38
+ # Serve text/html when the client accepts text/html
39
+ ["text/html", ["/", {"HTTP_ACCEPT" => "text/html"}]],
40
+ ["text/html", ["/", {"HTTP_ACCEPT" => "*/*"}]],
41
+ # Serve text/plain when the client does not accept text/html
42
+ ["text/plain", ["/"]],
43
+ ["text/plain", ["/", {"HTTP_ACCEPT" => "application/json"}]]
44
+ ].each do |exmime, rargs|
45
+ lambda{
46
+ res = req.get(*rargs)
47
+ }.should.not.raise
48
+
49
+ res.should.be.a.server_error
50
+ res.status.should.equal 500
51
+
52
+ res.content_type.should.equal exmime
53
+
54
+ res.body.should.include "RuntimeError"
55
+ res.body.should.include "It was never supposed to work"
56
+
57
+ if exmime == "text/html"
58
+ res.body.should.include '</html>'
59
+ else
60
+ res.body.should.not.include '</html>'
61
+ end
62
+ end
63
+ end
64
+
65
+ it "handles exceptions without a backtrace" do
66
+ res = nil
67
+
68
+ req = Rack::MockRequest.new(
69
+ show_exceptions(
70
+ lambda{|env| raise RuntimeError, "", [] }
71
+ )
72
+ )
73
+
74
+ lambda{
75
+ res = req.get("/", "HTTP_ACCEPT" => "text/html")
76
+ }.should.not.raise
77
+
78
+ res.should.be.a.server_error
79
+ res.status.should.equal 500
80
+
81
+ res.should =~ /RuntimeError/
82
+ res.should =~ /ShowExceptions/
83
+ res.should =~ /unknown location/
84
+ end
85
+ end