actionpack 4.2.10 → 7.2.0.rc1
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 +5 -5
- data/CHANGELOG.md +86 -600
- data/MIT-LICENSE +1 -1
- data/README.rdoc +13 -14
- data/lib/abstract_controller/asset_paths.rb +5 -1
- data/lib/abstract_controller/base.rb +166 -136
- data/lib/abstract_controller/caching/fragments.rb +149 -0
- data/lib/abstract_controller/caching.rb +68 -0
- data/lib/abstract_controller/callbacks.rb +126 -57
- data/lib/abstract_controller/collector.rb +13 -15
- data/lib/abstract_controller/deprecator.rb +9 -0
- data/lib/abstract_controller/error.rb +8 -0
- data/lib/abstract_controller/helpers.rb +181 -132
- data/lib/abstract_controller/logger.rb +5 -1
- data/lib/abstract_controller/railties/routes_helpers.rb +10 -3
- data/lib/abstract_controller/rendering.rb +56 -56
- data/lib/abstract_controller/translation.rb +29 -15
- data/lib/abstract_controller/url_for.rb +15 -11
- data/lib/abstract_controller.rb +21 -5
- data/lib/action_controller/api/api_rendering.rb +18 -0
- data/lib/action_controller/api.rb +154 -0
- data/lib/action_controller/base.rb +219 -155
- data/lib/action_controller/caching.rb +28 -68
- data/lib/action_controller/deprecator.rb +9 -0
- data/lib/action_controller/form_builder.rb +55 -0
- data/lib/action_controller/log_subscriber.rb +35 -22
- data/lib/action_controller/metal/allow_browser.rb +119 -0
- data/lib/action_controller/metal/basic_implicit_render.rb +17 -0
- data/lib/action_controller/metal/conditional_get.rb +259 -122
- data/lib/action_controller/metal/content_security_policy.rb +86 -0
- data/lib/action_controller/metal/cookies.rb +9 -5
- data/lib/action_controller/metal/data_streaming.rb +87 -104
- data/lib/action_controller/metal/default_headers.rb +21 -0
- data/lib/action_controller/metal/etag_with_flash.rb +22 -0
- data/lib/action_controller/metal/etag_with_template_digest.rb +35 -26
- data/lib/action_controller/metal/exceptions.rb +71 -24
- data/lib/action_controller/metal/flash.rb +26 -19
- data/lib/action_controller/metal/head.rb +45 -36
- data/lib/action_controller/metal/helpers.rb +80 -64
- data/lib/action_controller/metal/http_authentication.rb +297 -244
- data/lib/action_controller/metal/implicit_render.rb +57 -9
- data/lib/action_controller/metal/instrumentation.rb +76 -64
- data/lib/action_controller/metal/live.rb +238 -176
- data/lib/action_controller/metal/logging.rb +22 -0
- data/lib/action_controller/metal/mime_responds.rb +177 -166
- data/lib/action_controller/metal/parameter_encoding.rb +84 -0
- data/lib/action_controller/metal/params_wrapper.rb +145 -118
- data/lib/action_controller/metal/permissions_policy.rb +38 -0
- data/lib/action_controller/metal/rate_limiting.rb +62 -0
- data/lib/action_controller/metal/redirecting.rb +203 -64
- data/lib/action_controller/metal/renderers.rb +108 -65
- data/lib/action_controller/metal/rendering.rb +216 -56
- data/lib/action_controller/metal/request_forgery_protection.rb +496 -163
- data/lib/action_controller/metal/rescue.rb +19 -21
- data/lib/action_controller/metal/streaming.rb +179 -138
- data/lib/action_controller/metal/strong_parameters.rb +1058 -382
- data/lib/action_controller/metal/testing.rb +11 -17
- data/lib/action_controller/metal/url_for.rb +37 -21
- data/lib/action_controller/metal.rb +236 -138
- data/lib/action_controller/railtie.rb +89 -11
- data/lib/action_controller/railties/helpers.rb +5 -1
- data/lib/action_controller/renderer.rb +161 -0
- data/lib/action_controller/template_assertions.rb +13 -0
- data/lib/action_controller/test_case.rb +425 -497
- data/lib/action_controller.rb +44 -22
- data/lib/action_dispatch/constants.rb +34 -0
- data/lib/action_dispatch/deprecator.rb +9 -0
- data/lib/action_dispatch/http/cache.rb +119 -63
- data/lib/action_dispatch/http/content_disposition.rb +47 -0
- data/lib/action_dispatch/http/content_security_policy.rb +364 -0
- data/lib/action_dispatch/http/filter_parameters.rb +36 -34
- data/lib/action_dispatch/http/filter_redirect.rb +24 -12
- data/lib/action_dispatch/http/headers.rb +66 -31
- data/lib/action_dispatch/http/mime_negotiation.rb +106 -75
- data/lib/action_dispatch/http/mime_type.rb +196 -136
- data/lib/action_dispatch/http/mime_types.rb +25 -7
- data/lib/action_dispatch/http/parameters.rb +97 -45
- data/lib/action_dispatch/http/permissions_policy.rb +187 -0
- data/lib/action_dispatch/http/rack_cache.rb +6 -0
- data/lib/action_dispatch/http/request.rb +299 -170
- data/lib/action_dispatch/http/response.rb +311 -160
- data/lib/action_dispatch/http/upload.rb +52 -23
- data/lib/action_dispatch/http/url.rb +201 -125
- data/lib/action_dispatch/journey/formatter.rb +110 -50
- data/lib/action_dispatch/journey/gtg/builder.rb +37 -50
- data/lib/action_dispatch/journey/gtg/simulator.rb +20 -17
- data/lib/action_dispatch/journey/gtg/transition_table.rb +96 -36
- data/lib/action_dispatch/journey/nfa/dot.rb +5 -14
- data/lib/action_dispatch/journey/nodes/node.rb +100 -20
- data/lib/action_dispatch/journey/parser.rb +19 -17
- data/lib/action_dispatch/journey/parser.y +4 -3
- data/lib/action_dispatch/journey/parser_extras.rb +14 -4
- data/lib/action_dispatch/journey/path/pattern.rb +79 -63
- data/lib/action_dispatch/journey/route.rb +108 -44
- data/lib/action_dispatch/journey/router/utils.rb +41 -29
- data/lib/action_dispatch/journey/router.rb +64 -57
- data/lib/action_dispatch/journey/routes.rb +23 -21
- data/lib/action_dispatch/journey/scanner.rb +28 -17
- data/lib/action_dispatch/journey/visitors.rb +100 -54
- data/lib/action_dispatch/journey/visualizer/fsm.js +49 -24
- data/lib/action_dispatch/journey/visualizer/index.html.erb +1 -1
- data/lib/action_dispatch/journey.rb +7 -5
- data/lib/action_dispatch/log_subscriber.rb +25 -0
- data/lib/action_dispatch/middleware/actionable_exceptions.rb +46 -0
- data/lib/action_dispatch/middleware/assume_ssl.rb +27 -0
- data/lib/action_dispatch/middleware/callbacks.rb +7 -6
- data/lib/action_dispatch/middleware/cookies.rb +471 -328
- data/lib/action_dispatch/middleware/debug_exceptions.rb +149 -66
- data/lib/action_dispatch/middleware/debug_locks.rb +129 -0
- data/lib/action_dispatch/middleware/debug_view.rb +73 -0
- data/lib/action_dispatch/middleware/exception_wrapper.rb +275 -73
- data/lib/action_dispatch/middleware/executor.rb +32 -0
- data/lib/action_dispatch/middleware/flash.rb +143 -101
- data/lib/action_dispatch/middleware/host_authorization.rb +171 -0
- data/lib/action_dispatch/middleware/public_exceptions.rb +36 -27
- data/lib/action_dispatch/middleware/reloader.rb +10 -92
- data/lib/action_dispatch/middleware/remote_ip.rb +133 -107
- data/lib/action_dispatch/middleware/request_id.rb +29 -15
- data/lib/action_dispatch/middleware/server_timing.rb +78 -0
- data/lib/action_dispatch/middleware/session/abstract_store.rb +49 -27
- data/lib/action_dispatch/middleware/session/cache_store.rb +33 -16
- data/lib/action_dispatch/middleware/session/cookie_store.rb +86 -80
- data/lib/action_dispatch/middleware/session/mem_cache_store.rb +15 -3
- data/lib/action_dispatch/middleware/show_exceptions.rb +66 -36
- data/lib/action_dispatch/middleware/ssl.rb +134 -36
- data/lib/action_dispatch/middleware/stack.rb +109 -44
- data/lib/action_dispatch/middleware/static.rb +159 -90
- data/lib/action_dispatch/middleware/templates/rescues/_actions.html.erb +13 -0
- data/lib/action_dispatch/middleware/templates/rescues/_actions.text.erb +0 -0
- data/lib/action_dispatch/middleware/templates/rescues/_message_and_suggestions.html.erb +22 -0
- data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.html.erb +7 -24
- data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.text.erb +1 -1
- data/lib/action_dispatch/middleware/templates/rescues/_source.html.erb +36 -0
- data/lib/action_dispatch/middleware/templates/rescues/_source.text.erb +8 -0
- data/lib/action_dispatch/middleware/templates/rescues/_trace.html.erb +46 -36
- data/lib/action_dispatch/middleware/templates/rescues/blocked_host.html.erb +12 -0
- data/lib/action_dispatch/middleware/templates/rescues/blocked_host.text.erb +9 -0
- data/lib/action_dispatch/middleware/templates/rescues/diagnostics.html.erb +26 -7
- data/lib/action_dispatch/middleware/templates/rescues/diagnostics.text.erb +3 -3
- data/lib/action_dispatch/middleware/templates/rescues/invalid_statement.html.erb +24 -0
- data/lib/action_dispatch/middleware/templates/rescues/invalid_statement.text.erb +16 -0
- data/lib/action_dispatch/middleware/templates/rescues/layout.erb +139 -15
- data/lib/action_dispatch/middleware/templates/rescues/missing_exact_template.html.erb +23 -0
- data/lib/action_dispatch/middleware/templates/rescues/missing_exact_template.text.erb +3 -0
- data/lib/action_dispatch/middleware/templates/rescues/missing_template.html.erb +6 -6
- data/lib/action_dispatch/middleware/templates/rescues/routing_error.html.erb +7 -7
- data/lib/action_dispatch/middleware/templates/rescues/template_error.html.erb +9 -9
- data/lib/action_dispatch/middleware/templates/rescues/template_error.text.erb +1 -1
- data/lib/action_dispatch/middleware/templates/rescues/unknown_action.html.erb +4 -4
- data/lib/action_dispatch/middleware/templates/rescues/unknown_action.text.erb +1 -1
- data/lib/action_dispatch/middleware/templates/routes/_route.html.erb +7 -4
- data/lib/action_dispatch/middleware/templates/routes/_table.html.erb +125 -93
- data/lib/action_dispatch/railtie.rb +44 -16
- data/lib/action_dispatch/request/session.rb +159 -69
- data/lib/action_dispatch/request/utils.rb +97 -23
- data/lib/action_dispatch/routing/endpoint.rb +11 -2
- data/lib/action_dispatch/routing/inspector.rb +195 -106
- data/lib/action_dispatch/routing/mapper.rb +1338 -955
- data/lib/action_dispatch/routing/polymorphic_routes.rb +234 -201
- data/lib/action_dispatch/routing/redirection.rb +78 -51
- data/lib/action_dispatch/routing/route_set.rb +460 -374
- data/lib/action_dispatch/routing/routes_proxy.rb +36 -12
- data/lib/action_dispatch/routing/url_for.rb +172 -124
- data/lib/action_dispatch/routing.rb +159 -158
- data/lib/action_dispatch/system_test_case.rb +206 -0
- data/lib/action_dispatch/system_testing/browser.rb +84 -0
- data/lib/action_dispatch/system_testing/driver.rb +85 -0
- data/lib/action_dispatch/system_testing/server.rb +33 -0
- data/lib/action_dispatch/system_testing/test_helpers/screenshot_helper.rb +164 -0
- data/lib/action_dispatch/system_testing/test_helpers/setup_and_teardown.rb +23 -0
- data/lib/action_dispatch/testing/assertion_response.rb +48 -0
- data/lib/action_dispatch/testing/assertions/response.rb +71 -39
- data/lib/action_dispatch/testing/assertions/routing.rb +228 -103
- data/lib/action_dispatch/testing/assertions.rb +9 -6
- data/lib/action_dispatch/testing/integration.rb +486 -306
- data/lib/action_dispatch/testing/request_encoder.rb +60 -0
- data/lib/action_dispatch/testing/test_helpers/page_dump_helper.rb +35 -0
- data/lib/action_dispatch/testing/test_process.rb +35 -22
- data/lib/action_dispatch/testing/test_request.rb +29 -34
- data/lib/action_dispatch/testing/test_response.rb +48 -15
- data/lib/action_dispatch.rb +82 -40
- data/lib/action_pack/gem_version.rb +8 -4
- data/lib/action_pack/version.rb +6 -2
- data/lib/action_pack.rb +21 -18
- metadata +146 -56
- data/lib/action_controller/caching/fragments.rb +0 -103
- data/lib/action_controller/metal/force_ssl.rb +0 -97
- data/lib/action_controller/metal/hide_actions.rb +0 -40
- data/lib/action_controller/metal/rack_delegation.rb +0 -32
- data/lib/action_controller/middleware.rb +0 -39
- data/lib/action_controller/model_naming.rb +0 -12
- data/lib/action_dispatch/http/parameter_filter.rb +0 -72
- data/lib/action_dispatch/journey/backwards.rb +0 -5
- data/lib/action_dispatch/journey/nfa/builder.rb +0 -76
- data/lib/action_dispatch/journey/nfa/simulator.rb +0 -47
- data/lib/action_dispatch/journey/nfa/transition_table.rb +0 -163
- data/lib/action_dispatch/journey/router/strexp.rb +0 -27
- data/lib/action_dispatch/middleware/params_parser.rb +0 -60
- data/lib/action_dispatch/middleware/templates/rescues/_source.erb +0 -27
- data/lib/action_dispatch/testing/assertions/dom.rb +0 -3
- data/lib/action_dispatch/testing/assertions/selector.rb +0 -3
- data/lib/action_dispatch/testing/assertions/tag.rb +0 -3
@@ -1,4 +1,8 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# :markup: markdown
|
4
|
+
|
5
|
+
require "action_dispatch/journey/nfa/dot"
|
2
6
|
|
3
7
|
module ActionDispatch
|
4
8
|
module Journey # :nodoc:
|
@@ -8,11 +12,15 @@ module ActionDispatch
|
|
8
12
|
|
9
13
|
attr_reader :memos
|
10
14
|
|
15
|
+
DEFAULT_EXP = /[^.\/?]+/
|
16
|
+
DEFAULT_EXP_ANCHORED = /\A#{DEFAULT_EXP}\Z/
|
17
|
+
|
11
18
|
def initialize
|
12
|
-
@
|
13
|
-
@
|
14
|
-
@
|
15
|
-
@
|
19
|
+
@stdparam_states = {}
|
20
|
+
@regexp_states = {}
|
21
|
+
@string_states = {}
|
22
|
+
@accepting = {}
|
23
|
+
@memos = Hash.new { |h, k| h[k] = [] }
|
16
24
|
end
|
17
25
|
|
18
26
|
def add_accepting(state)
|
@@ -39,24 +47,58 @@ module ActionDispatch
|
|
39
47
|
Array(t)
|
40
48
|
end
|
41
49
|
|
42
|
-
def move(t,
|
50
|
+
def move(t, full_string, start_index, end_index)
|
43
51
|
return [] if t.empty?
|
44
52
|
|
45
|
-
|
53
|
+
next_states = []
|
46
54
|
|
47
|
-
|
48
|
-
|
49
|
-
|
55
|
+
tok = full_string.slice(start_index, end_index - start_index)
|
56
|
+
token_matches_default_component = DEFAULT_EXP_ANCHORED.match?(tok)
|
57
|
+
|
58
|
+
t.each { |s, previous_start|
|
59
|
+
if previous_start.nil?
|
60
|
+
# In the simple case of a "default" param regex do this fast-path and add all
|
61
|
+
# next states.
|
62
|
+
if token_matches_default_component && states = @stdparam_states[s]
|
63
|
+
states.each { |re, v| next_states << [v, nil].freeze if !v.nil? }
|
64
|
+
end
|
65
|
+
|
66
|
+
# When we have a literal string, we can just pull the next state
|
67
|
+
if states = @string_states[s]
|
68
|
+
next_states << [states[tok], nil].freeze unless states[tok].nil?
|
69
|
+
end
|
50
70
|
end
|
51
71
|
|
52
|
-
|
53
|
-
|
72
|
+
# For regexes that aren't the "default" style, they may potentially not be
|
73
|
+
# terminated by the first "token" [./?], so we need to continue to attempt to
|
74
|
+
# match this regexp as well as any successful paths that continue out of it.
|
75
|
+
# both paths could be valid.
|
76
|
+
if states = @regexp_states[s]
|
77
|
+
slice_start = if previous_start.nil?
|
78
|
+
start_index
|
79
|
+
else
|
80
|
+
previous_start
|
81
|
+
end
|
82
|
+
|
83
|
+
slice_length = end_index - slice_start
|
84
|
+
curr_slice = full_string.slice(slice_start, slice_length)
|
85
|
+
|
86
|
+
states.each { |re, v|
|
87
|
+
# if we match, we can try moving past this
|
88
|
+
next_states << [v, nil].freeze if !v.nil? && re.match?(curr_slice)
|
89
|
+
}
|
90
|
+
|
91
|
+
# and regardless, we must continue accepting tokens and retrying this regexp. we
|
92
|
+
# need to remember where we started as well so we can take bigger slices.
|
93
|
+
next_states << [s, slice_start].freeze
|
54
94
|
end
|
55
|
-
}
|
95
|
+
}
|
96
|
+
|
97
|
+
next_states
|
56
98
|
end
|
57
99
|
|
58
100
|
def as_json(options = nil)
|
59
|
-
simple_regexp = Hash.new { |h,k| h[k] = {} }
|
101
|
+
simple_regexp = Hash.new { |h, k| h[k] = {} }
|
60
102
|
|
61
103
|
@regexp_states.each do |from, hash|
|
62
104
|
hash.each do |re, to|
|
@@ -65,90 +107,108 @@ module ActionDispatch
|
|
65
107
|
end
|
66
108
|
|
67
109
|
{
|
68
|
-
regexp_states:
|
69
|
-
string_states:
|
70
|
-
|
110
|
+
regexp_states: simple_regexp,
|
111
|
+
string_states: @string_states,
|
112
|
+
stdparam_states: @stdparam_states,
|
113
|
+
accepting: @accepting
|
71
114
|
}
|
72
115
|
end
|
73
116
|
|
74
117
|
def to_svg
|
75
|
-
svg = IO.popen(
|
118
|
+
svg = IO.popen("dot -Tsvg", "w+") { |f|
|
76
119
|
f.write(to_dot)
|
77
120
|
f.close_write
|
78
121
|
f.readlines
|
79
122
|
}
|
80
123
|
3.times { svg.shift }
|
81
|
-
svg.join.sub(/width="[^"]*"/,
|
124
|
+
svg.join.sub(/width="[^"]*"/, "").sub(/height="[^"]*"/, "")
|
82
125
|
end
|
83
126
|
|
84
|
-
def visualizer(paths, title =
|
85
|
-
viz_dir = File.join
|
86
|
-
fsm_js = File.read File.join(viz_dir,
|
87
|
-
fsm_css = File.read File.join(viz_dir,
|
88
|
-
erb = File.read File.join(viz_dir,
|
127
|
+
def visualizer(paths, title = "FSM")
|
128
|
+
viz_dir = File.join __dir__, "..", "visualizer"
|
129
|
+
fsm_js = File.read File.join(viz_dir, "fsm.js")
|
130
|
+
fsm_css = File.read File.join(viz_dir, "fsm.css")
|
131
|
+
erb = File.read File.join(viz_dir, "index.html.erb")
|
89
132
|
states = "function tt() { return #{to_json}; }"
|
90
133
|
|
91
134
|
fun_routes = paths.sample(3).map do |ast|
|
92
|
-
ast.
|
135
|
+
ast.filter_map { |n|
|
93
136
|
case n
|
94
137
|
when Nodes::Symbol
|
95
138
|
case n.left
|
96
|
-
when
|
97
|
-
when
|
139
|
+
when ":id" then rand(100).to_s
|
140
|
+
when ":format" then %w{ xml json }.sample
|
98
141
|
else
|
99
|
-
|
142
|
+
"omg"
|
100
143
|
end
|
101
144
|
when Nodes::Terminal then n.symbol
|
102
145
|
else
|
103
146
|
nil
|
104
147
|
end
|
105
|
-
}.
|
148
|
+
}.join
|
106
149
|
end
|
107
150
|
|
108
151
|
stylesheets = [fsm_css]
|
109
152
|
svg = to_svg
|
110
153
|
javascripts = [states, fsm_js]
|
111
154
|
|
112
|
-
# Annoying hack for 1.9 warnings
|
113
155
|
fun_routes = fun_routes
|
114
156
|
stylesheets = stylesheets
|
115
157
|
svg = svg
|
116
158
|
javascripts = javascripts
|
117
159
|
|
118
|
-
require
|
160
|
+
require "erb"
|
119
161
|
template = ERB.new erb
|
120
162
|
template.result(binding)
|
121
163
|
end
|
122
164
|
|
123
165
|
def []=(from, to, sym)
|
124
166
|
to_mappings = states_hash_for(sym)[from] ||= {}
|
167
|
+
case sym
|
168
|
+
when Regexp
|
169
|
+
# we must match the whole string to a token boundary
|
170
|
+
if sym == DEFAULT_EXP
|
171
|
+
sym = DEFAULT_EXP_ANCHORED
|
172
|
+
else
|
173
|
+
sym = /\A#{sym}\Z/
|
174
|
+
end
|
175
|
+
when Symbol
|
176
|
+
# account for symbols in the constraints the same as strings
|
177
|
+
sym = sym.to_s
|
178
|
+
end
|
125
179
|
to_mappings[sym] = to
|
126
180
|
end
|
127
181
|
|
128
182
|
def states
|
129
183
|
ss = @string_states.keys + @string_states.values.flat_map(&:values)
|
184
|
+
ps = @stdparam_states.keys + @stdparam_states.values.flat_map(&:values)
|
130
185
|
rs = @regexp_states.keys + @regexp_states.values.flat_map(&:values)
|
131
|
-
(ss + rs).uniq
|
186
|
+
(ss + ps + rs).uniq
|
132
187
|
end
|
133
188
|
|
134
189
|
def transitions
|
135
190
|
@string_states.flat_map { |from, hash|
|
136
191
|
hash.map { |s, to| [from, s, to] }
|
192
|
+
} + @stdparam_states.flat_map { |from, hash|
|
193
|
+
hash.map { |s, to| [from, s, to] }
|
137
194
|
} + @regexp_states.flat_map { |from, hash|
|
138
195
|
hash.map { |s, to| [from, s, to] }
|
139
196
|
}
|
140
197
|
end
|
141
198
|
|
142
199
|
private
|
143
|
-
|
144
200
|
def states_hash_for(sym)
|
145
201
|
case sym
|
146
|
-
when String
|
202
|
+
when String, Symbol
|
147
203
|
@string_states
|
148
204
|
when Regexp
|
149
|
-
|
205
|
+
if sym == DEFAULT_EXP
|
206
|
+
@stdparam_states
|
207
|
+
else
|
208
|
+
@regexp_states
|
209
|
+
end
|
150
210
|
else
|
151
|
-
raise ArgumentError,
|
211
|
+
raise ArgumentError, "unknown symbol: %s" % sym.class
|
152
212
|
end
|
153
213
|
end
|
154
214
|
end
|
@@ -1,4 +1,6 @@
|
|
1
|
-
#
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# :markup: markdown
|
2
4
|
|
3
5
|
module ActionDispatch
|
4
6
|
module Journey # :nodoc:
|
@@ -9,18 +11,7 @@ module ActionDispatch
|
|
9
11
|
" #{from} -> #{to} [label=\"#{sym || 'ε'}\"];"
|
10
12
|
}
|
11
13
|
|
12
|
-
|
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
|
-
<<-eodot
|
14
|
+
<<-eodot
|
24
15
|
digraph nfa {
|
25
16
|
rankdir=LR;
|
26
17
|
node [shape = doublecircle];
|
@@ -28,7 +19,7 @@ digraph nfa {
|
|
28
19
|
node [shape = circle];
|
29
20
|
#{edges.join "\n"}
|
30
21
|
}
|
31
|
-
|
22
|
+
eodot
|
32
23
|
end
|
33
24
|
end
|
34
25
|
end
|
@@ -1,7 +1,70 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# :markup: markdown
|
4
|
+
|
5
|
+
require "action_dispatch/journey/visitors"
|
2
6
|
|
3
7
|
module ActionDispatch
|
4
8
|
module Journey # :nodoc:
|
9
|
+
class Ast # :nodoc:
|
10
|
+
attr_reader :names, :path_params, :tree, :wildcard_options, :terminals
|
11
|
+
alias :root :tree
|
12
|
+
|
13
|
+
def initialize(tree, formatted)
|
14
|
+
@tree = tree
|
15
|
+
@path_params = []
|
16
|
+
@names = []
|
17
|
+
@symbols = []
|
18
|
+
@stars = []
|
19
|
+
@terminals = []
|
20
|
+
@wildcard_options = {}
|
21
|
+
|
22
|
+
visit_tree(formatted)
|
23
|
+
end
|
24
|
+
|
25
|
+
def requirements=(requirements)
|
26
|
+
# inject any regexp requirements for `star` nodes so they can be determined
|
27
|
+
# nullable, which requires knowing if the regex accepts an empty string.
|
28
|
+
(symbols + stars).each do |node|
|
29
|
+
re = requirements[node.to_sym]
|
30
|
+
node.regexp = re if re
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def route=(route)
|
35
|
+
terminals.each { |n| n.memo = route }
|
36
|
+
end
|
37
|
+
|
38
|
+
def glob?
|
39
|
+
stars.any?
|
40
|
+
end
|
41
|
+
|
42
|
+
private
|
43
|
+
attr_reader :symbols, :stars
|
44
|
+
|
45
|
+
def visit_tree(formatted)
|
46
|
+
tree.each do |node|
|
47
|
+
if node.symbol?
|
48
|
+
path_params << node.to_sym
|
49
|
+
names << node.name
|
50
|
+
symbols << node
|
51
|
+
elsif node.star?
|
52
|
+
stars << node
|
53
|
+
|
54
|
+
if formatted != false
|
55
|
+
# Add a constraint for wildcard route to make it non-greedy and match the
|
56
|
+
# optional format part of the route by default.
|
57
|
+
wildcard_options[node.name.to_sym] ||= /.+?/m
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
if node.terminal?
|
62
|
+
terminals << node
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
5
68
|
module Nodes # :nodoc:
|
6
69
|
class Node # :nodoc:
|
7
70
|
include Enumerable
|
@@ -14,15 +77,15 @@ module ActionDispatch
|
|
14
77
|
end
|
15
78
|
|
16
79
|
def each(&block)
|
17
|
-
Visitors::Each.
|
80
|
+
Visitors::Each::INSTANCE.accept(self, block)
|
18
81
|
end
|
19
82
|
|
20
83
|
def to_s
|
21
|
-
Visitors::String.
|
84
|
+
Visitors::String::INSTANCE.accept(self, "")
|
22
85
|
end
|
23
86
|
|
24
87
|
def to_dot
|
25
|
-
Visitors::Dot.
|
88
|
+
Visitors::Dot::INSTANCE.accept(self)
|
26
89
|
end
|
27
90
|
|
28
91
|
def to_sym
|
@@ -30,7 +93,7 @@ module ActionDispatch
|
|
30
93
|
end
|
31
94
|
|
32
95
|
def name
|
33
|
-
left.tr
|
96
|
+
-left.tr("*:", "")
|
34
97
|
end
|
35
98
|
|
36
99
|
def type
|
@@ -39,10 +102,15 @@ module ActionDispatch
|
|
39
102
|
|
40
103
|
def symbol?; false; end
|
41
104
|
def literal?; false; end
|
105
|
+
def terminal?; false; end
|
106
|
+
def star?; false; end
|
107
|
+
def cat?; false; end
|
108
|
+
def group?; false; end
|
42
109
|
end
|
43
110
|
|
44
111
|
class Terminal < Node # :nodoc:
|
45
112
|
alias :symbol :left
|
113
|
+
def terminal?; true; end
|
46
114
|
end
|
47
115
|
|
48
116
|
class Literal < Terminal # :nodoc:
|
@@ -58,28 +126,28 @@ module ActionDispatch
|
|
58
126
|
def literal?; false; end
|
59
127
|
end
|
60
128
|
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
129
|
+
class Slash < Terminal # :nodoc:
|
130
|
+
def type; :SLASH; end
|
131
|
+
end
|
132
|
+
|
133
|
+
class Dot < Terminal # :nodoc:
|
134
|
+
def type; :DOT; end
|
67
135
|
end
|
68
136
|
|
69
137
|
class Symbol < Terminal # :nodoc:
|
70
138
|
attr_accessor :regexp
|
71
139
|
alias :symbol :regexp
|
140
|
+
attr_reader :name
|
72
141
|
|
73
|
-
DEFAULT_EXP = /[
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
def default_regexp?
|
80
|
-
regexp == DEFAULT_EXP
|
142
|
+
DEFAULT_EXP = /[^.\/?]+/
|
143
|
+
GREEDY_EXP = /(.+)/
|
144
|
+
def initialize(left, regexp = DEFAULT_EXP)
|
145
|
+
super(left)
|
146
|
+
@regexp = regexp
|
147
|
+
@name = -left.tr("*:", "")
|
81
148
|
end
|
82
149
|
|
150
|
+
def type; :SYMBOL; end
|
83
151
|
def symbol?; true; end
|
84
152
|
end
|
85
153
|
|
@@ -89,13 +157,24 @@ module ActionDispatch
|
|
89
157
|
|
90
158
|
class Group < Unary # :nodoc:
|
91
159
|
def type; :GROUP; end
|
160
|
+
def group?; true; end
|
92
161
|
end
|
93
162
|
|
94
163
|
class Star < Unary # :nodoc:
|
164
|
+
attr_accessor :regexp
|
165
|
+
|
166
|
+
def initialize(left)
|
167
|
+
super(left)
|
168
|
+
|
169
|
+
# By default wildcard routes are non-greedy and must match something.
|
170
|
+
@regexp = /.+?/m
|
171
|
+
end
|
172
|
+
|
173
|
+
def star?; true; end
|
95
174
|
def type; :STAR; end
|
96
175
|
|
97
176
|
def name
|
98
|
-
left.name.tr
|
177
|
+
left.name.tr "*:", ""
|
99
178
|
end
|
100
179
|
end
|
101
180
|
|
@@ -111,6 +190,7 @@ module ActionDispatch
|
|
111
190
|
end
|
112
191
|
|
113
192
|
class Cat < Binary # :nodoc:
|
193
|
+
def cat?; true; end
|
114
194
|
def type; :CAT; end
|
115
195
|
end
|
116
196
|
|
@@ -1,32 +1,34 @@
|
|
1
1
|
#
|
2
2
|
# DO NOT MODIFY!!!!
|
3
|
-
# This file is automatically generated by Racc 1.4.
|
4
|
-
#
|
5
|
-
|
3
|
+
# This file is automatically generated by Racc 1.4.16 from
|
4
|
+
# Racc grammar file "".
|
5
|
+
|
6
|
+
# :markup: markdown
|
6
7
|
|
7
8
|
require 'racc/parser.rb'
|
8
9
|
|
10
|
+
# :stopdoc:
|
9
11
|
|
10
|
-
require
|
12
|
+
require "action_dispatch/journey/parser_extras"
|
11
13
|
module ActionDispatch
|
12
14
|
module Journey
|
13
15
|
class Parser < Racc::Parser
|
14
16
|
##### State transition tables begin ###
|
15
17
|
|
16
18
|
racc_action_table = [
|
17
|
-
13, 15, 14, 7,
|
18
|
-
14, 7, 17, 16, 8, 13, 15, 14, 7,
|
19
|
-
16, 8, 13, 15, 14, 7,
|
19
|
+
13, 15, 14, 7, 19, 16, 8, 19, 13, 15,
|
20
|
+
14, 7, 17, 16, 8, 13, 15, 14, 7, 21,
|
21
|
+
16, 8, 13, 15, 14, 7, 24, 16, 8 ]
|
20
22
|
|
21
23
|
racc_action_check = [
|
22
|
-
2, 2, 2, 2,
|
23
|
-
|
24
|
-
|
24
|
+
2, 2, 2, 2, 22, 2, 2, 2, 19, 19,
|
25
|
+
19, 19, 1, 19, 19, 7, 7, 7, 7, 17,
|
26
|
+
7, 7, 0, 0, 0, 0, 20, 0, 0 ]
|
25
27
|
|
26
28
|
racc_action_pointer = [
|
27
|
-
|
28
|
-
nil, nil, nil, nil, nil, nil, nil,
|
29
|
-
|
29
|
+
20, 12, -2, nil, nil, nil, nil, 13, nil, nil,
|
30
|
+
nil, nil, nil, nil, nil, nil, nil, 19, nil, 6,
|
31
|
+
20, nil, -5, nil, nil ]
|
30
32
|
|
31
33
|
racc_action_default = [
|
32
34
|
-19, -19, -2, -3, -4, -5, -6, -19, -10, -11,
|
@@ -162,7 +164,7 @@ def _reduce_9(val, _values)
|
|
162
164
|
end
|
163
165
|
|
164
166
|
def _reduce_10(val, _values)
|
165
|
-
Star.new(Symbol.new(val.last))
|
167
|
+
Star.new(Symbol.new(val.last, Symbol::GREEDY_EXP))
|
166
168
|
end
|
167
169
|
|
168
170
|
# reduce 11 omitted
|
@@ -174,7 +176,7 @@ end
|
|
174
176
|
# reduce 14 omitted
|
175
177
|
|
176
178
|
def _reduce_15(val, _values)
|
177
|
-
Slash.new(
|
179
|
+
Slash.new(val.first)
|
178
180
|
end
|
179
181
|
|
180
182
|
def _reduce_16(val, _values)
|
@@ -194,5 +196,5 @@ def _reduce_none(val, _values)
|
|
194
196
|
end
|
195
197
|
|
196
198
|
end # class Parser
|
197
|
-
|
198
|
-
|
199
|
+
end # module Journey
|
200
|
+
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
|
@@ -30,7 +30,7 @@ rule
|
|
30
30
|
| dot
|
31
31
|
;
|
32
32
|
slash
|
33
|
-
: SLASH { Slash.new(
|
33
|
+
: SLASH { Slash.new(val.first) }
|
34
34
|
;
|
35
35
|
symbol
|
36
36
|
: SYMBOL { Symbol.new(val.first) }
|
@@ -45,5 +45,6 @@ rule
|
|
45
45
|
end
|
46
46
|
|
47
47
|
---- header
|
48
|
+
# :stopdoc:
|
48
49
|
|
49
|
-
require
|
50
|
+
require "action_dispatch/journey/parser_extras"
|
@@ -1,11 +1,20 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# :markup: markdown
|
4
|
+
|
5
|
+
require "action_dispatch/journey/scanner"
|
6
|
+
require "action_dispatch/journey/nodes/node"
|
3
7
|
|
4
8
|
module ActionDispatch
|
5
|
-
|
6
|
-
|
9
|
+
# :stopdoc:
|
10
|
+
module Journey
|
11
|
+
class Parser < Racc::Parser
|
7
12
|
include Journey::Nodes
|
8
13
|
|
14
|
+
def self.parse(string)
|
15
|
+
new.parse string
|
16
|
+
end
|
17
|
+
|
9
18
|
def initialize
|
10
19
|
@scanner = Scanner.new
|
11
20
|
end
|
@@ -20,4 +29,5 @@ module ActionDispatch
|
|
20
29
|
end
|
21
30
|
end
|
22
31
|
end
|
32
|
+
# :startdoc:
|
23
33
|
end
|