rack 1.6.11 → 2.1.4

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.

Files changed (187) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +77 -0
  3. data/{COPYING → MIT-LICENSE} +4 -2
  4. data/README.rdoc +89 -139
  5. data/Rakefile +27 -28
  6. data/SPEC +6 -7
  7. data/bin/rackup +1 -0
  8. data/contrib/rack_logo.svg +164 -111
  9. data/example/lobster.ru +2 -0
  10. data/example/protectedlobster.rb +4 -2
  11. data/example/protectedlobster.ru +3 -1
  12. data/lib/rack/auth/abstract/handler.rb +3 -1
  13. data/lib/rack/auth/abstract/request.rb +7 -1
  14. data/lib/rack/auth/basic.rb +4 -1
  15. data/lib/rack/auth/digest/md5.rb +9 -7
  16. data/lib/rack/auth/digest/nonce.rb +6 -3
  17. data/lib/rack/auth/digest/params.rb +5 -4
  18. data/lib/rack/auth/digest/request.rb +3 -1
  19. data/lib/rack/body_proxy.rb +11 -9
  20. data/lib/rack/builder.rb +42 -18
  21. data/lib/rack/cascade.rb +6 -5
  22. data/lib/rack/chunked.rb +33 -10
  23. data/lib/rack/{commonlogger.rb → common_logger.rb} +11 -10
  24. data/lib/rack/{conditionalget.rb → conditional_get.rb} +3 -1
  25. data/lib/rack/config.rb +2 -0
  26. data/lib/rack/content_length.rb +5 -3
  27. data/lib/rack/content_type.rb +3 -1
  28. data/lib/rack/core_ext/regexp.rb +14 -0
  29. data/lib/rack/deflater.rb +33 -53
  30. data/lib/rack/directory.rb +75 -60
  31. data/lib/rack/etag.rb +8 -5
  32. data/lib/rack/events.rb +156 -0
  33. data/lib/rack/file.rb +4 -149
  34. data/lib/rack/files.rb +178 -0
  35. data/lib/rack/handler/cgi.rb +18 -17
  36. data/lib/rack/handler/fastcgi.rb +17 -16
  37. data/lib/rack/handler/lsws.rb +14 -12
  38. data/lib/rack/handler/scgi.rb +22 -19
  39. data/lib/rack/handler/thin.rb +6 -1
  40. data/lib/rack/handler/webrick.rb +28 -28
  41. data/lib/rack/handler.rb +9 -26
  42. data/lib/rack/head.rb +17 -17
  43. data/lib/rack/lint.rb +54 -51
  44. data/lib/rack/lobster.rb +8 -6
  45. data/lib/rack/lock.rb +17 -10
  46. data/lib/rack/logger.rb +4 -2
  47. data/lib/rack/media_type.rb +43 -0
  48. data/lib/rack/{methodoverride.rb → method_override.rb} +10 -8
  49. data/lib/rack/mime.rb +27 -6
  50. data/lib/rack/mock.rb +101 -60
  51. data/lib/rack/multipart/generator.rb +11 -12
  52. data/lib/rack/multipart/parser.rb +280 -161
  53. data/lib/rack/multipart/uploaded_file.rb +3 -2
  54. data/lib/rack/multipart.rb +39 -8
  55. data/lib/rack/{nulllogger.rb → null_logger.rb} +3 -1
  56. data/lib/rack/query_parser.rb +218 -0
  57. data/lib/rack/recursive.rb +11 -9
  58. data/lib/rack/reloader.rb +10 -4
  59. data/lib/rack/request.rb +447 -305
  60. data/lib/rack/response.rb +196 -83
  61. data/lib/rack/rewindable_input.rb +5 -14
  62. data/lib/rack/runtime.rb +12 -18
  63. data/lib/rack/sendfile.rb +19 -14
  64. data/lib/rack/server.rb +118 -41
  65. data/lib/rack/session/abstract/id.rb +215 -94
  66. data/lib/rack/session/cookie.rb +45 -28
  67. data/lib/rack/session/memcache.rb +4 -87
  68. data/lib/rack/session/pool.rb +25 -16
  69. data/lib/rack/show_exceptions.rb +392 -0
  70. data/lib/rack/{showstatus.rb → show_status.rb} +7 -5
  71. data/lib/rack/static.rb +41 -11
  72. data/lib/rack/tempfile_reaper.rb +4 -2
  73. data/lib/rack/urlmap.rb +25 -15
  74. data/lib/rack/utils.rb +186 -272
  75. data/lib/rack.rb +76 -24
  76. data/rack.gemspec +25 -14
  77. metadata +62 -182
  78. data/HISTORY.md +0 -375
  79. data/KNOWN-ISSUES +0 -44
  80. data/lib/rack/backports/uri/common_18.rb +0 -56
  81. data/lib/rack/backports/uri/common_192.rb +0 -52
  82. data/lib/rack/backports/uri/common_193.rb +0 -29
  83. data/lib/rack/handler/evented_mongrel.rb +0 -8
  84. data/lib/rack/handler/mongrel.rb +0 -106
  85. data/lib/rack/handler/swiftiplied_mongrel.rb +0 -8
  86. data/lib/rack/showexceptions.rb +0 -387
  87. data/lib/rack/utils/okjson.rb +0 -600
  88. data/test/builder/anything.rb +0 -5
  89. data/test/builder/comment.ru +0 -4
  90. data/test/builder/end.ru +0 -5
  91. data/test/builder/line.ru +0 -1
  92. data/test/builder/options.ru +0 -2
  93. data/test/cgi/assets/folder/test.js +0 -1
  94. data/test/cgi/assets/fonts/font.eot +0 -1
  95. data/test/cgi/assets/images/image.png +0 -1
  96. data/test/cgi/assets/index.html +0 -1
  97. data/test/cgi/assets/javascripts/app.js +0 -1
  98. data/test/cgi/assets/stylesheets/app.css +0 -1
  99. data/test/cgi/lighttpd.conf +0 -26
  100. data/test/cgi/rackup_stub.rb +0 -6
  101. data/test/cgi/sample_rackup.ru +0 -5
  102. data/test/cgi/test +0 -9
  103. data/test/cgi/test+directory/test+file +0 -1
  104. data/test/cgi/test.fcgi +0 -8
  105. data/test/cgi/test.ru +0 -5
  106. data/test/gemloader.rb +0 -10
  107. data/test/multipart/bad_robots +0 -259
  108. data/test/multipart/binary +0 -0
  109. data/test/multipart/content_type_and_no_filename +0 -6
  110. data/test/multipart/empty +0 -10
  111. data/test/multipart/fail_16384_nofile +0 -814
  112. data/test/multipart/file1.txt +0 -1
  113. data/test/multipart/filename_and_modification_param +0 -7
  114. data/test/multipart/filename_and_no_name +0 -6
  115. data/test/multipart/filename_with_escaped_quotes +0 -6
  116. data/test/multipart/filename_with_escaped_quotes_and_modification_param +0 -7
  117. data/test/multipart/filename_with_null_byte +0 -7
  118. data/test/multipart/filename_with_percent_escaped_quotes +0 -6
  119. data/test/multipart/filename_with_unescaped_percentages +0 -6
  120. data/test/multipart/filename_with_unescaped_percentages2 +0 -6
  121. data/test/multipart/filename_with_unescaped_percentages3 +0 -6
  122. data/test/multipart/filename_with_unescaped_quotes +0 -6
  123. data/test/multipart/ie +0 -6
  124. data/test/multipart/invalid_character +0 -6
  125. data/test/multipart/mixed_files +0 -21
  126. data/test/multipart/nested +0 -10
  127. data/test/multipart/none +0 -9
  128. data/test/multipart/semicolon +0 -6
  129. data/test/multipart/text +0 -15
  130. data/test/multipart/three_files_three_fields +0 -31
  131. data/test/multipart/webkit +0 -32
  132. data/test/rackup/config.ru +0 -31
  133. data/test/registering_handler/rack/handler/registering_myself.rb +0 -8
  134. data/test/spec_auth_basic.rb +0 -81
  135. data/test/spec_auth_digest.rb +0 -259
  136. data/test/spec_body_proxy.rb +0 -85
  137. data/test/spec_builder.rb +0 -223
  138. data/test/spec_cascade.rb +0 -61
  139. data/test/spec_cgi.rb +0 -102
  140. data/test/spec_chunked.rb +0 -101
  141. data/test/spec_commonlogger.rb +0 -93
  142. data/test/spec_conditionalget.rb +0 -102
  143. data/test/spec_config.rb +0 -22
  144. data/test/spec_content_length.rb +0 -85
  145. data/test/spec_content_type.rb +0 -45
  146. data/test/spec_deflater.rb +0 -339
  147. data/test/spec_directory.rb +0 -88
  148. data/test/spec_etag.rb +0 -107
  149. data/test/spec_fastcgi.rb +0 -107
  150. data/test/spec_file.rb +0 -221
  151. data/test/spec_handler.rb +0 -72
  152. data/test/spec_head.rb +0 -45
  153. data/test/spec_lint.rb +0 -550
  154. data/test/spec_lobster.rb +0 -58
  155. data/test/spec_lock.rb +0 -164
  156. data/test/spec_logger.rb +0 -23
  157. data/test/spec_methodoverride.rb +0 -111
  158. data/test/spec_mime.rb +0 -51
  159. data/test/spec_mock.rb +0 -297
  160. data/test/spec_mongrel.rb +0 -182
  161. data/test/spec_multipart.rb +0 -600
  162. data/test/spec_nulllogger.rb +0 -20
  163. data/test/spec_recursive.rb +0 -72
  164. data/test/spec_request.rb +0 -1232
  165. data/test/spec_response.rb +0 -407
  166. data/test/spec_rewindable_input.rb +0 -118
  167. data/test/spec_runtime.rb +0 -49
  168. data/test/spec_sendfile.rb +0 -130
  169. data/test/spec_server.rb +0 -167
  170. data/test/spec_session_abstract_id.rb +0 -53
  171. data/test/spec_session_cookie.rb +0 -410
  172. data/test/spec_session_memcache.rb +0 -321
  173. data/test/spec_session_pool.rb +0 -209
  174. data/test/spec_showexceptions.rb +0 -98
  175. data/test/spec_showstatus.rb +0 -103
  176. data/test/spec_static.rb +0 -145
  177. data/test/spec_tempfile_reaper.rb +0 -63
  178. data/test/spec_thin.rb +0 -91
  179. data/test/spec_urlmap.rb +0 -236
  180. data/test/spec_utils.rb +0 -647
  181. data/test/spec_version.rb +0 -17
  182. data/test/spec_webrick.rb +0 -184
  183. data/test/static/another/index.html +0 -1
  184. data/test/static/index.html +0 -1
  185. data/test/testrequest.rb +0 -78
  186. data/test/unregistered_handler/rack/handler/unregistered.rb +0 -7
  187. data/test/unregistered_handler/rack/handler/unregistered_long_one.rb +0 -7
@@ -1,85 +0,0 @@
1
- require 'rack/body_proxy'
2
- require 'stringio'
3
- require 'ostruct'
4
-
5
- describe Rack::BodyProxy do
6
- should 'call each on the wrapped body' do
7
- called = false
8
- proxy = Rack::BodyProxy.new(['foo']) { }
9
- proxy.each do |str|
10
- called = true
11
- str.should.equal 'foo'
12
- end
13
- called.should.equal true
14
- end
15
-
16
- should 'call close on the wrapped body' do
17
- body = StringIO.new
18
- proxy = Rack::BodyProxy.new(body) { }
19
- proxy.close
20
- body.should.be.closed
21
- end
22
-
23
- should 'only call close on the wrapped body if it responds to close' do
24
- body = []
25
- proxy = Rack::BodyProxy.new(body) { }
26
- proc { proxy.close }.should.not.raise
27
- end
28
-
29
- should 'call the passed block on close' do
30
- called = false
31
- proxy = Rack::BodyProxy.new([]) { called = true }
32
- called.should.equal false
33
- proxy.close
34
- called.should.equal true
35
- end
36
-
37
- should 'call the passed block on close even if there is an exception' do
38
- object = Object.new
39
- def object.close() raise "No!" end
40
- called = false
41
-
42
- begin
43
- proxy = Rack::BodyProxy.new(object) { called = true }
44
- called.should.equal false
45
- proxy.close
46
- rescue RuntimeError => e
47
- end
48
-
49
- raise "Expected exception to have been raised" unless e
50
- called.should.equal true
51
- end
52
-
53
- should 'allow multiple arguments in respond_to?' do
54
- body = []
55
- proxy = Rack::BodyProxy.new(body) { }
56
- proc { proxy.respond_to?(:foo, false) }.should.not.raise
57
- end
58
-
59
- should 'not respond to :to_ary' do
60
- body = OpenStruct.new(:to_ary => true)
61
- body.respond_to?(:to_ary).should.equal true
62
-
63
- proxy = Rack::BodyProxy.new(body) { }
64
- proxy.respond_to?(:to_ary).should.equal false
65
- proxy.respond_to?("to_ary").should.equal false
66
- end
67
-
68
- should 'not close more than one time' do
69
- count = 0
70
- proxy = Rack::BodyProxy.new([]) { count += 1; raise "Block invoked more than 1 time!" if count > 1 }
71
- 2.times { proxy.close }
72
- count.should.equal 1
73
- end
74
-
75
- should 'be closed when the callback is triggered' do
76
- closed = false
77
- proxy = Rack::BodyProxy.new([]) { closed = proxy.closed? }
78
- proxy.close
79
- closed.should.equal true
80
- end
81
-
82
- should 'provide an #each method' do
83
- Rack::BodyProxy.method_defined?(:each).should.equal true
84
- end
85
- end
data/test/spec_builder.rb DELETED
@@ -1,223 +0,0 @@
1
- require 'rack/builder'
2
- require 'rack/lint'
3
- require 'rack/mock'
4
- require 'rack/showexceptions'
5
- require 'rack/urlmap'
6
-
7
- class NothingMiddleware
8
- def initialize(app)
9
- @app = app
10
- end
11
- def call(env)
12
- @@env = env
13
- response = @app.call(env)
14
- response
15
- end
16
- def self.env
17
- @@env
18
- end
19
- end
20
-
21
- describe Rack::Builder do
22
- def builder(&block)
23
- Rack::Lint.new Rack::Builder.new(&block)
24
- end
25
-
26
- def builder_to_app(&block)
27
- Rack::Lint.new Rack::Builder.new(&block).to_app
28
- end
29
-
30
- it "supports mapping" do
31
- app = builder_to_app do
32
- map '/' do |outer_env|
33
- run lambda { |inner_env| [200, {"Content-Type" => "text/plain"}, ['root']] }
34
- end
35
- map '/sub' do
36
- run lambda { |inner_env| [200, {"Content-Type" => "text/plain"}, ['sub']] }
37
- end
38
- end
39
- Rack::MockRequest.new(app).get("/").body.to_s.should.equal 'root'
40
- Rack::MockRequest.new(app).get("/sub").body.to_s.should.equal 'sub'
41
- end
42
-
43
- it "doesn't dupe env even when mapping" do
44
- app = builder_to_app do
45
- use NothingMiddleware
46
- map '/' do |outer_env|
47
- run lambda { |inner_env|
48
- inner_env['new_key'] = 'new_value'
49
- [200, {"Content-Type" => "text/plain"}, ['root']]
50
- }
51
- end
52
- end
53
- Rack::MockRequest.new(app).get("/").body.to_s.should.equal 'root'
54
- NothingMiddleware.env['new_key'].should.equal 'new_value'
55
- end
56
-
57
- it "chains apps by default" do
58
- app = builder_to_app do
59
- use Rack::ShowExceptions
60
- run lambda { |env| raise "bzzzt" }
61
- end
62
-
63
- Rack::MockRequest.new(app).get("/").should.be.server_error
64
- Rack::MockRequest.new(app).get("/").should.be.server_error
65
- Rack::MockRequest.new(app).get("/").should.be.server_error
66
- end
67
-
68
- it "has implicit #to_app" do
69
- app = builder do
70
- use Rack::ShowExceptions
71
- run lambda { |env| raise "bzzzt" }
72
- end
73
-
74
- Rack::MockRequest.new(app).get("/").should.be.server_error
75
- Rack::MockRequest.new(app).get("/").should.be.server_error
76
- Rack::MockRequest.new(app).get("/").should.be.server_error
77
- end
78
-
79
- it "supports blocks on use" do
80
- app = builder do
81
- use Rack::ShowExceptions
82
- use Rack::Auth::Basic do |username, password|
83
- 'secret' == password
84
- end
85
-
86
- run lambda { |env| [200, {"Content-Type" => "text/plain"}, ['Hi Boss']] }
87
- end
88
-
89
- response = Rack::MockRequest.new(app).get("/")
90
- response.should.be.client_error
91
- response.status.should.equal 401
92
-
93
- # with auth...
94
- response = Rack::MockRequest.new(app).get("/",
95
- 'HTTP_AUTHORIZATION' => 'Basic ' + ["joe:secret"].pack("m*"))
96
- response.status.should.equal 200
97
- response.body.to_s.should.equal 'Hi Boss'
98
- end
99
-
100
- it "has explicit #to_app" do
101
- app = builder do
102
- use Rack::ShowExceptions
103
- run lambda { |env| raise "bzzzt" }
104
- end
105
-
106
- Rack::MockRequest.new(app).get("/").should.be.server_error
107
- Rack::MockRequest.new(app).get("/").should.be.server_error
108
- Rack::MockRequest.new(app).get("/").should.be.server_error
109
- end
110
-
111
- it "can mix map and run for endpoints" do
112
- app = builder do
113
- map '/sub' do
114
- run lambda { |inner_env| [200, {"Content-Type" => "text/plain"}, ['sub']] }
115
- end
116
- run lambda { |inner_env| [200, {"Content-Type" => "text/plain"}, ['root']] }
117
- end
118
-
119
- Rack::MockRequest.new(app).get("/").body.to_s.should.equal 'root'
120
- Rack::MockRequest.new(app).get("/sub").body.to_s.should.equal 'sub'
121
- end
122
-
123
- it "accepts middleware-only map blocks" do
124
- app = builder do
125
- map('/foo') { use Rack::ShowExceptions }
126
- run lambda { |env| raise "bzzzt" }
127
- end
128
-
129
- proc { Rack::MockRequest.new(app).get("/") }.should.raise(RuntimeError)
130
- Rack::MockRequest.new(app).get("/foo").should.be.server_error
131
- end
132
-
133
- it "yields the generated app to a block for warmup" do
134
- warmed_up_app = nil
135
-
136
- app = Rack::Builder.new do
137
- warmup { |a| warmed_up_app = a }
138
- run lambda { |env| [200, {}, []] }
139
- end.to_app
140
-
141
- warmed_up_app.should.equal app
142
- end
143
-
144
- should "initialize apps once" do
145
- app = builder do
146
- class AppClass
147
- def initialize
148
- @called = 0
149
- end
150
- def call(env)
151
- raise "bzzzt" if @called > 0
152
- @called += 1
153
- [200, {'Content-Type' => 'text/plain'}, ['OK']]
154
- end
155
- end
156
-
157
- use Rack::ShowExceptions
158
- run AppClass.new
159
- end
160
-
161
- Rack::MockRequest.new(app).get("/").status.should.equal 200
162
- Rack::MockRequest.new(app).get("/").should.be.server_error
163
- end
164
-
165
- it "allows use after run" do
166
- app = builder do
167
- run lambda { |env| raise "bzzzt" }
168
- use Rack::ShowExceptions
169
- end
170
-
171
- Rack::MockRequest.new(app).get("/").should.be.server_error
172
- Rack::MockRequest.new(app).get("/").should.be.server_error
173
- Rack::MockRequest.new(app).get("/").should.be.server_error
174
- end
175
-
176
- it 'complains about a missing run' do
177
- proc do
178
- Rack::Lint.new Rack::Builder.app { use Rack::ShowExceptions }
179
- end.should.raise(RuntimeError)
180
- end
181
-
182
- describe "parse_file" do
183
- def config_file(name)
184
- File.join(File.dirname(__FILE__), 'builder', name)
185
- end
186
-
187
- it "parses commented options" do
188
- app, options = Rack::Builder.parse_file config_file('options.ru')
189
- options[:debug].should.be.true
190
- Rack::MockRequest.new(app).get("/").body.to_s.should.equal 'OK'
191
- end
192
-
193
- it "removes __END__ before evaluating app" do
194
- app, _ = Rack::Builder.parse_file config_file('end.ru')
195
- Rack::MockRequest.new(app).get("/").body.to_s.should.equal 'OK'
196
- end
197
-
198
- it "supports multi-line comments" do
199
- lambda {
200
- Rack::Builder.parse_file config_file('comment.ru')
201
- }.should.not.raise(SyntaxError)
202
- end
203
-
204
- it "requires anything not ending in .ru" do
205
- $: << File.dirname(__FILE__)
206
- app, * = Rack::Builder.parse_file 'builder/anything'
207
- Rack::MockRequest.new(app).get("/").body.to_s.should.equal 'OK'
208
- $:.pop
209
- end
210
-
211
- it "sets __LINE__ correctly" do
212
- app, _ = Rack::Builder.parse_file config_file('line.ru')
213
- Rack::MockRequest.new(app).get("/").body.to_s.should.equal '1'
214
- end
215
- end
216
-
217
- describe 'new_from_string' do
218
- it "builds a rack app from string" do
219
- app, = Rack::Builder.new_from_string "run lambda{|env| [200, {'Content-Type' => 'text/plane'}, ['OK']] }"
220
- Rack::MockRequest.new(app).get("/").body.to_s.should.equal 'OK'
221
- end
222
- end
223
- end
data/test/spec_cascade.rb DELETED
@@ -1,61 +0,0 @@
1
- require 'rack/cascade'
2
- require 'rack/file'
3
- require 'rack/lint'
4
- require 'rack/urlmap'
5
- require 'rack/mock'
6
-
7
- describe Rack::Cascade do
8
- def cascade(*args)
9
- Rack::Lint.new Rack::Cascade.new(*args)
10
- end
11
-
12
- docroot = File.expand_path(File.dirname(__FILE__))
13
- app1 = Rack::File.new(docroot)
14
-
15
- app2 = Rack::URLMap.new("/crash" => lambda { |env| raise "boom" })
16
-
17
- app3 = Rack::URLMap.new("/foo" => lambda { |env|
18
- [200, { "Content-Type" => "text/plain"}, [""]]})
19
-
20
- should "dispatch onward on 404 and 405 by default" do
21
- cascade = cascade([app1, app2, app3])
22
- Rack::MockRequest.new(cascade).get("/cgi/test").should.be.ok
23
- Rack::MockRequest.new(cascade).get("/foo").should.be.ok
24
- Rack::MockRequest.new(cascade).get("/toobad").should.be.not_found
25
- Rack::MockRequest.new(cascade).get("/cgi/../..").should.be.client_error
26
-
27
- # Put is not allowed by Rack::File so it'll 405.
28
- Rack::MockRequest.new(cascade).put("/foo").should.be.ok
29
- end
30
-
31
- should "dispatch onward on whatever is passed" do
32
- cascade = cascade([app1, app2, app3], [404, 403])
33
- Rack::MockRequest.new(cascade).get("/cgi/../bla").should.be.not_found
34
- end
35
-
36
- should "return 404 if empty" do
37
- Rack::MockRequest.new(cascade([])).get('/').should.be.not_found
38
- end
39
-
40
- should "append new app" do
41
- cascade = Rack::Cascade.new([], [404, 403])
42
- Rack::MockRequest.new(cascade).get('/').should.be.not_found
43
- cascade << app2
44
- Rack::MockRequest.new(cascade).get('/cgi/test').should.be.not_found
45
- Rack::MockRequest.new(cascade).get('/cgi/../bla').should.be.not_found
46
- cascade << app1
47
- Rack::MockRequest.new(cascade).get('/cgi/test').should.be.ok
48
- Rack::MockRequest.new(cascade).get('/cgi/../..').should.be.client_error
49
- Rack::MockRequest.new(cascade).get('/foo').should.be.not_found
50
- cascade << app3
51
- Rack::MockRequest.new(cascade).get('/foo').should.be.ok
52
- end
53
-
54
- should "close the body on cascade" do
55
- body = StringIO.new
56
- closer = lambda { |env| [404, {}, body] }
57
- cascade = Rack::Cascade.new([closer, app3], [404])
58
- Rack::MockRequest.new(cascade).get("/foo").should.be.ok
59
- body.should.be.closed
60
- end
61
- end
data/test/spec_cgi.rb DELETED
@@ -1,102 +0,0 @@
1
- begin
2
- require File.expand_path('../testrequest', __FILE__)
3
- require 'rack/handler/cgi'
4
-
5
- describe Rack::Handler::CGI do
6
- extend TestRequest::Helpers
7
-
8
- @host = '127.0.0.1'
9
- @port = 9203
10
-
11
- if `which lighttpd` && !$?.success?
12
- raise "lighttpd not found"
13
- end
14
-
15
- # Keep this first.
16
- $pid = fork {
17
- ENV['RACK_ENV'] = 'deployment'
18
- ENV['RUBYLIB'] = [
19
- File.expand_path('../../lib', __FILE__),
20
- ENV['RUBYLIB'],
21
- ].compact.join(':')
22
-
23
- Dir.chdir(File.expand_path("../cgi", __FILE__)) do
24
- exec "lighttpd -D -f lighttpd.conf"
25
- end
26
- }
27
-
28
- should "respond" do
29
- sleep 1
30
- GET("/test")
31
- response.should.not.be.nil
32
- end
33
-
34
- should "be a lighttpd" do
35
- GET("/test")
36
- status.should.equal 200
37
- response["SERVER_SOFTWARE"].should =~ /lighttpd/
38
- response["HTTP_VERSION"].should.equal "HTTP/1.1"
39
- response["SERVER_PROTOCOL"].should.equal "HTTP/1.1"
40
- response["SERVER_PORT"].should.equal @port.to_s
41
- response["SERVER_NAME"].should.equal @host
42
- end
43
-
44
- should "have rack headers" do
45
- GET("/test")
46
- response["rack.version"].should.equal([1,3])
47
- response["rack.multithread"].should.be.false
48
- response["rack.multiprocess"].should.be.true
49
- response["rack.run_once"].should.be.true
50
- end
51
-
52
- should "have CGI headers on GET" do
53
- GET("/test")
54
- response["REQUEST_METHOD"].should.equal "GET"
55
- response["SCRIPT_NAME"].should.equal "/test"
56
- response["REQUEST_PATH"].should.equal "/"
57
- response["PATH_INFO"].should.be.nil
58
- response["QUERY_STRING"].should.equal ""
59
- response["test.postdata"].should.equal ""
60
-
61
- GET("/test/foo?quux=1")
62
- response["REQUEST_METHOD"].should.equal "GET"
63
- response["SCRIPT_NAME"].should.equal "/test"
64
- response["REQUEST_PATH"].should.equal "/"
65
- response["PATH_INFO"].should.equal "/foo"
66
- response["QUERY_STRING"].should.equal "quux=1"
67
- end
68
-
69
- should "have CGI headers on POST" do
70
- POST("/test", {"rack-form-data" => "23"}, {'X-test-header' => '42'})
71
- status.should.equal 200
72
- response["REQUEST_METHOD"].should.equal "POST"
73
- response["SCRIPT_NAME"].should.equal "/test"
74
- response["REQUEST_PATH"].should.equal "/"
75
- response["QUERY_STRING"].should.equal ""
76
- response["HTTP_X_TEST_HEADER"].should.equal "42"
77
- response["test.postdata"].should.equal "rack-form-data=23"
78
- end
79
-
80
- should "support HTTP auth" do
81
- GET("/test", {:user => "ruth", :passwd => "secret"})
82
- response["HTTP_AUTHORIZATION"].should.equal "Basic cnV0aDpzZWNyZXQ="
83
- end
84
-
85
- should "set status" do
86
- GET("/test?secret")
87
- status.should.equal 403
88
- response["rack.url_scheme"].should.equal "http"
89
- end
90
-
91
- # Keep this last.
92
- should "shutdown" do
93
- Process.kill 15, $pid
94
- Process.wait($pid).should == $pid
95
- end
96
- end
97
-
98
- rescue RuntimeError
99
- $stderr.puts "Skipping Rack::Handler::CGI tests (lighttpd is required). Install lighttpd and try again."
100
- rescue NotImplementedError
101
- $stderr.puts "Your Ruby implemenation or platform does not support fork. Skipping Rack::Handler::CGI tests."
102
- end
data/test/spec_chunked.rb DELETED
@@ -1,101 +0,0 @@
1
- require 'rack/chunked'
2
- require 'rack/lint'
3
- require 'rack/mock'
4
-
5
- describe Rack::Chunked do
6
- def chunked(app)
7
- proc do |env|
8
- app = Rack::Chunked.new(app)
9
- response = Rack::Lint.new(app).call(env)
10
- # we want to use body like an array, but it only has #each
11
- response[2] = response[2].to_enum.to_a
12
- response
13
- end
14
- end
15
-
16
- before do
17
- @env = Rack::MockRequest.
18
- env_for('/', 'HTTP_VERSION' => '1.1', 'REQUEST_METHOD' => 'GET')
19
- end
20
-
21
- should 'chunk responses with no Content-Length' do
22
- app = lambda { |env| [200, {"Content-Type" => "text/plain"}, ['Hello', ' ', 'World!']] }
23
- response = Rack::MockResponse.new(*chunked(app).call(@env))
24
- response.headers.should.not.include 'Content-Length'
25
- response.headers['Transfer-Encoding'].should.equal 'chunked'
26
- response.body.should.equal "5\r\nHello\r\n1\r\n \r\n6\r\nWorld!\r\n0\r\n\r\n"
27
- end
28
-
29
- should 'chunks empty bodies properly' do
30
- app = lambda { |env| [200, {"Content-Type" => "text/plain"}, []] }
31
- response = Rack::MockResponse.new(*chunked(app).call(@env))
32
- response.headers.should.not.include 'Content-Length'
33
- response.headers['Transfer-Encoding'].should.equal 'chunked'
34
- response.body.should.equal "0\r\n\r\n"
35
- end
36
-
37
- should 'chunks encoded bodies properly' do
38
- body = ["\uFFFEHello", " ", "World"].map {|t| t.encode("UTF-16LE") }
39
- app = lambda { |env| [200, {"Content-Type" => "text/plain"}, body] }
40
- response = Rack::MockResponse.new(*chunked(app).call(@env))
41
- response.headers.should.not.include 'Content-Length'
42
- response.headers['Transfer-Encoding'].should.equal 'chunked'
43
- response.body.encoding.to_s.should.equal "ASCII-8BIT"
44
- response.body.should.equal "c\r\n\xFE\xFFH\x00e\x00l\x00l\x00o\x00\r\n2\r\n \x00\r\na\r\nW\x00o\x00r\x00l\x00d\x00\r\n0\r\n\r\n".force_encoding("BINARY")
45
- end if RUBY_VERSION >= "1.9"
46
-
47
- should 'not modify response when Content-Length header present' do
48
- app = lambda { |env|
49
- [200, {"Content-Type" => "text/plain", 'Content-Length'=>'12'}, ['Hello', ' ', 'World!']]
50
- }
51
- status, headers, body = chunked(app).call(@env)
52
- status.should.equal 200
53
- headers.should.not.include 'Transfer-Encoding'
54
- headers.should.include 'Content-Length'
55
- body.join.should.equal 'Hello World!'
56
- end
57
-
58
- should 'not modify response when client is HTTP/1.0' do
59
- app = lambda { |env| [200, {"Content-Type" => "text/plain"}, ['Hello', ' ', 'World!']] }
60
- @env['HTTP_VERSION'] = 'HTTP/1.0'
61
- status, headers, body = chunked(app).call(@env)
62
- status.should.equal 200
63
- headers.should.not.include 'Transfer-Encoding'
64
- body.join.should.equal 'Hello World!'
65
- end
66
-
67
- should 'not modify response when client is ancient, pre-HTTP/1.0' do
68
- app = lambda { |env| [200, {"Content-Type" => "text/plain"}, ['Hello', ' ', 'World!']] }
69
- check = lambda do
70
- status, headers, body = chunked(app).call(@env.dup)
71
- status.should.equal 200
72
- headers.should.not.include 'Transfer-Encoding'
73
- body.join.should.equal 'Hello World!'
74
- end
75
-
76
- @env.delete('HTTP_VERSION') # unicorn will do this on pre-HTTP/1.0 requests
77
- check.call
78
-
79
- @env['HTTP_VERSION'] = 'HTTP/0.9' # not sure if this happens in practice
80
- check.call
81
- end
82
-
83
- should 'not modify response when Transfer-Encoding header already present' do
84
- app = lambda { |env|
85
- [200, {"Content-Type" => "text/plain", 'Transfer-Encoding' => 'identity'}, ['Hello', ' ', 'World!']]
86
- }
87
- status, headers, body = chunked(app).call(@env)
88
- status.should.equal 200
89
- headers['Transfer-Encoding'].should.equal 'identity'
90
- body.join.should.equal 'Hello World!'
91
- end
92
-
93
- [100, 204, 205, 304].each do |status_code|
94
- should "not modify response when status code is #{status_code}" do
95
- app = lambda { |env| [status_code, {}, []] }
96
- status, headers, _ = chunked(app).call(@env)
97
- status.should.equal status_code
98
- headers.should.not.include 'Transfer-Encoding'
99
- end
100
- end
101
- end
@@ -1,93 +0,0 @@
1
- require 'rack/commonlogger'
2
- require 'rack/lint'
3
- require 'rack/mock'
4
-
5
- require 'logger'
6
-
7
- describe Rack::CommonLogger do
8
- obj = 'foobar'
9
- length = obj.size
10
-
11
- app = Rack::Lint.new lambda { |env|
12
- [200,
13
- {"Content-Type" => "text/html", "Content-Length" => length.to_s},
14
- [obj]]}
15
- app_without_length = Rack::Lint.new lambda { |env|
16
- [200,
17
- {"Content-Type" => "text/html"},
18
- []]}
19
- app_with_zero_length = Rack::Lint.new lambda { |env|
20
- [200,
21
- {"Content-Type" => "text/html", "Content-Length" => "0"},
22
- []]}
23
-
24
- should "log to rack.errors by default" do
25
- res = Rack::MockRequest.new(Rack::CommonLogger.new(app)).get("/")
26
-
27
- res.errors.should.not.be.empty
28
- res.errors.should =~ /"GET \/ " 200 #{length} /
29
- end
30
-
31
- should "log to anything with +write+" do
32
- log = StringIO.new
33
- Rack::MockRequest.new(Rack::CommonLogger.new(app, log)).get("/")
34
-
35
- log.string.should =~ /"GET \/ " 200 #{length} /
36
- end
37
-
38
- should "work with standartd library logger" do
39
- logdev = StringIO.new
40
- log = Logger.new(logdev)
41
- Rack::MockRequest.new(Rack::CommonLogger.new(app, log)).get("/")
42
-
43
- logdev.string.should =~ /"GET \/ " 200 #{length} /
44
- end
45
-
46
- should "log - content length if header is missing" do
47
- res = Rack::MockRequest.new(Rack::CommonLogger.new(app_without_length)).get("/")
48
-
49
- res.errors.should.not.be.empty
50
- res.errors.should =~ /"GET \/ " 200 - /
51
- end
52
-
53
- should "log - content length if header is zero" do
54
- res = Rack::MockRequest.new(Rack::CommonLogger.new(app_with_zero_length)).get("/")
55
-
56
- res.errors.should.not.be.empty
57
- res.errors.should =~ /"GET \/ " 200 - /
58
- end
59
-
60
- def with_mock_time(t = 0)
61
- mc = class <<Time; self; end
62
- mc.send :alias_method, :old_now, :now
63
- mc.send :define_method, :now do
64
- at(t)
65
- end
66
- yield
67
- ensure
68
- mc.send :alias_method, :now, :old_now
69
- end
70
-
71
- should "log in common log format" do
72
- log = StringIO.new
73
- with_mock_time do
74
- Rack::MockRequest.new(Rack::CommonLogger.new(app, log)).get("/")
75
- end
76
-
77
- md = /- - - \[([^\]]+)\] "(\w+) \/ " (\d{3}) \d+ ([\d\.]+)/.match(log.string)
78
- md.should.not.equal nil
79
- time, method, status, duration = *md.captures
80
- time.should.equal Time.at(0).strftime("%d/%b/%Y:%H:%M:%S %z")
81
- method.should.equal "GET"
82
- status.should.equal "200"
83
- (0..1).should.include?(duration.to_f)
84
- end
85
-
86
- def length
87
- 123
88
- end
89
-
90
- def self.obj
91
- "hello world"
92
- end
93
- end