actionpack 6.0.3 → 6.1.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of actionpack might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.md +260 -215
- data/MIT-LICENSE +1 -1
- data/lib/abstract_controller.rb +1 -0
- data/lib/abstract_controller/base.rb +35 -2
- data/lib/abstract_controller/callbacks.rb +2 -2
- data/lib/abstract_controller/helpers.rb +105 -90
- data/lib/abstract_controller/rendering.rb +9 -9
- data/lib/abstract_controller/translation.rb +8 -2
- data/lib/action_controller.rb +2 -3
- data/lib/action_controller/api.rb +2 -2
- data/lib/action_controller/base.rb +4 -2
- data/lib/action_controller/caching.rb +0 -1
- data/lib/action_controller/log_subscriber.rb +3 -3
- data/lib/action_controller/metal.rb +2 -2
- data/lib/action_controller/metal/conditional_get.rb +10 -2
- data/lib/action_controller/metal/content_security_policy.rb +1 -1
- data/lib/action_controller/metal/cookies.rb +3 -1
- data/lib/action_controller/metal/data_streaming.rb +1 -1
- data/lib/action_controller/metal/etag_with_template_digest.rb +2 -4
- data/lib/action_controller/metal/exceptions.rb +33 -0
- data/lib/action_controller/metal/head.rb +7 -4
- data/lib/action_controller/metal/helpers.rb +11 -1
- data/lib/action_controller/metal/http_authentication.rb +4 -2
- data/lib/action_controller/metal/implicit_render.rb +1 -1
- data/lib/action_controller/metal/instrumentation.rb +11 -9
- data/lib/action_controller/metal/live.rb +1 -1
- data/lib/action_controller/metal/logging.rb +20 -0
- data/lib/action_controller/metal/mime_responds.rb +6 -2
- data/lib/action_controller/metal/parameter_encoding.rb +35 -4
- data/lib/action_controller/metal/params_wrapper.rb +14 -8
- data/lib/action_controller/metal/permissions_policy.rb +46 -0
- data/lib/action_controller/metal/redirecting.rb +1 -1
- data/lib/action_controller/metal/rendering.rb +6 -0
- data/lib/action_controller/metal/request_forgery_protection.rb +74 -30
- data/lib/action_controller/metal/rescue.rb +1 -1
- data/lib/action_controller/metal/strong_parameters.rb +107 -15
- data/lib/action_controller/renderer.rb +24 -13
- data/lib/action_controller/test_case.rb +62 -56
- data/lib/action_dispatch.rb +3 -2
- data/lib/action_dispatch/http/cache.rb +12 -10
- data/lib/action_dispatch/http/content_disposition.rb +2 -2
- data/lib/action_dispatch/http/content_security_policy.rb +5 -1
- data/lib/action_dispatch/http/filter_parameters.rb +1 -1
- data/lib/action_dispatch/http/filter_redirect.rb +1 -1
- data/lib/action_dispatch/http/headers.rb +3 -2
- data/lib/action_dispatch/http/mime_negotiation.rb +20 -8
- data/lib/action_dispatch/http/mime_type.rb +28 -15
- data/lib/action_dispatch/http/parameters.rb +1 -19
- data/lib/action_dispatch/http/permissions_policy.rb +173 -0
- data/lib/action_dispatch/http/request.rb +26 -8
- data/lib/action_dispatch/http/response.rb +17 -16
- data/lib/action_dispatch/http/url.rb +3 -2
- data/lib/action_dispatch/journey.rb +0 -2
- data/lib/action_dispatch/journey/formatter.rb +53 -28
- data/lib/action_dispatch/journey/gtg/builder.rb +22 -36
- data/lib/action_dispatch/journey/gtg/simulator.rb +8 -7
- data/lib/action_dispatch/journey/gtg/transition_table.rb +6 -4
- data/lib/action_dispatch/journey/nfa/dot.rb +0 -11
- data/lib/action_dispatch/journey/nodes/node.rb +4 -3
- data/lib/action_dispatch/journey/parser.rb +13 -13
- data/lib/action_dispatch/journey/parser.y +1 -1
- data/lib/action_dispatch/journey/path/pattern.rb +13 -18
- data/lib/action_dispatch/journey/route.rb +7 -18
- data/lib/action_dispatch/journey/router.rb +26 -30
- data/lib/action_dispatch/journey/router/utils.rb +6 -4
- data/lib/action_dispatch/middleware/actionable_exceptions.rb +9 -2
- data/lib/action_dispatch/middleware/cookies.rb +74 -33
- data/lib/action_dispatch/middleware/debug_exceptions.rb +10 -17
- data/lib/action_dispatch/middleware/debug_view.rb +1 -1
- data/lib/action_dispatch/middleware/exception_wrapper.rb +29 -17
- data/lib/action_dispatch/middleware/host_authorization.rb +25 -5
- data/lib/action_dispatch/middleware/public_exceptions.rb +1 -1
- data/lib/action_dispatch/middleware/remote_ip.rb +5 -4
- data/lib/action_dispatch/middleware/request_id.rb +4 -5
- data/lib/action_dispatch/middleware/session/abstract_store.rb +2 -2
- data/lib/action_dispatch/middleware/session/cookie_store.rb +2 -2
- data/lib/action_dispatch/middleware/ssl.rb +9 -6
- data/lib/action_dispatch/middleware/stack.rb +18 -0
- data/lib/action_dispatch/middleware/static.rb +154 -93
- data/lib/action_dispatch/middleware/templates/rescues/_message_and_suggestions.html.erb +22 -0
- data/lib/action_dispatch/middleware/templates/rescues/diagnostics.html.erb +2 -5
- data/lib/action_dispatch/middleware/templates/rescues/invalid_statement.html.erb +2 -2
- data/lib/action_dispatch/middleware/templates/rescues/invalid_statement.text.erb +2 -2
- data/lib/action_dispatch/middleware/templates/rescues/layout.erb +100 -8
- data/lib/action_dispatch/middleware/templates/rescues/unknown_action.html.erb +1 -1
- data/lib/action_dispatch/middleware/templates/routes/_table.html.erb +12 -1
- data/lib/action_dispatch/railtie.rb +3 -2
- data/lib/action_dispatch/request/session.rb +2 -8
- data/lib/action_dispatch/request/utils.rb +26 -2
- data/lib/action_dispatch/routing/inspector.rb +8 -7
- data/lib/action_dispatch/routing/mapper.rb +102 -71
- data/lib/action_dispatch/routing/polymorphic_routes.rb +12 -11
- data/lib/action_dispatch/routing/redirection.rb +3 -3
- data/lib/action_dispatch/routing/route_set.rb +49 -41
- data/lib/action_dispatch/routing/url_for.rb +1 -0
- data/lib/action_dispatch/system_test_case.rb +29 -24
- data/lib/action_dispatch/system_testing/browser.rb +33 -27
- data/lib/action_dispatch/system_testing/driver.rb +6 -7
- data/lib/action_dispatch/system_testing/test_helpers/screenshot_helper.rb +47 -6
- data/lib/action_dispatch/system_testing/test_helpers/setup_and_teardown.rb +4 -7
- data/lib/action_dispatch/testing/assertions.rb +1 -1
- data/lib/action_dispatch/testing/assertions/response.rb +2 -4
- data/lib/action_dispatch/testing/assertions/routing.rb +5 -5
- data/lib/action_dispatch/testing/integration.rb +38 -27
- data/lib/action_dispatch/testing/test_process.rb +29 -4
- data/lib/action_dispatch/testing/test_request.rb +3 -3
- data/lib/action_pack.rb +1 -1
- data/lib/action_pack/gem_version.rb +2 -2
- metadata +18 -19
- data/lib/action_controller/metal/force_ssl.rb +0 -58
- data/lib/action_dispatch/http/parameter_filter.rb +0 -12
- data/lib/action_dispatch/journey/nfa/builder.rb +0 -78
- data/lib/action_dispatch/journey/nfa/simulator.rb +0 -47
- data/lib/action_dispatch/journey/nfa/transition_table.rb +0 -119
@@ -13,45 +13,44 @@ module ActionDispatch
|
|
13
13
|
def initialize(root)
|
14
14
|
@root = root
|
15
15
|
@ast = Nodes::Cat.new root, DUMMY
|
16
|
-
@followpos =
|
16
|
+
@followpos = build_followpos
|
17
17
|
end
|
18
18
|
|
19
19
|
def transition_table
|
20
20
|
dtrans = TransitionTable.new
|
21
|
-
marked = {}
|
22
|
-
state_id = Hash.new { |h, k| h[k] = h.length }
|
21
|
+
marked = {}.compare_by_identity
|
22
|
+
state_id = Hash.new { |h, k| h[k] = h.length }.compare_by_identity
|
23
|
+
dstates = [firstpos(root)]
|
23
24
|
|
24
|
-
start = firstpos(root)
|
25
|
-
dstates = [start]
|
26
25
|
until dstates.empty?
|
27
26
|
s = dstates.shift
|
28
27
|
next if marked[s]
|
29
28
|
marked[s] = true # mark s
|
30
29
|
|
31
30
|
s.group_by { |state| symbol(state) }.each do |sym, ps|
|
32
|
-
u = ps.flat_map { |l| followpos
|
31
|
+
u = ps.flat_map { |l| @followpos[l] }
|
33
32
|
next if u.empty?
|
34
33
|
|
35
|
-
|
36
|
-
from = state_id[s]
|
37
|
-
to = state_id[Object.new]
|
38
|
-
dtrans[from, to] = sym
|
34
|
+
from = state_id[s]
|
39
35
|
|
36
|
+
if u.all? { |pos| pos == DUMMY }
|
37
|
+
to = state_id[Object.new]
|
38
|
+
dtrans[from, to] = sym
|
40
39
|
dtrans.add_accepting(to)
|
40
|
+
|
41
41
|
ps.each { |state| dtrans.add_memo(to, state.memo) }
|
42
42
|
else
|
43
|
-
|
43
|
+
to = state_id[u]
|
44
|
+
dtrans[from, to] = sym
|
44
45
|
|
45
46
|
if u.include?(DUMMY)
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
dtrans.add_memo(to, accepting_state.memo)
|
52
|
-
}
|
47
|
+
ps.each do |state|
|
48
|
+
if @followpos[state].include?(DUMMY)
|
49
|
+
dtrans.add_memo(to, state.memo)
|
50
|
+
end
|
51
|
+
end
|
53
52
|
|
54
|
-
dtrans.add_accepting(
|
53
|
+
dtrans.add_accepting(to)
|
55
54
|
end
|
56
55
|
end
|
57
56
|
|
@@ -92,7 +91,7 @@ module ActionDispatch
|
|
92
91
|
firstpos(node.left)
|
93
92
|
end
|
94
93
|
when Nodes::Or
|
95
|
-
node.children.flat_map { |c| firstpos(c) }.uniq
|
94
|
+
node.children.flat_map { |c| firstpos(c) }.tap(&:uniq!)
|
96
95
|
when Nodes::Unary
|
97
96
|
firstpos(node.left)
|
98
97
|
when Nodes::Terminal
|
@@ -107,7 +106,7 @@ module ActionDispatch
|
|
107
106
|
when Nodes::Star
|
108
107
|
firstpos(node.left)
|
109
108
|
when Nodes::Or
|
110
|
-
node.children.flat_map { |c| lastpos(c) }.uniq
|
109
|
+
node.children.flat_map { |c| lastpos(c) }.tap(&:uniq!)
|
111
110
|
when Nodes::Cat
|
112
111
|
if nullable?(node.right)
|
113
112
|
lastpos(node.left) | lastpos(node.right)
|
@@ -123,17 +122,9 @@ module ActionDispatch
|
|
123
122
|
end
|
124
123
|
end
|
125
124
|
|
126
|
-
def followpos(node)
|
127
|
-
followpos_table[node]
|
128
|
-
end
|
129
|
-
|
130
125
|
private
|
131
|
-
def followpos_table
|
132
|
-
@followpos ||= build_followpos
|
133
|
-
end
|
134
|
-
|
135
126
|
def build_followpos
|
136
|
-
table = Hash.new { |h, k| h[k] = [] }
|
127
|
+
table = Hash.new { |h, k| h[k] = [] }.compare_by_identity
|
137
128
|
@ast.each do |n|
|
138
129
|
case n
|
139
130
|
when Nodes::Cat
|
@@ -150,12 +141,7 @@ module ActionDispatch
|
|
150
141
|
end
|
151
142
|
|
152
143
|
def symbol(edge)
|
153
|
-
|
154
|
-
when Journey::Nodes::Symbol
|
155
|
-
edge.regexp
|
156
|
-
else
|
157
|
-
edge.left
|
158
|
-
end
|
144
|
+
edge.symbol? ? edge.regexp : edge.left
|
159
145
|
end
|
160
146
|
end
|
161
147
|
end
|
@@ -14,6 +14,8 @@ module ActionDispatch
|
|
14
14
|
end
|
15
15
|
|
16
16
|
class Simulator # :nodoc:
|
17
|
+
INITIAL_STATE = [0].freeze
|
18
|
+
|
17
19
|
attr_reader :tt
|
18
20
|
|
19
21
|
def initialize(transition_table)
|
@@ -22,18 +24,17 @@ module ActionDispatch
|
|
22
24
|
|
23
25
|
def memos(string)
|
24
26
|
input = StringScanner.new(string)
|
25
|
-
state =
|
27
|
+
state = INITIAL_STATE
|
28
|
+
|
26
29
|
while sym = input.scan(%r([/.?]|[^/.?]+))
|
27
30
|
state = tt.move(state, sym)
|
28
31
|
end
|
29
32
|
|
30
|
-
acceptance_states = state.
|
31
|
-
tt.accepting?
|
32
|
-
|
33
|
-
|
34
|
-
return yield if acceptance_states.empty?
|
33
|
+
acceptance_states = state.each_with_object([]) do |s, memos|
|
34
|
+
memos.concat(tt.memo(s)) if tt.accepting?(s)
|
35
|
+
end
|
35
36
|
|
36
|
-
acceptance_states.
|
37
|
+
acceptance_states.empty? ? yield : acceptance_states
|
37
38
|
end
|
38
39
|
end
|
39
40
|
end
|
@@ -45,16 +45,18 @@ module ActionDispatch
|
|
45
45
|
return [] if t.empty?
|
46
46
|
|
47
47
|
regexps = []
|
48
|
+
strings = []
|
48
49
|
|
49
|
-
t.
|
50
|
+
t.each { |s|
|
50
51
|
if states = @regexp_states[s]
|
51
|
-
|
52
|
+
states.each { |re, v| regexps << v if re.match?(a) && !v.nil? }
|
52
53
|
end
|
53
54
|
|
54
55
|
if states = @string_states[s]
|
55
|
-
states[a]
|
56
|
+
strings << states[a] unless states[a].nil?
|
56
57
|
end
|
57
|
-
}
|
58
|
+
}
|
59
|
+
strings.concat regexps
|
58
60
|
end
|
59
61
|
|
60
62
|
def as_json(options = nil)
|
@@ -9,17 +9,6 @@ module ActionDispatch
|
|
9
9
|
" #{from} -> #{to} [label=\"#{sym || 'ε'}\"];"
|
10
10
|
}
|
11
11
|
|
12
|
-
# memo_nodes = memos.values.flatten.map { |n|
|
13
|
-
# label = n
|
14
|
-
# if Journey::Route === n
|
15
|
-
# label = "#{n.verb.source} #{n.path.spec}"
|
16
|
-
# end
|
17
|
-
# " #{n.object_id} [label=\"#{label}\", shape=box];"
|
18
|
-
# }
|
19
|
-
# memo_edges = memos.flat_map { |k, memos|
|
20
|
-
# (memos || []).map { |v| " #{k} -> #{v.object_id};" }
|
21
|
-
# }.uniq
|
22
|
-
|
23
12
|
<<-eodot
|
24
13
|
digraph nfa {
|
25
14
|
rankdir=LR;
|
@@ -79,9 +79,10 @@ module ActionDispatch
|
|
79
79
|
attr_reader :name
|
80
80
|
|
81
81
|
DEFAULT_EXP = /[^\.\/\?]+/
|
82
|
-
|
83
|
-
|
84
|
-
|
82
|
+
GREEDY_EXP = /(.+)/
|
83
|
+
def initialize(left, regexp = DEFAULT_EXP)
|
84
|
+
super(left)
|
85
|
+
@regexp = regexp
|
85
86
|
@name = -left.tr("*:", "")
|
86
87
|
end
|
87
88
|
|
@@ -1,6 +1,6 @@
|
|
1
1
|
#
|
2
2
|
# DO NOT MODIFY!!!!
|
3
|
-
# This file is automatically generated by Racc 1.4.
|
3
|
+
# This file is automatically generated by Racc 1.4.16
|
4
4
|
# from Racc grammar file "".
|
5
5
|
#
|
6
6
|
|
@@ -135,11 +135,11 @@ Racc_debug_parser = false
|
|
135
135
|
# reduce 0 omitted
|
136
136
|
|
137
137
|
def _reduce_1(val, _values)
|
138
|
-
Cat.new(val.first, val.last)
|
138
|
+
Cat.new(val.first, val.last)
|
139
139
|
end
|
140
140
|
|
141
141
|
def _reduce_2(val, _values)
|
142
|
-
val.first
|
142
|
+
val.first
|
143
143
|
end
|
144
144
|
|
145
145
|
# reduce 3 omitted
|
@@ -151,19 +151,19 @@ end
|
|
151
151
|
# reduce 6 omitted
|
152
152
|
|
153
153
|
def _reduce_7(val, _values)
|
154
|
-
Group.new(val[1])
|
154
|
+
Group.new(val[1])
|
155
155
|
end
|
156
156
|
|
157
157
|
def _reduce_8(val, _values)
|
158
|
-
Or.new([val.first, val.last])
|
158
|
+
Or.new([val.first, val.last])
|
159
159
|
end
|
160
160
|
|
161
161
|
def _reduce_9(val, _values)
|
162
|
-
Or.new([val.first, val.last])
|
162
|
+
Or.new([val.first, val.last])
|
163
163
|
end
|
164
164
|
|
165
165
|
def _reduce_10(val, _values)
|
166
|
-
Star.new(Symbol.new(val.last))
|
166
|
+
Star.new(Symbol.new(val.last, Symbol::GREEDY_EXP))
|
167
167
|
end
|
168
168
|
|
169
169
|
# reduce 11 omitted
|
@@ -175,19 +175,19 @@ end
|
|
175
175
|
# reduce 14 omitted
|
176
176
|
|
177
177
|
def _reduce_15(val, _values)
|
178
|
-
Slash.new(val.first)
|
178
|
+
Slash.new(val.first)
|
179
179
|
end
|
180
180
|
|
181
181
|
def _reduce_16(val, _values)
|
182
|
-
Symbol.new(val.first)
|
182
|
+
Symbol.new(val.first)
|
183
183
|
end
|
184
184
|
|
185
185
|
def _reduce_17(val, _values)
|
186
|
-
Literal.new(val.first)
|
186
|
+
Literal.new(val.first)
|
187
187
|
end
|
188
188
|
|
189
189
|
def _reduce_18(val, _values)
|
190
|
-
Dot.new(val.first)
|
190
|
+
Dot.new(val.first)
|
191
191
|
end
|
192
192
|
|
193
193
|
def _reduce_none(val, _values)
|
@@ -195,5 +195,5 @@ def _reduce_none(val, _values)
|
|
195
195
|
end
|
196
196
|
|
197
197
|
end # class Parser
|
198
|
-
|
199
|
-
|
198
|
+
end # module Journey
|
199
|
+
end # module ActionDispatch
|
@@ -6,16 +6,6 @@ module ActionDispatch
|
|
6
6
|
class Pattern # :nodoc:
|
7
7
|
attr_reader :spec, :requirements, :anchored
|
8
8
|
|
9
|
-
def self.from_string(string)
|
10
|
-
build(string, {}, "/.?", true)
|
11
|
-
end
|
12
|
-
|
13
|
-
def self.build(path, requirements, separators, anchored)
|
14
|
-
parser = Journey::Parser.new
|
15
|
-
ast = parser.parse path
|
16
|
-
new ast, requirements, separators, anchored
|
17
|
-
end
|
18
|
-
|
19
9
|
def initialize(ast, requirements, separators, anchored)
|
20
10
|
@spec = ast
|
21
11
|
@requirements = requirements
|
@@ -46,11 +36,6 @@ module ActionDispatch
|
|
46
36
|
node.regexp = re if re
|
47
37
|
end
|
48
38
|
|
49
|
-
@spec.find_all(&:star?).each do |node|
|
50
|
-
node = node.left
|
51
|
-
node.regexp = @requirements[node.to_sym] || /(.+)/
|
52
|
-
end
|
53
|
-
|
54
39
|
@spec
|
55
40
|
end
|
56
41
|
|
@@ -81,7 +66,7 @@ module ActionDispatch
|
|
81
66
|
end
|
82
67
|
|
83
68
|
def visit_CAT(node)
|
84
|
-
|
69
|
+
"#{visit(node.left)}#{visit(node.right)}"
|
85
70
|
end
|
86
71
|
|
87
72
|
def visit_SYMBOL(node)
|
@@ -107,8 +92,8 @@ module ActionDispatch
|
|
107
92
|
end
|
108
93
|
|
109
94
|
def visit_STAR(node)
|
110
|
-
re = @matchers[node.left.to_sym]
|
111
|
-
"(#{re})"
|
95
|
+
re = @matchers[node.left.to_sym]
|
96
|
+
re ? "(#{re})" : "(.+)"
|
112
97
|
end
|
113
98
|
|
114
99
|
def visit_OR(node)
|
@@ -165,6 +150,10 @@ module ActionDispatch
|
|
165
150
|
end
|
166
151
|
alias :=~ :match
|
167
152
|
|
153
|
+
def match?(other)
|
154
|
+
to_regexp.match?(other)
|
155
|
+
end
|
156
|
+
|
168
157
|
def source
|
169
158
|
to_regexp.source
|
170
159
|
end
|
@@ -173,6 +162,12 @@ module ActionDispatch
|
|
173
162
|
@re ||= regexp_visitor.new(@separators, @requirements).accept spec
|
174
163
|
end
|
175
164
|
|
165
|
+
def requirements_for_missing_keys_check
|
166
|
+
@requirements_for_missing_keys_check ||= requirements.transform_values do |regex|
|
167
|
+
/\A#{regex}\Z/
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
176
171
|
private
|
177
172
|
def regexp_visitor
|
178
173
|
@anchored ? AnchoredRegexp : UnanchoredRegexp
|
@@ -13,6 +13,7 @@ module ActionDispatch
|
|
13
13
|
VERBS = %w{ DELETE GET HEAD OPTIONS LINK PATCH POST PUT TRACE UNLINK }
|
14
14
|
VERBS.each do |v|
|
15
15
|
class_eval <<-eoc, __FILE__, __LINE__ + 1
|
16
|
+
# frozen_string_literal: true
|
16
17
|
class #{v}
|
17
18
|
def self.verb; name.split("::").last; end
|
18
19
|
def self.call(req); req.#{v.downcase}?; end
|
@@ -27,7 +28,7 @@ module ActionDispatch
|
|
27
28
|
@verb = verb
|
28
29
|
end
|
29
30
|
|
30
|
-
def call(request); @verb
|
31
|
+
def call(request); @verb == request.request_method; end
|
31
32
|
end
|
32
33
|
|
33
34
|
class All
|
@@ -49,15 +50,10 @@ module ActionDispatch
|
|
49
50
|
end
|
50
51
|
end
|
51
52
|
|
52
|
-
def self.build(name, app, path, constraints, required_defaults, defaults)
|
53
|
-
request_method_match = verb_matcher(constraints.delete(:request_method))
|
54
|
-
new name, app, path, constraints, required_defaults, defaults, request_method_match, 0, {}
|
55
|
-
end
|
56
|
-
|
57
53
|
##
|
58
54
|
# +path+ is a path constraint.
|
59
55
|
# +constraints+ is a hash of constraints to be applied to this route.
|
60
|
-
def initialize(name
|
56
|
+
def initialize(name:, app: nil, path:, constraints: {}, required_defaults: [], defaults: {}, request_method_match: nil, precedence: 0, scope_options: {}, internal: false)
|
61
57
|
@name = name
|
62
58
|
@app = app
|
63
59
|
@path = path
|
@@ -92,7 +88,7 @@ module ActionDispatch
|
|
92
88
|
end
|
93
89
|
end
|
94
90
|
|
95
|
-
# Needed for `rails routes`. Picks up succinctly defined requirements
|
91
|
+
# Needed for `bin/rails routes`. Picks up succinctly defined requirements
|
96
92
|
# for a route, for example route
|
97
93
|
#
|
98
94
|
# get 'photo/:id', :controller => 'photos', :action => 'show',
|
@@ -115,18 +111,11 @@ module ActionDispatch
|
|
115
111
|
end
|
116
112
|
|
117
113
|
def score(supplied_keys)
|
118
|
-
|
119
|
-
|
120
|
-
required_keys.each do |k|
|
114
|
+
path.required_names.each do |k|
|
121
115
|
return -1 unless supplied_keys.include?(k)
|
122
116
|
end
|
123
117
|
|
124
|
-
|
125
|
-
path.names.each do |k|
|
126
|
-
score += 1 if supplied_keys.include?(k)
|
127
|
-
end
|
128
|
-
|
129
|
-
score + (required_defaults.length * 2)
|
118
|
+
(required_defaults.length * 2) + path.names.count { |k| supplied_keys.include?(k) }
|
130
119
|
end
|
131
120
|
|
132
121
|
def parts
|
@@ -153,7 +142,7 @@ module ActionDispatch
|
|
153
142
|
end
|
154
143
|
|
155
144
|
def glob?
|
156
|
-
|
145
|
+
path.spec.any?(Nodes::Star)
|
157
146
|
end
|
158
147
|
|
159
148
|
def dispatcher?
|
@@ -40,11 +40,12 @@ module ActionDispatch
|
|
40
40
|
req.path_info = "/" + req.path_info unless req.path_info.start_with? "/"
|
41
41
|
end
|
42
42
|
|
43
|
-
|
44
|
-
|
43
|
+
tmp_params = set_params.merge route.defaults
|
44
|
+
parameters.each_pair { |key, val|
|
45
|
+
tmp_params[key] = val.force_encoding(::Encoding::UTF_8)
|
45
46
|
}
|
46
47
|
|
47
|
-
req.path_parameters =
|
48
|
+
req.path_parameters = tmp_params
|
48
49
|
|
49
50
|
status, headers, body = route.app.serve(req)
|
50
51
|
|
@@ -65,7 +66,8 @@ module ActionDispatch
|
|
65
66
|
find_routes(rails_req).each do |match, parameters, route|
|
66
67
|
unless route.path.anchored
|
67
68
|
rails_req.script_name = match.to_s
|
68
|
-
rails_req.path_info = match.post_match
|
69
|
+
rails_req.path_info = match.post_match
|
70
|
+
rails_req.path_info = "/" + rails_req.path_info unless rails_req.path_info.start_with? "/"
|
69
71
|
end
|
70
72
|
|
71
73
|
parameters = route.defaults.merge parameters
|
@@ -105,23 +107,24 @@ module ActionDispatch
|
|
105
107
|
end
|
106
108
|
|
107
109
|
def find_routes(req)
|
108
|
-
|
109
|
-
|
110
|
+
path_info = req.path_info
|
111
|
+
routes = filter_routes(path_info).concat custom_routes.find_all { |r|
|
112
|
+
r.path.match?(path_info)
|
110
113
|
}
|
111
114
|
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
end
|
115
|
+
if req.head?
|
116
|
+
routes = match_head_routes(routes, req)
|
117
|
+
else
|
118
|
+
routes.select! { |r| r.matches?(req) }
|
119
|
+
end
|
118
120
|
|
119
121
|
routes.sort_by!(&:precedence)
|
120
122
|
|
121
123
|
routes.map! { |r|
|
122
|
-
match_data = r.path.match(
|
124
|
+
match_data = r.path.match(path_info)
|
123
125
|
path_parameters = {}
|
124
|
-
match_data.names.
|
126
|
+
match_data.names.each_with_index { |name, i|
|
127
|
+
val = match_data[i + 1]
|
125
128
|
path_parameters[name.to_sym] = Utils.unescape_uri(val) if val
|
126
129
|
}
|
127
130
|
[match_data, path_parameters, r]
|
@@ -129,24 +132,17 @@ module ActionDispatch
|
|
129
132
|
end
|
130
133
|
|
131
134
|
def match_head_routes(routes, req)
|
132
|
-
|
133
|
-
head_routes
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
end
|
142
|
-
else
|
143
|
-
head_routes
|
135
|
+
head_routes = routes.select { |r| r.requires_matching_verb? && r.matches?(req) }
|
136
|
+
return head_routes unless head_routes.empty?
|
137
|
+
|
138
|
+
begin
|
139
|
+
req.request_method = "GET"
|
140
|
+
routes.select! { |r| r.matches?(req) }
|
141
|
+
routes
|
142
|
+
ensure
|
143
|
+
req.request_method = "HEAD"
|
144
144
|
end
|
145
145
|
end
|
146
|
-
|
147
|
-
def match_routes(routes, req)
|
148
|
-
routes.select { |r| r.matches?(req) }
|
149
|
-
end
|
150
146
|
end
|
151
147
|
end
|
152
148
|
end
|