rack 0.9.1 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of rack might be problematic. Click here for more details.
- data/COPYING +1 -1
- data/RDOX +115 -16
- data/README +54 -7
- data/Rakefile +61 -85
- data/SPEC +50 -17
- data/bin/rackup +9 -5
- data/example/protectedlobster.ru +1 -1
- data/lib/rack.rb +7 -3
- data/lib/rack/auth/abstract/handler.rb +13 -4
- data/lib/rack/auth/digest/md5.rb +1 -1
- data/lib/rack/auth/digest/request.rb +2 -2
- data/lib/rack/auth/openid.rb +344 -302
- data/lib/rack/builder.rb +1 -5
- data/lib/rack/chunked.rb +49 -0
- data/lib/rack/conditionalget.rb +4 -0
- data/lib/rack/content_length.rb +7 -3
- data/lib/rack/content_type.rb +23 -0
- data/lib/rack/deflater.rb +83 -74
- data/lib/rack/directory.rb +5 -2
- data/lib/rack/file.rb +4 -1
- data/lib/rack/handler.rb +22 -1
- data/lib/rack/handler/cgi.rb +7 -3
- data/lib/rack/handler/fastcgi.rb +26 -24
- data/lib/rack/handler/lsws.rb +7 -4
- data/lib/rack/handler/mongrel.rb +5 -3
- data/lib/rack/handler/scgi.rb +5 -3
- data/lib/rack/handler/thin.rb +3 -0
- data/lib/rack/handler/webrick.rb +11 -5
- data/lib/rack/lint.rb +138 -66
- data/lib/rack/lock.rb +16 -0
- data/lib/rack/mime.rb +4 -4
- data/lib/rack/mock.rb +3 -3
- data/lib/rack/reloader.rb +88 -46
- data/lib/rack/request.rb +46 -10
- data/lib/rack/response.rb +15 -3
- data/lib/rack/rewindable_input.rb +98 -0
- data/lib/rack/session/abstract/id.rb +71 -82
- data/lib/rack/session/cookie.rb +2 -0
- data/lib/rack/session/memcache.rb +59 -47
- data/lib/rack/session/pool.rb +56 -29
- data/lib/rack/showexceptions.rb +2 -1
- data/lib/rack/showstatus.rb +1 -1
- data/lib/rack/urlmap.rb +12 -5
- data/lib/rack/utils.rb +115 -65
- data/rack.gemspec +54 -0
- data/test/multipart/binary +0 -0
- data/test/multipart/empty +10 -0
- data/test/multipart/ie +6 -0
- data/test/multipart/nested +10 -0
- data/test/multipart/none +9 -0
- data/test/multipart/text +10 -0
- data/test/spec_rack_auth_basic.rb +5 -1
- data/test/spec_rack_auth_digest.rb +93 -36
- data/test/spec_rack_auth_openid.rb +47 -100
- data/test/spec_rack_builder.rb +2 -2
- data/test/spec_rack_chunked.rb +62 -0
- data/test/spec_rack_conditionalget.rb +7 -7
- data/test/spec_rack_content_type.rb +30 -0
- data/test/spec_rack_deflater.rb +36 -14
- data/test/spec_rack_directory.rb +1 -1
- data/test/spec_rack_file.rb +11 -0
- data/test/spec_rack_handler.rb +21 -2
- data/test/spec_rack_lint.rb +163 -44
- data/test/spec_rack_lock.rb +38 -0
- data/test/spec_rack_mock.rb +6 -1
- data/test/spec_rack_request.rb +81 -12
- data/test/spec_rack_response.rb +46 -2
- data/test/spec_rack_rewindable_input.rb +118 -0
- data/test/spec_rack_session_memcache.rb +170 -62
- data/test/spec_rack_session_pool.rb +129 -41
- data/test/spec_rack_static.rb +2 -2
- data/test/spec_rack_thin.rb +3 -2
- data/test/spec_rack_urlmap.rb +10 -0
- data/test/spec_rack_utils.rb +214 -49
- data/test/spec_rack_webrick.rb +7 -0
- data/test/unregistered_handler/rack/handler/unregistered.rb +7 -0
- data/test/unregistered_handler/rack/handler/unregistered_long_one.rb +7 -0
- metadata +95 -6
- data/AUTHORS +0 -8
@@ -14,7 +14,7 @@ context 'Rack::Auth::Digest::MD5' do
|
|
14
14
|
[ 200, {'Content-Type' => 'text/plain'}, ["Hi #{env['REMOTE_USER']}"] ]
|
15
15
|
end
|
16
16
|
end
|
17
|
-
|
17
|
+
|
18
18
|
def protected_app
|
19
19
|
app = Rack::Auth::Digest::MD5.new(unprotected_app) do |username|
|
20
20
|
{ 'Alice' => 'correct-password' }[username]
|
@@ -23,7 +23,7 @@ context 'Rack::Auth::Digest::MD5' do
|
|
23
23
|
app.opaque = 'this-should-be-secret'
|
24
24
|
app
|
25
25
|
end
|
26
|
-
|
26
|
+
|
27
27
|
def protected_app_with_hashed_passwords
|
28
28
|
app = Rack::Auth::Digest::MD5.new(unprotected_app) do |username|
|
29
29
|
username == 'Alice' ? Digest::MD5.hexdigest("Alice:#{realm}:correct-password") : nil
|
@@ -33,17 +33,28 @@ context 'Rack::Auth::Digest::MD5' do
|
|
33
33
|
app.passwords_hashed = true
|
34
34
|
app
|
35
35
|
end
|
36
|
-
|
36
|
+
|
37
|
+
def partially_protected_app
|
38
|
+
Rack::URLMap.new({
|
39
|
+
'/' => unprotected_app,
|
40
|
+
'/protected' => protected_app
|
41
|
+
})
|
42
|
+
end
|
43
|
+
|
44
|
+
def protected_app_with_method_override
|
45
|
+
Rack::MethodOverride.new(protected_app)
|
46
|
+
end
|
47
|
+
|
37
48
|
setup do
|
38
49
|
@request = Rack::MockRequest.new(protected_app)
|
39
50
|
end
|
40
51
|
|
41
|
-
def request(path, headers = {}, &block)
|
42
|
-
response = @request.
|
52
|
+
def request(method, path, headers = {}, &block)
|
53
|
+
response = @request.request(method, path, headers)
|
43
54
|
block.call(response) if block
|
44
55
|
return response
|
45
56
|
end
|
46
|
-
|
57
|
+
|
47
58
|
class MockDigestRequest
|
48
59
|
def initialize(params)
|
49
60
|
@params = params
|
@@ -55,22 +66,25 @@ context 'Rack::Auth::Digest::MD5' do
|
|
55
66
|
super
|
56
67
|
end
|
57
68
|
def method
|
58
|
-
'
|
69
|
+
@params['method']
|
59
70
|
end
|
60
71
|
def response(password)
|
61
72
|
Rack::Auth::Digest::MD5.new(nil).send :digest, self, password
|
62
73
|
end
|
63
74
|
end
|
64
|
-
|
65
|
-
def request_with_digest_auth(path, username, password, options = {}, &block)
|
66
|
-
|
67
|
-
|
75
|
+
|
76
|
+
def request_with_digest_auth(method, path, username, password, options = {}, &block)
|
77
|
+
request_options = {}
|
78
|
+
request_options[:input] = options.delete(:input) if options.include? :input
|
79
|
+
|
80
|
+
response = request(method, path, request_options)
|
81
|
+
|
68
82
|
return response unless response.status == 401
|
69
|
-
|
83
|
+
|
70
84
|
if wait = options.delete(:wait)
|
71
85
|
sleep wait
|
72
86
|
end
|
73
|
-
|
87
|
+
|
74
88
|
challenge = response['WWW-Authenticate'].split(' ', 2).last
|
75
89
|
|
76
90
|
params = Rack::Auth::Digest::Params.parse(challenge)
|
@@ -79,12 +93,14 @@ context 'Rack::Auth::Digest::MD5' do
|
|
79
93
|
params['nc'] = '00000001'
|
80
94
|
params['cnonce'] = 'nonsensenonce'
|
81
95
|
params['uri'] = path
|
82
|
-
|
96
|
+
|
97
|
+
params['method'] = method
|
98
|
+
|
83
99
|
params.update options
|
84
|
-
|
100
|
+
|
85
101
|
params['response'] = MockDigestRequest.new(params).response(password)
|
86
|
-
|
87
|
-
request(path,
|
102
|
+
|
103
|
+
request(method, path, request_options.merge('HTTP_AUTHORIZATION' => "Digest #{params}"), &block)
|
88
104
|
end
|
89
105
|
|
90
106
|
def assert_digest_auth_challenge(response)
|
@@ -94,7 +110,7 @@ context 'Rack::Auth::Digest::MD5' do
|
|
94
110
|
response.headers['WWW-Authenticate'].should =~ /^Digest /
|
95
111
|
response.body.should.be.empty
|
96
112
|
end
|
97
|
-
|
113
|
+
|
98
114
|
def assert_bad_request(response)
|
99
115
|
response.should.be.a.client_error
|
100
116
|
response.status.should.equal 400
|
@@ -102,44 +118,44 @@ context 'Rack::Auth::Digest::MD5' do
|
|
102
118
|
end
|
103
119
|
|
104
120
|
specify 'should challenge when no credentials are specified' do
|
105
|
-
request '/' do |response|
|
121
|
+
request 'GET', '/' do |response|
|
106
122
|
assert_digest_auth_challenge response
|
107
123
|
end
|
108
124
|
end
|
109
|
-
|
125
|
+
|
110
126
|
specify 'should return application output if correct credentials given' do
|
111
|
-
request_with_digest_auth '/', 'Alice', 'correct-password' do |response|
|
127
|
+
request_with_digest_auth 'GET', '/', 'Alice', 'correct-password' do |response|
|
112
128
|
response.status.should.equal 200
|
113
129
|
response.body.to_s.should.equal 'Hi Alice'
|
114
130
|
end
|
115
|
-
end
|
131
|
+
end
|
116
132
|
|
117
133
|
specify 'should return application output if correct credentials given (hashed passwords)' do
|
118
134
|
@request = Rack::MockRequest.new(protected_app_with_hashed_passwords)
|
119
|
-
|
120
|
-
request_with_digest_auth '/', 'Alice', 'correct-password' do |response|
|
135
|
+
|
136
|
+
request_with_digest_auth 'GET', '/', 'Alice', 'correct-password' do |response|
|
121
137
|
response.status.should.equal 200
|
122
138
|
response.body.to_s.should.equal 'Hi Alice'
|
123
139
|
end
|
124
|
-
end
|
125
|
-
|
140
|
+
end
|
141
|
+
|
126
142
|
specify 'should rechallenge if incorrect username given' do
|
127
|
-
request_with_digest_auth '/', 'Bob', 'correct-password' do |response|
|
143
|
+
request_with_digest_auth 'GET', '/', 'Bob', 'correct-password' do |response|
|
128
144
|
assert_digest_auth_challenge response
|
129
145
|
end
|
130
146
|
end
|
131
|
-
|
147
|
+
|
132
148
|
specify 'should rechallenge if incorrect password given' do
|
133
|
-
request_with_digest_auth '/', 'Alice', 'wrong-password' do |response|
|
149
|
+
request_with_digest_auth 'GET', '/', 'Alice', 'wrong-password' do |response|
|
134
150
|
assert_digest_auth_challenge response
|
135
151
|
end
|
136
152
|
end
|
137
|
-
|
153
|
+
|
138
154
|
specify 'should rechallenge with stale parameter if nonce is stale' do
|
139
155
|
begin
|
140
156
|
Rack::Auth::Digest::Nonce.time_limit = 1
|
141
|
-
|
142
|
-
request_with_digest_auth '/', 'Alice', 'correct-password', :wait => 2 do |response|
|
157
|
+
|
158
|
+
request_with_digest_auth 'GET', '/', 'Alice', 'correct-password', :wait => 2 do |response|
|
143
159
|
assert_digest_auth_challenge response
|
144
160
|
response.headers['WWW-Authenticate'].should =~ /\bstale=true\b/
|
145
161
|
end
|
@@ -149,21 +165,62 @@ context 'Rack::Auth::Digest::MD5' do
|
|
149
165
|
end
|
150
166
|
|
151
167
|
specify 'should return 400 Bad Request if incorrect qop given' do
|
152
|
-
request_with_digest_auth '/', 'Alice', 'correct-password', 'qop' => 'auth-int' do |response|
|
168
|
+
request_with_digest_auth 'GET', '/', 'Alice', 'correct-password', 'qop' => 'auth-int' do |response|
|
153
169
|
assert_bad_request response
|
154
170
|
end
|
155
171
|
end
|
156
172
|
|
157
173
|
specify 'should return 400 Bad Request if incorrect uri given' do
|
158
|
-
request_with_digest_auth '/', 'Alice', 'correct-password', 'uri' => '/foo' do |response|
|
174
|
+
request_with_digest_auth 'GET', '/', 'Alice', 'correct-password', 'uri' => '/foo' do |response|
|
159
175
|
assert_bad_request response
|
160
176
|
end
|
161
177
|
end
|
162
178
|
|
163
179
|
specify 'should return 400 Bad Request if different auth scheme used' do
|
164
|
-
request '/', 'HTTP_AUTHORIZATION' => 'Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==' do |response|
|
180
|
+
request 'GET', '/', 'HTTP_AUTHORIZATION' => 'Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==' do |response|
|
165
181
|
assert_bad_request response
|
166
182
|
end
|
167
183
|
end
|
168
|
-
|
184
|
+
|
185
|
+
specify 'should not require credentials for unprotected path' do
|
186
|
+
@request = Rack::MockRequest.new(partially_protected_app)
|
187
|
+
request 'GET', '/' do |response|
|
188
|
+
response.should.be.ok
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
192
|
+
specify 'should challenge when no credentials are specified for protected path' do
|
193
|
+
@request = Rack::MockRequest.new(partially_protected_app)
|
194
|
+
request 'GET', '/protected' do |response|
|
195
|
+
assert_digest_auth_challenge response
|
196
|
+
end
|
197
|
+
end
|
198
|
+
|
199
|
+
specify 'should return application output if correct credentials given for protected path' do
|
200
|
+
@request = Rack::MockRequest.new(partially_protected_app)
|
201
|
+
request_with_digest_auth 'GET', '/protected', 'Alice', 'correct-password' do |response|
|
202
|
+
response.status.should.equal 200
|
203
|
+
response.body.to_s.should.equal 'Hi Alice'
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
207
|
+
specify 'should return application output if correct credentials given for POST' do
|
208
|
+
request_with_digest_auth 'POST', '/', 'Alice', 'correct-password' do |response|
|
209
|
+
response.status.should.equal 200
|
210
|
+
response.body.to_s.should.equal 'Hi Alice'
|
211
|
+
end
|
212
|
+
end
|
213
|
+
|
214
|
+
specify 'should return application output if correct credentials given for PUT (using method override of POST)' do
|
215
|
+
@request = Rack::MockRequest.new(protected_app_with_method_override)
|
216
|
+
request_with_digest_auth 'POST', '/', 'Alice', 'correct-password', :input => "_method=put" do |response|
|
217
|
+
response.status.should.equal 200
|
218
|
+
response.body.to_s.should.equal 'Hi Alice'
|
219
|
+
end
|
220
|
+
end
|
221
|
+
|
222
|
+
specify 'realm as optional constructor arg' do
|
223
|
+
app = Rack::Auth::Digest::MD5.new(unprotected_app, realm) { true }
|
224
|
+
assert_equal realm, app.realm
|
225
|
+
end
|
169
226
|
end
|
@@ -6,129 +6,76 @@ require 'rack/auth/openid'
|
|
6
6
|
|
7
7
|
context "Rack::Auth::OpenID" do
|
8
8
|
OID = Rack::Auth::OpenID
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
9
|
+
host = 'host'
|
10
|
+
subd = 'sub.host'
|
11
|
+
wild = '*.host'
|
12
|
+
path = 'path'
|
13
|
+
long = 'path/long'
|
14
|
+
scheme = 'http://'
|
15
|
+
realm = scheme+host+'/'+path
|
13
16
|
|
14
|
-
specify 'realm uri should be
|
15
|
-
lambda{OID.new('/path
|
16
|
-
|
17
|
-
lambda{OID.new(
|
18
|
-
|
19
|
-
lambda{OID.new('
|
20
|
-
|
21
|
-
lambda{OID.new('
|
22
|
-
|
17
|
+
specify 'realm uri should be valid' do
|
18
|
+
lambda{OID.new('/'+path)}.should.raise ArgumentError
|
19
|
+
lambda{OID.new('/'+long)}.should.raise ArgumentError
|
20
|
+
lambda{OID.new(scheme+host)}.should.not.raise
|
21
|
+
lambda{OID.new(scheme+host+'/')}.should.not.raise
|
22
|
+
lambda{OID.new(scheme+host+'/'+path)}.should.not.raise
|
23
|
+
lambda{OID.new(scheme+subd)}.should.not.raise
|
24
|
+
lambda{OID.new(scheme+subd+'/')}.should.not.raise
|
25
|
+
lambda{OID.new(scheme+subd+'/'+path)}.should.not.raise
|
23
26
|
end
|
24
27
|
|
25
|
-
specify 'uri
|
26
|
-
[:login_good, :login_fail, :login_quit, :return_to].each do |param|
|
27
|
-
ruri.each do |uri|
|
28
|
-
lambda{OID.new(realm, {param=>uri})}.
|
29
|
-
should.raise ArgumentError
|
30
|
-
end
|
31
|
-
auri.each do |uri|
|
32
|
-
lambda{OID.new(realm, {param=>uri})}.
|
33
|
-
should.raise ArgumentError
|
34
|
-
end
|
35
|
-
furi.each do |uri|
|
36
|
-
lambda{OID.new(realm, {param=>uri})}.
|
37
|
-
should.not.raise
|
38
|
-
end
|
39
|
-
end
|
28
|
+
specify 'should be able to check if a uri is within the realm' do
|
40
29
|
end
|
41
30
|
|
42
|
-
specify 'return_to should be
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
lambda{OID.new(realm).add_extension(ext)}.
|
58
|
-
should.raise(TypeError).
|
59
|
-
message.should.match(/not a module/)
|
60
|
-
ext2 = Module.new
|
61
|
-
lambda{OID.new(realm).add_extension(ext2)}.
|
62
|
-
should.raise(ArgumentError).
|
63
|
-
message.should.not.match(/not a module/)
|
31
|
+
specify 'return_to should be valid' do
|
32
|
+
uri = '/'+path
|
33
|
+
lambda{OID.new(realm, :return_to=>uri)}.should.raise ArgumentError
|
34
|
+
uri = '/'+long
|
35
|
+
lambda{OID.new(realm, :return_to=>uri)}.should.raise ArgumentError
|
36
|
+
uri = scheme+host
|
37
|
+
lambda{OID.new(realm, :return_to=>uri)}.should.raise ArgumentError
|
38
|
+
uri = scheme+host+'/'+path
|
39
|
+
lambda{OID.new(realm, :return_to=>uri)}.should.not.raise
|
40
|
+
uri = scheme+subd+'/'+path
|
41
|
+
lambda{OID.new(realm, :return_to=>uri)}.should.raise ArgumentError
|
42
|
+
uri = scheme+host+'/'+long
|
43
|
+
lambda{OID.new(realm, :return_to=>uri)}.should.not.raise
|
44
|
+
uri = scheme+subd+'/'+long
|
45
|
+
lambda{OID.new(realm, :return_to=>uri)}.should.raise ArgumentError
|
64
46
|
end
|
65
47
|
|
66
48
|
specify 'extensions should have required constants defined' do
|
49
|
+
badext = Rack::Auth::OpenID::BadExtension
|
50
|
+
ext = Object.new
|
51
|
+
lambda{OID.new(realm).add_extension(ext)}.should.raise(badext)
|
67
52
|
ext = Module.new
|
68
|
-
lambda{OID.new(realm).add_extension(ext)}.
|
69
|
-
should.raise(ArgumentError).
|
70
|
-
message.should.match(/missing/)
|
53
|
+
lambda{OID.new(realm).add_extension(ext)}.should.raise(badext)
|
71
54
|
ext::Request = nil
|
72
|
-
lambda{OID.new(realm).add_extension(ext)}.
|
73
|
-
should.raise(ArgumentError).
|
74
|
-
message.should.match(/missing/).
|
75
|
-
should.not.match(/Request/)
|
55
|
+
lambda{OID.new(realm).add_extension(ext)}.should.raise(badext)
|
76
56
|
ext::Response = nil
|
77
|
-
lambda{OID.new(realm).add_extension(ext)}.
|
78
|
-
should.raise(ArgumentError).
|
79
|
-
message.should.match(/missing/).
|
80
|
-
should.not.match(/Response/)
|
57
|
+
lambda{OID.new(realm).add_extension(ext)}.should.raise(badext)
|
81
58
|
ext::NS_URI = nil
|
82
|
-
lambda{OID.new(realm).add_extension(ext)}.
|
83
|
-
should.raise(TypeError).
|
84
|
-
message.should.not.match(/missing/)
|
59
|
+
lambda{OID.new(realm).add_extension(ext)}.should.raise(badext)
|
85
60
|
end
|
86
61
|
|
87
62
|
specify 'extensions should have Request and Response defined and inherit from OpenID::Extension' do
|
88
|
-
$-w, w = nil, $-w # yuck
|
63
|
+
$-w, w = nil, $-w # yuck
|
64
|
+
badext = Rack::Auth::OpenID::BadExtension
|
89
65
|
ext = Module.new
|
90
66
|
ext::Request = nil
|
91
67
|
ext::Response = nil
|
92
68
|
ext::NS_URI = nil
|
93
|
-
lambda{OID.new(realm).add_extension(ext)}.
|
94
|
-
should.raise(TypeError).
|
95
|
-
message.should.match(/not a class/)
|
69
|
+
lambda{OID.new(realm).add_extension(ext)}.should.raise(badext)
|
96
70
|
ext::Request = Class.new()
|
97
|
-
lambda{OID.new(realm).add_extension(ext)}.
|
98
|
-
should.raise(TypeError).
|
99
|
-
message.should.match(/not a class/)
|
71
|
+
lambda{OID.new(realm).add_extension(ext)}.should.raise(badext)
|
100
72
|
ext::Response = Class.new()
|
101
|
-
lambda{OID.new(realm).add_extension(ext)}.
|
102
|
-
should.raise(ArgumentError).
|
103
|
-
message.should.match(/not a decendant/)
|
104
|
-
ext::Request = Class.new(::OpenID::Extension)
|
105
|
-
lambda{OID.new(realm).add_extension(ext)}.
|
106
|
-
should.raise(ArgumentError).
|
107
|
-
message.should.match(/not a decendant/)
|
108
|
-
ext::Response = Class.new(::OpenID::Extension)
|
109
|
-
lambda{OID.new(realm).add_extension(ext)}.
|
110
|
-
should.raise(TypeError).
|
111
|
-
message.should.match(/NS_URI/)
|
112
|
-
$-w = w
|
113
|
-
end
|
114
|
-
|
115
|
-
specify 'extensions should have NS_URI defined and be a string of an absolute http uri' do
|
116
|
-
$-w, w = nil, $-w # yuck
|
117
|
-
ext = Module.new
|
73
|
+
lambda{OID.new(realm).add_extension(ext)}.should.raise(badext)
|
118
74
|
ext::Request = Class.new(::OpenID::Extension)
|
75
|
+
lambda{OID.new(realm).add_extension(ext)}.should.raise(badext)
|
119
76
|
ext::Response = Class.new(::OpenID::Extension)
|
120
|
-
ext
|
121
|
-
|
122
|
-
should.raise(TypeError).
|
123
|
-
message.should.match(/not a string/)
|
124
|
-
ext::NS_URI = 'openid.net'
|
125
|
-
lambda{OID.new(realm).add_extension(ext)}.
|
126
|
-
should.raise(ArgumentError).
|
127
|
-
message.should.match(/not an http uri/)
|
128
|
-
ext::NS_URI = 'http://openid.net'
|
129
|
-
lambda{OID.new(realm).add_extension(ext)}.
|
130
|
-
should.not.raise
|
131
|
-
$-w = w
|
77
|
+
lambda{OID.new(realm).add_extension(ext)}.should.raise(badext)
|
78
|
+
$-w = w
|
132
79
|
end
|
133
80
|
end
|
134
81
|
|
data/test/spec_rack_builder.rb
CHANGED
@@ -35,7 +35,7 @@ context "Rack::Builder" do
|
|
35
35
|
'secret' == password
|
36
36
|
end
|
37
37
|
|
38
|
-
run lambda { |env| [200, {}, 'Hi Boss'] }
|
38
|
+
run lambda { |env| [200, {}, ['Hi Boss']] }
|
39
39
|
end
|
40
40
|
|
41
41
|
response = Rack::MockRequest.new(app).get("/")
|
@@ -69,7 +69,7 @@ context "Rack::Builder" do
|
|
69
69
|
def call(env)
|
70
70
|
raise "bzzzt" if @called > 0
|
71
71
|
@called += 1
|
72
|
-
[200, {'Content-Type' => 'text/plain'}, 'OK']
|
72
|
+
[200, {'Content-Type' => 'text/plain'}, ['OK']]
|
73
73
|
end
|
74
74
|
end
|
75
75
|
|
@@ -0,0 +1,62 @@
|
|
1
|
+
require 'rack/mock'
|
2
|
+
require 'rack/chunked'
|
3
|
+
require 'rack/utils'
|
4
|
+
|
5
|
+
context "Rack::Chunked" do
|
6
|
+
|
7
|
+
before do
|
8
|
+
@env = Rack::MockRequest.
|
9
|
+
env_for('/', 'HTTP_VERSION' => '1.1', 'REQUEST_METHOD' => 'GET')
|
10
|
+
end
|
11
|
+
|
12
|
+
specify 'chunks responses with no Content-Length' do
|
13
|
+
app = lambda { |env| [200, {}, ['Hello', ' ', 'World!']] }
|
14
|
+
response = Rack::MockResponse.new(*Rack::Chunked.new(app).call(@env))
|
15
|
+
response.headers.should.not.include 'Content-Length'
|
16
|
+
response.headers['Transfer-Encoding'].should.equal 'chunked'
|
17
|
+
response.body.should.equal "5\r\nHello\r\n1\r\n \r\n6\r\nWorld!\r\n0\r\n\r\n"
|
18
|
+
end
|
19
|
+
|
20
|
+
specify 'chunks empty bodies properly' do
|
21
|
+
app = lambda { |env| [200, {}, []] }
|
22
|
+
response = Rack::MockResponse.new(*Rack::Chunked.new(app).call(@env))
|
23
|
+
response.headers.should.not.include 'Content-Length'
|
24
|
+
response.headers['Transfer-Encoding'].should.equal 'chunked'
|
25
|
+
response.body.should.equal "0\r\n\r\n"
|
26
|
+
end
|
27
|
+
|
28
|
+
specify 'does not modify response when Content-Length header present' do
|
29
|
+
app = lambda { |env| [200, {'Content-Length'=>'12'}, ['Hello', ' ', 'World!']] }
|
30
|
+
status, headers, body = Rack::Chunked.new(app).call(@env)
|
31
|
+
status.should.equal 200
|
32
|
+
headers.should.not.include 'Transfer-Encoding'
|
33
|
+
headers.should.include 'Content-Length'
|
34
|
+
body.join.should.equal 'Hello World!'
|
35
|
+
end
|
36
|
+
|
37
|
+
specify 'does not modify response when client is HTTP/1.0' do
|
38
|
+
app = lambda { |env| [200, {}, ['Hello', ' ', 'World!']] }
|
39
|
+
@env['HTTP_VERSION'] = 'HTTP/1.0'
|
40
|
+
status, headers, body = Rack::Chunked.new(app).call(@env)
|
41
|
+
status.should.equal 200
|
42
|
+
headers.should.not.include 'Transfer-Encoding'
|
43
|
+
body.join.should.equal 'Hello World!'
|
44
|
+
end
|
45
|
+
|
46
|
+
specify 'does not modify response when Transfer-Encoding header already present' do
|
47
|
+
app = lambda { |env| [200, {'Transfer-Encoding' => 'identity'}, ['Hello', ' ', 'World!']] }
|
48
|
+
status, headers, body = Rack::Chunked.new(app).call(@env)
|
49
|
+
status.should.equal 200
|
50
|
+
headers['Transfer-Encoding'].should.equal 'identity'
|
51
|
+
body.join.should.equal 'Hello World!'
|
52
|
+
end
|
53
|
+
|
54
|
+
[100, 204, 304].each do |status_code|
|
55
|
+
specify "does not modify response when status code is #{status_code}" do
|
56
|
+
app = lambda { |env| [status_code, {}, []] }
|
57
|
+
status, headers, body = Rack::Chunked.new(app).call(@env)
|
58
|
+
status.should.equal status_code
|
59
|
+
headers.should.not.include 'Transfer-Encoding'
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|