sinatra 0.9.0.3 → 0.9.0.4
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of sinatra might be problematic. Click here for more details.
- data/CHANGES +9 -0
- data/compat/compat_test.rb +12 -0
- data/lib/sinatra/base.rb +46 -27
- data/lib/sinatra/compat.rb +12 -1
- data/sinatra.gemspec +3 -2
- data/test/filter_test.rb +24 -0
- data/test/routing_test.rb +55 -1
- metadata +3 -2
data/CHANGES
CHANGED
@@ -1,3 +1,12 @@
|
|
1
|
+
= 0.9.0.4 / 2009-01-25
|
2
|
+
|
3
|
+
* Using halt with more than 1 args causes ArgumentError [#131]
|
4
|
+
* using halt in a before filter doesn't modify response [#127]
|
5
|
+
* Add deprecated Sinatra::EventContext to unbreak plugins [#130]
|
6
|
+
* Give access to GET/POST params in filters [#129]
|
7
|
+
* Preserve non-nested params in nested params hash [#117]
|
8
|
+
* Fix backtrace dump with Rack::Lint [#116]
|
9
|
+
|
1
10
|
= 0.9.0.3 / 2009-01-21
|
2
11
|
|
3
12
|
* Fall back on mongrel then webrick when thin not found. [#75]
|
data/lib/sinatra/base.rb
CHANGED
@@ -4,7 +4,7 @@ require 'rack'
|
|
4
4
|
require 'rack/builder'
|
5
5
|
|
6
6
|
module Sinatra
|
7
|
-
VERSION = '0.9.0.
|
7
|
+
VERSION = '0.9.0.4'
|
8
8
|
|
9
9
|
class Request < Rack::Request
|
10
10
|
def user_agent
|
@@ -311,7 +311,11 @@ module Sinatra
|
|
311
311
|
@request = Request.new(env)
|
312
312
|
@response = Response.new
|
313
313
|
@params = nil
|
314
|
-
|
314
|
+
|
315
|
+
invoke { dispatch! }
|
316
|
+
invoke { error_block!(response.status) }
|
317
|
+
|
318
|
+
@response.body = [] if @env['REQUEST_METHOD'] == 'HEAD'
|
315
319
|
@response.finish
|
316
320
|
end
|
317
321
|
|
@@ -320,7 +324,8 @@ module Sinatra
|
|
320
324
|
end
|
321
325
|
|
322
326
|
def halt(*response)
|
323
|
-
|
327
|
+
response = response.first if response.length == 1
|
328
|
+
throw :halt, response
|
324
329
|
end
|
325
330
|
|
326
331
|
def pass
|
@@ -328,19 +333,21 @@ module Sinatra
|
|
328
333
|
end
|
329
334
|
|
330
335
|
private
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
return unless res == :continue
|
335
|
-
end
|
336
|
+
# Run before filters and then locate and run a matching route.
|
337
|
+
def route!
|
338
|
+
@params = nested_params(@request.params)
|
336
339
|
|
340
|
+
# before filters
|
341
|
+
self.class.filters.each { |block| instance_eval(&block) }
|
342
|
+
|
343
|
+
# routes
|
337
344
|
if routes = self.class.routes[@request.request_method]
|
345
|
+
original_params = @params
|
338
346
|
path = @request.path_info
|
339
|
-
original_params = nested_params(@request.params)
|
340
347
|
|
341
|
-
routes.each do |pattern, keys, conditions,
|
342
|
-
if
|
343
|
-
values =
|
348
|
+
routes.each do |pattern, keys, conditions, block|
|
349
|
+
if match = pattern.match(path)
|
350
|
+
values = match.captures.map{|val| val && unescape(val) }
|
344
351
|
params =
|
345
352
|
if keys.any?
|
346
353
|
keys.zip(values).inject({}) do |hash,(k,v)|
|
@@ -358,14 +365,15 @@ module Sinatra
|
|
358
365
|
end
|
359
366
|
@params = original_params.merge(params)
|
360
367
|
|
361
|
-
catch(:pass)
|
368
|
+
catch(:pass) do
|
362
369
|
conditions.each { |cond|
|
363
370
|
throw :pass if instance_eval(&cond) == false }
|
364
|
-
|
365
|
-
|
371
|
+
throw :halt, instance_eval(&block)
|
372
|
+
end
|
366
373
|
end
|
367
374
|
end
|
368
375
|
end
|
376
|
+
|
369
377
|
raise NotFound
|
370
378
|
end
|
371
379
|
|
@@ -376,6 +384,8 @@ module Sinatra
|
|
376
384
|
splat = key.scan(/(^[^\[]+)|\[([^\]]+)\]/).flatten.compact
|
377
385
|
head, last = splat[0..-2], splat[-1]
|
378
386
|
head.inject(res){ |s,v| s[v] ||= indifferent_hash }[last] = val
|
387
|
+
else
|
388
|
+
res[key] = val
|
379
389
|
end
|
380
390
|
res
|
381
391
|
end
|
@@ -385,7 +395,8 @@ module Sinatra
|
|
385
395
|
Hash.new {|hash,key| hash[key.to_s] if Symbol === key }
|
386
396
|
end
|
387
397
|
|
388
|
-
|
398
|
+
# Run the block with 'throw :halt' support and apply result to the response.
|
399
|
+
def invoke(&block)
|
389
400
|
res = catch(:halt) { instance_eval(&block) }
|
390
401
|
return if res.nil?
|
391
402
|
|
@@ -417,30 +428,38 @@ module Sinatra
|
|
417
428
|
res
|
418
429
|
end
|
419
430
|
|
420
|
-
|
421
|
-
|
422
|
-
|
431
|
+
# Dispatch a request with error handling.
|
432
|
+
def dispatch!
|
433
|
+
route!
|
423
434
|
rescue NotFound => boom
|
424
435
|
@env['sinatra.error'] = boom
|
425
436
|
@response.status = 404
|
426
437
|
@response.body = ['<h1>Not Found</h1>']
|
427
|
-
|
428
|
-
|
438
|
+
error_block! boom.class, NotFound
|
439
|
+
|
429
440
|
rescue ::Exception => boom
|
430
441
|
@env['sinatra.error'] = boom
|
431
442
|
|
432
443
|
if options.dump_errors?
|
433
444
|
msg = ["#{boom.class} - #{boom.message}:", *boom.backtrace].join("\n ")
|
434
|
-
@env['rack.errors']
|
445
|
+
@env['rack.errors'].write msg
|
435
446
|
end
|
436
447
|
|
437
448
|
raise boom if options.raise_errors?
|
438
449
|
@response.status = 500
|
439
|
-
|
440
|
-
|
441
|
-
|
442
|
-
|
450
|
+
error_block! boom.class, Exception
|
451
|
+
end
|
452
|
+
|
453
|
+
# Find an custom error block for the key(s) specified.
|
454
|
+
def error_block!(*keys)
|
455
|
+
errmap = self.class.errors
|
456
|
+
keys.each do |key|
|
457
|
+
if block = errmap[key]
|
458
|
+
res = instance_eval(&block)
|
459
|
+
return res
|
460
|
+
end
|
443
461
|
end
|
462
|
+
nil
|
444
463
|
end
|
445
464
|
|
446
465
|
@routes = {}
|
@@ -570,7 +589,7 @@ module Sinatra
|
|
570
589
|
route('GET', path, opts, &block)
|
571
590
|
|
572
591
|
@conditions = conditions
|
573
|
-
|
592
|
+
route('HEAD', path, opts, &block)
|
574
593
|
end
|
575
594
|
|
576
595
|
def put(path, opts={}, &bk); route 'PUT', path, opts, &bk; end
|
data/lib/sinatra/compat.rb
CHANGED
@@ -51,6 +51,17 @@ module Sinatra
|
|
51
51
|
module Compat
|
52
52
|
end
|
53
53
|
|
54
|
+
# Make Sinatra::EventContext an alias for Sinatra::Default to unbreak plugins.
|
55
|
+
def self.const_missing(const_name)
|
56
|
+
if const_name == :EventContext
|
57
|
+
const_set :EventContext, Sinatra::Default
|
58
|
+
sinatra_warn 'Sinatra::EventContext is deprecated; use Sinatra::Default instead.'
|
59
|
+
Sinatra::Default
|
60
|
+
else
|
61
|
+
super
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
54
65
|
# The ServerError exception is deprecated. Any exception is considered an
|
55
66
|
# internal server error.
|
56
67
|
class ServerError < RuntimeError
|
@@ -107,7 +118,7 @@ module Sinatra
|
|
107
118
|
# Throwing halt with a Symbol and the to_result convention are
|
108
119
|
# deprecated. Override the invoke method to detect those types of return
|
109
120
|
# values.
|
110
|
-
def invoke(
|
121
|
+
def invoke(&block)
|
111
122
|
res = super
|
112
123
|
case
|
113
124
|
when res.kind_of?(Symbol)
|
data/sinatra.gemspec
CHANGED
@@ -3,8 +3,8 @@ Gem::Specification.new do |s|
|
|
3
3
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
4
4
|
|
5
5
|
s.name = 'sinatra'
|
6
|
-
s.version = '0.9.0.
|
7
|
-
s.date = '2009-01-
|
6
|
+
s.version = '0.9.0.4'
|
7
|
+
s.date = '2009-01-25'
|
8
8
|
|
9
9
|
s.description = "Classy web-development dressed in a DSL"
|
10
10
|
s.summary = "Classy web-development dressed in a DSL"
|
@@ -22,6 +22,7 @@ Gem::Specification.new do |s|
|
|
22
22
|
compat/app_test.rb
|
23
23
|
compat/application_test.rb
|
24
24
|
compat/builder_test.rb
|
25
|
+
compat/compat_test.rb
|
25
26
|
compat/custom_error_test.rb
|
26
27
|
compat/erb_test.rb
|
27
28
|
compat/events_test.rb
|
data/test/filter_test.rb
CHANGED
@@ -72,4 +72,28 @@ describe "Filters" do
|
|
72
72
|
assert ok?
|
73
73
|
assert_equal 'cool', body
|
74
74
|
end
|
75
|
+
|
76
|
+
it "does modify the response with halt" do
|
77
|
+
mock_app {
|
78
|
+
before { halt 302, 'Hi' }
|
79
|
+
get '/foo' do
|
80
|
+
"should not happen"
|
81
|
+
end
|
82
|
+
}
|
83
|
+
|
84
|
+
get '/foo'
|
85
|
+
assert_equal 302, response.status
|
86
|
+
assert_equal 'Hi', body
|
87
|
+
end
|
88
|
+
|
89
|
+
it "gives you access to params" do
|
90
|
+
mock_app {
|
91
|
+
before { @foo = params['foo'] }
|
92
|
+
get('/foo') { @foo }
|
93
|
+
}
|
94
|
+
|
95
|
+
get '/foo?foo=cool'
|
96
|
+
assert ok?
|
97
|
+
assert_equal 'cool', body
|
98
|
+
end
|
75
99
|
end
|
data/test/routing_test.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
require File.dirname(__FILE__) + '/helper'
|
2
2
|
|
3
3
|
describe "Routing" do
|
4
|
-
%w[get put post delete
|
4
|
+
%w[get put post delete].each do |verb|
|
5
5
|
it "defines #{verb.upcase} request handlers with #{verb}" do
|
6
6
|
mock_app {
|
7
7
|
send verb, '/hello' do
|
@@ -16,6 +16,21 @@ describe "Routing" do
|
|
16
16
|
end
|
17
17
|
end
|
18
18
|
|
19
|
+
it "defines HEAD request handlers with HEAD" do
|
20
|
+
mock_app {
|
21
|
+
head '/hello' do
|
22
|
+
response['X-Hello'] = 'World!'
|
23
|
+
'remove me'
|
24
|
+
end
|
25
|
+
}
|
26
|
+
|
27
|
+
request = Rack::MockRequest.new(@app)
|
28
|
+
response = request.request('HEAD', '/hello', {})
|
29
|
+
assert response.ok?
|
30
|
+
assert_equal 'World!', response['X-Hello']
|
31
|
+
assert_equal '', response.body
|
32
|
+
end
|
33
|
+
|
19
34
|
it "404s when no route satisfies the request" do
|
20
35
|
mock_app {
|
21
36
|
get('/foo') { }
|
@@ -176,6 +191,21 @@ describe "Routing" do
|
|
176
191
|
assert_equal 'looks good', body
|
177
192
|
end
|
178
193
|
|
194
|
+
it "preserves non-nested params" do
|
195
|
+
mock_app {
|
196
|
+
get '/foo' do
|
197
|
+
assert_equal "2", params["article_id"]
|
198
|
+
assert_equal "awesome", params['comment']['body']
|
199
|
+
assert_nil params['comment[body]']
|
200
|
+
'looks good'
|
201
|
+
end
|
202
|
+
}
|
203
|
+
|
204
|
+
get '/foo?article_id=2&comment[body]=awesome'
|
205
|
+
assert ok?
|
206
|
+
assert_equal 'looks good', body
|
207
|
+
end
|
208
|
+
|
179
209
|
it "supports paths that include spaces" do
|
180
210
|
mock_app {
|
181
211
|
get '/path with spaces' do
|
@@ -239,6 +269,30 @@ describe "Routing" do
|
|
239
269
|
assert_equal 'Hello World', body
|
240
270
|
end
|
241
271
|
|
272
|
+
it "halts with a response tuple" do
|
273
|
+
mock_app {
|
274
|
+
get '/' do
|
275
|
+
halt 295, {'Content-Type' => 'text/plain'}, 'Hello World'
|
276
|
+
end
|
277
|
+
}
|
278
|
+
|
279
|
+
get '/'
|
280
|
+
assert_equal 295, status
|
281
|
+
assert_equal 'text/plain', response['Content-Type']
|
282
|
+
assert_equal 'Hello World', body
|
283
|
+
end
|
284
|
+
|
285
|
+
it "halts with an array of strings" do
|
286
|
+
mock_app {
|
287
|
+
get '/' do
|
288
|
+
halt %w[Hello World How Are You]
|
289
|
+
end
|
290
|
+
}
|
291
|
+
|
292
|
+
get '/'
|
293
|
+
assert_equal 'HelloWorldHowAreYou', body
|
294
|
+
end
|
295
|
+
|
242
296
|
it "transitions to the next matching route on pass" do
|
243
297
|
mock_app {
|
244
298
|
get '/:foo' do
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sinatra
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.9.0.
|
4
|
+
version: 0.9.0.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Blake Mizerany
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-01-
|
12
|
+
date: 2009-01-25 00:00:00 -08:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -40,6 +40,7 @@ files:
|
|
40
40
|
- compat/app_test.rb
|
41
41
|
- compat/application_test.rb
|
42
42
|
- compat/builder_test.rb
|
43
|
+
- compat/compat_test.rb
|
43
44
|
- compat/custom_error_test.rb
|
44
45
|
- compat/erb_test.rb
|
45
46
|
- compat/events_test.rb
|