rack 1.6.13 → 2.0.9.3
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 +4 -4
- data/COPYING +1 -1
- data/HISTORY.md +153 -8
- data/README.rdoc +35 -31
- data/Rakefile +6 -14
- data/SPEC +10 -11
- 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} +6 -3
- data/lib/rack/content_length.rb +2 -2
- data/lib/rack/deflater.rb +4 -39
- data/lib/rack/directory.rb +66 -54
- data/lib/rack/etag.rb +5 -4
- data/lib/rack/events.rb +154 -0
- data/lib/rack/file.rb +64 -40
- 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 +24 -26
- data/lib/rack/handler.rb +3 -25
- data/lib/rack/head.rb +15 -17
- data/lib/rack/lint.rb +41 -41
- data/lib/rack/lobster.rb +1 -1
- data/lib/rack/lock.rb +15 -10
- data/lib/rack/logger.rb +2 -2
- data/lib/rack/media_type.rb +38 -0
- data/lib/rack/{methodoverride.rb → method_override.rb} +6 -6
- data/lib/rack/mime.rb +18 -5
- data/lib/rack/mock.rb +36 -54
- data/lib/rack/multipart/generator.rb +5 -5
- data/lib/rack/multipart/parser.rb +283 -157
- data/lib/rack/multipart/uploaded_file.rb +1 -2
- data/lib/rack/multipart.rb +36 -8
- 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 +394 -305
- data/lib/rack/response.rb +130 -57
- 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 +30 -23
- data/lib/rack/session/abstract/id.rb +110 -75
- data/lib/rack/session/cookie.rb +24 -17
- data/lib/rack/session/memcache.rb +9 -9
- data/lib/rack/session/pool.rb +8 -8
- 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 +156 -217
- data/lib/rack.rb +70 -21
- data/rack.gemspec +10 -9
- 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_escaped_quotes_and_modification_param +1 -1
- data/test/multipart/filename_with_single_quote +7 -0
- 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 +37 -35
- data/test/{spec_commonlogger.rb → spec_common_logger.rb} +35 -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 +85 -49
- 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 +120 -77
- data/test/spec_handler.rb +19 -34
- data/test/spec_head.rb +15 -14
- data/test/spec_lint.rb +169 -199
- data/test/spec_lobster.rb +24 -23
- data/test/spec_lock.rb +79 -39
- data/test/spec_logger.rb +4 -3
- data/test/spec_media_type.rb +42 -0
- data/test/{spec_methodoverride.rb → spec_method_override.rb} +34 -35
- data/test/spec_mime.rb +19 -19
- data/test/spec_mock.rb +206 -144
- data/test/spec_multipart.rb +329 -208
- data/test/{spec_nulllogger.rb → spec_null_logger.rb} +5 -4
- data/test/spec_recursive.rb +17 -14
- data/test/spec_request.rb +796 -605
- data/test/spec_response.rb +233 -112
- 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 +45 -0
- data/test/spec_session_cookie.rb +99 -67
- data/test/spec_session_memcache.rb +67 -68
- data/test/spec_session_pool.rb +52 -51
- data/test/{spec_showexceptions.rb → spec_show_exceptions.rb} +23 -28
- 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 +93 -71
- 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 +95 -74
- 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_mongrel.rb +0 -182
- /data/lib/rack/{conditionalget.rb → conditional_get.rb} +0 -0
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,150 @@ 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_be_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"
|
116
|
+
end
|
117
|
+
|
118
|
+
it "can set SameSite cookies with symbol value :none" do
|
119
|
+
response = Rack::Response.new
|
120
|
+
response.set_cookie "foo", { value: "bar", same_site: :none }
|
121
|
+
response["Set-Cookie"].must_equal "foo=bar; SameSite=None"
|
122
|
+
end
|
123
|
+
|
124
|
+
it "can set SameSite cookies with symbol value :None" do
|
125
|
+
response = Rack::Response.new
|
126
|
+
response.set_cookie "foo", { value: "bar", same_site: :None }
|
127
|
+
response["Set-Cookie"].must_equal "foo=bar; SameSite=None"
|
128
|
+
end
|
129
|
+
|
130
|
+
it "can set SameSite cookies with string value 'None'" do
|
131
|
+
response = Rack::Response.new
|
132
|
+
response.set_cookie "foo", { value: "bar", same_site: "None" }
|
133
|
+
response["Set-Cookie"].must_equal "foo=bar; SameSite=None"
|
98
134
|
end
|
99
135
|
|
100
136
|
it "can set SameSite cookies with symbol value :lax" do
|
101
137
|
response = Rack::Response.new
|
102
138
|
response.set_cookie "foo", {:value => "bar", :same_site => :lax}
|
103
|
-
response["Set-Cookie"].
|
139
|
+
response["Set-Cookie"].must_equal "foo=bar; SameSite=Lax"
|
104
140
|
end
|
105
141
|
|
106
142
|
it "can set SameSite cookies with symbol value :Lax" do
|
107
143
|
response = Rack::Response.new
|
108
144
|
response.set_cookie "foo", {:value => "bar", :same_site => :lax}
|
109
|
-
response["Set-Cookie"].
|
145
|
+
response["Set-Cookie"].must_equal "foo=bar; SameSite=Lax"
|
110
146
|
end
|
111
147
|
|
112
148
|
it "can set SameSite cookies with string value 'Lax'" do
|
113
149
|
response = Rack::Response.new
|
114
150
|
response.set_cookie "foo", {:value => "bar", :same_site => "Lax"}
|
115
|
-
response["Set-Cookie"].
|
151
|
+
response["Set-Cookie"].must_equal "foo=bar; SameSite=Lax"
|
116
152
|
end
|
117
153
|
|
118
154
|
it "can set SameSite cookies with boolean value true" do
|
119
155
|
response = Rack::Response.new
|
120
156
|
response.set_cookie "foo", {:value => "bar", :same_site => true}
|
121
|
-
response["Set-Cookie"].
|
157
|
+
response["Set-Cookie"].must_equal "foo=bar; SameSite=Strict"
|
122
158
|
end
|
123
159
|
|
124
160
|
it "can set SameSite cookies with symbol value :strict" do
|
125
161
|
response = Rack::Response.new
|
126
162
|
response.set_cookie "foo", {:value => "bar", :same_site => :strict}
|
127
|
-
response["Set-Cookie"].
|
163
|
+
response["Set-Cookie"].must_equal "foo=bar; SameSite=Strict"
|
128
164
|
end
|
129
165
|
|
130
166
|
it "can set SameSite cookies with symbol value :Strict" do
|
131
167
|
response = Rack::Response.new
|
132
168
|
response.set_cookie "foo", {:value => "bar", :same_site => :Strict}
|
133
|
-
response["Set-Cookie"].
|
169
|
+
response["Set-Cookie"].must_equal "foo=bar; SameSite=Strict"
|
134
170
|
end
|
135
171
|
|
136
172
|
it "can set SameSite cookies with string value 'Strict'" do
|
137
173
|
response = Rack::Response.new
|
138
174
|
response.set_cookie "foo", {:value => "bar", :same_site => "Strict"}
|
139
|
-
response["Set-Cookie"].
|
175
|
+
response["Set-Cookie"].must_equal "foo=bar; SameSite=Strict"
|
140
176
|
end
|
141
177
|
|
142
178
|
it "validates the SameSite option value" do
|
143
179
|
response = Rack::Response.new
|
144
180
|
lambda {
|
145
181
|
response.set_cookie "foo", {:value => "bar", :same_site => "Foo"}
|
146
|
-
}.
|
147
|
-
message.
|
182
|
+
}.must_raise(ArgumentError).
|
183
|
+
message.must_match(/Invalid SameSite value: "Foo"/)
|
148
184
|
end
|
149
185
|
|
150
186
|
it "can set SameSite cookies with symbol value" do
|
151
187
|
response = Rack::Response.new
|
152
188
|
response.set_cookie "foo", {:value => "bar", :same_site => :Strict}
|
153
|
-
response["Set-Cookie"].
|
189
|
+
response["Set-Cookie"].must_equal "foo=bar; SameSite=Strict"
|
154
190
|
end
|
155
191
|
|
156
192
|
[ nil, false ].each do |non_truthy|
|
157
193
|
it "omits SameSite attribute given a #{non_truthy.inspect} value" do
|
158
194
|
response = Rack::Response.new
|
159
195
|
response.set_cookie "foo", {:value => "bar", :same_site => non_truthy}
|
160
|
-
response["Set-Cookie"].
|
196
|
+
response["Set-Cookie"].must_equal "foo=bar"
|
161
197
|
end
|
162
198
|
end
|
163
199
|
|
@@ -166,7 +202,7 @@ describe Rack::Response do
|
|
166
202
|
response.set_cookie "foo", "bar"
|
167
203
|
response.set_cookie "foo2", "bar2"
|
168
204
|
response.delete_cookie "foo"
|
169
|
-
response["Set-Cookie"].
|
205
|
+
response["Set-Cookie"].must_equal [
|
170
206
|
"foo2=bar2",
|
171
207
|
"foo=; max-age=0; expires=Thu, 01 Jan 1970 00:00:00 -0000"
|
172
208
|
].join("\n")
|
@@ -176,11 +212,11 @@ describe Rack::Response do
|
|
176
212
|
response = Rack::Response.new
|
177
213
|
response.set_cookie "foo", {:value => "bar", :domain => "sample.example.com"}
|
178
214
|
response.set_cookie "foo", {:value => "bar", :domain => ".example.com"}
|
179
|
-
response["Set-Cookie"].
|
215
|
+
response["Set-Cookie"].must_equal ["foo=bar; domain=sample.example.com", "foo=bar; domain=.example.com"].join("\n")
|
180
216
|
response.delete_cookie "foo", :domain => ".example.com"
|
181
|
-
response["Set-Cookie"].
|
217
|
+
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
218
|
response.delete_cookie "foo", :domain => "sample.example.com"
|
183
|
-
response["Set-Cookie"].
|
219
|
+
response["Set-Cookie"].must_equal ["foo=; domain=.example.com; max-age=0; expires=Thu, 01 Jan 1970 00:00:00 -0000",
|
184
220
|
"foo=; domain=sample.example.com; max-age=0; expires=Thu, 01 Jan 1970 00:00:00 -0000"].join("\n")
|
185
221
|
end
|
186
222
|
|
@@ -188,11 +224,11 @@ describe Rack::Response do
|
|
188
224
|
response = Rack::Response.new
|
189
225
|
response.set_cookie "foo", {:value => "bar", :path => "/"}
|
190
226
|
response.set_cookie "foo", {:value => "bar", :path => "/path"}
|
191
|
-
response["Set-Cookie"].
|
227
|
+
response["Set-Cookie"].must_equal ["foo=bar; path=/",
|
192
228
|
"foo=bar; path=/path"].join("\n")
|
193
229
|
|
194
230
|
response.delete_cookie "foo", :path => "/path"
|
195
|
-
response["Set-Cookie"].
|
231
|
+
response["Set-Cookie"].must_equal ["foo=bar; path=/",
|
196
232
|
"foo=; path=/path; max-age=0; expires=Thu, 01 Jan 1970 00:00:00 -0000"].join("\n")
|
197
233
|
end
|
198
234
|
|
@@ -200,26 +236,26 @@ describe Rack::Response do
|
|
200
236
|
response = Rack::Response.new
|
201
237
|
response.redirect "/foo"
|
202
238
|
status, header, body = response.finish
|
203
|
-
status.
|
204
|
-
header["Location"].
|
239
|
+
status.must_equal 302
|
240
|
+
header["Location"].must_equal "/foo"
|
205
241
|
|
206
242
|
response = Rack::Response.new
|
207
243
|
response.redirect "/foo", 307
|
208
244
|
status, header, body = response.finish
|
209
245
|
|
210
|
-
status.
|
246
|
+
status.must_equal 307
|
211
247
|
end
|
212
248
|
|
213
249
|
it "has a useful constructor" do
|
214
250
|
r = Rack::Response.new("foo")
|
215
251
|
status, header, body = r.finish
|
216
252
|
str = ""; body.each { |part| str << part }
|
217
|
-
str.
|
253
|
+
str.must_equal "foo"
|
218
254
|
|
219
255
|
r = Rack::Response.new(["foo", "bar"])
|
220
256
|
status, header, body = r.finish
|
221
257
|
str = ""; body.each { |part| str << part }
|
222
|
-
str.
|
258
|
+
str.must_equal "foobar"
|
223
259
|
|
224
260
|
object_with_each = Object.new
|
225
261
|
def object_with_each.each
|
@@ -230,13 +266,13 @@ describe Rack::Response do
|
|
230
266
|
r.write "foo"
|
231
267
|
status, header, body = r.finish
|
232
268
|
str = ""; body.each { |part| str << part }
|
233
|
-
str.
|
269
|
+
str.must_equal "foobarfoo"
|
234
270
|
|
235
271
|
r = Rack::Response.new([], 500)
|
236
|
-
r.status.
|
272
|
+
r.status.must_equal 500
|
237
273
|
|
238
274
|
r = Rack::Response.new([], "200 OK")
|
239
|
-
r.status.
|
275
|
+
r.status.must_equal 200
|
240
276
|
end
|
241
277
|
|
242
278
|
it "has a constructor that can take a block" do
|
@@ -246,162 +282,247 @@ describe Rack::Response do
|
|
246
282
|
}
|
247
283
|
status, _, body = r.finish
|
248
284
|
str = ""; body.each { |part| str << part }
|
249
|
-
str.
|
250
|
-
status.
|
285
|
+
str.must_equal "foo"
|
286
|
+
status.must_equal 404
|
251
287
|
end
|
252
288
|
|
253
289
|
it "doesn't return invalid responses" do
|
254
290
|
r = Rack::Response.new(["foo", "bar"], 204)
|
255
291
|
_, header, body = r.finish
|
256
292
|
str = ""; body.each { |part| str << part }
|
257
|
-
str.
|
258
|
-
header["Content-Type"].
|
259
|
-
header['Content-Length'].
|
293
|
+
str.must_be :empty?
|
294
|
+
header["Content-Type"].must_be_nil
|
295
|
+
header['Content-Length'].must_be_nil
|
260
296
|
|
261
297
|
lambda {
|
262
298
|
Rack::Response.new(Object.new)
|
263
|
-
}.
|
264
|
-
message.
|
299
|
+
}.must_raise(TypeError).
|
300
|
+
message.must_match(/stringable or iterable required/)
|
265
301
|
end
|
266
302
|
|
267
303
|
it "knows if it's empty" do
|
268
304
|
r = Rack::Response.new
|
269
|
-
r.
|
305
|
+
r.must_be :empty?
|
270
306
|
r.write "foo"
|
271
|
-
r.
|
307
|
+
r.wont_be :empty?
|
272
308
|
|
273
309
|
r = Rack::Response.new
|
274
|
-
r.
|
310
|
+
r.must_be :empty?
|
275
311
|
r.finish
|
276
|
-
r.
|
312
|
+
r.must_be :empty?
|
277
313
|
|
278
314
|
r = Rack::Response.new
|
279
|
-
r.
|
315
|
+
r.must_be :empty?
|
280
316
|
r.finish { }
|
281
|
-
r.
|
317
|
+
r.wont_be :empty?
|
282
318
|
end
|
283
319
|
|
284
|
-
|
320
|
+
it "provide access to the HTTP status" do
|
285
321
|
res = Rack::Response.new
|
286
322
|
res.status = 200
|
287
|
-
res.
|
288
|
-
res.
|
323
|
+
res.must_be :successful?
|
324
|
+
res.must_be :ok?
|
289
325
|
|
290
326
|
res.status = 201
|
291
|
-
res.
|
292
|
-
res.
|
327
|
+
res.must_be :successful?
|
328
|
+
res.must_be :created?
|
293
329
|
|
294
330
|
res.status = 202
|
295
|
-
res.
|
296
|
-
res.
|
331
|
+
res.must_be :successful?
|
332
|
+
res.must_be :accepted?
|
333
|
+
|
334
|
+
res.status = 204
|
335
|
+
res.must_be :successful?
|
336
|
+
res.must_be :no_content?
|
337
|
+
|
338
|
+
res.status = 301
|
339
|
+
res.must_be :redirect?
|
340
|
+
res.must_be :moved_permanently?
|
341
|
+
|
342
|
+
res.status = 302
|
343
|
+
res.must_be :redirect?
|
344
|
+
|
345
|
+
res.status = 303
|
346
|
+
res.must_be :redirect?
|
347
|
+
|
348
|
+
res.status = 307
|
349
|
+
res.must_be :redirect?
|
350
|
+
|
351
|
+
res.status = 308
|
352
|
+
res.must_be :redirect?
|
297
353
|
|
298
354
|
res.status = 400
|
299
|
-
res.
|
300
|
-
res.
|
301
|
-
res.
|
355
|
+
res.wont_be :successful?
|
356
|
+
res.must_be :client_error?
|
357
|
+
res.must_be :bad_request?
|
302
358
|
|
303
359
|
res.status = 401
|
304
|
-
res.
|
305
|
-
res.
|
306
|
-
res.
|
360
|
+
res.wont_be :successful?
|
361
|
+
res.must_be :client_error?
|
362
|
+
res.must_be :unauthorized?
|
307
363
|
|
308
364
|
res.status = 404
|
309
|
-
res.
|
310
|
-
res.
|
311
|
-
res.
|
365
|
+
res.wont_be :successful?
|
366
|
+
res.must_be :client_error?
|
367
|
+
res.must_be :not_found?
|
312
368
|
|
313
369
|
res.status = 405
|
314
|
-
res.
|
315
|
-
res.
|
316
|
-
res.
|
370
|
+
res.wont_be :successful?
|
371
|
+
res.must_be :client_error?
|
372
|
+
res.must_be :method_not_allowed?
|
317
373
|
|
318
|
-
res.status =
|
319
|
-
res.
|
320
|
-
res.
|
321
|
-
res.
|
374
|
+
res.status = 412
|
375
|
+
res.wont_be :successful?
|
376
|
+
res.must_be :client_error?
|
377
|
+
res.must_be :precondition_failed?
|
322
378
|
|
323
379
|
res.status = 422
|
324
|
-
res.
|
325
|
-
res.
|
326
|
-
res.
|
380
|
+
res.wont_be :successful?
|
381
|
+
res.must_be :client_error?
|
382
|
+
res.must_be :unprocessable?
|
327
383
|
|
328
384
|
res.status = 501
|
329
|
-
res.
|
330
|
-
res.
|
331
|
-
|
332
|
-
res.status = 307
|
333
|
-
res.should.be.redirect
|
385
|
+
res.wont_be :successful?
|
386
|
+
res.must_be :server_error?
|
334
387
|
end
|
335
388
|
|
336
|
-
|
389
|
+
it "provide access to the HTTP headers" do
|
337
390
|
res = Rack::Response.new
|
338
391
|
res["Content-Type"] = "text/yaml"
|
339
392
|
|
340
|
-
res.
|
341
|
-
res.headers["Content-Type"].
|
342
|
-
res["Content-Type"].
|
343
|
-
res.content_type.
|
344
|
-
res.content_length.
|
345
|
-
res.location.
|
393
|
+
res.must_include "Content-Type"
|
394
|
+
res.headers["Content-Type"].must_equal "text/yaml"
|
395
|
+
res["Content-Type"].must_equal "text/yaml"
|
396
|
+
res.content_type.must_equal "text/yaml"
|
397
|
+
res.content_length.must_be_nil
|
398
|
+
res.location.must_be_nil
|
346
399
|
end
|
347
400
|
|
348
401
|
it "does not add or change Content-Length when #finish()ing" do
|
349
402
|
res = Rack::Response.new
|
350
403
|
res.status = 200
|
351
404
|
res.finish
|
352
|
-
res.headers["Content-Length"].
|
405
|
+
res.headers["Content-Length"].must_be_nil
|
353
406
|
|
354
407
|
res = Rack::Response.new
|
355
408
|
res.status = 200
|
356
409
|
res.headers["Content-Length"] = "10"
|
357
410
|
res.finish
|
358
|
-
res.headers["Content-Length"].
|
411
|
+
res.headers["Content-Length"].must_equal "10"
|
359
412
|
end
|
360
413
|
|
361
414
|
it "updates Content-Length when body appended to using #write" do
|
362
415
|
res = Rack::Response.new
|
363
416
|
res.status = 200
|
364
|
-
res.headers["Content-Length"].
|
417
|
+
res.headers["Content-Length"].must_be_nil
|
365
418
|
res.write "Hi"
|
366
|
-
res.headers["Content-Length"].
|
419
|
+
res.headers["Content-Length"].must_equal "2"
|
367
420
|
res.write " there"
|
368
|
-
res.headers["Content-Length"].
|
421
|
+
res.headers["Content-Length"].must_equal "8"
|
369
422
|
end
|
370
423
|
|
371
424
|
it "calls close on #body" do
|
372
425
|
res = Rack::Response.new
|
373
426
|
res.body = StringIO.new
|
374
427
|
res.close
|
375
|
-
res.body.
|
428
|
+
res.body.must_be :closed?
|
376
429
|
end
|
377
430
|
|
378
|
-
it "calls close on #body when 204
|
431
|
+
it "calls close on #body when 204 or 304" do
|
379
432
|
res = Rack::Response.new
|
380
433
|
res.body = StringIO.new
|
381
434
|
res.finish
|
382
|
-
res.body.
|
435
|
+
res.body.wont_be :closed?
|
383
436
|
|
384
437
|
res.status = 204
|
385
438
|
_, _, b = res.finish
|
386
|
-
res.body.
|
387
|
-
b.
|
439
|
+
res.body.must_be :closed?
|
440
|
+
b.wont_equal res.body
|
388
441
|
|
389
442
|
res.body = StringIO.new
|
390
443
|
res.status = 205
|
391
444
|
_, _, b = res.finish
|
392
|
-
res.body.
|
393
|
-
b.
|
445
|
+
res.body.wont_be :closed?
|
446
|
+
b.wont_equal res.body
|
394
447
|
|
395
448
|
res.body = StringIO.new
|
396
449
|
res.status = 304
|
397
450
|
_, _, b = res.finish
|
398
|
-
res.body.
|
399
|
-
b.
|
451
|
+
res.body.must_be :closed?
|
452
|
+
b.wont_equal res.body
|
400
453
|
end
|
401
454
|
|
402
455
|
it "wraps the body from #to_ary to prevent infinite loops" do
|
403
456
|
res = Rack::Response.new
|
404
|
-
res.finish.last.
|
405
|
-
lambda { res.finish.last.to_ary }.
|
457
|
+
res.finish.last.wont_respond_to(:to_ary)
|
458
|
+
lambda { res.finish.last.to_ary }.must_raise NoMethodError
|
459
|
+
end
|
460
|
+
end
|
461
|
+
|
462
|
+
describe Rack::Response, 'headers' do
|
463
|
+
before do
|
464
|
+
@response = Rack::Response.new([], 200, { 'Foo' => '1' })
|
465
|
+
end
|
466
|
+
|
467
|
+
it 'has_header?' do
|
468
|
+
lambda { @response.has_header? nil }.must_raise NoMethodError
|
469
|
+
|
470
|
+
@response.has_header?('Foo').must_equal true
|
471
|
+
@response.has_header?('foo').must_equal true
|
472
|
+
end
|
473
|
+
|
474
|
+
it 'get_header' do
|
475
|
+
lambda { @response.get_header nil }.must_raise NoMethodError
|
476
|
+
|
477
|
+
@response.get_header('Foo').must_equal '1'
|
478
|
+
@response.get_header('foo').must_equal '1'
|
479
|
+
end
|
480
|
+
|
481
|
+
it 'set_header' do
|
482
|
+
lambda { @response.set_header nil, '1' }.must_raise NoMethodError
|
483
|
+
|
484
|
+
@response.set_header('Foo', '2').must_equal '2'
|
485
|
+
@response.has_header?('Foo').must_equal true
|
486
|
+
@response.get_header('Foo').must_equal('2')
|
487
|
+
|
488
|
+
@response.set_header('Foo', nil).must_be_nil
|
489
|
+
@response.has_header?('Foo').must_equal true
|
490
|
+
@response.get_header('Foo').must_be_nil
|
491
|
+
end
|
492
|
+
|
493
|
+
it 'add_header' do
|
494
|
+
lambda { @response.add_header nil, '1' }.must_raise NoMethodError
|
495
|
+
|
496
|
+
# Add a value to an existing header
|
497
|
+
@response.add_header('Foo', '2').must_equal '1,2'
|
498
|
+
@response.get_header('Foo').must_equal '1,2'
|
499
|
+
|
500
|
+
# Add nil to an existing header
|
501
|
+
@response.add_header('Foo', nil).must_equal '1,2'
|
502
|
+
@response.get_header('Foo').must_equal '1,2'
|
503
|
+
|
504
|
+
# Add nil to a nonexistent header
|
505
|
+
@response.add_header('Bar', nil).must_be_nil
|
506
|
+
@response.has_header?('Bar').must_equal false
|
507
|
+
@response.get_header('Bar').must_be_nil
|
508
|
+
|
509
|
+
# Add a value to a nonexistent header
|
510
|
+
@response.add_header('Bar', '1').must_equal '1'
|
511
|
+
@response.has_header?('Bar').must_equal true
|
512
|
+
@response.get_header('Bar').must_equal '1'
|
513
|
+
end
|
514
|
+
|
515
|
+
it 'delete_header' do
|
516
|
+
lambda { @response.delete_header nil }.must_raise NoMethodError
|
517
|
+
|
518
|
+
@response.delete_header('Foo').must_equal '1'
|
519
|
+
(!!@response.has_header?('Foo')).must_equal false
|
520
|
+
|
521
|
+
@response.delete_header('Foo').must_be_nil
|
522
|
+
@response.has_header?('Foo').must_equal false
|
523
|
+
|
524
|
+
@response.set_header('Foo', 1)
|
525
|
+
@response.delete_header('foo').must_equal 1
|
526
|
+
@response.has_header?('Foo').must_equal false
|
406
527
|
end
|
407
528
|
end
|