rack 1.6.13 → 2.0.1
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.
- checksums.yaml +5 -5
- data/COPYING +1 -1
- data/HISTORY.md +138 -8
- data/README.rdoc +17 -25
- data/Rakefile +6 -14
- data/SPEC +8 -9
- data/contrib/rack_logo.svg +164 -111
- data/example/protectedlobster.rb +1 -1
- data/example/protectedlobster.ru +1 -1
- data/lib/rack/auth/abstract/request.rb +5 -1
- data/lib/rack/auth/digest/params.rb +2 -3
- data/lib/rack/auth/digest/request.rb +1 -1
- data/lib/rack/body_proxy.rb +14 -9
- data/lib/rack/builder.rb +3 -3
- data/lib/rack/chunked.rb +5 -5
- data/lib/rack/{commonlogger.rb → common_logger.rb} +3 -3
- data/lib/rack/{conditionalget.rb → conditional_get.rb} +0 -0
- data/lib/rack/content_length.rb +2 -2
- data/lib/rack/deflater.rb +4 -4
- data/lib/rack/directory.rb +66 -54
- data/lib/rack/etag.rb +4 -3
- data/lib/rack/events.rb +154 -0
- data/lib/rack/file.rb +63 -39
- data/lib/rack/handler/cgi.rb +15 -16
- data/lib/rack/handler/fastcgi.rb +13 -14
- data/lib/rack/handler/lsws.rb +11 -11
- data/lib/rack/handler/scgi.rb +15 -15
- data/lib/rack/handler/thin.rb +3 -0
- data/lib/rack/handler/webrick.rb +22 -24
- data/lib/rack/handler.rb +3 -25
- data/lib/rack/head.rb +15 -17
- data/lib/rack/lint.rb +38 -38
- data/lib/rack/lobster.rb +1 -1
- data/lib/rack/lock.rb +6 -10
- data/lib/rack/logger.rb +2 -2
- data/lib/rack/media_type.rb +38 -0
- data/lib/rack/{methodoverride.rb → method_override.rb} +4 -11
- data/lib/rack/mime.rb +18 -5
- data/lib/rack/mock.rb +35 -53
- data/lib/rack/multipart/generator.rb +5 -5
- data/lib/rack/multipart/parser.rb +272 -158
- data/lib/rack/multipart/uploaded_file.rb +1 -2
- data/lib/rack/multipart.rb +35 -6
- data/lib/rack/{nulllogger.rb → null_logger.rb} +1 -1
- data/lib/rack/query_parser.rb +192 -0
- data/lib/rack/recursive.rb +8 -8
- data/lib/rack/request.rb +383 -307
- data/lib/rack/response.rb +129 -56
- data/lib/rack/rewindable_input.rb +1 -12
- data/lib/rack/runtime.rb +10 -18
- data/lib/rack/sendfile.rb +5 -7
- data/lib/rack/server.rb +31 -25
- data/lib/rack/session/abstract/id.rb +95 -135
- data/lib/rack/session/cookie.rb +26 -28
- data/lib/rack/session/memcache.rb +8 -14
- data/lib/rack/session/pool.rb +14 -21
- data/lib/rack/show_exceptions.rb +386 -0
- data/lib/rack/{showstatus.rb → show_status.rb} +3 -3
- data/lib/rack/static.rb +30 -5
- data/lib/rack/tempfile_reaper.rb +2 -2
- data/lib/rack/urlmap.rb +15 -14
- data/lib/rack/utils.rb +135 -210
- data/lib/rack.rb +70 -21
- data/rack.gemspec +7 -5
- data/test/builder/an_underscore_app.rb +5 -0
- data/test/builder/options.ru +1 -1
- data/test/cgi/test.fcgi +1 -0
- data/test/cgi/test.gz +0 -0
- data/test/helper.rb +34 -0
- data/test/multipart/filename_with_encoded_words +7 -0
- data/test/multipart/{filename_with_null_byte → filename_with_single_quote} +1 -1
- data/test/multipart/quoted +15 -0
- data/test/multipart/rack-logo.png +0 -0
- data/test/multipart/unity3d_wwwform +11 -0
- data/test/registering_handler/rack/handler/registering_myself.rb +1 -1
- data/test/spec_auth_basic.rb +27 -19
- data/test/spec_auth_digest.rb +47 -46
- data/test/spec_body_proxy.rb +27 -27
- data/test/spec_builder.rb +51 -41
- data/test/spec_cascade.rb +24 -22
- data/test/spec_cgi.rb +49 -67
- data/test/spec_chunked.rb +36 -34
- data/test/{spec_commonlogger.rb → spec_common_logger.rb} +23 -21
- data/test/{spec_conditionalget.rb → spec_conditional_get.rb} +29 -28
- data/test/spec_config.rb +3 -2
- data/test/spec_content_length.rb +18 -17
- data/test/spec_content_type.rb +13 -12
- data/test/spec_deflater.rb +66 -40
- data/test/spec_directory.rb +87 -27
- data/test/spec_etag.rb +32 -31
- data/test/spec_events.rb +133 -0
- data/test/spec_fastcgi.rb +50 -72
- data/test/spec_file.rb +107 -77
- data/test/spec_handler.rb +19 -34
- data/test/spec_head.rb +15 -14
- data/test/spec_lint.rb +162 -197
- data/test/spec_lobster.rb +24 -23
- data/test/spec_lock.rb +69 -39
- data/test/spec_logger.rb +4 -3
- data/test/spec_media_type.rb +42 -0
- data/test/spec_method_override.rb +83 -0
- data/test/spec_mime.rb +19 -19
- data/test/spec_mock.rb +196 -151
- data/test/spec_multipart.rb +317 -201
- data/test/{spec_nulllogger.rb → spec_null_logger.rb} +5 -4
- data/test/spec_recursive.rb +17 -14
- data/test/spec_request.rb +768 -607
- data/test/spec_response.rb +214 -111
- data/test/spec_rewindable_input.rb +50 -40
- data/test/spec_runtime.rb +11 -10
- data/test/spec_sendfile.rb +30 -35
- data/test/spec_server.rb +78 -52
- data/test/spec_session_abstract_id.rb +11 -33
- data/test/spec_session_abstract_session_hash.rb +28 -0
- data/test/spec_session_cookie.rb +97 -65
- data/test/spec_session_memcache.rb +63 -101
- data/test/spec_session_pool.rb +48 -84
- data/test/spec_show_exceptions.rb +80 -0
- data/test/{spec_showstatus.rb → spec_show_status.rb} +36 -35
- data/test/spec_static.rb +71 -32
- data/test/spec_tempfile_reaper.rb +11 -10
- data/test/spec_thin.rb +55 -50
- data/test/spec_urlmap.rb +79 -78
- data/test/spec_utils.rb +441 -346
- data/test/spec_version.rb +2 -8
- data/test/spec_webrick.rb +91 -67
- data/test/static/foo.html +1 -0
- data/test/testrequest.rb +1 -1
- data/test/unregistered_handler/rack/handler/unregistered.rb +1 -1
- data/test/unregistered_handler/rack/handler/unregistered_long_one.rb +1 -1
- metadata +103 -69
- data/KNOWN-ISSUES +0 -44
- data/lib/rack/backports/uri/common_18.rb +0 -56
- data/lib/rack/backports/uri/common_192.rb +0 -52
- data/lib/rack/backports/uri/common_193.rb +0 -29
- data/lib/rack/handler/evented_mongrel.rb +0 -8
- data/lib/rack/handler/mongrel.rb +0 -106
- data/lib/rack/handler/swiftiplied_mongrel.rb +0 -8
- data/lib/rack/showexceptions.rb +0 -387
- data/lib/rack/utils/okjson.rb +0 -600
- data/test/spec_methodoverride.rb +0 -111
- data/test/spec_mongrel.rb +0 -182
- data/test/spec_session_persisted_secure_secure_session_hash.rb +0 -73
- data/test/spec_showexceptions.rb +0 -98
data/test/spec_response.rb
CHANGED
@@ -1,22 +1,40 @@
|
|
1
|
+
require 'minitest/autorun'
|
2
|
+
require 'rack'
|
1
3
|
require 'rack/response'
|
2
4
|
require 'stringio'
|
3
5
|
|
4
6
|
describe Rack::Response do
|
5
|
-
|
7
|
+
it 'has cache-control methods' do
|
8
|
+
response = Rack::Response.new
|
9
|
+
cc = 'foo'
|
10
|
+
response.cache_control = cc
|
11
|
+
assert_equal cc, response.cache_control
|
12
|
+
assert_equal cc, response.to_a[2]['Cache-Control']
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'has an etag method' do
|
16
|
+
response = Rack::Response.new
|
17
|
+
etag = 'foo'
|
18
|
+
response.etag = etag
|
19
|
+
assert_equal etag, response.etag
|
20
|
+
assert_equal etag, response.to_a[2]['ETag']
|
21
|
+
end
|
22
|
+
|
23
|
+
it "have sensible default values" do
|
6
24
|
response = Rack::Response.new
|
7
25
|
status, header, body = response.finish
|
8
|
-
status.
|
9
|
-
header.
|
26
|
+
status.must_equal 200
|
27
|
+
header.must_equal({})
|
10
28
|
body.each { |part|
|
11
|
-
part.
|
29
|
+
part.must_equal ""
|
12
30
|
}
|
13
31
|
|
14
32
|
response = Rack::Response.new
|
15
33
|
status, header, body = *response
|
16
|
-
status.
|
17
|
-
header.
|
34
|
+
status.must_equal 200
|
35
|
+
header.must_equal({})
|
18
36
|
body.each { |part|
|
19
|
-
part.
|
37
|
+
part.must_equal ""
|
20
38
|
}
|
21
39
|
end
|
22
40
|
|
@@ -32,132 +50,132 @@ describe Rack::Response do
|
|
32
50
|
parts = []
|
33
51
|
body.each { |part| parts << part }
|
34
52
|
|
35
|
-
parts.
|
53
|
+
parts.must_equal ["foo", "bar", "baz"]
|
36
54
|
end
|
37
55
|
|
38
56
|
it "can set and read headers" do
|
39
57
|
response = Rack::Response.new
|
40
|
-
response["Content-Type"].
|
58
|
+
response["Content-Type"].must_equal nil
|
41
59
|
response["Content-Type"] = "text/plain"
|
42
|
-
response["Content-Type"].
|
60
|
+
response["Content-Type"].must_equal "text/plain"
|
43
61
|
end
|
44
62
|
|
45
63
|
it "can override the initial Content-Type with a different case" do
|
46
64
|
response = Rack::Response.new("", 200, "content-type" => "text/plain")
|
47
|
-
response["Content-Type"].
|
65
|
+
response["Content-Type"].must_equal "text/plain"
|
48
66
|
end
|
49
67
|
|
50
68
|
it "can set cookies" do
|
51
69
|
response = Rack::Response.new
|
52
70
|
|
53
71
|
response.set_cookie "foo", "bar"
|
54
|
-
response["Set-Cookie"].
|
72
|
+
response["Set-Cookie"].must_equal "foo=bar"
|
55
73
|
response.set_cookie "foo2", "bar2"
|
56
|
-
response["Set-Cookie"].
|
74
|
+
response["Set-Cookie"].must_equal ["foo=bar", "foo2=bar2"].join("\n")
|
57
75
|
response.set_cookie "foo3", "bar3"
|
58
|
-
response["Set-Cookie"].
|
76
|
+
response["Set-Cookie"].must_equal ["foo=bar", "foo2=bar2", "foo3=bar3"].join("\n")
|
59
77
|
end
|
60
78
|
|
61
79
|
it "can set cookies with the same name for multiple domains" do
|
62
80
|
response = Rack::Response.new
|
63
81
|
response.set_cookie "foo", {:value => "bar", :domain => "sample.example.com"}
|
64
82
|
response.set_cookie "foo", {:value => "bar", :domain => ".example.com"}
|
65
|
-
response["Set-Cookie"].
|
83
|
+
response["Set-Cookie"].must_equal ["foo=bar; domain=sample.example.com", "foo=bar; domain=.example.com"].join("\n")
|
66
84
|
end
|
67
85
|
|
68
86
|
it "formats the Cookie expiration date accordingly to RFC 6265" do
|
69
87
|
response = Rack::Response.new
|
70
88
|
|
71
89
|
response.set_cookie "foo", {:value => "bar", :expires => Time.now+10}
|
72
|
-
response["Set-Cookie"].
|
90
|
+
response["Set-Cookie"].must_match(
|
73
91
|
/expires=..., \d\d ... \d\d\d\d \d\d:\d\d:\d\d .../)
|
74
92
|
end
|
75
93
|
|
76
94
|
it "can set secure cookies" do
|
77
95
|
response = Rack::Response.new
|
78
96
|
response.set_cookie "foo", {:value => "bar", :secure => true}
|
79
|
-
response["Set-Cookie"].
|
97
|
+
response["Set-Cookie"].must_equal "foo=bar; secure"
|
80
98
|
end
|
81
99
|
|
82
100
|
it "can set http only cookies" do
|
83
101
|
response = Rack::Response.new
|
84
102
|
response.set_cookie "foo", {:value => "bar", :httponly => true}
|
85
|
-
response["Set-Cookie"].
|
103
|
+
response["Set-Cookie"].must_equal "foo=bar; HttpOnly"
|
86
104
|
end
|
87
105
|
|
88
106
|
it "can set http only cookies with :http_only" do
|
89
107
|
response = Rack::Response.new
|
90
108
|
response.set_cookie "foo", {:value => "bar", :http_only => true}
|
91
|
-
response["Set-Cookie"].
|
109
|
+
response["Set-Cookie"].must_equal "foo=bar; HttpOnly"
|
92
110
|
end
|
93
111
|
|
94
112
|
it "can set prefers :httponly for http only cookie setting when :httponly and :http_only provided" do
|
95
113
|
response = Rack::Response.new
|
96
114
|
response.set_cookie "foo", {:value => "bar", :httponly => false, :http_only => true}
|
97
|
-
response["Set-Cookie"].
|
115
|
+
response["Set-Cookie"].must_equal "foo=bar"
|
98
116
|
end
|
99
117
|
|
100
118
|
it "can set SameSite cookies with symbol value :lax" do
|
101
119
|
response = Rack::Response.new
|
102
120
|
response.set_cookie "foo", {:value => "bar", :same_site => :lax}
|
103
|
-
response["Set-Cookie"].
|
121
|
+
response["Set-Cookie"].must_equal "foo=bar; SameSite=Lax"
|
104
122
|
end
|
105
123
|
|
106
124
|
it "can set SameSite cookies with symbol value :Lax" do
|
107
125
|
response = Rack::Response.new
|
108
126
|
response.set_cookie "foo", {:value => "bar", :same_site => :lax}
|
109
|
-
response["Set-Cookie"].
|
127
|
+
response["Set-Cookie"].must_equal "foo=bar; SameSite=Lax"
|
110
128
|
end
|
111
129
|
|
112
130
|
it "can set SameSite cookies with string value 'Lax'" do
|
113
131
|
response = Rack::Response.new
|
114
132
|
response.set_cookie "foo", {:value => "bar", :same_site => "Lax"}
|
115
|
-
response["Set-Cookie"].
|
133
|
+
response["Set-Cookie"].must_equal "foo=bar; SameSite=Lax"
|
116
134
|
end
|
117
135
|
|
118
136
|
it "can set SameSite cookies with boolean value true" do
|
119
137
|
response = Rack::Response.new
|
120
138
|
response.set_cookie "foo", {:value => "bar", :same_site => true}
|
121
|
-
response["Set-Cookie"].
|
139
|
+
response["Set-Cookie"].must_equal "foo=bar; SameSite=Strict"
|
122
140
|
end
|
123
141
|
|
124
142
|
it "can set SameSite cookies with symbol value :strict" do
|
125
143
|
response = Rack::Response.new
|
126
144
|
response.set_cookie "foo", {:value => "bar", :same_site => :strict}
|
127
|
-
response["Set-Cookie"].
|
145
|
+
response["Set-Cookie"].must_equal "foo=bar; SameSite=Strict"
|
128
146
|
end
|
129
147
|
|
130
148
|
it "can set SameSite cookies with symbol value :Strict" do
|
131
149
|
response = Rack::Response.new
|
132
150
|
response.set_cookie "foo", {:value => "bar", :same_site => :Strict}
|
133
|
-
response["Set-Cookie"].
|
151
|
+
response["Set-Cookie"].must_equal "foo=bar; SameSite=Strict"
|
134
152
|
end
|
135
153
|
|
136
154
|
it "can set SameSite cookies with string value 'Strict'" do
|
137
155
|
response = Rack::Response.new
|
138
156
|
response.set_cookie "foo", {:value => "bar", :same_site => "Strict"}
|
139
|
-
response["Set-Cookie"].
|
157
|
+
response["Set-Cookie"].must_equal "foo=bar; SameSite=Strict"
|
140
158
|
end
|
141
159
|
|
142
160
|
it "validates the SameSite option value" do
|
143
161
|
response = Rack::Response.new
|
144
162
|
lambda {
|
145
163
|
response.set_cookie "foo", {:value => "bar", :same_site => "Foo"}
|
146
|
-
}.
|
147
|
-
message.
|
164
|
+
}.must_raise(ArgumentError).
|
165
|
+
message.must_match(/Invalid SameSite value: "Foo"/)
|
148
166
|
end
|
149
167
|
|
150
168
|
it "can set SameSite cookies with symbol value" do
|
151
169
|
response = Rack::Response.new
|
152
170
|
response.set_cookie "foo", {:value => "bar", :same_site => :Strict}
|
153
|
-
response["Set-Cookie"].
|
171
|
+
response["Set-Cookie"].must_equal "foo=bar; SameSite=Strict"
|
154
172
|
end
|
155
173
|
|
156
174
|
[ nil, false ].each do |non_truthy|
|
157
175
|
it "omits SameSite attribute given a #{non_truthy.inspect} value" do
|
158
176
|
response = Rack::Response.new
|
159
177
|
response.set_cookie "foo", {:value => "bar", :same_site => non_truthy}
|
160
|
-
response["Set-Cookie"].
|
178
|
+
response["Set-Cookie"].must_equal "foo=bar"
|
161
179
|
end
|
162
180
|
end
|
163
181
|
|
@@ -166,7 +184,7 @@ describe Rack::Response do
|
|
166
184
|
response.set_cookie "foo", "bar"
|
167
185
|
response.set_cookie "foo2", "bar2"
|
168
186
|
response.delete_cookie "foo"
|
169
|
-
response["Set-Cookie"].
|
187
|
+
response["Set-Cookie"].must_equal [
|
170
188
|
"foo2=bar2",
|
171
189
|
"foo=; max-age=0; expires=Thu, 01 Jan 1970 00:00:00 -0000"
|
172
190
|
].join("\n")
|
@@ -176,11 +194,11 @@ describe Rack::Response do
|
|
176
194
|
response = Rack::Response.new
|
177
195
|
response.set_cookie "foo", {:value => "bar", :domain => "sample.example.com"}
|
178
196
|
response.set_cookie "foo", {:value => "bar", :domain => ".example.com"}
|
179
|
-
response["Set-Cookie"].
|
197
|
+
response["Set-Cookie"].must_equal ["foo=bar; domain=sample.example.com", "foo=bar; domain=.example.com"].join("\n")
|
180
198
|
response.delete_cookie "foo", :domain => ".example.com"
|
181
|
-
response["Set-Cookie"].
|
199
|
+
response["Set-Cookie"].must_equal ["foo=bar; domain=sample.example.com", "foo=; domain=.example.com; max-age=0; expires=Thu, 01 Jan 1970 00:00:00 -0000"].join("\n")
|
182
200
|
response.delete_cookie "foo", :domain => "sample.example.com"
|
183
|
-
response["Set-Cookie"].
|
201
|
+
response["Set-Cookie"].must_equal ["foo=; domain=.example.com; max-age=0; expires=Thu, 01 Jan 1970 00:00:00 -0000",
|
184
202
|
"foo=; domain=sample.example.com; max-age=0; expires=Thu, 01 Jan 1970 00:00:00 -0000"].join("\n")
|
185
203
|
end
|
186
204
|
|
@@ -188,11 +206,11 @@ describe Rack::Response do
|
|
188
206
|
response = Rack::Response.new
|
189
207
|
response.set_cookie "foo", {:value => "bar", :path => "/"}
|
190
208
|
response.set_cookie "foo", {:value => "bar", :path => "/path"}
|
191
|
-
response["Set-Cookie"].
|
209
|
+
response["Set-Cookie"].must_equal ["foo=bar; path=/",
|
192
210
|
"foo=bar; path=/path"].join("\n")
|
193
211
|
|
194
212
|
response.delete_cookie "foo", :path => "/path"
|
195
|
-
response["Set-Cookie"].
|
213
|
+
response["Set-Cookie"].must_equal ["foo=bar; path=/",
|
196
214
|
"foo=; path=/path; max-age=0; expires=Thu, 01 Jan 1970 00:00:00 -0000"].join("\n")
|
197
215
|
end
|
198
216
|
|
@@ -200,26 +218,26 @@ describe Rack::Response do
|
|
200
218
|
response = Rack::Response.new
|
201
219
|
response.redirect "/foo"
|
202
220
|
status, header, body = response.finish
|
203
|
-
status.
|
204
|
-
header["Location"].
|
221
|
+
status.must_equal 302
|
222
|
+
header["Location"].must_equal "/foo"
|
205
223
|
|
206
224
|
response = Rack::Response.new
|
207
225
|
response.redirect "/foo", 307
|
208
226
|
status, header, body = response.finish
|
209
227
|
|
210
|
-
status.
|
228
|
+
status.must_equal 307
|
211
229
|
end
|
212
230
|
|
213
231
|
it "has a useful constructor" do
|
214
232
|
r = Rack::Response.new("foo")
|
215
233
|
status, header, body = r.finish
|
216
234
|
str = ""; body.each { |part| str << part }
|
217
|
-
str.
|
235
|
+
str.must_equal "foo"
|
218
236
|
|
219
237
|
r = Rack::Response.new(["foo", "bar"])
|
220
238
|
status, header, body = r.finish
|
221
239
|
str = ""; body.each { |part| str << part }
|
222
|
-
str.
|
240
|
+
str.must_equal "foobar"
|
223
241
|
|
224
242
|
object_with_each = Object.new
|
225
243
|
def object_with_each.each
|
@@ -230,13 +248,13 @@ describe Rack::Response do
|
|
230
248
|
r.write "foo"
|
231
249
|
status, header, body = r.finish
|
232
250
|
str = ""; body.each { |part| str << part }
|
233
|
-
str.
|
251
|
+
str.must_equal "foobarfoo"
|
234
252
|
|
235
253
|
r = Rack::Response.new([], 500)
|
236
|
-
r.status.
|
254
|
+
r.status.must_equal 500
|
237
255
|
|
238
256
|
r = Rack::Response.new([], "200 OK")
|
239
|
-
r.status.
|
257
|
+
r.status.must_equal 200
|
240
258
|
end
|
241
259
|
|
242
260
|
it "has a constructor that can take a block" do
|
@@ -246,162 +264,247 @@ describe Rack::Response do
|
|
246
264
|
}
|
247
265
|
status, _, body = r.finish
|
248
266
|
str = ""; body.each { |part| str << part }
|
249
|
-
str.
|
250
|
-
status.
|
267
|
+
str.must_equal "foo"
|
268
|
+
status.must_equal 404
|
251
269
|
end
|
252
270
|
|
253
271
|
it "doesn't return invalid responses" do
|
254
272
|
r = Rack::Response.new(["foo", "bar"], 204)
|
255
273
|
_, header, body = r.finish
|
256
274
|
str = ""; body.each { |part| str << part }
|
257
|
-
str.
|
258
|
-
header["Content-Type"].
|
259
|
-
header['Content-Length'].
|
275
|
+
str.must_be :empty?
|
276
|
+
header["Content-Type"].must_equal nil
|
277
|
+
header['Content-Length'].must_equal nil
|
260
278
|
|
261
279
|
lambda {
|
262
280
|
Rack::Response.new(Object.new)
|
263
|
-
}.
|
264
|
-
message.
|
281
|
+
}.must_raise(TypeError).
|
282
|
+
message.must_match(/stringable or iterable required/)
|
265
283
|
end
|
266
284
|
|
267
285
|
it "knows if it's empty" do
|
268
286
|
r = Rack::Response.new
|
269
|
-
r.
|
287
|
+
r.must_be :empty?
|
270
288
|
r.write "foo"
|
271
|
-
r.
|
289
|
+
r.wont_be :empty?
|
272
290
|
|
273
291
|
r = Rack::Response.new
|
274
|
-
r.
|
292
|
+
r.must_be :empty?
|
275
293
|
r.finish
|
276
|
-
r.
|
294
|
+
r.must_be :empty?
|
277
295
|
|
278
296
|
r = Rack::Response.new
|
279
|
-
r.
|
297
|
+
r.must_be :empty?
|
280
298
|
r.finish { }
|
281
|
-
r.
|
299
|
+
r.wont_be :empty?
|
282
300
|
end
|
283
301
|
|
284
|
-
|
302
|
+
it "provide access to the HTTP status" do
|
285
303
|
res = Rack::Response.new
|
286
304
|
res.status = 200
|
287
|
-
res.
|
288
|
-
res.
|
305
|
+
res.must_be :successful?
|
306
|
+
res.must_be :ok?
|
289
307
|
|
290
308
|
res.status = 201
|
291
|
-
res.
|
292
|
-
res.
|
309
|
+
res.must_be :successful?
|
310
|
+
res.must_be :created?
|
293
311
|
|
294
312
|
res.status = 202
|
295
|
-
res.
|
296
|
-
res.
|
313
|
+
res.must_be :successful?
|
314
|
+
res.must_be :accepted?
|
315
|
+
|
316
|
+
res.status = 204
|
317
|
+
res.must_be :successful?
|
318
|
+
res.must_be :no_content?
|
319
|
+
|
320
|
+
res.status = 301
|
321
|
+
res.must_be :redirect?
|
322
|
+
res.must_be :moved_permanently?
|
323
|
+
|
324
|
+
res.status = 302
|
325
|
+
res.must_be :redirect?
|
326
|
+
|
327
|
+
res.status = 303
|
328
|
+
res.must_be :redirect?
|
329
|
+
|
330
|
+
res.status = 307
|
331
|
+
res.must_be :redirect?
|
332
|
+
|
333
|
+
res.status = 308
|
334
|
+
res.must_be :redirect?
|
297
335
|
|
298
336
|
res.status = 400
|
299
|
-
res.
|
300
|
-
res.
|
301
|
-
res.
|
337
|
+
res.wont_be :successful?
|
338
|
+
res.must_be :client_error?
|
339
|
+
res.must_be :bad_request?
|
302
340
|
|
303
341
|
res.status = 401
|
304
|
-
res.
|
305
|
-
res.
|
306
|
-
res.
|
342
|
+
res.wont_be :successful?
|
343
|
+
res.must_be :client_error?
|
344
|
+
res.must_be :unauthorized?
|
307
345
|
|
308
346
|
res.status = 404
|
309
|
-
res.
|
310
|
-
res.
|
311
|
-
res.
|
347
|
+
res.wont_be :successful?
|
348
|
+
res.must_be :client_error?
|
349
|
+
res.must_be :not_found?
|
312
350
|
|
313
351
|
res.status = 405
|
314
|
-
res.
|
315
|
-
res.
|
316
|
-
res.
|
352
|
+
res.wont_be :successful?
|
353
|
+
res.must_be :client_error?
|
354
|
+
res.must_be :method_not_allowed?
|
317
355
|
|
318
|
-
res.status =
|
319
|
-
res.
|
320
|
-
res.
|
321
|
-
res.
|
356
|
+
res.status = 412
|
357
|
+
res.wont_be :successful?
|
358
|
+
res.must_be :client_error?
|
359
|
+
res.must_be :precondition_failed?
|
322
360
|
|
323
361
|
res.status = 422
|
324
|
-
res.
|
325
|
-
res.
|
326
|
-
res.
|
362
|
+
res.wont_be :successful?
|
363
|
+
res.must_be :client_error?
|
364
|
+
res.must_be :unprocessable?
|
327
365
|
|
328
366
|
res.status = 501
|
329
|
-
res.
|
330
|
-
res.
|
331
|
-
|
332
|
-
res.status = 307
|
333
|
-
res.should.be.redirect
|
367
|
+
res.wont_be :successful?
|
368
|
+
res.must_be :server_error?
|
334
369
|
end
|
335
370
|
|
336
|
-
|
371
|
+
it "provide access to the HTTP headers" do
|
337
372
|
res = Rack::Response.new
|
338
373
|
res["Content-Type"] = "text/yaml"
|
339
374
|
|
340
|
-
res.
|
341
|
-
res.headers["Content-Type"].
|
342
|
-
res["Content-Type"].
|
343
|
-
res.content_type.
|
344
|
-
res.content_length.
|
345
|
-
res.location.
|
375
|
+
res.must_include "Content-Type"
|
376
|
+
res.headers["Content-Type"].must_equal "text/yaml"
|
377
|
+
res["Content-Type"].must_equal "text/yaml"
|
378
|
+
res.content_type.must_equal "text/yaml"
|
379
|
+
res.content_length.must_be_nil
|
380
|
+
res.location.must_be_nil
|
346
381
|
end
|
347
382
|
|
348
383
|
it "does not add or change Content-Length when #finish()ing" do
|
349
384
|
res = Rack::Response.new
|
350
385
|
res.status = 200
|
351
386
|
res.finish
|
352
|
-
res.headers["Content-Length"].
|
387
|
+
res.headers["Content-Length"].must_be_nil
|
353
388
|
|
354
389
|
res = Rack::Response.new
|
355
390
|
res.status = 200
|
356
391
|
res.headers["Content-Length"] = "10"
|
357
392
|
res.finish
|
358
|
-
res.headers["Content-Length"].
|
393
|
+
res.headers["Content-Length"].must_equal "10"
|
359
394
|
end
|
360
395
|
|
361
396
|
it "updates Content-Length when body appended to using #write" do
|
362
397
|
res = Rack::Response.new
|
363
398
|
res.status = 200
|
364
|
-
res.headers["Content-Length"].
|
399
|
+
res.headers["Content-Length"].must_be_nil
|
365
400
|
res.write "Hi"
|
366
|
-
res.headers["Content-Length"].
|
401
|
+
res.headers["Content-Length"].must_equal "2"
|
367
402
|
res.write " there"
|
368
|
-
res.headers["Content-Length"].
|
403
|
+
res.headers["Content-Length"].must_equal "8"
|
369
404
|
end
|
370
405
|
|
371
406
|
it "calls close on #body" do
|
372
407
|
res = Rack::Response.new
|
373
408
|
res.body = StringIO.new
|
374
409
|
res.close
|
375
|
-
res.body.
|
410
|
+
res.body.must_be :closed?
|
376
411
|
end
|
377
412
|
|
378
413
|
it "calls close on #body when 204, 205, or 304" do
|
379
414
|
res = Rack::Response.new
|
380
415
|
res.body = StringIO.new
|
381
416
|
res.finish
|
382
|
-
res.body.
|
417
|
+
res.body.wont_be :closed?
|
383
418
|
|
384
419
|
res.status = 204
|
385
420
|
_, _, b = res.finish
|
386
|
-
res.body.
|
387
|
-
b.
|
421
|
+
res.body.must_be :closed?
|
422
|
+
b.wont_equal res.body
|
388
423
|
|
389
424
|
res.body = StringIO.new
|
390
425
|
res.status = 205
|
391
426
|
_, _, b = res.finish
|
392
|
-
res.body.
|
393
|
-
b.
|
427
|
+
res.body.must_be :closed?
|
428
|
+
b.wont_equal res.body
|
394
429
|
|
395
430
|
res.body = StringIO.new
|
396
431
|
res.status = 304
|
397
432
|
_, _, b = res.finish
|
398
|
-
res.body.
|
399
|
-
b.
|
433
|
+
res.body.must_be :closed?
|
434
|
+
b.wont_equal res.body
|
400
435
|
end
|
401
436
|
|
402
437
|
it "wraps the body from #to_ary to prevent infinite loops" do
|
403
438
|
res = Rack::Response.new
|
404
|
-
res.finish.last.
|
405
|
-
lambda { res.finish.last.to_ary }.
|
439
|
+
res.finish.last.wont_respond_to(:to_ary)
|
440
|
+
lambda { res.finish.last.to_ary }.must_raise NoMethodError
|
441
|
+
end
|
442
|
+
end
|
443
|
+
|
444
|
+
describe Rack::Response, 'headers' do
|
445
|
+
before do
|
446
|
+
@response = Rack::Response.new([], 200, { 'Foo' => '1' })
|
447
|
+
end
|
448
|
+
|
449
|
+
it 'has_header?' do
|
450
|
+
lambda { @response.has_header? nil }.must_raise NoMethodError
|
451
|
+
|
452
|
+
@response.has_header?('Foo').must_equal true
|
453
|
+
@response.has_header?('foo').must_equal true
|
454
|
+
end
|
455
|
+
|
456
|
+
it 'get_header' do
|
457
|
+
lambda { @response.get_header nil }.must_raise NoMethodError
|
458
|
+
|
459
|
+
@response.get_header('Foo').must_equal '1'
|
460
|
+
@response.get_header('foo').must_equal '1'
|
461
|
+
end
|
462
|
+
|
463
|
+
it 'set_header' do
|
464
|
+
lambda { @response.set_header nil, '1' }.must_raise NoMethodError
|
465
|
+
|
466
|
+
@response.set_header('Foo', '2').must_equal '2'
|
467
|
+
@response.has_header?('Foo').must_equal true
|
468
|
+
@response.get_header('Foo').must_equal('2')
|
469
|
+
|
470
|
+
@response.set_header('Foo', nil).must_be_nil
|
471
|
+
@response.has_header?('Foo').must_equal true
|
472
|
+
@response.get_header('Foo').must_be_nil
|
473
|
+
end
|
474
|
+
|
475
|
+
it 'add_header' do
|
476
|
+
lambda { @response.add_header nil, '1' }.must_raise NoMethodError
|
477
|
+
|
478
|
+
# Add a value to an existing header
|
479
|
+
@response.add_header('Foo', '2').must_equal '1,2'
|
480
|
+
@response.get_header('Foo').must_equal '1,2'
|
481
|
+
|
482
|
+
# Add nil to an existing header
|
483
|
+
@response.add_header('Foo', nil).must_equal '1,2'
|
484
|
+
@response.get_header('Foo').must_equal '1,2'
|
485
|
+
|
486
|
+
# Add nil to a nonexistent header
|
487
|
+
@response.add_header('Bar', nil).must_be_nil
|
488
|
+
@response.has_header?('Bar').must_equal false
|
489
|
+
@response.get_header('Bar').must_be_nil
|
490
|
+
|
491
|
+
# Add a value to a nonexistent header
|
492
|
+
@response.add_header('Bar', '1').must_equal '1'
|
493
|
+
@response.has_header?('Bar').must_equal true
|
494
|
+
@response.get_header('Bar').must_equal '1'
|
495
|
+
end
|
496
|
+
|
497
|
+
it 'delete_header' do
|
498
|
+
lambda { @response.delete_header nil }.must_raise NoMethodError
|
499
|
+
|
500
|
+
@response.delete_header('Foo').must_equal '1'
|
501
|
+
(!!@response.has_header?('Foo')).must_equal false
|
502
|
+
|
503
|
+
@response.delete_header('Foo').must_be_nil
|
504
|
+
@response.has_header?('Foo').must_equal false
|
505
|
+
|
506
|
+
@response.set_header('Foo', 1)
|
507
|
+
@response.delete_header('foo').must_equal 1
|
508
|
+
@response.has_header?('Foo').must_equal false
|
406
509
|
end
|
407
510
|
end
|