actionpack 5.2.3

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 (170) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +429 -0
  3. data/MIT-LICENSE +21 -0
  4. data/README.rdoc +57 -0
  5. data/lib/abstract_controller.rb +27 -0
  6. data/lib/abstract_controller/asset_paths.rb +12 -0
  7. data/lib/abstract_controller/base.rb +265 -0
  8. data/lib/abstract_controller/caching.rb +66 -0
  9. data/lib/abstract_controller/caching/fragments.rb +166 -0
  10. data/lib/abstract_controller/callbacks.rb +212 -0
  11. data/lib/abstract_controller/collector.rb +43 -0
  12. data/lib/abstract_controller/error.rb +6 -0
  13. data/lib/abstract_controller/helpers.rb +194 -0
  14. data/lib/abstract_controller/logger.rb +14 -0
  15. data/lib/abstract_controller/railties/routes_helpers.rb +20 -0
  16. data/lib/abstract_controller/rendering.rb +127 -0
  17. data/lib/abstract_controller/translation.rb +31 -0
  18. data/lib/abstract_controller/url_for.rb +35 -0
  19. data/lib/action_controller.rb +66 -0
  20. data/lib/action_controller/api.rb +149 -0
  21. data/lib/action_controller/api/api_rendering.rb +16 -0
  22. data/lib/action_controller/base.rb +276 -0
  23. data/lib/action_controller/caching.rb +46 -0
  24. data/lib/action_controller/form_builder.rb +50 -0
  25. data/lib/action_controller/log_subscriber.rb +78 -0
  26. data/lib/action_controller/metal.rb +256 -0
  27. data/lib/action_controller/metal/basic_implicit_render.rb +13 -0
  28. data/lib/action_controller/metal/conditional_get.rb +274 -0
  29. data/lib/action_controller/metal/content_security_policy.rb +52 -0
  30. data/lib/action_controller/metal/cookies.rb +16 -0
  31. data/lib/action_controller/metal/data_streaming.rb +152 -0
  32. data/lib/action_controller/metal/etag_with_flash.rb +18 -0
  33. data/lib/action_controller/metal/etag_with_template_digest.rb +57 -0
  34. data/lib/action_controller/metal/exceptions.rb +53 -0
  35. data/lib/action_controller/metal/flash.rb +61 -0
  36. data/lib/action_controller/metal/force_ssl.rb +99 -0
  37. data/lib/action_controller/metal/head.rb +60 -0
  38. data/lib/action_controller/metal/helpers.rb +123 -0
  39. data/lib/action_controller/metal/http_authentication.rb +519 -0
  40. data/lib/action_controller/metal/implicit_render.rb +73 -0
  41. data/lib/action_controller/metal/instrumentation.rb +107 -0
  42. data/lib/action_controller/metal/live.rb +312 -0
  43. data/lib/action_controller/metal/mime_responds.rb +313 -0
  44. data/lib/action_controller/metal/parameter_encoding.rb +51 -0
  45. data/lib/action_controller/metal/params_wrapper.rb +293 -0
  46. data/lib/action_controller/metal/redirecting.rb +133 -0
  47. data/lib/action_controller/metal/renderers.rb +181 -0
  48. data/lib/action_controller/metal/rendering.rb +122 -0
  49. data/lib/action_controller/metal/request_forgery_protection.rb +445 -0
  50. data/lib/action_controller/metal/rescue.rb +28 -0
  51. data/lib/action_controller/metal/streaming.rb +223 -0
  52. data/lib/action_controller/metal/strong_parameters.rb +1086 -0
  53. data/lib/action_controller/metal/testing.rb +16 -0
  54. data/lib/action_controller/metal/url_for.rb +58 -0
  55. data/lib/action_controller/railtie.rb +89 -0
  56. data/lib/action_controller/railties/helpers.rb +24 -0
  57. data/lib/action_controller/renderer.rb +117 -0
  58. data/lib/action_controller/template_assertions.rb +11 -0
  59. data/lib/action_controller/test_case.rb +629 -0
  60. data/lib/action_dispatch.rb +112 -0
  61. data/lib/action_dispatch/http/cache.rb +222 -0
  62. data/lib/action_dispatch/http/content_security_policy.rb +272 -0
  63. data/lib/action_dispatch/http/filter_parameters.rb +84 -0
  64. data/lib/action_dispatch/http/filter_redirect.rb +37 -0
  65. data/lib/action_dispatch/http/headers.rb +132 -0
  66. data/lib/action_dispatch/http/mime_negotiation.rb +175 -0
  67. data/lib/action_dispatch/http/mime_type.rb +342 -0
  68. data/lib/action_dispatch/http/mime_types.rb +50 -0
  69. data/lib/action_dispatch/http/parameter_filter.rb +86 -0
  70. data/lib/action_dispatch/http/parameters.rb +126 -0
  71. data/lib/action_dispatch/http/rack_cache.rb +63 -0
  72. data/lib/action_dispatch/http/request.rb +430 -0
  73. data/lib/action_dispatch/http/response.rb +519 -0
  74. data/lib/action_dispatch/http/upload.rb +84 -0
  75. data/lib/action_dispatch/http/url.rb +350 -0
  76. data/lib/action_dispatch/journey.rb +7 -0
  77. data/lib/action_dispatch/journey/formatter.rb +189 -0
  78. data/lib/action_dispatch/journey/gtg/builder.rb +164 -0
  79. data/lib/action_dispatch/journey/gtg/simulator.rb +41 -0
  80. data/lib/action_dispatch/journey/gtg/transition_table.rb +158 -0
  81. data/lib/action_dispatch/journey/nfa/builder.rb +78 -0
  82. data/lib/action_dispatch/journey/nfa/dot.rb +36 -0
  83. data/lib/action_dispatch/journey/nfa/simulator.rb +49 -0
  84. data/lib/action_dispatch/journey/nfa/transition_table.rb +120 -0
  85. data/lib/action_dispatch/journey/nodes/node.rb +140 -0
  86. data/lib/action_dispatch/journey/parser.rb +199 -0
  87. data/lib/action_dispatch/journey/parser.y +50 -0
  88. data/lib/action_dispatch/journey/parser_extras.rb +31 -0
  89. data/lib/action_dispatch/journey/path/pattern.rb +198 -0
  90. data/lib/action_dispatch/journey/route.rb +203 -0
  91. data/lib/action_dispatch/journey/router.rb +156 -0
  92. data/lib/action_dispatch/journey/router/utils.rb +102 -0
  93. data/lib/action_dispatch/journey/routes.rb +82 -0
  94. data/lib/action_dispatch/journey/scanner.rb +64 -0
  95. data/lib/action_dispatch/journey/visitors.rb +268 -0
  96. data/lib/action_dispatch/journey/visualizer/fsm.css +30 -0
  97. data/lib/action_dispatch/journey/visualizer/fsm.js +134 -0
  98. data/lib/action_dispatch/journey/visualizer/index.html.erb +52 -0
  99. data/lib/action_dispatch/middleware/callbacks.rb +36 -0
  100. data/lib/action_dispatch/middleware/cookies.rb +685 -0
  101. data/lib/action_dispatch/middleware/debug_exceptions.rb +205 -0
  102. data/lib/action_dispatch/middleware/debug_locks.rb +124 -0
  103. data/lib/action_dispatch/middleware/exception_wrapper.rb +147 -0
  104. data/lib/action_dispatch/middleware/executor.rb +21 -0
  105. data/lib/action_dispatch/middleware/flash.rb +300 -0
  106. data/lib/action_dispatch/middleware/public_exceptions.rb +57 -0
  107. data/lib/action_dispatch/middleware/reloader.rb +12 -0
  108. data/lib/action_dispatch/middleware/remote_ip.rb +183 -0
  109. data/lib/action_dispatch/middleware/request_id.rb +43 -0
  110. data/lib/action_dispatch/middleware/session/abstract_store.rb +92 -0
  111. data/lib/action_dispatch/middleware/session/cache_store.rb +54 -0
  112. data/lib/action_dispatch/middleware/session/cookie_store.rb +118 -0
  113. data/lib/action_dispatch/middleware/session/mem_cache_store.rb +28 -0
  114. data/lib/action_dispatch/middleware/show_exceptions.rb +62 -0
  115. data/lib/action_dispatch/middleware/ssl.rb +150 -0
  116. data/lib/action_dispatch/middleware/stack.rb +116 -0
  117. data/lib/action_dispatch/middleware/static.rb +130 -0
  118. data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.html.erb +22 -0
  119. data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.text.erb +23 -0
  120. data/lib/action_dispatch/middleware/templates/rescues/_source.html.erb +27 -0
  121. data/lib/action_dispatch/middleware/templates/rescues/_source.text.erb +8 -0
  122. data/lib/action_dispatch/middleware/templates/rescues/_trace.html.erb +52 -0
  123. data/lib/action_dispatch/middleware/templates/rescues/_trace.text.erb +9 -0
  124. data/lib/action_dispatch/middleware/templates/rescues/diagnostics.html.erb +16 -0
  125. data/lib/action_dispatch/middleware/templates/rescues/diagnostics.text.erb +9 -0
  126. data/lib/action_dispatch/middleware/templates/rescues/invalid_statement.html.erb +21 -0
  127. data/lib/action_dispatch/middleware/templates/rescues/invalid_statement.text.erb +13 -0
  128. data/lib/action_dispatch/middleware/templates/rescues/layout.erb +161 -0
  129. data/lib/action_dispatch/middleware/templates/rescues/missing_template.html.erb +11 -0
  130. data/lib/action_dispatch/middleware/templates/rescues/missing_template.text.erb +3 -0
  131. data/lib/action_dispatch/middleware/templates/rescues/routing_error.html.erb +32 -0
  132. data/lib/action_dispatch/middleware/templates/rescues/routing_error.text.erb +11 -0
  133. data/lib/action_dispatch/middleware/templates/rescues/template_error.html.erb +20 -0
  134. data/lib/action_dispatch/middleware/templates/rescues/template_error.text.erb +7 -0
  135. data/lib/action_dispatch/middleware/templates/rescues/unknown_action.html.erb +6 -0
  136. data/lib/action_dispatch/middleware/templates/rescues/unknown_action.text.erb +3 -0
  137. data/lib/action_dispatch/middleware/templates/routes/_route.html.erb +16 -0
  138. data/lib/action_dispatch/middleware/templates/routes/_table.html.erb +200 -0
  139. data/lib/action_dispatch/railtie.rb +55 -0
  140. data/lib/action_dispatch/request/session.rb +234 -0
  141. data/lib/action_dispatch/request/utils.rb +78 -0
  142. data/lib/action_dispatch/routing.rb +260 -0
  143. data/lib/action_dispatch/routing/endpoint.rb +17 -0
  144. data/lib/action_dispatch/routing/inspector.rb +225 -0
  145. data/lib/action_dispatch/routing/mapper.rb +2267 -0
  146. data/lib/action_dispatch/routing/polymorphic_routes.rb +352 -0
  147. data/lib/action_dispatch/routing/redirection.rb +201 -0
  148. data/lib/action_dispatch/routing/route_set.rb +890 -0
  149. data/lib/action_dispatch/routing/routes_proxy.rb +69 -0
  150. data/lib/action_dispatch/routing/url_for.rb +236 -0
  151. data/lib/action_dispatch/system_test_case.rb +147 -0
  152. data/lib/action_dispatch/system_testing/browser.rb +49 -0
  153. data/lib/action_dispatch/system_testing/driver.rb +59 -0
  154. data/lib/action_dispatch/system_testing/server.rb +31 -0
  155. data/lib/action_dispatch/system_testing/test_helpers/screenshot_helper.rb +96 -0
  156. data/lib/action_dispatch/system_testing/test_helpers/setup_and_teardown.rb +31 -0
  157. data/lib/action_dispatch/system_testing/test_helpers/undef_methods.rb +26 -0
  158. data/lib/action_dispatch/testing/assertion_response.rb +47 -0
  159. data/lib/action_dispatch/testing/assertions.rb +24 -0
  160. data/lib/action_dispatch/testing/assertions/response.rb +107 -0
  161. data/lib/action_dispatch/testing/assertions/routing.rb +222 -0
  162. data/lib/action_dispatch/testing/integration.rb +652 -0
  163. data/lib/action_dispatch/testing/request_encoder.rb +55 -0
  164. data/lib/action_dispatch/testing/test_process.rb +50 -0
  165. data/lib/action_dispatch/testing/test_request.rb +71 -0
  166. data/lib/action_dispatch/testing/test_response.rb +53 -0
  167. data/lib/action_pack.rb +26 -0
  168. data/lib/action_pack/gem_version.rb +17 -0
  169. data/lib/action_pack/version.rb +10 -0
  170. metadata +318 -0
@@ -0,0 +1,50 @@
1
+ class ActionDispatch::Journey::Parser
2
+ options no_result_var
3
+ token SLASH LITERAL SYMBOL LPAREN RPAREN DOT STAR OR
4
+
5
+ rule
6
+ expressions
7
+ : expression expressions { Cat.new(val.first, val.last) }
8
+ | expression { val.first }
9
+ | or
10
+ ;
11
+ expression
12
+ : terminal
13
+ | group
14
+ | star
15
+ ;
16
+ group
17
+ : LPAREN expressions RPAREN { Group.new(val[1]) }
18
+ ;
19
+ or
20
+ : expression OR expression { Or.new([val.first, val.last]) }
21
+ | expression OR or { Or.new([val.first, val.last]) }
22
+ ;
23
+ star
24
+ : STAR { Star.new(Symbol.new(val.last)) }
25
+ ;
26
+ terminal
27
+ : symbol
28
+ | literal
29
+ | slash
30
+ | dot
31
+ ;
32
+ slash
33
+ : SLASH { Slash.new(val.first) }
34
+ ;
35
+ symbol
36
+ : SYMBOL { Symbol.new(val.first) }
37
+ ;
38
+ literal
39
+ : LITERAL { Literal.new(val.first) }
40
+ ;
41
+ dot
42
+ : DOT { Dot.new(val.first) }
43
+ ;
44
+
45
+ end
46
+
47
+ ---- header
48
+ # :stopdoc:
49
+
50
+ require "action_dispatch/journey/parser_extras"
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "action_dispatch/journey/scanner"
4
+ require "action_dispatch/journey/nodes/node"
5
+
6
+ module ActionDispatch
7
+ # :stopdoc:
8
+ module Journey
9
+ class Parser < Racc::Parser
10
+ include Journey::Nodes
11
+
12
+ def self.parse(string)
13
+ new.parse string
14
+ end
15
+
16
+ def initialize
17
+ @scanner = Scanner.new
18
+ end
19
+
20
+ def parse(string)
21
+ @scanner.scan_setup(string)
22
+ do_parse
23
+ end
24
+
25
+ def next_token
26
+ @scanner.next_token
27
+ end
28
+ end
29
+ end
30
+ # :startdoc:
31
+ end
@@ -0,0 +1,198 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActionDispatch
4
+ module Journey # :nodoc:
5
+ module Path # :nodoc:
6
+ class Pattern # :nodoc:
7
+ attr_reader :spec, :requirements, :anchored
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
+ def initialize(ast, requirements, separators, anchored)
20
+ @spec = ast
21
+ @requirements = requirements
22
+ @separators = separators
23
+ @anchored = anchored
24
+
25
+ @names = nil
26
+ @optional_names = nil
27
+ @required_names = nil
28
+ @re = nil
29
+ @offsets = nil
30
+ end
31
+
32
+ def build_formatter
33
+ Visitors::FormatBuilder.new.accept(spec)
34
+ end
35
+
36
+ def eager_load!
37
+ required_names
38
+ offsets
39
+ to_regexp
40
+ nil
41
+ end
42
+
43
+ def ast
44
+ @spec.find_all(&:symbol?).each do |node|
45
+ re = @requirements[node.to_sym]
46
+ node.regexp = re if re
47
+ end
48
+
49
+ @spec.find_all(&:star?).each do |node|
50
+ node = node.left
51
+ node.regexp = @requirements[node.to_sym] || /(.+)/
52
+ end
53
+
54
+ @spec
55
+ end
56
+
57
+ def names
58
+ @names ||= spec.find_all(&:symbol?).map(&:name)
59
+ end
60
+
61
+ def required_names
62
+ @required_names ||= names - optional_names
63
+ end
64
+
65
+ def optional_names
66
+ @optional_names ||= spec.find_all(&:group?).flat_map { |group|
67
+ group.find_all(&:symbol?)
68
+ }.map(&:name).uniq
69
+ end
70
+
71
+ class AnchoredRegexp < Journey::Visitors::Visitor # :nodoc:
72
+ def initialize(separator, matchers)
73
+ @separator = separator
74
+ @matchers = matchers
75
+ @separator_re = "([^#{separator}]+)"
76
+ super()
77
+ end
78
+
79
+ def accept(node)
80
+ %r{\A#{visit node}\Z}
81
+ end
82
+
83
+ def visit_CAT(node)
84
+ [visit(node.left), visit(node.right)].join
85
+ end
86
+
87
+ def visit_SYMBOL(node)
88
+ node = node.to_sym
89
+
90
+ return @separator_re unless @matchers.key?(node)
91
+
92
+ re = @matchers[node]
93
+ "(#{re})"
94
+ end
95
+
96
+ def visit_GROUP(node)
97
+ "(?:#{visit node.left})?"
98
+ end
99
+
100
+ def visit_LITERAL(node)
101
+ Regexp.escape(node.left)
102
+ end
103
+ alias :visit_DOT :visit_LITERAL
104
+
105
+ def visit_SLASH(node)
106
+ node.left
107
+ end
108
+
109
+ def visit_STAR(node)
110
+ re = @matchers[node.left.to_sym] || ".+"
111
+ "(#{re})"
112
+ end
113
+
114
+ def visit_OR(node)
115
+ children = node.children.map { |n| visit n }
116
+ "(?:#{children.join(?|)})"
117
+ end
118
+ end
119
+
120
+ class UnanchoredRegexp < AnchoredRegexp # :nodoc:
121
+ def accept(node)
122
+ %r{\A#{visit node}(?:\b|\Z)}
123
+ end
124
+ end
125
+
126
+ class MatchData # :nodoc:
127
+ attr_reader :names
128
+
129
+ def initialize(names, offsets, match)
130
+ @names = names
131
+ @offsets = offsets
132
+ @match = match
133
+ end
134
+
135
+ def captures
136
+ Array.new(length - 1) { |i| self[i + 1] }
137
+ end
138
+
139
+ def [](x)
140
+ idx = @offsets[x - 1] + x
141
+ @match[idx]
142
+ end
143
+
144
+ def length
145
+ @offsets.length
146
+ end
147
+
148
+ def post_match
149
+ @match.post_match
150
+ end
151
+
152
+ def to_s
153
+ @match.to_s
154
+ end
155
+ end
156
+
157
+ def match(other)
158
+ return unless match = to_regexp.match(other)
159
+ MatchData.new(names, offsets, match)
160
+ end
161
+ alias :=~ :match
162
+
163
+ def source
164
+ to_regexp.source
165
+ end
166
+
167
+ def to_regexp
168
+ @re ||= regexp_visitor.new(@separators, @requirements).accept spec
169
+ end
170
+
171
+ private
172
+
173
+ def regexp_visitor
174
+ @anchored ? AnchoredRegexp : UnanchoredRegexp
175
+ end
176
+
177
+ def offsets
178
+ return @offsets if @offsets
179
+
180
+ @offsets = [0]
181
+
182
+ spec.find_all(&:symbol?).each do |node|
183
+ node = node.to_sym
184
+
185
+ if @requirements.key?(node)
186
+ re = /#{@requirements[node]}|/
187
+ @offsets.push((re.match("").length - 1) + @offsets.last)
188
+ else
189
+ @offsets << @offsets.last
190
+ end
191
+ end
192
+
193
+ @offsets
194
+ end
195
+ end
196
+ end
197
+ end
198
+ end
@@ -0,0 +1,203 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActionDispatch
4
+ # :stopdoc:
5
+ module Journey
6
+ class Route
7
+ attr_reader :app, :path, :defaults, :name, :precedence
8
+
9
+ attr_reader :constraints, :internal
10
+ alias :conditions :constraints
11
+
12
+ module VerbMatchers
13
+ VERBS = %w{ DELETE GET HEAD OPTIONS LINK PATCH POST PUT TRACE UNLINK }
14
+ VERBS.each do |v|
15
+ class_eval <<-eoc, __FILE__, __LINE__ + 1
16
+ class #{v}
17
+ def self.verb; name.split("::").last; end
18
+ def self.call(req); req.#{v.downcase}?; end
19
+ end
20
+ eoc
21
+ end
22
+
23
+ class Unknown
24
+ attr_reader :verb
25
+
26
+ def initialize(verb)
27
+ @verb = verb
28
+ end
29
+
30
+ def call(request); @verb === request.request_method; end
31
+ end
32
+
33
+ class All
34
+ def self.call(_); true; end
35
+ def self.verb; ""; end
36
+ end
37
+
38
+ VERB_TO_CLASS = VERBS.each_with_object(all: All) do |verb, hash|
39
+ klass = const_get verb
40
+ hash[verb] = klass
41
+ hash[verb.downcase] = klass
42
+ hash[verb.downcase.to_sym] = klass
43
+ end
44
+ end
45
+
46
+ def self.verb_matcher(verb)
47
+ VerbMatchers::VERB_TO_CLASS.fetch(verb) do
48
+ VerbMatchers::Unknown.new verb.to_s.dasherize.upcase
49
+ end
50
+ end
51
+
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
+ ##
58
+ # +path+ is a path constraint.
59
+ # +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)
61
+ @name = name
62
+ @app = app
63
+ @path = path
64
+
65
+ @request_method_match = request_method_match
66
+ @constraints = constraints
67
+ @defaults = defaults
68
+ @required_defaults = nil
69
+ @_required_defaults = required_defaults
70
+ @required_parts = nil
71
+ @parts = nil
72
+ @decorated_ast = nil
73
+ @precedence = precedence
74
+ @path_formatter = @path.build_formatter
75
+ @internal = internal
76
+ end
77
+
78
+ def eager_load!
79
+ path.eager_load!
80
+ ast
81
+ parts
82
+ required_defaults
83
+ nil
84
+ end
85
+
86
+ def ast
87
+ @decorated_ast ||= begin
88
+ decorated_ast = path.ast
89
+ decorated_ast.find_all(&:terminal?).each { |n| n.memo = self }
90
+ decorated_ast
91
+ end
92
+ end
93
+
94
+ # Needed for `rails routes`. Picks up succinctly defined requirements
95
+ # for a route, for example route
96
+ #
97
+ # get 'photo/:id', :controller => 'photos', :action => 'show',
98
+ # :id => /[A-Z]\d{5}/
99
+ #
100
+ # will have {:controller=>"photos", :action=>"show", :id=>/[A-Z]\d{5}/}
101
+ # as requirements.
102
+ def requirements
103
+ @defaults.merge(path.requirements).delete_if { |_, v|
104
+ /.+?/ == v
105
+ }
106
+ end
107
+
108
+ def segments
109
+ path.names
110
+ end
111
+
112
+ def required_keys
113
+ required_parts + required_defaults.keys
114
+ end
115
+
116
+ def score(supplied_keys)
117
+ required_keys = path.required_names
118
+
119
+ required_keys.each do |k|
120
+ return -1 unless supplied_keys.include?(k)
121
+ end
122
+
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)
129
+ end
130
+
131
+ def parts
132
+ @parts ||= segments.map(&:to_sym)
133
+ end
134
+ alias :segment_keys :parts
135
+
136
+ def format(path_options)
137
+ @path_formatter.evaluate path_options
138
+ end
139
+
140
+ def required_parts
141
+ @required_parts ||= path.required_names.map(&:to_sym)
142
+ end
143
+
144
+ def required_default?(key)
145
+ @_required_defaults.include?(key)
146
+ end
147
+
148
+ def required_defaults
149
+ @required_defaults ||= @defaults.dup.delete_if do |k, _|
150
+ parts.include?(k) || !required_default?(k)
151
+ end
152
+ end
153
+
154
+ def glob?
155
+ !path.spec.grep(Nodes::Star).empty?
156
+ end
157
+
158
+ def dispatcher?
159
+ @app.dispatcher?
160
+ end
161
+
162
+ def matches?(request)
163
+ match_verb(request) &&
164
+ constraints.all? { |method, value|
165
+ case value
166
+ when Regexp, String
167
+ value === request.send(method).to_s
168
+ when Array
169
+ value.include?(request.send(method))
170
+ when TrueClass
171
+ request.send(method).present?
172
+ when FalseClass
173
+ request.send(method).blank?
174
+ else
175
+ value === request.send(method)
176
+ end
177
+ }
178
+ end
179
+
180
+ def ip
181
+ constraints[:ip] || //
182
+ end
183
+
184
+ def requires_matching_verb?
185
+ !@request_method_match.all? { |x| x == VerbMatchers::All }
186
+ end
187
+
188
+ def verb
189
+ verbs.join("|")
190
+ end
191
+
192
+ private
193
+ def verbs
194
+ @request_method_match.map(&:verb)
195
+ end
196
+
197
+ def match_verb(request)
198
+ @request_method_match.any? { |m| m.call request }
199
+ end
200
+ end
201
+ end
202
+ # :startdoc:
203
+ end