actionpack 5.2.4.4 → 6.1.1

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.

Files changed (155) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +264 -322
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +4 -3
  5. data/lib/abstract_controller.rb +1 -0
  6. data/lib/abstract_controller/base.rb +38 -4
  7. data/lib/abstract_controller/caching.rb +1 -1
  8. data/lib/abstract_controller/caching/fragments.rb +6 -22
  9. data/lib/abstract_controller/callbacks.rb +14 -2
  10. data/lib/abstract_controller/collector.rb +1 -2
  11. data/lib/abstract_controller/helpers.rb +106 -90
  12. data/lib/abstract_controller/railties/routes_helpers.rb +1 -1
  13. data/lib/abstract_controller/rendering.rb +9 -9
  14. data/lib/abstract_controller/translation.rb +11 -5
  15. data/lib/action_controller.rb +7 -4
  16. data/lib/action_controller/api.rb +4 -3
  17. data/lib/action_controller/base.rb +6 -9
  18. data/lib/action_controller/caching.rb +1 -3
  19. data/lib/action_controller/log_subscriber.rb +10 -7
  20. data/lib/action_controller/metal.rb +10 -8
  21. data/lib/action_controller/metal/basic_implicit_render.rb +1 -1
  22. data/lib/action_controller/metal/conditional_get.rb +19 -5
  23. data/lib/action_controller/metal/content_security_policy.rb +1 -2
  24. data/lib/action_controller/metal/cookies.rb +3 -1
  25. data/lib/action_controller/metal/data_streaming.rb +6 -7
  26. data/lib/action_controller/metal/default_headers.rb +17 -0
  27. data/lib/action_controller/metal/etag_with_template_digest.rb +3 -5
  28. data/lib/action_controller/metal/exceptions.rb +56 -2
  29. data/lib/action_controller/metal/flash.rb +5 -5
  30. data/lib/action_controller/metal/head.rb +7 -4
  31. data/lib/action_controller/metal/helpers.rb +14 -5
  32. data/lib/action_controller/metal/http_authentication.rb +24 -23
  33. data/lib/action_controller/metal/implicit_render.rb +5 -15
  34. data/lib/action_controller/metal/instrumentation.rb +13 -14
  35. data/lib/action_controller/metal/live.rb +30 -32
  36. data/lib/action_controller/metal/logging.rb +20 -0
  37. data/lib/action_controller/metal/mime_responds.rb +19 -4
  38. data/lib/action_controller/metal/parameter_encoding.rb +35 -4
  39. data/lib/action_controller/metal/params_wrapper.rb +31 -22
  40. data/lib/action_controller/metal/permissions_policy.rb +46 -0
  41. data/lib/action_controller/metal/redirecting.rb +6 -6
  42. data/lib/action_controller/metal/renderers.rb +4 -4
  43. data/lib/action_controller/metal/rendering.rb +8 -3
  44. data/lib/action_controller/metal/request_forgery_protection.rb +62 -34
  45. data/lib/action_controller/metal/rescue.rb +1 -1
  46. data/lib/action_controller/metal/streaming.rb +0 -1
  47. data/lib/action_controller/metal/strong_parameters.rb +167 -58
  48. data/lib/action_controller/metal/url_for.rb +1 -1
  49. data/lib/action_controller/railties/helpers.rb +1 -1
  50. data/lib/action_controller/renderer.rb +37 -13
  51. data/lib/action_controller/template_assertions.rb +1 -1
  52. data/lib/action_controller/test_case.rb +70 -65
  53. data/lib/action_dispatch.rb +9 -3
  54. data/lib/action_dispatch/http/cache.rb +26 -21
  55. data/lib/action_dispatch/http/content_disposition.rb +45 -0
  56. data/lib/action_dispatch/http/content_security_policy.rb +33 -19
  57. data/lib/action_dispatch/http/filter_parameters.rb +9 -8
  58. data/lib/action_dispatch/http/filter_redirect.rb +2 -3
  59. data/lib/action_dispatch/http/headers.rb +4 -4
  60. data/lib/action_dispatch/http/mime_negotiation.rb +26 -13
  61. data/lib/action_dispatch/http/mime_type.rb +42 -23
  62. data/lib/action_dispatch/http/parameters.rb +14 -23
  63. data/lib/action_dispatch/http/permissions_policy.rb +173 -0
  64. data/lib/action_dispatch/http/request.rb +45 -22
  65. data/lib/action_dispatch/http/response.rb +45 -25
  66. data/lib/action_dispatch/http/upload.rb +9 -1
  67. data/lib/action_dispatch/http/url.rb +82 -82
  68. data/lib/action_dispatch/journey.rb +0 -2
  69. data/lib/action_dispatch/journey/formatter.rb +54 -30
  70. data/lib/action_dispatch/journey/gtg/builder.rb +22 -37
  71. data/lib/action_dispatch/journey/gtg/simulator.rb +8 -7
  72. data/lib/action_dispatch/journey/gtg/transition_table.rb +6 -5
  73. data/lib/action_dispatch/journey/nfa/dot.rb +0 -11
  74. data/lib/action_dispatch/journey/nodes/node.rb +13 -11
  75. data/lib/action_dispatch/journey/parser.rb +13 -13
  76. data/lib/action_dispatch/journey/parser.y +1 -1
  77. data/lib/action_dispatch/journey/path/pattern.rb +19 -21
  78. data/lib/action_dispatch/journey/route.rb +10 -20
  79. data/lib/action_dispatch/journey/router.rb +26 -34
  80. data/lib/action_dispatch/journey/router/utils.rb +14 -12
  81. data/lib/action_dispatch/journey/routes.rb +0 -2
  82. data/lib/action_dispatch/journey/scanner.rb +10 -4
  83. data/lib/action_dispatch/journey/visitors.rb +1 -4
  84. data/lib/action_dispatch/middleware/actionable_exceptions.rb +46 -0
  85. data/lib/action_dispatch/middleware/callbacks.rb +2 -4
  86. data/lib/action_dispatch/middleware/cookies.rb +128 -109
  87. data/lib/action_dispatch/middleware/debug_exceptions.rb +43 -66
  88. data/lib/action_dispatch/middleware/debug_locks.rb +5 -5
  89. data/lib/action_dispatch/middleware/debug_view.rb +66 -0
  90. data/lib/action_dispatch/middleware/exception_wrapper.rb +75 -30
  91. data/lib/action_dispatch/middleware/flash.rb +1 -1
  92. data/lib/action_dispatch/middleware/host_authorization.rb +121 -0
  93. data/lib/action_dispatch/middleware/public_exceptions.rb +6 -3
  94. data/lib/action_dispatch/middleware/remote_ip.rb +14 -16
  95. data/lib/action_dispatch/middleware/request_id.rb +5 -6
  96. data/lib/action_dispatch/middleware/session/abstract_store.rb +2 -3
  97. data/lib/action_dispatch/middleware/session/cookie_store.rb +3 -9
  98. data/lib/action_dispatch/middleware/show_exceptions.rb +3 -2
  99. data/lib/action_dispatch/middleware/ssl.rb +20 -15
  100. data/lib/action_dispatch/middleware/stack.rb +56 -2
  101. data/lib/action_dispatch/middleware/static.rb +153 -93
  102. data/lib/action_dispatch/middleware/templates/rescues/_actions.html.erb +13 -0
  103. data/lib/action_dispatch/middleware/templates/rescues/_actions.text.erb +0 -0
  104. data/lib/action_dispatch/middleware/templates/rescues/_message_and_suggestions.html.erb +22 -0
  105. data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.html.erb +3 -1
  106. data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.text.erb +1 -1
  107. data/lib/action_dispatch/middleware/templates/rescues/_source.html.erb +4 -2
  108. data/lib/action_dispatch/middleware/templates/rescues/_trace.html.erb +45 -35
  109. data/lib/action_dispatch/middleware/templates/rescues/blocked_host.html.erb +7 -0
  110. data/lib/action_dispatch/middleware/templates/rescues/blocked_host.text.erb +5 -0
  111. data/lib/action_dispatch/middleware/templates/rescues/diagnostics.html.erb +23 -4
  112. data/lib/action_dispatch/middleware/templates/rescues/diagnostics.text.erb +1 -1
  113. data/lib/action_dispatch/middleware/templates/rescues/invalid_statement.html.erb +6 -3
  114. data/lib/action_dispatch/middleware/templates/rescues/invalid_statement.text.erb +3 -1
  115. data/lib/action_dispatch/middleware/templates/rescues/layout.erb +104 -8
  116. data/lib/action_dispatch/middleware/templates/rescues/missing_exact_template.html.erb +19 -0
  117. data/lib/action_dispatch/middleware/templates/rescues/missing_exact_template.text.erb +3 -0
  118. data/lib/action_dispatch/middleware/templates/rescues/missing_template.html.erb +2 -2
  119. data/lib/action_dispatch/middleware/templates/rescues/routing_error.html.erb +1 -1
  120. data/lib/action_dispatch/middleware/templates/rescues/template_error.html.erb +2 -2
  121. data/lib/action_dispatch/middleware/templates/rescues/unknown_action.html.erb +1 -1
  122. data/lib/action_dispatch/middleware/templates/routes/_table.html.erb +24 -1
  123. data/lib/action_dispatch/railtie.rb +8 -2
  124. data/lib/action_dispatch/request/session.rb +10 -9
  125. data/lib/action_dispatch/request/utils.rb +26 -2
  126. data/lib/action_dispatch/routing.rb +21 -20
  127. data/lib/action_dispatch/routing/inspector.rb +100 -52
  128. data/lib/action_dispatch/routing/mapper.rb +155 -103
  129. data/lib/action_dispatch/routing/polymorphic_routes.rb +13 -15
  130. data/lib/action_dispatch/routing/redirection.rb +3 -3
  131. data/lib/action_dispatch/routing/route_set.rb +71 -69
  132. data/lib/action_dispatch/routing/url_for.rb +2 -2
  133. data/lib/action_dispatch/system_test_case.rb +54 -11
  134. data/lib/action_dispatch/system_testing/browser.rb +53 -16
  135. data/lib/action_dispatch/system_testing/driver.rb +11 -3
  136. data/lib/action_dispatch/system_testing/test_helpers/screenshot_helper.rb +49 -7
  137. data/lib/action_dispatch/system_testing/test_helpers/setup_and_teardown.rb +8 -10
  138. data/lib/action_dispatch/testing/assertion_response.rb +0 -1
  139. data/lib/action_dispatch/testing/assertions.rb +1 -1
  140. data/lib/action_dispatch/testing/assertions/response.rb +4 -7
  141. data/lib/action_dispatch/testing/assertions/routing.rb +20 -8
  142. data/lib/action_dispatch/testing/integration.rb +61 -28
  143. data/lib/action_dispatch/testing/request_encoder.rb +2 -2
  144. data/lib/action_dispatch/testing/test_process.rb +29 -4
  145. data/lib/action_dispatch/testing/test_request.rb +3 -3
  146. data/lib/action_dispatch/testing/test_response.rb +4 -32
  147. data/lib/action_pack.rb +1 -1
  148. data/lib/action_pack/gem_version.rb +4 -4
  149. metadata +38 -26
  150. data/lib/action_controller/metal/force_ssl.rb +0 -99
  151. data/lib/action_dispatch/http/parameter_filter.rb +0 -86
  152. data/lib/action_dispatch/journey/nfa/builder.rb +0 -78
  153. data/lib/action_dispatch/journey/nfa/simulator.rb +0 -49
  154. data/lib/action_dispatch/journey/nfa/transition_table.rb +0 -120
  155. data/lib/action_dispatch/system_testing/test_helpers/undef_methods.rb +0 -26
@@ -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 = [0]
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.find_all { |s|
31
- tt.accepting? s
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.flat_map { |x| tt.memo(x) }.compact
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.map { |s|
50
+ t.each { |s|
50
51
  if states = @regexp_states[s]
51
- regexps.concat states.map { |re, v| re === a ? v : nil }
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
- }.compact.concat regexps
58
+ }
59
+ strings.concat regexps
58
60
  end
59
61
 
60
62
  def as_json(options = nil)
@@ -141,7 +143,6 @@ module ActionDispatch
141
143
  end
142
144
 
143
145
  private
144
-
145
146
  def states_hash_for(sym)
146
147
  case sym
147
148
  when String
@@ -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;
@@ -32,7 +32,7 @@ module ActionDispatch
32
32
  end
33
33
 
34
34
  def name
35
- left.tr "*:".freeze, "".freeze
35
+ -left.tr("*:", "")
36
36
  end
37
37
 
38
38
  def type
@@ -65,12 +65,12 @@ module ActionDispatch
65
65
  def literal?; false; end
66
66
  end
67
67
 
68
- %w{ Symbol Slash Dot }.each do |t|
69
- class_eval <<-eoruby, __FILE__, __LINE__ + 1
70
- class #{t} < Terminal;
71
- def type; :#{t.upcase}; end
72
- end
73
- eoruby
68
+ class Slash < Terminal # :nodoc:
69
+ def type; :SLASH; end
70
+ end
71
+
72
+ class Dot < Terminal # :nodoc:
73
+ def type; :DOT; end
74
74
  end
75
75
 
76
76
  class Symbol < Terminal # :nodoc:
@@ -79,16 +79,18 @@ module ActionDispatch
79
79
  attr_reader :name
80
80
 
81
81
  DEFAULT_EXP = /[^\.\/\?]+/
82
- def initialize(left)
83
- super
84
- @regexp = DEFAULT_EXP
85
- @name = left.tr "*:".freeze, "".freeze
82
+ GREEDY_EXP = /(.+)/
83
+ def initialize(left, regexp = DEFAULT_EXP)
84
+ super(left)
85
+ @regexp = regexp
86
+ @name = -left.tr("*:", "")
86
87
  end
87
88
 
88
89
  def default_regexp?
89
90
  regexp == DEFAULT_EXP
90
91
  end
91
92
 
93
+ def type; :SYMBOL; end
92
94
  def symbol?; true; end
93
95
  end
94
96
 
@@ -1,6 +1,6 @@
1
1
  #
2
2
  # DO NOT MODIFY!!!!
3
- # This file is automatically generated by Racc 1.4.14
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
- end # module Journey
199
- end # module ActionDispatch
198
+ end # module Journey
199
+ end # module ActionDispatch
@@ -21,7 +21,7 @@ rule
21
21
  | expression OR or { Or.new([val.first, val.last]) }
22
22
  ;
23
23
  star
24
- : STAR { Star.new(Symbol.new(val.last)) }
24
+ : STAR { Star.new(Symbol.new(val.last, Symbol::GREEDY_EXP)) }
25
25
  ;
26
26
  terminal
27
27
  : symbol
@@ -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
- [visit(node.left), visit(node.right)].join
69
+ "#{visit(node.left)}#{visit(node.right)}"
85
70
  end
86
71
 
87
72
  def visit_SYMBOL(node)
@@ -90,7 +75,7 @@ module ActionDispatch
90
75
  return @separator_re unless @matchers.key?(node)
91
76
 
92
77
  re = @matchers[node]
93
- "(#{re})"
78
+ "(#{Regexp.union(re)})"
94
79
  end
95
80
 
96
81
  def visit_GROUP(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)
@@ -137,6 +122,10 @@ module ActionDispatch
137
122
  Array.new(length - 1) { |i| self[i + 1] }
138
123
  end
139
124
 
125
+ def named_captures
126
+ @names.zip(captures).to_h
127
+ end
128
+
140
129
  def [](x)
141
130
  idx = @offsets[x - 1] + x
142
131
  @match[idx]
@@ -161,6 +150,10 @@ module ActionDispatch
161
150
  end
162
151
  alias :=~ :match
163
152
 
153
+ def match?(other)
154
+ to_regexp.match?(other)
155
+ end
156
+
164
157
  def source
165
158
  to_regexp.source
166
159
  end
@@ -169,8 +162,13 @@ module ActionDispatch
169
162
  @re ||= regexp_visitor.new(@separators, @requirements).accept spec
170
163
  end
171
164
 
172
- private
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
173
170
 
171
+ private
174
172
  def regexp_visitor
175
173
  @anchored ? AnchoredRegexp : UnanchoredRegexp
176
174
  end
@@ -184,7 +182,7 @@ module ActionDispatch
184
182
  node = node.to_sym
185
183
 
186
184
  if @requirements.key?(node)
187
- re = /#{@requirements[node]}|/
185
+ re = /#{Regexp.union(@requirements[node])}|/
188
186
  @offsets.push((re.match("").length - 1) + @offsets.last)
189
187
  else
190
188
  @offsets << @offsets.last
@@ -4,15 +4,16 @@ module ActionDispatch
4
4
  # :stopdoc:
5
5
  module Journey
6
6
  class Route
7
- attr_reader :app, :path, :defaults, :name, :precedence
7
+ attr_reader :app, :path, :defaults, :name, :precedence, :constraints,
8
+ :internal, :scope_options
8
9
 
9
- attr_reader :constraints, :internal
10
10
  alias :conditions :constraints
11
11
 
12
12
  module VerbMatchers
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 === request.request_method; end
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, app, path, constraints, required_defaults, defaults, request_method_match, precedence, internal = false)
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
@@ -72,6 +68,7 @@ module ActionDispatch
72
68
  @decorated_ast = nil
73
69
  @precedence = precedence
74
70
  @path_formatter = @path.build_formatter
71
+ @scope_options = scope_options
75
72
  @internal = internal
76
73
  end
77
74
 
@@ -91,7 +88,7 @@ module ActionDispatch
91
88
  end
92
89
  end
93
90
 
94
- # Needed for `rails routes`. Picks up succinctly defined requirements
91
+ # Needed for `bin/rails routes`. Picks up succinctly defined requirements
95
92
  # for a route, for example route
96
93
  #
97
94
  # get 'photo/:id', :controller => 'photos', :action => 'show',
@@ -114,18 +111,11 @@ module ActionDispatch
114
111
  end
115
112
 
116
113
  def score(supplied_keys)
117
- required_keys = path.required_names
118
-
119
- required_keys.each do |k|
114
+ path.required_names.each do |k|
120
115
  return -1 unless supplied_keys.include?(k)
121
116
  end
122
117
 
123
- score = 0
124
- path.names.each do |k|
125
- score += 1 if supplied_keys.include?(k)
126
- end
127
-
128
- score + (required_defaults.length * 2)
118
+ (required_defaults.length * 2) + path.names.count { |k| supplied_keys.include?(k) }
129
119
  end
130
120
 
131
121
  def parts
@@ -152,7 +142,7 @@ module ActionDispatch
152
142
  end
153
143
 
154
144
  def glob?
155
- !path.spec.grep(Nodes::Star).empty?
145
+ path.spec.any?(Nodes::Star)
156
146
  end
157
147
 
158
148
  def dispatcher?
@@ -15,9 +15,6 @@ require "action_dispatch/journey/path/pattern"
15
15
  module ActionDispatch
16
16
  module Journey # :nodoc:
17
17
  class Router # :nodoc:
18
- class RoutingError < ::StandardError # :nodoc:
19
- end
20
-
21
18
  attr_accessor :routes
22
19
 
23
20
  def initialize(routes)
@@ -43,11 +40,12 @@ module ActionDispatch
43
40
  req.path_info = "/" + req.path_info unless req.path_info.start_with? "/"
44
41
  end
45
42
 
46
- parameters = route.defaults.merge parameters.transform_values { |val|
47
- val.dup.force_encoding(::Encoding::UTF_8)
43
+ tmp_params = set_params.merge route.defaults
44
+ parameters.each_pair { |key, val|
45
+ tmp_params[key] = val.force_encoding(::Encoding::UTF_8)
48
46
  }
49
47
 
50
- req.path_parameters = set_params.merge parameters
48
+ req.path_parameters = tmp_params
51
49
 
52
50
  status, headers, body = route.app.serve(req)
53
51
 
@@ -68,7 +66,8 @@ module ActionDispatch
68
66
  find_routes(rails_req).each do |match, parameters, route|
69
67
  unless route.path.anchored
70
68
  rails_req.script_name = match.to_s
71
- rails_req.path_info = match.post_match.sub(/^([^\/])/, '/\1')
69
+ rails_req.path_info = match.post_match
70
+ rails_req.path_info = "/" + rails_req.path_info unless rails_req.path_info.start_with? "/"
72
71
  end
73
72
 
74
73
  parameters = route.defaults.merge parameters
@@ -84,7 +83,6 @@ module ActionDispatch
84
83
  end
85
84
 
86
85
  private
87
-
88
86
  def partitioned_routes
89
87
  routes.partition { |r|
90
88
  r.path.anchored && r.ast.grep(Nodes::Symbol).all? { |n| n.default_regexp? }
@@ -109,23 +107,24 @@ module ActionDispatch
109
107
  end
110
108
 
111
109
  def find_routes(req)
112
- routes = filter_routes(req.path_info).concat custom_routes.find_all { |r|
113
- r.path.match(req.path_info)
110
+ path_info = req.path_info
111
+ routes = filter_routes(path_info).concat custom_routes.find_all { |r|
112
+ r.path.match?(path_info)
114
113
  }
115
114
 
116
- routes =
117
- if req.head?
118
- match_head_routes(routes, req)
119
- else
120
- match_routes(routes, req)
121
- end
115
+ if req.head?
116
+ routes = match_head_routes(routes, req)
117
+ else
118
+ routes.select! { |r| r.matches?(req) }
119
+ end
122
120
 
123
121
  routes.sort_by!(&:precedence)
124
122
 
125
123
  routes.map! { |r|
126
- match_data = r.path.match(req.path_info)
124
+ match_data = r.path.match(path_info)
127
125
  path_parameters = {}
128
- match_data.names.zip(match_data.captures) { |name, val|
126
+ match_data.names.each_with_index { |name, i|
127
+ val = match_data[i + 1]
129
128
  path_parameters[name.to_sym] = Utils.unescape_uri(val) if val
130
129
  }
131
130
  [match_data, path_parameters, r]
@@ -133,24 +132,17 @@ module ActionDispatch
133
132
  end
134
133
 
135
134
  def match_head_routes(routes, req)
136
- verb_specific_routes = routes.select(&:requires_matching_verb?)
137
- head_routes = match_routes(verb_specific_routes, req)
138
-
139
- if head_routes.empty?
140
- begin
141
- req.request_method = "GET"
142
- match_routes(routes, req)
143
- ensure
144
- req.request_method = "HEAD"
145
- end
146
- else
147
- 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"
148
144
  end
149
145
  end
150
-
151
- def match_routes(routes, req)
152
- routes.select { |r| r.matches?(req) }
153
- end
154
146
  end
155
147
  end
156
148
  end