rack 1.6.13 → 2.0.0.alpha
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/HISTORY.md +139 -18
- data/README.rdoc +17 -25
- data/Rakefile +6 -14
- data/SPEC +8 -9
- data/contrib/rack_logo.svg +164 -111
- data/lib/rack.rb +70 -21
- 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} +2 -2
- 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 +49 -55
- data/lib/rack/etag.rb +2 -1
- data/lib/rack/events.rb +154 -0
- data/lib/rack/file.rb +55 -40
- data/lib/rack/handler.rb +2 -24
- 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/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 -52
- data/lib/rack/multipart.rb +35 -6
- data/lib/rack/multipart/generator.rb +4 -4
- data/lib/rack/multipart/parser.rb +273 -158
- data/lib/rack/multipart/uploaded_file.rb +1 -2
- data/lib/rack/{nulllogger.rb → null_logger.rb} +1 -1
- data/lib/rack/query_parser.rb +174 -0
- data/lib/rack/recursive.rb +8 -8
- data/lib/rack/reloader.rb +1 -2
- data/lib/rack/request.rb +370 -304
- 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 +93 -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 +13 -14
- data/lib/rack/utils.rb +128 -221
- data/rack.gemspec +9 -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 +31 -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/registering_handler/rack/handler/registering_myself.rb +1 -1
- data/test/spec_auth_basic.rb +20 -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 +72 -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 +96 -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 +310 -202
- data/test/{spec_nulllogger.rb → spec_null_logger.rb} +5 -4
- data/test/spec_recursive.rb +17 -14
- data/test/spec_request.rb +763 -607
- data/test/spec_response.rb +209 -156
- 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_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 +417 -345
- data/test/spec_version.rb +2 -8
- data/test/spec_webrick.rb +77 -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 +116 -71
- 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,82 @@ 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"].
|
98
|
-
end
|
99
|
-
|
100
|
-
it "can set SameSite cookies with symbol value :lax" do
|
101
|
-
response = Rack::Response.new
|
102
|
-
response.set_cookie "foo", {:value => "bar", :same_site => :lax}
|
103
|
-
response["Set-Cookie"].should.equal "foo=bar; SameSite=Lax"
|
115
|
+
response["Set-Cookie"].must_equal "foo=bar"
|
104
116
|
end
|
105
117
|
|
106
|
-
it "can set
|
118
|
+
it "can set First-Party cookies" do
|
107
119
|
response = Rack::Response.new
|
108
|
-
response.set_cookie "foo", {:value => "bar", :
|
109
|
-
response["Set-Cookie"].
|
110
|
-
end
|
111
|
-
|
112
|
-
it "can set SameSite cookies with string value 'Lax'" do
|
113
|
-
response = Rack::Response.new
|
114
|
-
response.set_cookie "foo", {:value => "bar", :same_site => "Lax"}
|
115
|
-
response["Set-Cookie"].should.equal "foo=bar; SameSite=Lax"
|
116
|
-
end
|
117
|
-
|
118
|
-
it "can set SameSite cookies with boolean value true" do
|
119
|
-
response = Rack::Response.new
|
120
|
-
response.set_cookie "foo", {:value => "bar", :same_site => true}
|
121
|
-
response["Set-Cookie"].should.equal "foo=bar; SameSite=Strict"
|
122
|
-
end
|
123
|
-
|
124
|
-
it "can set SameSite cookies with symbol value :strict" do
|
125
|
-
response = Rack::Response.new
|
126
|
-
response.set_cookie "foo", {:value => "bar", :same_site => :strict}
|
127
|
-
response["Set-Cookie"].should.equal "foo=bar; SameSite=Strict"
|
128
|
-
end
|
129
|
-
|
130
|
-
it "can set SameSite cookies with symbol value :Strict" do
|
131
|
-
response = Rack::Response.new
|
132
|
-
response.set_cookie "foo", {:value => "bar", :same_site => :Strict}
|
133
|
-
response["Set-Cookie"].should.equal "foo=bar; SameSite=Strict"
|
134
|
-
end
|
135
|
-
|
136
|
-
it "can set SameSite cookies with string value 'Strict'" do
|
137
|
-
response = Rack::Response.new
|
138
|
-
response.set_cookie "foo", {:value => "bar", :same_site => "Strict"}
|
139
|
-
response["Set-Cookie"].should.equal "foo=bar; SameSite=Strict"
|
140
|
-
end
|
141
|
-
|
142
|
-
it "validates the SameSite option value" do
|
143
|
-
response = Rack::Response.new
|
144
|
-
lambda {
|
145
|
-
response.set_cookie "foo", {:value => "bar", :same_site => "Foo"}
|
146
|
-
}.should.raise(ArgumentError).
|
147
|
-
message.should.match(/Invalid SameSite value: "Foo"/)
|
148
|
-
end
|
149
|
-
|
150
|
-
it "can set SameSite cookies with symbol value" do
|
151
|
-
response = Rack::Response.new
|
152
|
-
response.set_cookie "foo", {:value => "bar", :same_site => :Strict}
|
153
|
-
response["Set-Cookie"].should.equal "foo=bar; SameSite=Strict"
|
120
|
+
response.set_cookie "foo", {:value => "bar", :first_party => true}
|
121
|
+
response["Set-Cookie"].must_equal "foo=bar; First-Party"
|
154
122
|
end
|
155
123
|
|
156
124
|
[ nil, false ].each do |non_truthy|
|
157
|
-
it "omits
|
125
|
+
it "omits First-Party attribute given a #{non_truthy.inspect} value" do
|
158
126
|
response = Rack::Response.new
|
159
|
-
response.set_cookie "foo", {:value => "bar", :
|
160
|
-
response["Set-Cookie"].
|
127
|
+
response.set_cookie "foo", {:value => "bar", :first_party => non_truthy}
|
128
|
+
response["Set-Cookie"].must_equal "foo=bar"
|
161
129
|
end
|
162
130
|
end
|
163
131
|
|
@@ -166,7 +134,7 @@ describe Rack::Response do
|
|
166
134
|
response.set_cookie "foo", "bar"
|
167
135
|
response.set_cookie "foo2", "bar2"
|
168
136
|
response.delete_cookie "foo"
|
169
|
-
response["Set-Cookie"].
|
137
|
+
response["Set-Cookie"].must_equal [
|
170
138
|
"foo2=bar2",
|
171
139
|
"foo=; max-age=0; expires=Thu, 01 Jan 1970 00:00:00 -0000"
|
172
140
|
].join("\n")
|
@@ -176,11 +144,11 @@ describe Rack::Response do
|
|
176
144
|
response = Rack::Response.new
|
177
145
|
response.set_cookie "foo", {:value => "bar", :domain => "sample.example.com"}
|
178
146
|
response.set_cookie "foo", {:value => "bar", :domain => ".example.com"}
|
179
|
-
response["Set-Cookie"].
|
147
|
+
response["Set-Cookie"].must_equal ["foo=bar; domain=sample.example.com", "foo=bar; domain=.example.com"].join("\n")
|
180
148
|
response.delete_cookie "foo", :domain => ".example.com"
|
181
|
-
response["Set-Cookie"].
|
149
|
+
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
150
|
response.delete_cookie "foo", :domain => "sample.example.com"
|
183
|
-
response["Set-Cookie"].
|
151
|
+
response["Set-Cookie"].must_equal ["foo=; domain=.example.com; max-age=0; expires=Thu, 01 Jan 1970 00:00:00 -0000",
|
184
152
|
"foo=; domain=sample.example.com; max-age=0; expires=Thu, 01 Jan 1970 00:00:00 -0000"].join("\n")
|
185
153
|
end
|
186
154
|
|
@@ -188,11 +156,11 @@ describe Rack::Response do
|
|
188
156
|
response = Rack::Response.new
|
189
157
|
response.set_cookie "foo", {:value => "bar", :path => "/"}
|
190
158
|
response.set_cookie "foo", {:value => "bar", :path => "/path"}
|
191
|
-
response["Set-Cookie"].
|
159
|
+
response["Set-Cookie"].must_equal ["foo=bar; path=/",
|
192
160
|
"foo=bar; path=/path"].join("\n")
|
193
161
|
|
194
162
|
response.delete_cookie "foo", :path => "/path"
|
195
|
-
response["Set-Cookie"].
|
163
|
+
response["Set-Cookie"].must_equal ["foo=bar; path=/",
|
196
164
|
"foo=; path=/path; max-age=0; expires=Thu, 01 Jan 1970 00:00:00 -0000"].join("\n")
|
197
165
|
end
|
198
166
|
|
@@ -200,26 +168,26 @@ describe Rack::Response do
|
|
200
168
|
response = Rack::Response.new
|
201
169
|
response.redirect "/foo"
|
202
170
|
status, header, body = response.finish
|
203
|
-
status.
|
204
|
-
header["Location"].
|
171
|
+
status.must_equal 302
|
172
|
+
header["Location"].must_equal "/foo"
|
205
173
|
|
206
174
|
response = Rack::Response.new
|
207
175
|
response.redirect "/foo", 307
|
208
176
|
status, header, body = response.finish
|
209
177
|
|
210
|
-
status.
|
178
|
+
status.must_equal 307
|
211
179
|
end
|
212
180
|
|
213
181
|
it "has a useful constructor" do
|
214
182
|
r = Rack::Response.new("foo")
|
215
183
|
status, header, body = r.finish
|
216
184
|
str = ""; body.each { |part| str << part }
|
217
|
-
str.
|
185
|
+
str.must_equal "foo"
|
218
186
|
|
219
187
|
r = Rack::Response.new(["foo", "bar"])
|
220
188
|
status, header, body = r.finish
|
221
189
|
str = ""; body.each { |part| str << part }
|
222
|
-
str.
|
190
|
+
str.must_equal "foobar"
|
223
191
|
|
224
192
|
object_with_each = Object.new
|
225
193
|
def object_with_each.each
|
@@ -230,13 +198,13 @@ describe Rack::Response do
|
|
230
198
|
r.write "foo"
|
231
199
|
status, header, body = r.finish
|
232
200
|
str = ""; body.each { |part| str << part }
|
233
|
-
str.
|
201
|
+
str.must_equal "foobarfoo"
|
234
202
|
|
235
203
|
r = Rack::Response.new([], 500)
|
236
|
-
r.status.
|
204
|
+
r.status.must_equal 500
|
237
205
|
|
238
206
|
r = Rack::Response.new([], "200 OK")
|
239
|
-
r.status.
|
207
|
+
r.status.must_equal 200
|
240
208
|
end
|
241
209
|
|
242
210
|
it "has a constructor that can take a block" do
|
@@ -246,162 +214,247 @@ describe Rack::Response do
|
|
246
214
|
}
|
247
215
|
status, _, body = r.finish
|
248
216
|
str = ""; body.each { |part| str << part }
|
249
|
-
str.
|
250
|
-
status.
|
217
|
+
str.must_equal "foo"
|
218
|
+
status.must_equal 404
|
251
219
|
end
|
252
220
|
|
253
221
|
it "doesn't return invalid responses" do
|
254
222
|
r = Rack::Response.new(["foo", "bar"], 204)
|
255
223
|
_, header, body = r.finish
|
256
224
|
str = ""; body.each { |part| str << part }
|
257
|
-
str.
|
258
|
-
header["Content-Type"].
|
259
|
-
header['Content-Length'].
|
225
|
+
str.must_be :empty?
|
226
|
+
header["Content-Type"].must_equal nil
|
227
|
+
header['Content-Length'].must_equal nil
|
260
228
|
|
261
229
|
lambda {
|
262
230
|
Rack::Response.new(Object.new)
|
263
|
-
}.
|
264
|
-
message.
|
231
|
+
}.must_raise(TypeError).
|
232
|
+
message.must_match(/stringable or iterable required/)
|
265
233
|
end
|
266
234
|
|
267
235
|
it "knows if it's empty" do
|
268
236
|
r = Rack::Response.new
|
269
|
-
r.
|
237
|
+
r.must_be :empty?
|
270
238
|
r.write "foo"
|
271
|
-
r.
|
239
|
+
r.wont_be :empty?
|
272
240
|
|
273
241
|
r = Rack::Response.new
|
274
|
-
r.
|
242
|
+
r.must_be :empty?
|
275
243
|
r.finish
|
276
|
-
r.
|
244
|
+
r.must_be :empty?
|
277
245
|
|
278
246
|
r = Rack::Response.new
|
279
|
-
r.
|
247
|
+
r.must_be :empty?
|
280
248
|
r.finish { }
|
281
|
-
r.
|
249
|
+
r.wont_be :empty?
|
282
250
|
end
|
283
251
|
|
284
|
-
|
252
|
+
it "provide access to the HTTP status" do
|
285
253
|
res = Rack::Response.new
|
286
254
|
res.status = 200
|
287
|
-
res.
|
288
|
-
res.
|
255
|
+
res.must_be :successful?
|
256
|
+
res.must_be :ok?
|
289
257
|
|
290
258
|
res.status = 201
|
291
|
-
res.
|
292
|
-
res.
|
259
|
+
res.must_be :successful?
|
260
|
+
res.must_be :created?
|
293
261
|
|
294
262
|
res.status = 202
|
295
|
-
res.
|
296
|
-
res.
|
263
|
+
res.must_be :successful?
|
264
|
+
res.must_be :accepted?
|
265
|
+
|
266
|
+
res.status = 204
|
267
|
+
res.must_be :successful?
|
268
|
+
res.must_be :no_content?
|
269
|
+
|
270
|
+
res.status = 301
|
271
|
+
res.must_be :redirect?
|
272
|
+
res.must_be :moved_permanently?
|
273
|
+
|
274
|
+
res.status = 302
|
275
|
+
res.must_be :redirect?
|
276
|
+
|
277
|
+
res.status = 303
|
278
|
+
res.must_be :redirect?
|
279
|
+
|
280
|
+
res.status = 307
|
281
|
+
res.must_be :redirect?
|
282
|
+
|
283
|
+
res.status = 308
|
284
|
+
res.must_be :redirect?
|
297
285
|
|
298
286
|
res.status = 400
|
299
|
-
res.
|
300
|
-
res.
|
301
|
-
res.
|
287
|
+
res.wont_be :successful?
|
288
|
+
res.must_be :client_error?
|
289
|
+
res.must_be :bad_request?
|
302
290
|
|
303
291
|
res.status = 401
|
304
|
-
res.
|
305
|
-
res.
|
306
|
-
res.
|
292
|
+
res.wont_be :successful?
|
293
|
+
res.must_be :client_error?
|
294
|
+
res.must_be :unauthorized?
|
307
295
|
|
308
296
|
res.status = 404
|
309
|
-
res.
|
310
|
-
res.
|
311
|
-
res.
|
297
|
+
res.wont_be :successful?
|
298
|
+
res.must_be :client_error?
|
299
|
+
res.must_be :not_found?
|
312
300
|
|
313
301
|
res.status = 405
|
314
|
-
res.
|
315
|
-
res.
|
316
|
-
res.
|
302
|
+
res.wont_be :successful?
|
303
|
+
res.must_be :client_error?
|
304
|
+
res.must_be :method_not_allowed?
|
317
305
|
|
318
|
-
res.status =
|
319
|
-
res.
|
320
|
-
res.
|
321
|
-
res.
|
306
|
+
res.status = 412
|
307
|
+
res.wont_be :successful?
|
308
|
+
res.must_be :client_error?
|
309
|
+
res.must_be :precondition_failed?
|
322
310
|
|
323
311
|
res.status = 422
|
324
|
-
res.
|
325
|
-
res.
|
326
|
-
res.
|
312
|
+
res.wont_be :successful?
|
313
|
+
res.must_be :client_error?
|
314
|
+
res.must_be :unprocessable?
|
327
315
|
|
328
316
|
res.status = 501
|
329
|
-
res.
|
330
|
-
res.
|
331
|
-
|
332
|
-
res.status = 307
|
333
|
-
res.should.be.redirect
|
317
|
+
res.wont_be :successful?
|
318
|
+
res.must_be :server_error?
|
334
319
|
end
|
335
320
|
|
336
|
-
|
321
|
+
it "provide access to the HTTP headers" do
|
337
322
|
res = Rack::Response.new
|
338
323
|
res["Content-Type"] = "text/yaml"
|
339
324
|
|
340
|
-
res.
|
341
|
-
res.headers["Content-Type"].
|
342
|
-
res["Content-Type"].
|
343
|
-
res.content_type.
|
344
|
-
res.content_length.
|
345
|
-
res.location.
|
325
|
+
res.must_include "Content-Type"
|
326
|
+
res.headers["Content-Type"].must_equal "text/yaml"
|
327
|
+
res["Content-Type"].must_equal "text/yaml"
|
328
|
+
res.content_type.must_equal "text/yaml"
|
329
|
+
res.content_length.must_be_nil
|
330
|
+
res.location.must_be_nil
|
346
331
|
end
|
347
332
|
|
348
333
|
it "does not add or change Content-Length when #finish()ing" do
|
349
334
|
res = Rack::Response.new
|
350
335
|
res.status = 200
|
351
336
|
res.finish
|
352
|
-
res.headers["Content-Length"].
|
337
|
+
res.headers["Content-Length"].must_be_nil
|
353
338
|
|
354
339
|
res = Rack::Response.new
|
355
340
|
res.status = 200
|
356
341
|
res.headers["Content-Length"] = "10"
|
357
342
|
res.finish
|
358
|
-
res.headers["Content-Length"].
|
343
|
+
res.headers["Content-Length"].must_equal "10"
|
359
344
|
end
|
360
345
|
|
361
346
|
it "updates Content-Length when body appended to using #write" do
|
362
347
|
res = Rack::Response.new
|
363
348
|
res.status = 200
|
364
|
-
res.headers["Content-Length"].
|
349
|
+
res.headers["Content-Length"].must_be_nil
|
365
350
|
res.write "Hi"
|
366
|
-
res.headers["Content-Length"].
|
351
|
+
res.headers["Content-Length"].must_equal "2"
|
367
352
|
res.write " there"
|
368
|
-
res.headers["Content-Length"].
|
353
|
+
res.headers["Content-Length"].must_equal "8"
|
369
354
|
end
|
370
355
|
|
371
356
|
it "calls close on #body" do
|
372
357
|
res = Rack::Response.new
|
373
358
|
res.body = StringIO.new
|
374
359
|
res.close
|
375
|
-
res.body.
|
360
|
+
res.body.must_be :closed?
|
376
361
|
end
|
377
362
|
|
378
363
|
it "calls close on #body when 204, 205, or 304" do
|
379
364
|
res = Rack::Response.new
|
380
365
|
res.body = StringIO.new
|
381
366
|
res.finish
|
382
|
-
res.body.
|
367
|
+
res.body.wont_be :closed?
|
383
368
|
|
384
369
|
res.status = 204
|
385
370
|
_, _, b = res.finish
|
386
|
-
res.body.
|
387
|
-
b.
|
371
|
+
res.body.must_be :closed?
|
372
|
+
b.wont_equal res.body
|
388
373
|
|
389
374
|
res.body = StringIO.new
|
390
375
|
res.status = 205
|
391
376
|
_, _, b = res.finish
|
392
|
-
res.body.
|
393
|
-
b.
|
377
|
+
res.body.must_be :closed?
|
378
|
+
b.wont_equal res.body
|
394
379
|
|
395
380
|
res.body = StringIO.new
|
396
381
|
res.status = 304
|
397
382
|
_, _, b = res.finish
|
398
|
-
res.body.
|
399
|
-
b.
|
383
|
+
res.body.must_be :closed?
|
384
|
+
b.wont_equal res.body
|
400
385
|
end
|
401
386
|
|
402
387
|
it "wraps the body from #to_ary to prevent infinite loops" do
|
403
388
|
res = Rack::Response.new
|
404
|
-
res.finish.last.
|
405
|
-
lambda { res.finish.last.to_ary }.
|
389
|
+
res.finish.last.wont_respond_to(:to_ary)
|
390
|
+
lambda { res.finish.last.to_ary }.must_raise NoMethodError
|
391
|
+
end
|
392
|
+
end
|
393
|
+
|
394
|
+
describe Rack::Response, 'headers' do
|
395
|
+
before do
|
396
|
+
@response = Rack::Response.new([], 200, { 'Foo' => '1' })
|
397
|
+
end
|
398
|
+
|
399
|
+
it 'has_header?' do
|
400
|
+
lambda { @response.has_header? nil }.must_raise NoMethodError
|
401
|
+
|
402
|
+
@response.has_header?('Foo').must_equal true
|
403
|
+
@response.has_header?('foo').must_equal true
|
404
|
+
end
|
405
|
+
|
406
|
+
it 'get_header' do
|
407
|
+
lambda { @response.get_header nil }.must_raise NoMethodError
|
408
|
+
|
409
|
+
@response.get_header('Foo').must_equal '1'
|
410
|
+
@response.get_header('foo').must_equal '1'
|
411
|
+
end
|
412
|
+
|
413
|
+
it 'set_header' do
|
414
|
+
lambda { @response.set_header nil, '1' }.must_raise NoMethodError
|
415
|
+
|
416
|
+
@response.set_header('Foo', '2').must_equal '2'
|
417
|
+
@response.has_header?('Foo').must_equal true
|
418
|
+
@response.get_header('Foo').must_equal('2')
|
419
|
+
|
420
|
+
@response.set_header('Foo', nil).must_be_nil
|
421
|
+
@response.has_header?('Foo').must_equal true
|
422
|
+
@response.get_header('Foo').must_be_nil
|
423
|
+
end
|
424
|
+
|
425
|
+
it 'add_header' do
|
426
|
+
lambda { @response.add_header nil, '1' }.must_raise NoMethodError
|
427
|
+
|
428
|
+
# Add a value to an existing header
|
429
|
+
@response.add_header('Foo', '2').must_equal '1,2'
|
430
|
+
@response.get_header('Foo').must_equal '1,2'
|
431
|
+
|
432
|
+
# Add nil to an existing header
|
433
|
+
@response.add_header('Foo', nil).must_equal '1,2'
|
434
|
+
@response.get_header('Foo').must_equal '1,2'
|
435
|
+
|
436
|
+
# Add nil to a nonexistent header
|
437
|
+
@response.add_header('Bar', nil).must_be_nil
|
438
|
+
@response.has_header?('Bar').must_equal false
|
439
|
+
@response.get_header('Bar').must_be_nil
|
440
|
+
|
441
|
+
# Add a value to a nonexistent header
|
442
|
+
@response.add_header('Bar', '1').must_equal '1'
|
443
|
+
@response.has_header?('Bar').must_equal true
|
444
|
+
@response.get_header('Bar').must_equal '1'
|
445
|
+
end
|
446
|
+
|
447
|
+
it 'delete_header' do
|
448
|
+
lambda { @response.delete_header nil }.must_raise NoMethodError
|
449
|
+
|
450
|
+
@response.delete_header('Foo').must_equal '1'
|
451
|
+
(!!@response.has_header?('Foo')).must_equal false
|
452
|
+
|
453
|
+
@response.delete_header('Foo').must_be_nil
|
454
|
+
@response.has_header?('Foo').must_equal false
|
455
|
+
|
456
|
+
@response.set_header('Foo', 1)
|
457
|
+
@response.delete_header('foo').must_equal 1
|
458
|
+
@response.has_header?('Foo').must_equal false
|
406
459
|
end
|
407
460
|
end
|