rack 1.4.7 → 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.
- checksums.yaml +5 -5
- data/CHANGELOG.md +77 -0
- data/{COPYING → MIT-LICENSE} +4 -2
- data/README.rdoc +122 -456
- data/Rakefile +32 -31
- data/SPEC +119 -29
- data/bin/rackup +1 -0
- data/contrib/rack_logo.svg +164 -111
- data/example/lobster.ru +2 -0
- data/example/protectedlobster.rb +4 -2
- data/example/protectedlobster.ru +3 -1
- data/lib/rack/auth/abstract/handler.rb +7 -5
- data/lib/rack/auth/abstract/request.rb +8 -6
- data/lib/rack/auth/basic.rb +5 -2
- data/lib/rack/auth/digest/md5.rb +10 -8
- data/lib/rack/auth/digest/nonce.rb +6 -3
- data/lib/rack/auth/digest/params.rb +5 -4
- data/lib/rack/auth/digest/request.rb +4 -2
- data/lib/rack/body_proxy.rb +11 -9
- data/lib/rack/builder.rb +63 -20
- data/lib/rack/cascade.rb +10 -9
- data/lib/rack/chunked.rb +45 -11
- data/lib/rack/{commonlogger.rb → common_logger.rb} +24 -15
- data/lib/rack/{conditionalget.rb → conditional_get.rb} +20 -6
- data/lib/rack/config.rb +7 -0
- data/lib/rack/content_length.rb +12 -6
- data/lib/rack/content_type.rb +4 -2
- data/lib/rack/core_ext/regexp.rb +14 -0
- data/lib/rack/deflater.rb +73 -42
- data/lib/rack/directory.rb +77 -56
- data/lib/rack/etag.rb +25 -13
- data/lib/rack/events.rb +156 -0
- data/lib/rack/file.rb +4 -143
- data/lib/rack/files.rb +178 -0
- data/lib/rack/handler/cgi.rb +18 -17
- data/lib/rack/handler/fastcgi.rb +21 -17
- data/lib/rack/handler/lsws.rb +14 -12
- data/lib/rack/handler/scgi.rb +27 -21
- data/lib/rack/handler/thin.rb +19 -5
- data/lib/rack/handler/webrick.rb +66 -24
- data/lib/rack/handler.rb +29 -19
- data/lib/rack/head.rb +21 -14
- data/lib/rack/lint.rb +259 -65
- data/lib/rack/lobster.rb +17 -10
- data/lib/rack/lock.rb +19 -10
- data/lib/rack/logger.rb +4 -2
- data/lib/rack/media_type.rb +43 -0
- data/lib/rack/method_override.rb +52 -0
- data/lib/rack/mime.rb +43 -6
- data/lib/rack/mock.rb +109 -44
- data/lib/rack/multipart/generator.rb +11 -12
- data/lib/rack/multipart/parser.rb +302 -115
- data/lib/rack/multipart/uploaded_file.rb +4 -3
- data/lib/rack/multipart.rb +40 -9
- data/lib/rack/null_logger.rb +39 -0
- data/lib/rack/query_parser.rb +218 -0
- data/lib/rack/recursive.rb +14 -11
- data/lib/rack/reloader.rb +12 -5
- data/lib/rack/request.rb +484 -270
- data/lib/rack/response.rb +196 -77
- data/lib/rack/rewindable_input.rb +5 -14
- data/lib/rack/runtime.rb +13 -6
- data/lib/rack/sendfile.rb +44 -20
- data/lib/rack/server.rb +175 -61
- data/lib/rack/session/abstract/id.rb +276 -133
- data/lib/rack/session/cookie.rb +75 -40
- data/lib/rack/session/memcache.rb +4 -87
- data/lib/rack/session/pool.rb +24 -18
- data/lib/rack/show_exceptions.rb +392 -0
- data/lib/rack/{showstatus.rb → show_status.rb} +11 -9
- data/lib/rack/static.rb +65 -38
- data/lib/rack/tempfile_reaper.rb +24 -0
- data/lib/rack/urlmap.rb +40 -15
- data/lib/rack/utils.rb +316 -285
- data/lib/rack.rb +78 -23
- data/rack.gemspec +26 -19
- metadata +44 -209
- data/KNOWN-ISSUES +0 -30
- 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 -100
- data/lib/rack/handler/swiftiplied_mongrel.rb +0 -8
- data/lib/rack/methodoverride.rb +0 -33
- data/lib/rack/nulllogger.rb +0 -18
- data/lib/rack/showexceptions.rb +0 -378
- data/test/builder/anything.rb +0 -5
- data/test/builder/comment.ru +0 -4
- data/test/builder/end.ru +0 -5
- data/test/builder/line.ru +0 -1
- data/test/builder/options.ru +0 -2
- data/test/cgi/assets/folder/test.js +0 -1
- data/test/cgi/assets/fonts/font.eot +0 -1
- data/test/cgi/assets/images/image.png +0 -1
- data/test/cgi/assets/index.html +0 -1
- data/test/cgi/assets/javascripts/app.js +0 -1
- data/test/cgi/assets/stylesheets/app.css +0 -1
- data/test/cgi/lighttpd.conf +0 -26
- data/test/cgi/lighttpd.errors +0 -1
- data/test/cgi/rackup_stub.rb +0 -6
- data/test/cgi/sample_rackup.ru +0 -5
- data/test/cgi/test +0 -9
- data/test/cgi/test+directory/test+file +0 -1
- data/test/cgi/test.fcgi +0 -8
- data/test/cgi/test.ru +0 -5
- data/test/gemloader.rb +0 -10
- data/test/multipart/bad_robots +0 -259
- data/test/multipart/binary +0 -0
- data/test/multipart/content_type_and_no_filename +0 -6
- data/test/multipart/empty +0 -10
- data/test/multipart/fail_16384_nofile +0 -814
- data/test/multipart/file1.txt +0 -1
- data/test/multipart/filename_and_modification_param +0 -7
- data/test/multipart/filename_with_escaped_quotes +0 -6
- data/test/multipart/filename_with_escaped_quotes_and_modification_param +0 -7
- data/test/multipart/filename_with_percent_escaped_quotes +0 -6
- data/test/multipart/filename_with_unescaped_percentages +0 -6
- data/test/multipart/filename_with_unescaped_percentages2 +0 -6
- data/test/multipart/filename_with_unescaped_percentages3 +0 -6
- data/test/multipart/filename_with_unescaped_quotes +0 -6
- data/test/multipart/ie +0 -6
- data/test/multipart/mixed_files +0 -21
- data/test/multipart/nested +0 -10
- data/test/multipart/none +0 -9
- data/test/multipart/semicolon +0 -6
- data/test/multipart/text +0 -15
- data/test/multipart/three_files_three_fields +0 -31
- data/test/multipart/webkit +0 -32
- data/test/rackup/config.ru +0 -31
- data/test/registering_handler/rack/handler/registering_myself.rb +0 -8
- data/test/spec_auth.rb +0 -57
- data/test/spec_auth_basic.rb +0 -81
- data/test/spec_auth_digest.rb +0 -259
- data/test/spec_body_proxy.rb +0 -69
- data/test/spec_builder.rb +0 -207
- data/test/spec_cascade.rb +0 -61
- data/test/spec_cgi.rb +0 -102
- data/test/spec_chunked.rb +0 -87
- data/test/spec_commonlogger.rb +0 -57
- data/test/spec_conditionalget.rb +0 -102
- data/test/spec_config.rb +0 -22
- data/test/spec_content_length.rb +0 -86
- data/test/spec_content_type.rb +0 -45
- data/test/spec_deflater.rb +0 -187
- data/test/spec_directory.rb +0 -88
- data/test/spec_etag.rb +0 -98
- data/test/spec_fastcgi.rb +0 -107
- data/test/spec_file.rb +0 -200
- data/test/spec_handler.rb +0 -59
- data/test/spec_head.rb +0 -48
- data/test/spec_lint.rb +0 -515
- data/test/spec_lobster.rb +0 -58
- data/test/spec_lock.rb +0 -167
- data/test/spec_logger.rb +0 -23
- data/test/spec_methodoverride.rb +0 -72
- data/test/spec_mock.rb +0 -269
- data/test/spec_mongrel.rb +0 -182
- data/test/spec_multipart.rb +0 -479
- data/test/spec_nulllogger.rb +0 -23
- data/test/spec_recursive.rb +0 -72
- data/test/spec_request.rb +0 -955
- data/test/spec_response.rb +0 -313
- data/test/spec_rewindable_input.rb +0 -118
- data/test/spec_runtime.rb +0 -49
- data/test/spec_sendfile.rb +0 -90
- data/test/spec_server.rb +0 -121
- data/test/spec_session_abstract_id.rb +0 -43
- data/test/spec_session_cookie.rb +0 -361
- data/test/spec_session_memcache.rb +0 -321
- data/test/spec_session_pool.rb +0 -209
- data/test/spec_showexceptions.rb +0 -92
- data/test/spec_showstatus.rb +0 -84
- data/test/spec_static.rb +0 -145
- data/test/spec_thin.rb +0 -86
- data/test/spec_urlmap.rb +0 -213
- data/test/spec_utils.rb +0 -554
- data/test/spec_webrick.rb +0 -143
- data/test/static/another/index.html +0 -1
- data/test/static/index.html +0 -1
- data/test/testrequest.rb +0 -78
- data/test/unregistered_handler/rack/handler/unregistered.rb +0 -7
- data/test/unregistered_handler/rack/handler/unregistered_long_one.rb +0 -7
data/test/spec_body_proxy.rb
DELETED
@@ -1,69 +0,0 @@
|
|
1
|
-
require 'rack/body_proxy'
|
2
|
-
require 'stringio'
|
3
|
-
|
4
|
-
describe Rack::BodyProxy do
|
5
|
-
should 'call each on the wrapped body' do
|
6
|
-
called = false
|
7
|
-
proxy = Rack::BodyProxy.new(['foo']) { }
|
8
|
-
proxy.each do |str|
|
9
|
-
called = true
|
10
|
-
str.should.equal 'foo'
|
11
|
-
end
|
12
|
-
called.should.equal true
|
13
|
-
end
|
14
|
-
|
15
|
-
should 'call close on the wrapped body' do
|
16
|
-
body = StringIO.new
|
17
|
-
proxy = Rack::BodyProxy.new(body) { }
|
18
|
-
proxy.close
|
19
|
-
body.should.be.closed
|
20
|
-
end
|
21
|
-
|
22
|
-
should 'only call close on the wrapped body if it responds to close' do
|
23
|
-
body = []
|
24
|
-
proxy = Rack::BodyProxy.new(body) { }
|
25
|
-
proc { proxy.close }.should.not.raise
|
26
|
-
end
|
27
|
-
|
28
|
-
should 'call the passed block on close' do
|
29
|
-
called = false
|
30
|
-
proxy = Rack::BodyProxy.new([]) { called = true }
|
31
|
-
called.should.equal false
|
32
|
-
proxy.close
|
33
|
-
called.should.equal true
|
34
|
-
end
|
35
|
-
|
36
|
-
should 'call the passed block on close even if there is an exception' do
|
37
|
-
object = Object.new
|
38
|
-
def object.close() raise "No!" end
|
39
|
-
called = false
|
40
|
-
|
41
|
-
begin
|
42
|
-
proxy = Rack::BodyProxy.new(object) { called = true }
|
43
|
-
called.should.equal false
|
44
|
-
proxy.close
|
45
|
-
rescue RuntimeError => e
|
46
|
-
end
|
47
|
-
|
48
|
-
raise "Expected exception to have been raised" unless e
|
49
|
-
called.should.equal true
|
50
|
-
end
|
51
|
-
|
52
|
-
should 'not close more than one time' do
|
53
|
-
count = 0
|
54
|
-
proxy = Rack::BodyProxy.new([]) { count += 1; raise "Block invoked more than 1 time!" if count > 1 }
|
55
|
-
2.times { proxy.close }
|
56
|
-
count.should.equal 1
|
57
|
-
end
|
58
|
-
|
59
|
-
should 'be closed when the callback is triggered' do
|
60
|
-
closed = false
|
61
|
-
proxy = Rack::BodyProxy.new([]) { closed = proxy.closed? }
|
62
|
-
proxy.close
|
63
|
-
closed.should.equal true
|
64
|
-
end
|
65
|
-
|
66
|
-
should 'provide an #each method' do
|
67
|
-
Rack::BodyProxy.method_defined?(:each).should.equal true
|
68
|
-
end
|
69
|
-
end
|
data/test/spec_builder.rb
DELETED
@@ -1,207 +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
|
-
should "initialize apps once" do
|
134
|
-
app = builder do
|
135
|
-
class AppClass
|
136
|
-
def initialize
|
137
|
-
@called = 0
|
138
|
-
end
|
139
|
-
def call(env)
|
140
|
-
raise "bzzzt" if @called > 0
|
141
|
-
@called += 1
|
142
|
-
[200, {'Content-Type' => 'text/plain'}, ['OK']]
|
143
|
-
end
|
144
|
-
end
|
145
|
-
|
146
|
-
use Rack::ShowExceptions
|
147
|
-
run AppClass.new
|
148
|
-
end
|
149
|
-
|
150
|
-
Rack::MockRequest.new(app).get("/").status.should.equal 200
|
151
|
-
Rack::MockRequest.new(app).get("/").should.be.server_error
|
152
|
-
end
|
153
|
-
|
154
|
-
it "allows use after run" do
|
155
|
-
app = builder do
|
156
|
-
run lambda { |env| raise "bzzzt" }
|
157
|
-
use Rack::ShowExceptions
|
158
|
-
end
|
159
|
-
|
160
|
-
Rack::MockRequest.new(app).get("/").should.be.server_error
|
161
|
-
Rack::MockRequest.new(app).get("/").should.be.server_error
|
162
|
-
Rack::MockRequest.new(app).get("/").should.be.server_error
|
163
|
-
end
|
164
|
-
|
165
|
-
it 'complains about a missing run' do
|
166
|
-
proc do
|
167
|
-
Rack::Lint.new Rack::Builder.app { use Rack::ShowExceptions }
|
168
|
-
end.should.raise(RuntimeError)
|
169
|
-
end
|
170
|
-
|
171
|
-
describe "parse_file" do
|
172
|
-
def config_file(name)
|
173
|
-
File.join(File.dirname(__FILE__), 'builder', name)
|
174
|
-
end
|
175
|
-
|
176
|
-
it "parses commented options" do
|
177
|
-
app, options = Rack::Builder.parse_file config_file('options.ru')
|
178
|
-
options[:debug].should.be.true
|
179
|
-
Rack::MockRequest.new(app).get("/").body.to_s.should.equal 'OK'
|
180
|
-
end
|
181
|
-
|
182
|
-
it "removes __END__ before evaluating app" do
|
183
|
-
app, options = Rack::Builder.parse_file config_file('end.ru')
|
184
|
-
options = nil # ignored, prevents warning
|
185
|
-
Rack::MockRequest.new(app).get("/").body.to_s.should.equal 'OK'
|
186
|
-
end
|
187
|
-
|
188
|
-
it "supports multi-line comments" do
|
189
|
-
lambda {
|
190
|
-
Rack::Builder.parse_file config_file('comment.ru')
|
191
|
-
}.should.not.raise(SyntaxError)
|
192
|
-
end
|
193
|
-
|
194
|
-
it "requires anything not ending in .ru" do
|
195
|
-
$: << File.dirname(__FILE__)
|
196
|
-
app, * = Rack::Builder.parse_file 'builder/anything'
|
197
|
-
Rack::MockRequest.new(app).get("/").body.to_s.should.equal 'OK'
|
198
|
-
$:.pop
|
199
|
-
end
|
200
|
-
|
201
|
-
it "sets __LINE__ correctly" do
|
202
|
-
app, options = Rack::Builder.parse_file config_file('line.ru')
|
203
|
-
options = nil # ignored, prevents warning
|
204
|
-
Rack::MockRequest.new(app).get("/").body.to_s.should.equal '1'
|
205
|
-
end
|
206
|
-
end
|
207
|
-
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,1])
|
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,87 +0,0 @@
|
|
1
|
-
require 'rack/chunked'
|
2
|
-
require 'rack/lint'
|
3
|
-
require 'rack/mock'
|
4
|
-
|
5
|
-
describe Rack::Chunked do
|
6
|
-
::Enumerator = ::Enumerable::Enumerator unless Object.const_defined?(:Enumerator)
|
7
|
-
|
8
|
-
def chunked(app)
|
9
|
-
proc do |env|
|
10
|
-
app = Rack::Chunked.new(app)
|
11
|
-
response = Rack::Lint.new(app).call(env)
|
12
|
-
# we want to use body like an array, but it only has #each
|
13
|
-
response[2] = Enumerator.new(response[2]).to_a
|
14
|
-
response
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
18
|
-
before do
|
19
|
-
@env = Rack::MockRequest.
|
20
|
-
env_for('/', 'HTTP_VERSION' => '1.1', 'REQUEST_METHOD' => 'GET')
|
21
|
-
end
|
22
|
-
|
23
|
-
should 'chunk responses with no Content-Length' do
|
24
|
-
app = lambda { |env| [200, {"Content-Type" => "text/plain"}, ['Hello', ' ', 'World!']] }
|
25
|
-
response = Rack::MockResponse.new(*chunked(app).call(@env))
|
26
|
-
response.headers.should.not.include 'Content-Length'
|
27
|
-
response.headers['Transfer-Encoding'].should.equal 'chunked'
|
28
|
-
response.body.should.equal "5\r\nHello\r\n1\r\n \r\n6\r\nWorld!\r\n0\r\n\r\n"
|
29
|
-
end
|
30
|
-
|
31
|
-
should 'chunks empty bodies properly' do
|
32
|
-
app = lambda { |env| [200, {"Content-Type" => "text/plain"}, []] }
|
33
|
-
response = Rack::MockResponse.new(*chunked(app).call(@env))
|
34
|
-
response.headers.should.not.include 'Content-Length'
|
35
|
-
response.headers['Transfer-Encoding'].should.equal 'chunked'
|
36
|
-
response.body.should.equal "0\r\n\r\n"
|
37
|
-
end
|
38
|
-
|
39
|
-
should 'chunks encoded bodies properly' do
|
40
|
-
body = ["\uFFFEHello", " ", "World"].map {|t| t.encode("UTF-16LE") }
|
41
|
-
app = lambda { |env| [200, {"Content-Type" => "text/plain"}, body] }
|
42
|
-
response = Rack::MockResponse.new(*chunked(app).call(@env))
|
43
|
-
response.headers.should.not.include 'Content-Length'
|
44
|
-
response.headers['Transfer-Encoding'].should.equal 'chunked'
|
45
|
-
response.body.encoding.to_s.should.equal "ASCII-8BIT"
|
46
|
-
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"
|
47
|
-
end if RUBY_VERSION >= "1.9"
|
48
|
-
|
49
|
-
should 'not modify response when Content-Length header present' do
|
50
|
-
app = lambda { |env|
|
51
|
-
[200, {"Content-Type" => "text/plain", 'Content-Length'=>'12'}, ['Hello', ' ', 'World!']]
|
52
|
-
}
|
53
|
-
status, headers, body = chunked(app).call(@env)
|
54
|
-
status.should.equal 200
|
55
|
-
headers.should.not.include 'Transfer-Encoding'
|
56
|
-
headers.should.include 'Content-Length'
|
57
|
-
body.join.should.equal 'Hello World!'
|
58
|
-
end
|
59
|
-
|
60
|
-
should 'not modify response when client is HTTP/1.0' do
|
61
|
-
app = lambda { |env| [200, {"Content-Type" => "text/plain"}, ['Hello', ' ', 'World!']] }
|
62
|
-
@env['HTTP_VERSION'] = 'HTTP/1.0'
|
63
|
-
status, headers, body = chunked(app).call(@env)
|
64
|
-
status.should.equal 200
|
65
|
-
headers.should.not.include 'Transfer-Encoding'
|
66
|
-
body.join.should.equal 'Hello World!'
|
67
|
-
end
|
68
|
-
|
69
|
-
should 'not modify response when Transfer-Encoding header already present' do
|
70
|
-
app = lambda { |env|
|
71
|
-
[200, {"Content-Type" => "text/plain", 'Transfer-Encoding' => 'identity'}, ['Hello', ' ', 'World!']]
|
72
|
-
}
|
73
|
-
status, headers, body = chunked(app).call(@env)
|
74
|
-
status.should.equal 200
|
75
|
-
headers['Transfer-Encoding'].should.equal 'identity'
|
76
|
-
body.join.should.equal 'Hello World!'
|
77
|
-
end
|
78
|
-
|
79
|
-
[100, 204, 205, 304].each do |status_code|
|
80
|
-
should "not modify response when status code is #{status_code}" do
|
81
|
-
app = lambda { |env| [status_code, {}, []] }
|
82
|
-
status, headers, _ = chunked(app).call(@env)
|
83
|
-
status.should.equal status_code
|
84
|
-
headers.should.not.include 'Transfer-Encoding'
|
85
|
-
end
|
86
|
-
end
|
87
|
-
end
|
data/test/spec_commonlogger.rb
DELETED
@@ -1,57 +0,0 @@
|
|
1
|
-
require 'rack/commonlogger'
|
2
|
-
require 'rack/lint'
|
3
|
-
require 'rack/mock'
|
4
|
-
|
5
|
-
describe Rack::CommonLogger do
|
6
|
-
obj = 'foobar'
|
7
|
-
length = obj.size
|
8
|
-
|
9
|
-
app = Rack::Lint.new lambda { |env|
|
10
|
-
[200,
|
11
|
-
{"Content-Type" => "text/html", "Content-Length" => length.to_s},
|
12
|
-
[obj]]}
|
13
|
-
app_without_length = Rack::Lint.new lambda { |env|
|
14
|
-
[200,
|
15
|
-
{"Content-Type" => "text/html"},
|
16
|
-
[]]}
|
17
|
-
app_with_zero_length = Rack::Lint.new lambda { |env|
|
18
|
-
[200,
|
19
|
-
{"Content-Type" => "text/html", "Content-Length" => "0"},
|
20
|
-
[]]}
|
21
|
-
|
22
|
-
should "log to rack.errors by default" do
|
23
|
-
res = Rack::MockRequest.new(Rack::CommonLogger.new(app)).get("/")
|
24
|
-
|
25
|
-
res.errors.should.not.be.empty
|
26
|
-
res.errors.should =~ /"GET \/ " 200 #{length} /
|
27
|
-
end
|
28
|
-
|
29
|
-
should "log to anything with +write+" do
|
30
|
-
log = StringIO.new
|
31
|
-
Rack::MockRequest.new(Rack::CommonLogger.new(app, log)).get("/")
|
32
|
-
|
33
|
-
log.string.should =~ /"GET \/ " 200 #{length} /
|
34
|
-
end
|
35
|
-
|
36
|
-
should "log - content length if header is missing" do
|
37
|
-
res = Rack::MockRequest.new(Rack::CommonLogger.new(app_without_length)).get("/")
|
38
|
-
|
39
|
-
res.errors.should.not.be.empty
|
40
|
-
res.errors.should =~ /"GET \/ " 200 - /
|
41
|
-
end
|
42
|
-
|
43
|
-
should "log - content length if header is zero" do
|
44
|
-
res = Rack::MockRequest.new(Rack::CommonLogger.new(app_with_zero_length)).get("/")
|
45
|
-
|
46
|
-
res.errors.should.not.be.empty
|
47
|
-
res.errors.should =~ /"GET \/ " 200 - /
|
48
|
-
end
|
49
|
-
|
50
|
-
def length
|
51
|
-
123
|
52
|
-
end
|
53
|
-
|
54
|
-
def self.obj
|
55
|
-
"hello world"
|
56
|
-
end
|
57
|
-
end
|
data/test/spec_conditionalget.rb
DELETED
@@ -1,102 +0,0 @@
|
|
1
|
-
require 'time'
|
2
|
-
require 'rack/conditionalget'
|
3
|
-
require 'rack/mock'
|
4
|
-
|
5
|
-
describe Rack::ConditionalGet do
|
6
|
-
def conditional_get(app)
|
7
|
-
Rack::Lint.new Rack::ConditionalGet.new(app)
|
8
|
-
end
|
9
|
-
|
10
|
-
should "set a 304 status and truncate body when If-Modified-Since hits" do
|
11
|
-
timestamp = Time.now.httpdate
|
12
|
-
app = conditional_get(lambda { |env|
|
13
|
-
[200, {'Last-Modified'=>timestamp}, ['TEST']] })
|
14
|
-
|
15
|
-
response = Rack::MockRequest.new(app).
|
16
|
-
get("/", 'HTTP_IF_MODIFIED_SINCE' => timestamp)
|
17
|
-
|
18
|
-
response.status.should.equal 304
|
19
|
-
response.body.should.be.empty
|
20
|
-
end
|
21
|
-
|
22
|
-
should "set a 304 status and truncate body when If-Modified-Since hits and is higher than current time" do
|
23
|
-
app = conditional_get(lambda { |env|
|
24
|
-
[200, {'Last-Modified'=>(Time.now - 3600).httpdate}, ['TEST']] })
|
25
|
-
|
26
|
-
response = Rack::MockRequest.new(app).
|
27
|
-
get("/", 'HTTP_IF_MODIFIED_SINCE' => Time.now.httpdate)
|
28
|
-
|
29
|
-
response.status.should.equal 304
|
30
|
-
response.body.should.be.empty
|
31
|
-
end
|
32
|
-
|
33
|
-
should "set a 304 status and truncate body when If-None-Match hits" do
|
34
|
-
app = conditional_get(lambda { |env|
|
35
|
-
[200, {'Etag'=>'1234'}, ['TEST']] })
|
36
|
-
|
37
|
-
response = Rack::MockRequest.new(app).
|
38
|
-
get("/", 'HTTP_IF_NONE_MATCH' => '1234')
|
39
|
-
|
40
|
-
response.status.should.equal 304
|
41
|
-
response.body.should.be.empty
|
42
|
-
end
|
43
|
-
|
44
|
-
should "not set a 304 status if If-Modified-Since hits but Etag does not" do
|
45
|
-
timestamp = Time.now.httpdate
|
46
|
-
app = conditional_get(lambda { |env|
|
47
|
-
[200, {'Last-Modified'=>timestamp, 'Etag'=>'1234', 'Content-Type' => 'text/plain'}, ['TEST']] })
|
48
|
-
|
49
|
-
response = Rack::MockRequest.new(app).
|
50
|
-
get("/", 'HTTP_IF_MODIFIED_SINCE' => timestamp, 'HTTP_IF_NONE_MATCH' => '4321')
|
51
|
-
|
52
|
-
response.status.should.equal 200
|
53
|
-
response.body.should.equal 'TEST'
|
54
|
-
end
|
55
|
-
|
56
|
-
should "set a 304 status and truncate body when both If-None-Match and If-Modified-Since hits" do
|
57
|
-
timestamp = Time.now.httpdate
|
58
|
-
app = conditional_get(lambda { |env|
|
59
|
-
[200, {'Last-Modified'=>timestamp, 'Etag'=>'1234'}, ['TEST']] })
|
60
|
-
|
61
|
-
response = Rack::MockRequest.new(app).
|
62
|
-
get("/", 'HTTP_IF_MODIFIED_SINCE' => timestamp, 'HTTP_IF_NONE_MATCH' => '1234')
|
63
|
-
|
64
|
-
response.status.should.equal 304
|
65
|
-
response.body.should.be.empty
|
66
|
-
end
|
67
|
-
|
68
|
-
should "not affect non-GET/HEAD requests" do
|
69
|
-
app = conditional_get(lambda { |env|
|
70
|
-
[200, {'Etag'=>'1234', 'Content-Type' => 'text/plain'}, ['TEST']] })
|
71
|
-
|
72
|
-
response = Rack::MockRequest.new(app).
|
73
|
-
post("/", 'HTTP_IF_NONE_MATCH' => '1234')
|
74
|
-
|
75
|
-
response.status.should.equal 200
|
76
|
-
response.body.should.equal 'TEST'
|
77
|
-
end
|
78
|
-
|
79
|
-
should "not affect non-200 requests" do
|
80
|
-
app = conditional_get(lambda { |env|
|
81
|
-
[302, {'Etag'=>'1234', 'Content-Type' => 'text/plain'}, ['TEST']] })
|
82
|
-
|
83
|
-
response = Rack::MockRequest.new(app).
|
84
|
-
get("/", 'HTTP_IF_NONE_MATCH' => '1234')
|
85
|
-
|
86
|
-
response.status.should.equal 302
|
87
|
-
response.body.should.equal 'TEST'
|
88
|
-
end
|
89
|
-
|
90
|
-
should "not affect requests with malformed HTTP_IF_NONE_MATCH" do
|
91
|
-
bad_timestamp = Time.now.strftime('%Y-%m-%d %H:%M:%S %z')
|
92
|
-
app = conditional_get(lambda { |env|
|
93
|
-
[200,{'Last-Modified'=>(Time.now - 3600).httpdate, 'Content-Type' => 'text/plain'}, ['TEST']] })
|
94
|
-
|
95
|
-
response = Rack::MockRequest.new(app).
|
96
|
-
get("/", 'HTTP_IF_MODIFIED_SINCE' => bad_timestamp)
|
97
|
-
|
98
|
-
response.status.should.equal 200
|
99
|
-
response.body.should.equal 'TEST'
|
100
|
-
end
|
101
|
-
|
102
|
-
end
|