scorched 0.16 → 0.17
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.
- checksums.yaml +4 -4
- data/CHANGES.md +5 -0
- data/lib/scorched/controller.rb +17 -12
- data/lib/scorched/request.rb +3 -2
- data/lib/scorched/version.rb +1 -1
- data/spec/controller_spec.rb +75 -26
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5ad267343b4c7040dda32f6c394418bf9494dbcf
|
4
|
+
data.tar.gz: e8161cbafa5becf64f73ee970ac247a2ed43ef5f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d8184c8ba998ffc82d2292b089fccbb0ce60e9e6c89e35679b0e8a14121ff3da46ad338cb33296b0139a98ba4fe226228d83387f34f1f424567f8620c26a1278
|
7
|
+
data.tar.gz: 723fd6f62103871197a99b39912677ebff7c4bc77d1e3cf707efc842e948da8c79aa4c8806cefe0cdc88d843c6aa9df89ea4e804bb54cf5e54f0c786606db194
|
data/CHANGES.md
CHANGED
@@ -1,6 +1,11 @@
|
|
1
1
|
Changelog
|
2
2
|
=========
|
3
3
|
|
4
|
+
### v0.17
|
5
|
+
* Fixes an issue introduced in v0.16 where joining `SCRIPT_NAME` and `PATH_INFO` would sometimes produce a path with two forward slashes, and a related issue where `PATH_INFO` would sometimes be missing a leading forward slash when it should have had one.
|
6
|
+
* Mappings are now sorted by the best matching `media type` in addition to the existing logic that included definition order and priority. This required that mappings be sorted at request-time rather than at the time they're mapped. Note, because of limitations of `rack-accept`, this doesn't completely respect the HTTP spec when it comes to prioritising which media type to serve for a given request. Full support for the HTTP spec is intended for a future release.
|
7
|
+
* File path references to views are now joined to the view directory using #expand_path. This allows views to be specified with an absolute path (effectively ignoring the view directory), and better support for relative paths.
|
8
|
+
|
4
9
|
### v0.16
|
5
10
|
* A copy of the Rack env hash is now handed off to sub-controllers and other Rack-callable objects, with `PATH_INFO` and `SCRIPT_NAME` now set to appropriate values, bring Scorched inline with the Rack specification. This differs from the original behaviour which was to just forward on the original env hash unmodified.
|
6
11
|
* URL helper method `absolute` and `url` now use the new env property `scorched.root_path` as their base path, rather than `SCRIPT_NAME`.
|
data/lib/scorched/controller.rb
CHANGED
@@ -72,7 +72,7 @@ module Scorched
|
|
72
72
|
handled: proc { |bool|
|
73
73
|
@_handled == bool
|
74
74
|
},
|
75
|
-
proc: proc {
|
75
|
+
proc: proc { |blocks|
|
76
76
|
[*blocks].all? { |b| instance_exec(&b) }
|
77
77
|
},
|
78
78
|
user_agent: proc { |user_agent|
|
@@ -127,14 +127,12 @@ module Scorched
|
|
127
127
|
# Raises ArgumentError if required key values are not provided.
|
128
128
|
def map(pattern: nil, priority: nil, conditions: {}, target: nil)
|
129
129
|
raise ArgumentError, "Mapping must specify url pattern and target" unless pattern && target
|
130
|
-
|
131
|
-
insert_pos = mappings.take_while { |v| priority <= v[:priority] }.length
|
132
|
-
mappings.insert(insert_pos, {
|
130
|
+
mappings << {
|
133
131
|
pattern: compile(pattern),
|
134
|
-
priority: priority,
|
132
|
+
priority: priority.to_i,
|
135
133
|
conditions: conditions,
|
136
134
|
target: target
|
137
|
-
}
|
135
|
+
}
|
138
136
|
end
|
139
137
|
alias :<< :map
|
140
138
|
|
@@ -242,8 +240,6 @@ module Scorched
|
|
242
240
|
env
|
243
241
|
end
|
244
242
|
env['scorched.root_path'] ||= env['SCRIPT_NAME']
|
245
|
-
env['scorched.path_info'] ||= env['PATH_INFO']
|
246
|
-
env['scorched.script_name'] ||= env['SCRIPT_NAME']
|
247
243
|
@request = Request.new(env)
|
248
244
|
@response = Response.new
|
249
245
|
end
|
@@ -267,7 +263,16 @@ module Scorched
|
|
267
263
|
pass if config[:auto_pass] && eligable_matches.empty?
|
268
264
|
run_filters(:before)
|
269
265
|
begin
|
270
|
-
|
266
|
+
# Re-order matches based on media_type, ensuring priority and definition order are respected appropriately.
|
267
|
+
eligable_matches.each_with_index.sort_by { |m,idx|
|
268
|
+
[
|
269
|
+
m.mapping[:priority] || 0,
|
270
|
+
[*m.mapping[:conditions][:media_type]].map { |type|
|
271
|
+
env['rack-accept.request'].media_type.qvalue(type)
|
272
|
+
}.max || 0,
|
273
|
+
-idx
|
274
|
+
]
|
275
|
+
}.reverse.each { |match,|
|
271
276
|
request.breadcrumb << match
|
272
277
|
break if catch(:pass) {
|
273
278
|
target = match.mapping[:target]
|
@@ -276,8 +281,8 @@ module Scorched
|
|
276
281
|
instance_exec(&target)
|
277
282
|
else
|
278
283
|
target.call(env.merge(
|
279
|
-
'SCRIPT_NAME' => request.matched_path,
|
280
|
-
'PATH_INFO' => request.unmatched_path[match.path.length..-1]
|
284
|
+
'SCRIPT_NAME' => request.matched_path.chomp('/'),
|
285
|
+
'PATH_INFO' => request.unmatched_path[match.path.chomp('/').length..-1]
|
281
286
|
))
|
282
287
|
end
|
283
288
|
end
|
@@ -431,7 +436,7 @@ module Scorched
|
|
431
436
|
template = if Symbol === string_or_file
|
432
437
|
file = string_or_file.to_s
|
433
438
|
file = file << ".#{engine}" unless derived_engine
|
434
|
-
file = File.
|
439
|
+
file = File.expand_path(file, dir) if dir
|
435
440
|
# Tilt still has unresolved file encoding issues. Until that's fixed, we read the file manually.
|
436
441
|
template_cache.fetch(:file, tilt_engine, file, tilt_options) do
|
437
442
|
tilt_engine.new(file, nil, tilt_options)
|
data/lib/scorched/request.rb
CHANGED
@@ -5,7 +5,7 @@ module Scorched
|
|
5
5
|
# Keeps track of the matched URL portions and what object handled them. Useful for debugging and building
|
6
6
|
# breadcrumb navigation.
|
7
7
|
def breadcrumb
|
8
|
-
env['breadcrumb'] ||= []
|
8
|
+
env['scorched.breadcrumb'] ||= []
|
9
9
|
end
|
10
10
|
|
11
11
|
# Returns a hash of captured strings from the last matched URL in the breadcrumb.
|
@@ -25,7 +25,7 @@ module Scorched
|
|
25
25
|
|
26
26
|
# The remaining portion of the path that has yet to be matched by any mappings.
|
27
27
|
def unmatched_path
|
28
|
-
path = unescaped_path
|
28
|
+
path = unescaped_path
|
29
29
|
path[0,0] = '/' if (path[0] != '/' && matched_path[-1] == '/') || path.empty?
|
30
30
|
path
|
31
31
|
end
|
@@ -35,6 +35,7 @@ module Scorched
|
|
35
35
|
def unescaped_path
|
36
36
|
path_info.split(/(%25|%2F)/i).each_slice(2).map { |v, m| URI.unescape(v) << (m || '') }.join('')
|
37
37
|
end
|
38
|
+
|
38
39
|
private
|
39
40
|
|
40
41
|
# Joins an array of path segments ensuring a single forward slash seperates them.
|
data/lib/scorched/version.rb
CHANGED
data/spec/controller_spec.rb
CHANGED
@@ -159,14 +159,29 @@ module Scorched
|
|
159
159
|
end
|
160
160
|
|
161
161
|
it "matches routes based on priority, otherwise giving precedence to those defined first" do
|
162
|
-
|
163
|
-
app << {pattern: '/', target: proc { |env|
|
164
|
-
app << {pattern: '/', target: proc { |env|
|
165
|
-
app << {pattern: '/',
|
166
|
-
|
167
|
-
rt.get('/').body.should == '
|
168
|
-
|
169
|
-
|
162
|
+
order = []
|
163
|
+
app << {pattern: '/', priority: -1, target: proc { |env| order << 'four'; [200, {}, ['ok']] }}
|
164
|
+
app << {pattern: '/', target: proc { |env| order << 'two'; throw :pass }}
|
165
|
+
app << {pattern: '/', target: proc { |env| order << 'three'; throw :pass }}
|
166
|
+
app << {pattern: '/', priority: 2, target: proc { |env| order << 'one'; throw :pass }}
|
167
|
+
rt.get('/').body.should == 'ok'
|
168
|
+
order.should == %w{one two three four}
|
169
|
+
end
|
170
|
+
|
171
|
+
it "finds the best match for media type whilst respecting priority and definition order" do
|
172
|
+
app << {pattern: '/', conditions: {media_type: 'text/html'}, target: proc { |env|
|
173
|
+
[200, {}, ['text/html']]
|
174
|
+
}}
|
175
|
+
app << {pattern: '/', conditions: {media_type: 'application/json'}, target: proc { |env|
|
176
|
+
[200, {}, ['application/json']]
|
177
|
+
}}
|
178
|
+
app << {pattern: '/', priority: 1, target: proc { |env|
|
179
|
+
[200, {}, ['anything']]
|
180
|
+
}}
|
181
|
+
rt.get('/', media_type: 'application/json, */*;q=0.5').body.should == 'anything'
|
182
|
+
app.mappings.pop
|
183
|
+
rt.get('/', {}, 'HTTP_ACCEPT' => 'text/html;q=0.5, application/json').body.should == 'application/json'
|
184
|
+
rt.get('/', {}, 'HTTP_ACCEPT' => 'text/html, */*;q=0.5').body.should == 'text/html'
|
170
185
|
end
|
171
186
|
end
|
172
187
|
|
@@ -267,24 +282,37 @@ module Scorched
|
|
267
282
|
rt.get('/article/hello-world').body.should == 'hello-world'
|
268
283
|
end
|
269
284
|
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
rt.get('/article/name').body.should == '/article/name'
|
277
|
-
end
|
278
|
-
|
279
|
-
it "propagates correclty mangles escaped PATH_INFO before passing to sub-controller" do
|
280
|
-
app << {pattern: '/:category', target: Class.new(Scorched::Controller) do
|
281
|
-
get('/:name') {
|
285
|
+
it "copies env, modifying PATH_INFO and SCRIPT_NAME, before passing onto Rack-callable object" do
|
286
|
+
inner_env, outer_env = nil, nil
|
287
|
+
app.before { outer_env = env }
|
288
|
+
app.controller '/article' do
|
289
|
+
get '/name' do
|
290
|
+
inner_env = env
|
282
291
|
'hello'
|
283
|
-
|
284
|
-
end
|
285
|
-
|
292
|
+
end
|
293
|
+
end
|
294
|
+
|
295
|
+
resp = rt.get('/article/name')
|
286
296
|
resp.status.should == 200
|
287
|
-
|
297
|
+
outer_env['SCRIPT_NAME'].should == ''
|
298
|
+
outer_env['PATH_INFO'].should == '/article/name'
|
299
|
+
inner_env['SCRIPT_NAME'].should == '/article'
|
300
|
+
inner_env['PATH_INFO'].should == '/name'
|
301
|
+
end
|
302
|
+
|
303
|
+
example "PATH_INFO and SCRIPT_NAME joined, should produce a full path" do
|
304
|
+
app.controller '/article/' do
|
305
|
+
get '/name' do
|
306
|
+
env['SCRIPT_NAME'] + env['PATH_INFO']
|
307
|
+
end
|
308
|
+
end
|
309
|
+
app.controller '/blah' do
|
310
|
+
get '/baz' do
|
311
|
+
env['SCRIPT_NAME'] + env['PATH_INFO']
|
312
|
+
end
|
313
|
+
end
|
314
|
+
rt.get('/article/name').body.should == '/article/name'
|
315
|
+
rt.get('/blah/baz').body.should == '/blah/baz'
|
288
316
|
end
|
289
317
|
|
290
318
|
describe "controller helper" do
|
@@ -895,7 +923,7 @@ module Scorched
|
|
895
923
|
app.render_defaults.each { |k,v| app.render_defaults[k] = nil }
|
896
924
|
end
|
897
925
|
|
898
|
-
it "can render a file, relative to the
|
926
|
+
it "can render a file, relative to the working directory" do
|
899
927
|
app.get('/') do
|
900
928
|
render(:'views/main.erb').should == "3 for me"
|
901
929
|
end
|
@@ -909,12 +937,24 @@ module Scorched
|
|
909
937
|
rt.get('/')
|
910
938
|
end
|
911
939
|
|
912
|
-
it "takes an optional view directory, relative to the
|
940
|
+
it "takes an optional view directory, relative to the working directory" do
|
913
941
|
app.get('/') do
|
914
942
|
render(:'main.erb', dir: 'views').should == "3 for me"
|
915
943
|
end
|
916
944
|
rt.get('/')
|
917
945
|
end
|
946
|
+
|
947
|
+
it "properly respects absolute and relative file paths in respect to the view directory" do
|
948
|
+
app.get('/relative') do
|
949
|
+
render(:'../views/main.erb', dir: 'views')
|
950
|
+
end
|
951
|
+
app.get('/absolute') do
|
952
|
+
File.dirname(__FILE__)
|
953
|
+
render(:"#{File.dirname(__FILE__)}/views/main.erb", dir: 'views')
|
954
|
+
end
|
955
|
+
rt.get('/relative').body.should == "3 for me"
|
956
|
+
rt.get('/absolute').body.should == "3 for me"
|
957
|
+
end
|
918
958
|
|
919
959
|
it "takes an optional block to be yielded by the view" do
|
920
960
|
app.get('/') do
|
@@ -1014,6 +1054,15 @@ module Scorched
|
|
1014
1054
|
builder.to_app
|
1015
1055
|
end
|
1016
1056
|
|
1057
|
+
it "can determine the root path of the current Scorched application" do
|
1058
|
+
my_app.controller '/article' do
|
1059
|
+
get '/name' do
|
1060
|
+
env['scorched.root_path']
|
1061
|
+
end
|
1062
|
+
end
|
1063
|
+
rt.get('/myapp/article/name').body.should == '/myapp'
|
1064
|
+
end
|
1065
|
+
|
1017
1066
|
describe "url" do
|
1018
1067
|
it "returns the fully qualified URL" do
|
1019
1068
|
my_app.get('/') { url }
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: scorched
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: '0.
|
4
|
+
version: '0.17'
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tom Wardrop
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2013-
|
11
|
+
date: 2013-09-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rack
|