qoobaa-rack 1.0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (116) hide show
  1. data/COPYING +18 -0
  2. data/KNOWN-ISSUES +18 -0
  3. data/RDOX +0 -0
  4. data/README +353 -0
  5. data/Rakefile +164 -0
  6. data/SPEC +164 -0
  7. data/bin/rackup +176 -0
  8. data/contrib/rack_logo.svg +111 -0
  9. data/example/lobster.ru +4 -0
  10. data/example/protectedlobster.rb +14 -0
  11. data/example/protectedlobster.ru +8 -0
  12. data/lib/rack/adapter/camping.rb +22 -0
  13. data/lib/rack/auth/abstract/handler.rb +37 -0
  14. data/lib/rack/auth/abstract/request.rb +37 -0
  15. data/lib/rack/auth/basic.rb +58 -0
  16. data/lib/rack/auth/digest/md5.rb +124 -0
  17. data/lib/rack/auth/digest/nonce.rb +51 -0
  18. data/lib/rack/auth/digest/params.rb +55 -0
  19. data/lib/rack/auth/digest/request.rb +40 -0
  20. data/lib/rack/auth/openid.rb +487 -0
  21. data/lib/rack/builder.rb +63 -0
  22. data/lib/rack/cascade.rb +41 -0
  23. data/lib/rack/chunked.rb +49 -0
  24. data/lib/rack/commonlogger.rb +52 -0
  25. data/lib/rack/conditionalget.rb +47 -0
  26. data/lib/rack/content_length.rb +29 -0
  27. data/lib/rack/content_type.rb +23 -0
  28. data/lib/rack/deflater.rb +96 -0
  29. data/lib/rack/directory.rb +153 -0
  30. data/lib/rack/file.rb +88 -0
  31. data/lib/rack/handler/cgi.rb +61 -0
  32. data/lib/rack/handler/evented_mongrel.rb +8 -0
  33. data/lib/rack/handler/fastcgi.rb +88 -0
  34. data/lib/rack/handler/lsws.rb +60 -0
  35. data/lib/rack/handler/mongrel.rb +87 -0
  36. data/lib/rack/handler/scgi.rb +62 -0
  37. data/lib/rack/handler/swiftiplied_mongrel.rb +8 -0
  38. data/lib/rack/handler/thin.rb +18 -0
  39. data/lib/rack/handler/webrick.rb +71 -0
  40. data/lib/rack/handler.rb +69 -0
  41. data/lib/rack/head.rb +19 -0
  42. data/lib/rack/lint.rb +546 -0
  43. data/lib/rack/lobster.rb +65 -0
  44. data/lib/rack/lock.rb +16 -0
  45. data/lib/rack/methodoverride.rb +27 -0
  46. data/lib/rack/mime.rb +204 -0
  47. data/lib/rack/mock.rb +187 -0
  48. data/lib/rack/recursive.rb +57 -0
  49. data/lib/rack/reloader.rb +107 -0
  50. data/lib/rack/request.rb +248 -0
  51. data/lib/rack/response.rb +183 -0
  52. data/lib/rack/rewindable_input.rb +100 -0
  53. data/lib/rack/session/abstract/id.rb +142 -0
  54. data/lib/rack/session/cookie.rb +91 -0
  55. data/lib/rack/session/memcache.rb +109 -0
  56. data/lib/rack/session/pool.rb +100 -0
  57. data/lib/rack/showexceptions.rb +349 -0
  58. data/lib/rack/showstatus.rb +106 -0
  59. data/lib/rack/static.rb +38 -0
  60. data/lib/rack/urlmap.rb +55 -0
  61. data/lib/rack/utils.rb +528 -0
  62. data/lib/rack.rb +90 -0
  63. data/rack.gemspec +60 -0
  64. data/test/cgi/lighttpd.conf +20 -0
  65. data/test/cgi/test +9 -0
  66. data/test/cgi/test.fcgi +8 -0
  67. data/test/cgi/test.ru +7 -0
  68. data/test/multipart/binary +0 -0
  69. data/test/multipart/empty +10 -0
  70. data/test/multipart/file1.txt +1 -0
  71. data/test/multipart/ie +6 -0
  72. data/test/multipart/nested +10 -0
  73. data/test/multipart/none +9 -0
  74. data/test/multipart/text +10 -0
  75. data/test/spec_rack_auth_basic.rb +73 -0
  76. data/test/spec_rack_auth_digest.rb +226 -0
  77. data/test/spec_rack_auth_openid.rb +84 -0
  78. data/test/spec_rack_builder.rb +84 -0
  79. data/test/spec_rack_camping.rb +51 -0
  80. data/test/spec_rack_cascade.rb +48 -0
  81. data/test/spec_rack_cgi.rb +89 -0
  82. data/test/spec_rack_chunked.rb +62 -0
  83. data/test/spec_rack_commonlogger.rb +61 -0
  84. data/test/spec_rack_conditionalget.rb +41 -0
  85. data/test/spec_rack_content_length.rb +43 -0
  86. data/test/spec_rack_content_type.rb +30 -0
  87. data/test/spec_rack_deflater.rb +127 -0
  88. data/test/spec_rack_directory.rb +61 -0
  89. data/test/spec_rack_fastcgi.rb +89 -0
  90. data/test/spec_rack_file.rb +75 -0
  91. data/test/spec_rack_handler.rb +43 -0
  92. data/test/spec_rack_head.rb +30 -0
  93. data/test/spec_rack_lint.rb +521 -0
  94. data/test/spec_rack_lobster.rb +45 -0
  95. data/test/spec_rack_lock.rb +38 -0
  96. data/test/spec_rack_methodoverride.rb +60 -0
  97. data/test/spec_rack_mock.rb +243 -0
  98. data/test/spec_rack_mongrel.rb +189 -0
  99. data/test/spec_rack_recursive.rb +77 -0
  100. data/test/spec_rack_request.rb +504 -0
  101. data/test/spec_rack_response.rb +218 -0
  102. data/test/spec_rack_rewindable_input.rb +118 -0
  103. data/test/spec_rack_session_cookie.rb +82 -0
  104. data/test/spec_rack_session_memcache.rb +250 -0
  105. data/test/spec_rack_session_pool.rb +172 -0
  106. data/test/spec_rack_showexceptions.rb +21 -0
  107. data/test/spec_rack_showstatus.rb +72 -0
  108. data/test/spec_rack_static.rb +37 -0
  109. data/test/spec_rack_thin.rb +91 -0
  110. data/test/spec_rack_urlmap.rb +185 -0
  111. data/test/spec_rack_utils.rb +467 -0
  112. data/test/spec_rack_webrick.rb +130 -0
  113. data/test/testrequest.rb +57 -0
  114. data/test/unregistered_handler/rack/handler/unregistered.rb +7 -0
  115. data/test/unregistered_handler/rack/handler/unregistered_long_one.rb +7 -0
  116. metadata +276 -0
@@ -0,0 +1,20 @@
1
+ server.modules = ("mod_fastcgi", "mod_cgi")
2
+ server.document-root = "."
3
+ server.errorlog = "lighttpd.errors"
4
+ server.port = 9203
5
+
6
+ server.event-handler = "select"
7
+
8
+ cgi.assign = ("/test" => "",
9
+ # ".ru" => ""
10
+ )
11
+
12
+ fastcgi.server = ("test.fcgi" => ("localhost" =>
13
+ ("min-procs" => 1,
14
+ "socket" => "/tmp/rack-test-fcgi",
15
+ "bin-path" => "test.fcgi")),
16
+ "test.ru" => ("localhost" =>
17
+ ("min-procs" => 1,
18
+ "socket" => "/tmp/rack-test-ru-fcgi",
19
+ "bin-path" => "test.ru")),
20
+ )
data/test/cgi/test ADDED
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env ruby
2
+ # -*- ruby -*-
3
+
4
+ $: << File.join(File.dirname(__FILE__), "..", "..", "lib")
5
+
6
+ require 'rack'
7
+ require '../testrequest'
8
+
9
+ Rack::Handler::CGI.run(Rack::Lint.new(TestRequest.new))
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env ruby
2
+ # -*- ruby -*-
3
+
4
+ $:.unshift '../../lib'
5
+ require 'rack'
6
+ require '../testrequest'
7
+
8
+ Rack::Handler::FastCGI.run(Rack::Lint.new(TestRequest.new))
data/test/cgi/test.ru ADDED
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env ../../bin/rackup
2
+ #\ -E deployment -I ../../lib
3
+ # -*- ruby -*-
4
+
5
+ require '../testrequest'
6
+
7
+ run TestRequest.new
Binary file
@@ -0,0 +1,10 @@
1
+ --AaB03x
2
+ Content-Disposition: form-data; name="submit-name"
3
+
4
+ Larry
5
+ --AaB03x
6
+ Content-Disposition: form-data; name="files"; filename="file1.txt"
7
+ Content-Type: text/plain
8
+
9
+
10
+ --AaB03x--
@@ -0,0 +1 @@
1
+ contents
data/test/multipart/ie ADDED
@@ -0,0 +1,6 @@
1
+ --AaB03x
2
+ Content-Disposition: form-data; name="files"; filename="C:\Documents and Settings\Administrator\Desktop\file1.txt"
3
+ Content-Type: text/plain
4
+
5
+ contents
6
+ --AaB03x--
@@ -0,0 +1,10 @@
1
+ --AaB03x
2
+ Content-Disposition: form-data; name="foo[submit-name]"
3
+
4
+ Larry
5
+ --AaB03x
6
+ Content-Disposition: form-data; name="foo[files]"; filename="file1.txt"
7
+ Content-Type: text/plain
8
+
9
+ contents
10
+ --AaB03x--
@@ -0,0 +1,9 @@
1
+ --AaB03x
2
+ Content-Disposition: form-data; name="submit-name"
3
+
4
+ Larry
5
+ --AaB03x
6
+ Content-Disposition: form-data; name="files"; filename=""
7
+
8
+
9
+ --AaB03x--
@@ -0,0 +1,10 @@
1
+ --AaB03x
2
+ Content-Disposition: form-data; name="submit-name"
3
+
4
+ Larry
5
+ --AaB03x
6
+ Content-Disposition: form-data; name="files"; filename="file1.txt"
7
+ Content-Type: text/plain
8
+
9
+ contents
10
+ --AaB03x--
@@ -0,0 +1,73 @@
1
+ require 'test/spec'
2
+
3
+ require 'rack/auth/basic'
4
+ require 'rack/mock'
5
+
6
+ context 'Rack::Auth::Basic' do
7
+
8
+ def realm
9
+ 'WallysWorld'
10
+ end
11
+
12
+ def unprotected_app
13
+ lambda { |env| [ 200, {'Content-Type' => 'text/plain'}, ["Hi #{env['REMOTE_USER']}"] ] }
14
+ end
15
+
16
+ def protected_app
17
+ app = Rack::Auth::Basic.new(unprotected_app) { |username, password| 'Boss' == username }
18
+ app.realm = realm
19
+ app
20
+ end
21
+
22
+ setup do
23
+ @request = Rack::MockRequest.new(protected_app)
24
+ end
25
+
26
+ def request_with_basic_auth(username, password, &block)
27
+ request 'HTTP_AUTHORIZATION' => 'Basic ' + ["#{username}:#{password}"].pack("m*"), &block
28
+ end
29
+
30
+ def request(headers = {})
31
+ yield @request.get('/', headers)
32
+ end
33
+
34
+ def assert_basic_auth_challenge(response)
35
+ response.should.be.a.client_error
36
+ response.status.should.equal 401
37
+ response.should.include 'WWW-Authenticate'
38
+ response.headers['WWW-Authenticate'].should =~ /Basic realm="#{Regexp.escape(realm)}"/
39
+ response.body.should.be.empty
40
+ end
41
+
42
+ specify 'should challenge correctly when no credentials are specified' do
43
+ request do |response|
44
+ assert_basic_auth_challenge response
45
+ end
46
+ end
47
+
48
+ specify 'should rechallenge if incorrect credentials are specified' do
49
+ request_with_basic_auth 'joe', 'password' do |response|
50
+ assert_basic_auth_challenge response
51
+ end
52
+ end
53
+
54
+ specify 'should return application output if correct credentials are specified' do
55
+ request_with_basic_auth 'Boss', 'password' do |response|
56
+ response.status.should.equal 200
57
+ response.body.to_s.should.equal 'Hi Boss'
58
+ end
59
+ end
60
+
61
+ specify 'should return 400 Bad Request if different auth scheme used' do
62
+ request 'HTTP_AUTHORIZATION' => 'Digest params' do |response|
63
+ response.should.be.a.client_error
64
+ response.status.should.equal 400
65
+ response.should.not.include 'WWW-Authenticate'
66
+ end
67
+ end
68
+
69
+ specify 'realm as optional constructor arg' do
70
+ app = Rack::Auth::Basic.new(unprotected_app, realm) { true }
71
+ assert_equal realm, app.realm
72
+ end
73
+ end
@@ -0,0 +1,226 @@
1
+ require 'test/spec'
2
+
3
+ require 'rack/auth/digest/md5'
4
+ require 'rack/mock'
5
+
6
+ context 'Rack::Auth::Digest::MD5' do
7
+
8
+ def realm
9
+ 'WallysWorld'
10
+ end
11
+
12
+ def unprotected_app
13
+ lambda do |env|
14
+ [ 200, {'Content-Type' => 'text/plain'}, ["Hi #{env['REMOTE_USER']}"] ]
15
+ end
16
+ end
17
+
18
+ def protected_app
19
+ app = Rack::Auth::Digest::MD5.new(unprotected_app) do |username|
20
+ { 'Alice' => 'correct-password' }[username]
21
+ end
22
+ app.realm = realm
23
+ app.opaque = 'this-should-be-secret'
24
+ app
25
+ end
26
+
27
+ def protected_app_with_hashed_passwords
28
+ app = Rack::Auth::Digest::MD5.new(unprotected_app) do |username|
29
+ username == 'Alice' ? Digest::MD5.hexdigest("Alice:#{realm}:correct-password") : nil
30
+ end
31
+ app.realm = realm
32
+ app.opaque = 'this-should-be-secret'
33
+ app.passwords_hashed = true
34
+ app
35
+ end
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
+
48
+ setup do
49
+ @request = Rack::MockRequest.new(protected_app)
50
+ end
51
+
52
+ def request(method, path, headers = {}, &block)
53
+ response = @request.request(method, path, headers)
54
+ block.call(response) if block
55
+ return response
56
+ end
57
+
58
+ class MockDigestRequest
59
+ def initialize(params)
60
+ @params = params
61
+ end
62
+ def method_missing(sym)
63
+ if @params.has_key? k = sym.to_s
64
+ return @params[k]
65
+ end
66
+ super
67
+ end
68
+ def method
69
+ @params['method']
70
+ end
71
+ def response(password)
72
+ Rack::Auth::Digest::MD5.new(nil).send :digest, self, password
73
+ end
74
+ end
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
+
82
+ return response unless response.status == 401
83
+
84
+ if wait = options.delete(:wait)
85
+ sleep wait
86
+ end
87
+
88
+ challenge = response['WWW-Authenticate'].split(' ', 2).last
89
+
90
+ params = Rack::Auth::Digest::Params.parse(challenge)
91
+
92
+ params['username'] = username
93
+ params['nc'] = '00000001'
94
+ params['cnonce'] = 'nonsensenonce'
95
+ params['uri'] = path
96
+
97
+ params['method'] = method
98
+
99
+ params.update options
100
+
101
+ params['response'] = MockDigestRequest.new(params).response(password)
102
+
103
+ request(method, path, request_options.merge('HTTP_AUTHORIZATION' => "Digest #{params}"), &block)
104
+ end
105
+
106
+ def assert_digest_auth_challenge(response)
107
+ response.should.be.a.client_error
108
+ response.status.should.equal 401
109
+ response.should.include 'WWW-Authenticate'
110
+ response.headers['WWW-Authenticate'].should =~ /^Digest /
111
+ response.body.should.be.empty
112
+ end
113
+
114
+ def assert_bad_request(response)
115
+ response.should.be.a.client_error
116
+ response.status.should.equal 400
117
+ response.should.not.include 'WWW-Authenticate'
118
+ end
119
+
120
+ specify 'should challenge when no credentials are specified' do
121
+ request 'GET', '/' do |response|
122
+ assert_digest_auth_challenge response
123
+ end
124
+ end
125
+
126
+ specify 'should return application output if correct credentials given' do
127
+ request_with_digest_auth 'GET', '/', 'Alice', 'correct-password' do |response|
128
+ response.status.should.equal 200
129
+ response.body.to_s.should.equal 'Hi Alice'
130
+ end
131
+ end
132
+
133
+ specify 'should return application output if correct credentials given (hashed passwords)' do
134
+ @request = Rack::MockRequest.new(protected_app_with_hashed_passwords)
135
+
136
+ request_with_digest_auth 'GET', '/', 'Alice', 'correct-password' do |response|
137
+ response.status.should.equal 200
138
+ response.body.to_s.should.equal 'Hi Alice'
139
+ end
140
+ end
141
+
142
+ specify 'should rechallenge if incorrect username given' do
143
+ request_with_digest_auth 'GET', '/', 'Bob', 'correct-password' do |response|
144
+ assert_digest_auth_challenge response
145
+ end
146
+ end
147
+
148
+ specify 'should rechallenge if incorrect password given' do
149
+ request_with_digest_auth 'GET', '/', 'Alice', 'wrong-password' do |response|
150
+ assert_digest_auth_challenge response
151
+ end
152
+ end
153
+
154
+ specify 'should rechallenge with stale parameter if nonce is stale' do
155
+ begin
156
+ Rack::Auth::Digest::Nonce.time_limit = 1
157
+
158
+ request_with_digest_auth 'GET', '/', 'Alice', 'correct-password', :wait => 2 do |response|
159
+ assert_digest_auth_challenge response
160
+ response.headers['WWW-Authenticate'].should =~ /\bstale=true\b/
161
+ end
162
+ ensure
163
+ Rack::Auth::Digest::Nonce.time_limit = nil
164
+ end
165
+ end
166
+
167
+ specify 'should return 400 Bad Request if incorrect qop given' do
168
+ request_with_digest_auth 'GET', '/', 'Alice', 'correct-password', 'qop' => 'auth-int' do |response|
169
+ assert_bad_request response
170
+ end
171
+ end
172
+
173
+ specify 'should return 400 Bad Request if incorrect uri given' do
174
+ request_with_digest_auth 'GET', '/', 'Alice', 'correct-password', 'uri' => '/foo' do |response|
175
+ assert_bad_request response
176
+ end
177
+ end
178
+
179
+ specify 'should return 400 Bad Request if different auth scheme used' do
180
+ request 'GET', '/', 'HTTP_AUTHORIZATION' => 'Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==' do |response|
181
+ assert_bad_request response
182
+ end
183
+ end
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
226
+ end
@@ -0,0 +1,84 @@
1
+ require 'test/spec'
2
+
3
+ begin
4
+ # requires the ruby-openid gem
5
+ require 'rack/auth/openid'
6
+
7
+ context "Rack::Auth::OpenID" do
8
+ OID = Rack::Auth::OpenID
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
16
+
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
26
+ end
27
+
28
+ specify 'should be able to check if a uri is within the realm' do
29
+ end
30
+
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
46
+ end
47
+
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)
52
+ ext = Module.new
53
+ lambda{OID.new(realm).add_extension(ext)}.should.raise(badext)
54
+ ext::Request = nil
55
+ lambda{OID.new(realm).add_extension(ext)}.should.raise(badext)
56
+ ext::Response = nil
57
+ lambda{OID.new(realm).add_extension(ext)}.should.raise(badext)
58
+ ext::NS_URI = nil
59
+ lambda{OID.new(realm).add_extension(ext)}.should.raise(badext)
60
+ end
61
+
62
+ specify 'extensions should have Request and Response defined and inherit from OpenID::Extension' do
63
+ $-w, w = nil, $-w # yuck
64
+ badext = Rack::Auth::OpenID::BadExtension
65
+ ext = Module.new
66
+ ext::Request = nil
67
+ ext::Response = nil
68
+ ext::NS_URI = nil
69
+ lambda{OID.new(realm).add_extension(ext)}.should.raise(badext)
70
+ ext::Request = Class.new()
71
+ lambda{OID.new(realm).add_extension(ext)}.should.raise(badext)
72
+ ext::Response = Class.new()
73
+ lambda{OID.new(realm).add_extension(ext)}.should.raise(badext)
74
+ ext::Request = Class.new(::OpenID::Extension)
75
+ lambda{OID.new(realm).add_extension(ext)}.should.raise(badext)
76
+ ext::Response = Class.new(::OpenID::Extension)
77
+ lambda{OID.new(realm).add_extension(ext)}.should.raise(badext)
78
+ $-w = w
79
+ end
80
+ end
81
+
82
+ rescue LoadError
83
+ $stderr.puts "Skipping Rack::Auth::OpenID tests (ruby-openid 2 is required). `gem install ruby-openid` and try again."
84
+ end
@@ -0,0 +1,84 @@
1
+ require 'test/spec'
2
+
3
+ require 'rack/builder'
4
+ require 'rack/mock'
5
+ require 'rack/showexceptions'
6
+ require 'rack/auth/basic'
7
+
8
+ context "Rack::Builder" do
9
+ specify "chains apps by default" do
10
+ app = Rack::Builder.new do
11
+ use Rack::ShowExceptions
12
+ run lambda { |env| raise "bzzzt" }
13
+ end.to_app
14
+
15
+ Rack::MockRequest.new(app).get("/").should.be.server_error
16
+ Rack::MockRequest.new(app).get("/").should.be.server_error
17
+ Rack::MockRequest.new(app).get("/").should.be.server_error
18
+ end
19
+
20
+ specify "has implicit #to_app" do
21
+ app = Rack::Builder.new do
22
+ use Rack::ShowExceptions
23
+ run lambda { |env| raise "bzzzt" }
24
+ end
25
+
26
+ Rack::MockRequest.new(app).get("/").should.be.server_error
27
+ Rack::MockRequest.new(app).get("/").should.be.server_error
28
+ Rack::MockRequest.new(app).get("/").should.be.server_error
29
+ end
30
+
31
+ specify "supports blocks on use" do
32
+ app = Rack::Builder.new do
33
+ use Rack::ShowExceptions
34
+ use Rack::Auth::Basic do |username, password|
35
+ 'secret' == password
36
+ end
37
+
38
+ run lambda { |env| [200, {}, ['Hi Boss']] }
39
+ end
40
+
41
+ response = Rack::MockRequest.new(app).get("/")
42
+ response.should.be.client_error
43
+ response.status.should.equal 401
44
+
45
+ # with auth...
46
+ response = Rack::MockRequest.new(app).get("/",
47
+ 'HTTP_AUTHORIZATION' => 'Basic ' + ["joe:secret"].pack("m*"))
48
+ response.status.should.equal 200
49
+ response.body.to_s.should.equal 'Hi Boss'
50
+ end
51
+
52
+ specify "has explicit #to_app" do
53
+ app = Rack::Builder.app do
54
+ use Rack::ShowExceptions
55
+ run lambda { |env| raise "bzzzt" }
56
+ end
57
+
58
+ Rack::MockRequest.new(app).get("/").should.be.server_error
59
+ Rack::MockRequest.new(app).get("/").should.be.server_error
60
+ Rack::MockRequest.new(app).get("/").should.be.server_error
61
+ end
62
+
63
+ specify "apps are initialized once" do
64
+ app = Rack::Builder.new do
65
+ class AppClass
66
+ def initialize
67
+ @called = 0
68
+ end
69
+ def call(env)
70
+ raise "bzzzt" if @called > 0
71
+ @called += 1
72
+ [200, {'Content-Type' => 'text/plain'}, ['OK']]
73
+ end
74
+ end
75
+
76
+ use Rack::ShowExceptions
77
+ run AppClass.new
78
+ end
79
+
80
+ Rack::MockRequest.new(app).get("/").status.should.equal 200
81
+ Rack::MockRequest.new(app).get("/").should.be.server_error
82
+ end
83
+
84
+ end
@@ -0,0 +1,51 @@
1
+ require 'test/spec'
2
+ require 'stringio'
3
+ require 'uri'
4
+
5
+ begin
6
+ require 'rack/mock'
7
+
8
+ $-w, w = nil, $-w # yuck
9
+ require 'camping'
10
+ require 'rack/adapter/camping'
11
+
12
+ Camping.goes :CampApp
13
+ module CampApp
14
+ module Controllers
15
+ class HW < R('/')
16
+ def get
17
+ @headers["X-Served-By"] = URI("http://rack.rubyforge.org")
18
+ "Camping works!"
19
+ end
20
+
21
+ def post
22
+ "Data: #{input.foo}"
23
+ end
24
+ end
25
+ end
26
+ end
27
+ $-w = w
28
+
29
+ context "Rack::Adapter::Camping" do
30
+ specify "works with GET" do
31
+ res = Rack::MockRequest.new(Rack::Adapter::Camping.new(CampApp)).
32
+ get("/")
33
+
34
+ res.should.be.ok
35
+ res["Content-Type"].should.equal "text/html"
36
+ res["X-Served-By"].should.equal "http://rack.rubyforge.org"
37
+
38
+ res.body.should.equal "Camping works!"
39
+ end
40
+
41
+ specify "works with POST" do
42
+ res = Rack::MockRequest.new(Rack::Adapter::Camping.new(CampApp)).
43
+ post("/", :input => "foo=bar")
44
+
45
+ res.should.be.ok
46
+ res.body.should.equal "Data: bar"
47
+ end
48
+ end
49
+ rescue LoadError
50
+ $stderr.puts "Skipping Rack::Adapter::Camping tests (Camping is required). `gem install camping` and try again."
51
+ end
@@ -0,0 +1,48 @@
1
+ require 'test/spec'
2
+
3
+ require 'rack/cascade'
4
+ require 'rack/mock'
5
+
6
+ require 'rack/urlmap'
7
+ require 'rack/file'
8
+
9
+ context "Rack::Cascade" do
10
+ docroot = File.expand_path(File.dirname(__FILE__))
11
+ app1 = Rack::File.new(docroot)
12
+
13
+ app2 = Rack::URLMap.new("/crash" => lambda { |env| raise "boom" })
14
+
15
+ app3 = Rack::URLMap.new("/foo" => lambda { |env|
16
+ [200, { "Content-Type" => "text/plain"}, [""]]})
17
+
18
+ specify "should dispatch onward on 404 by default" do
19
+ cascade = Rack::Cascade.new([app1, app2, app3])
20
+ Rack::MockRequest.new(cascade).get("/cgi/test").should.be.ok
21
+ Rack::MockRequest.new(cascade).get("/foo").should.be.ok
22
+ Rack::MockRequest.new(cascade).get("/toobad").should.be.not_found
23
+ Rack::MockRequest.new(cascade).get("/cgi/../bla").should.be.forbidden
24
+ end
25
+
26
+ specify "should dispatch onward on whatever is passed" do
27
+ cascade = Rack::Cascade.new([app1, app2, app3], [404, 403])
28
+ Rack::MockRequest.new(cascade).get("/cgi/../bla").should.be.not_found
29
+ end
30
+
31
+ specify "should return 404 if empty" do
32
+ Rack::MockRequest.new(Rack::Cascade.new([])).get('/').should.be.not_found
33
+ end
34
+
35
+ specify "should append new app" do
36
+ cascade = Rack::Cascade.new([], [404, 403])
37
+ Rack::MockRequest.new(cascade).get('/').should.be.not_found
38
+ cascade << app2
39
+ Rack::MockRequest.new(cascade).get('/cgi/test').should.be.not_found
40
+ Rack::MockRequest.new(cascade).get('/cgi/../bla').should.be.not_found
41
+ cascade << app1
42
+ Rack::MockRequest.new(cascade).get('/cgi/test').should.be.ok
43
+ Rack::MockRequest.new(cascade).get('/cgi/../bla').should.be.forbidden
44
+ Rack::MockRequest.new(cascade).get('/foo').should.be.not_found
45
+ cascade << app3
46
+ Rack::MockRequest.new(cascade).get('/foo').should.be.ok
47
+ end
48
+ end