actionpack 7.2.3 → 8.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +394 -119
- data/lib/abstract_controller/asset_paths.rb +4 -2
- data/lib/abstract_controller/base.rb +11 -5
- data/lib/abstract_controller/caching.rb +6 -3
- data/lib/abstract_controller/callbacks.rb +6 -0
- data/lib/abstract_controller/logger.rb +2 -1
- data/lib/abstract_controller/rendering.rb +0 -1
- data/lib/action_controller/api.rb +1 -0
- data/lib/action_controller/base.rb +3 -2
- data/lib/action_controller/caching.rb +1 -2
- data/lib/action_controller/form_builder.rb +4 -4
- data/lib/action_controller/log_subscriber.rb +22 -3
- data/lib/action_controller/metal/allow_browser.rb +12 -2
- data/lib/action_controller/metal/conditional_get.rb +30 -1
- data/lib/action_controller/metal/data_streaming.rb +5 -5
- data/lib/action_controller/metal/exceptions.rb +5 -0
- data/lib/action_controller/metal/flash.rb +1 -4
- data/lib/action_controller/metal/head.rb +3 -1
- data/lib/action_controller/metal/instrumentation.rb +1 -2
- data/lib/action_controller/metal/live.rb +65 -25
- data/lib/action_controller/metal/permissions_policy.rb +9 -0
- data/lib/action_controller/metal/rate_limiting.rb +39 -9
- data/lib/action_controller/metal/redirecting.rb +105 -13
- data/lib/action_controller/metal/renderers.rb +29 -9
- data/lib/action_controller/metal/rendering.rb +7 -1
- data/lib/action_controller/metal/request_forgery_protection.rb +18 -10
- data/lib/action_controller/metal/rescue.rb +9 -0
- data/lib/action_controller/metal/streaming.rb +5 -84
- data/lib/action_controller/metal/strong_parameters.rb +277 -89
- data/lib/action_controller/railtie.rb +33 -15
- data/lib/action_controller/structured_event_subscriber.rb +116 -0
- data/lib/action_controller/test_case.rb +12 -2
- data/lib/action_dispatch/http/cache.rb +138 -11
- data/lib/action_dispatch/http/content_security_policy.rb +14 -1
- data/lib/action_dispatch/http/filter_parameters.rb +5 -3
- data/lib/action_dispatch/http/mime_negotiation.rb +55 -1
- data/lib/action_dispatch/http/mime_types.rb +1 -0
- data/lib/action_dispatch/http/param_builder.rb +187 -0
- data/lib/action_dispatch/http/param_error.rb +26 -0
- data/lib/action_dispatch/http/parameters.rb +3 -3
- data/lib/action_dispatch/http/permissions_policy.rb +6 -0
- data/lib/action_dispatch/http/query_parser.rb +55 -0
- data/lib/action_dispatch/http/request.rb +70 -21
- data/lib/action_dispatch/http/response.rb +50 -16
- data/lib/action_dispatch/http/url.rb +110 -14
- data/lib/action_dispatch/journey/gtg/simulator.rb +33 -12
- data/lib/action_dispatch/journey/gtg/transition_table.rb +33 -41
- data/lib/action_dispatch/journey/nodes/node.rb +2 -1
- data/lib/action_dispatch/journey/parser.rb +99 -196
- data/lib/action_dispatch/journey/route.rb +45 -31
- data/lib/action_dispatch/journey/router/utils.rb +8 -14
- data/lib/action_dispatch/journey/router.rb +59 -81
- data/lib/action_dispatch/journey/routes.rb +7 -0
- data/lib/action_dispatch/journey/scanner.rb +44 -42
- data/lib/action_dispatch/journey/visitors.rb +55 -23
- data/lib/action_dispatch/journey/visualizer/fsm.js +4 -6
- data/lib/action_dispatch/log_subscriber.rb +7 -3
- data/lib/action_dispatch/middleware/cookies.rb +8 -4
- data/lib/action_dispatch/middleware/debug_exceptions.rb +24 -5
- data/lib/action_dispatch/middleware/debug_view.rb +11 -5
- data/lib/action_dispatch/middleware/exception_wrapper.rb +11 -11
- data/lib/action_dispatch/middleware/executor.rb +12 -2
- data/lib/action_dispatch/middleware/public_exceptions.rb +1 -5
- data/lib/action_dispatch/middleware/remote_ip.rb +11 -5
- data/lib/action_dispatch/middleware/request_id.rb +2 -1
- data/lib/action_dispatch/middleware/session/cache_store.rb +17 -0
- data/lib/action_dispatch/middleware/ssl.rb +13 -3
- data/lib/action_dispatch/middleware/templates/rescues/_copy_button.html.erb +1 -0
- data/lib/action_dispatch/middleware/templates/rescues/_source.html.erb +3 -5
- data/lib/action_dispatch/middleware/templates/rescues/_trace.html.erb +9 -5
- data/lib/action_dispatch/middleware/templates/rescues/blocked_host.html.erb +1 -0
- data/lib/action_dispatch/middleware/templates/rescues/diagnostics.html.erb +1 -0
- data/lib/action_dispatch/middleware/templates/rescues/invalid_statement.html.erb +4 -0
- data/lib/action_dispatch/middleware/templates/rescues/invalid_statement.text.erb +3 -0
- data/lib/action_dispatch/middleware/templates/rescues/layout.erb +50 -0
- data/lib/action_dispatch/middleware/templates/rescues/missing_exact_template.html.erb +1 -0
- data/lib/action_dispatch/middleware/templates/rescues/missing_template.html.erb +1 -0
- data/lib/action_dispatch/middleware/templates/rescues/routing_error.html.erb +1 -0
- data/lib/action_dispatch/middleware/templates/rescues/template_error.html.erb +1 -0
- data/lib/action_dispatch/middleware/templates/rescues/unknown_action.html.erb +1 -0
- data/lib/action_dispatch/railtie.rb +21 -0
- data/lib/action_dispatch/request/session.rb +1 -0
- data/lib/action_dispatch/request/utils.rb +9 -3
- data/lib/action_dispatch/routing/inspector.rb +80 -57
- data/lib/action_dispatch/routing/mapper.rb +404 -223
- data/lib/action_dispatch/routing/polymorphic_routes.rb +2 -2
- data/lib/action_dispatch/routing/redirection.rb +10 -7
- data/lib/action_dispatch/routing/route_set.rb +21 -12
- data/lib/action_dispatch/routing/routes_proxy.rb +1 -0
- data/lib/action_dispatch/structured_event_subscriber.rb +20 -0
- data/lib/action_dispatch/system_test_case.rb +3 -3
- data/lib/action_dispatch/system_testing/browser.rb +12 -21
- data/lib/action_dispatch/system_testing/test_helpers/screenshot_helper.rb +2 -2
- data/lib/action_dispatch/testing/assertions/response.rb +26 -2
- data/lib/action_dispatch/testing/assertions/routing.rb +27 -15
- data/lib/action_dispatch/testing/integration.rb +18 -7
- data/lib/action_dispatch.rb +14 -4
- data/lib/action_pack/gem_version.rb +2 -2
- metadata +18 -48
- data/lib/action_dispatch/journey/parser.y +0 -50
- data/lib/action_dispatch/journey/parser_extras.rb +0 -33
|
@@ -13,7 +13,6 @@ module ActionDispatch
|
|
|
13
13
|
attr_reader :memos
|
|
14
14
|
|
|
15
15
|
DEFAULT_EXP = /[^.\/?]+/
|
|
16
|
-
DEFAULT_EXP_ANCHORED = /\A#{DEFAULT_EXP}\Z/
|
|
17
16
|
|
|
18
17
|
def initialize
|
|
19
18
|
@stdparam_states = {}
|
|
@@ -47,25 +46,27 @@ module ActionDispatch
|
|
|
47
46
|
Array(t)
|
|
48
47
|
end
|
|
49
48
|
|
|
50
|
-
def move(t, full_string, start_index,
|
|
49
|
+
def move(t, full_string, token, start_index, token_matches_default)
|
|
51
50
|
return [] if t.empty?
|
|
52
51
|
|
|
53
52
|
next_states = []
|
|
54
53
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
54
|
+
transitions_count = t.size
|
|
55
|
+
i = 0
|
|
56
|
+
while i < transitions_count
|
|
57
|
+
s = t[i]
|
|
58
|
+
previous_start = t[i + 1]
|
|
59
59
|
if previous_start.nil?
|
|
60
60
|
# In the simple case of a "default" param regex do this fast-path and add all
|
|
61
61
|
# next states.
|
|
62
|
-
if
|
|
63
|
-
|
|
62
|
+
if token_matches_default && std_state = @stdparam_states[s]
|
|
63
|
+
next_states << std_state << nil
|
|
64
64
|
end
|
|
65
65
|
|
|
66
66
|
# When we have a literal string, we can just pull the next state
|
|
67
67
|
if states = @string_states[s]
|
|
68
|
-
|
|
68
|
+
state = states[token]
|
|
69
|
+
next_states << state << nil unless state.nil?
|
|
69
70
|
end
|
|
70
71
|
end
|
|
71
72
|
|
|
@@ -80,19 +81,21 @@ module ActionDispatch
|
|
|
80
81
|
previous_start
|
|
81
82
|
end
|
|
82
83
|
|
|
83
|
-
slice_length =
|
|
84
|
+
slice_length = start_index + token.length - slice_start
|
|
84
85
|
curr_slice = full_string.slice(slice_start, slice_length)
|
|
85
86
|
|
|
86
87
|
states.each { |re, v|
|
|
87
88
|
# if we match, we can try moving past this
|
|
88
|
-
next_states <<
|
|
89
|
+
next_states << v << nil if !v.nil? && re.match?(curr_slice)
|
|
89
90
|
}
|
|
90
91
|
|
|
91
92
|
# and regardless, we must continue accepting tokens and retrying this regexp. we
|
|
92
93
|
# need to remember where we started as well so we can take bigger slices.
|
|
93
|
-
next_states <<
|
|
94
|
+
next_states << s << slice_start
|
|
94
95
|
end
|
|
95
|
-
|
|
96
|
+
|
|
97
|
+
i += 2
|
|
98
|
+
end
|
|
96
99
|
|
|
97
100
|
next_states
|
|
98
101
|
end
|
|
@@ -163,54 +166,43 @@ module ActionDispatch
|
|
|
163
166
|
end
|
|
164
167
|
|
|
165
168
|
def []=(from, to, sym)
|
|
166
|
-
to_mappings = states_hash_for(sym)[from] ||= {}
|
|
167
169
|
case sym
|
|
170
|
+
when String, Symbol
|
|
171
|
+
to_mapping = @string_states[from] ||= {}
|
|
172
|
+
# account for symbols in the constraints the same as strings
|
|
173
|
+
to_mapping[sym.to_s] = to
|
|
168
174
|
when Regexp
|
|
169
|
-
# we must match the whole string to a token boundary
|
|
170
175
|
if sym == DEFAULT_EXP
|
|
171
|
-
|
|
176
|
+
@stdparam_states[from] = to
|
|
172
177
|
else
|
|
173
|
-
|
|
178
|
+
to_mapping = @regexp_states[from] ||= {}
|
|
179
|
+
# we must match the whole string to a token boundary
|
|
180
|
+
to_mapping[/\A#{sym}\Z/] = to
|
|
174
181
|
end
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
sym = sym.to_s
|
|
182
|
+
else
|
|
183
|
+
raise ArgumentError, "unknown symbol: %s" % sym.class
|
|
178
184
|
end
|
|
179
|
-
to_mappings[sym] = to
|
|
180
185
|
end
|
|
181
186
|
|
|
182
187
|
def states
|
|
183
188
|
ss = @string_states.keys + @string_states.values.flat_map(&:values)
|
|
184
|
-
ps = @stdparam_states.keys + @stdparam_states.values
|
|
189
|
+
ps = @stdparam_states.keys + @stdparam_states.values
|
|
185
190
|
rs = @regexp_states.keys + @regexp_states.values.flat_map(&:values)
|
|
186
191
|
(ss + ps + rs).uniq
|
|
187
192
|
end
|
|
188
193
|
|
|
189
194
|
def transitions
|
|
195
|
+
# double escaped because dot evaluates escapes
|
|
196
|
+
default_exp_anchored = "\\\\A#{DEFAULT_EXP.source}\\\\Z"
|
|
197
|
+
|
|
190
198
|
@string_states.flat_map { |from, hash|
|
|
191
199
|
hash.map { |s, to| [from, s, to] }
|
|
192
|
-
} + @stdparam_states.
|
|
193
|
-
|
|
200
|
+
} + @stdparam_states.map { |from, to|
|
|
201
|
+
[from, default_exp_anchored, to]
|
|
194
202
|
} + @regexp_states.flat_map { |from, hash|
|
|
195
|
-
hash.map { |
|
|
203
|
+
hash.map { |r, to| [from, r.source.gsub("\\") { "\\\\" }, to] }
|
|
196
204
|
}
|
|
197
205
|
end
|
|
198
|
-
|
|
199
|
-
private
|
|
200
|
-
def states_hash_for(sym)
|
|
201
|
-
case sym
|
|
202
|
-
when String, Symbol
|
|
203
|
-
@string_states
|
|
204
|
-
when Regexp
|
|
205
|
-
if sym == DEFAULT_EXP
|
|
206
|
-
@stdparam_states
|
|
207
|
-
else
|
|
208
|
-
@regexp_states
|
|
209
|
-
end
|
|
210
|
-
else
|
|
211
|
-
raise ArgumentError, "unknown symbol: %s" % sym.class
|
|
212
|
-
end
|
|
213
|
-
end
|
|
214
206
|
end
|
|
215
207
|
end
|
|
216
208
|
end
|
|
@@ -74,6 +74,7 @@ module ActionDispatch
|
|
|
74
74
|
def initialize(left)
|
|
75
75
|
@left = left
|
|
76
76
|
@memo = nil
|
|
77
|
+
@to_s = nil
|
|
77
78
|
end
|
|
78
79
|
|
|
79
80
|
def each(&block)
|
|
@@ -81,7 +82,7 @@ module ActionDispatch
|
|
|
81
82
|
end
|
|
82
83
|
|
|
83
84
|
def to_s
|
|
84
|
-
Visitors::String::INSTANCE.accept(self, "")
|
|
85
|
+
@to_s ||= Visitors::String::INSTANCE.accept(self, "".dup).freeze
|
|
85
86
|
end
|
|
86
87
|
|
|
87
88
|
def to_dot
|
|
@@ -1,200 +1,103 @@
|
|
|
1
|
-
#
|
|
2
|
-
# DO NOT MODIFY!!!!
|
|
3
|
-
# This file is automatically generated by Racc 1.4.16 from
|
|
4
|
-
# Racc grammar file "".
|
|
1
|
+
# frozen_string_literal: true
|
|
5
2
|
|
|
6
|
-
|
|
3
|
+
require "action_dispatch/journey/scanner"
|
|
4
|
+
require "action_dispatch/journey/nodes/node"
|
|
7
5
|
|
|
8
|
-
require 'racc/parser.rb'
|
|
9
|
-
|
|
10
|
-
# :stopdoc:
|
|
11
|
-
|
|
12
|
-
require "action_dispatch/journey/parser_extras"
|
|
13
6
|
module ActionDispatch
|
|
14
|
-
module Journey
|
|
15
|
-
class Parser
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
"$end",
|
|
111
|
-
"error",
|
|
112
|
-
"SLASH",
|
|
113
|
-
"LITERAL",
|
|
114
|
-
"SYMBOL",
|
|
115
|
-
"LPAREN",
|
|
116
|
-
"RPAREN",
|
|
117
|
-
"DOT",
|
|
118
|
-
"STAR",
|
|
119
|
-
"OR",
|
|
120
|
-
"$start",
|
|
121
|
-
"expressions",
|
|
122
|
-
"expression",
|
|
123
|
-
"or",
|
|
124
|
-
"terminal",
|
|
125
|
-
"group",
|
|
126
|
-
"star",
|
|
127
|
-
"symbol",
|
|
128
|
-
"literal",
|
|
129
|
-
"slash",
|
|
130
|
-
"dot" ]
|
|
131
|
-
|
|
132
|
-
Racc_debug_parser = false
|
|
133
|
-
|
|
134
|
-
##### State transition tables end #####
|
|
135
|
-
|
|
136
|
-
# reduce 0 omitted
|
|
137
|
-
|
|
138
|
-
def _reduce_1(val, _values)
|
|
139
|
-
Cat.new(val.first, val.last)
|
|
140
|
-
end
|
|
141
|
-
|
|
142
|
-
def _reduce_2(val, _values)
|
|
143
|
-
val.first
|
|
144
|
-
end
|
|
145
|
-
|
|
146
|
-
# reduce 3 omitted
|
|
147
|
-
|
|
148
|
-
# reduce 4 omitted
|
|
149
|
-
|
|
150
|
-
# reduce 5 omitted
|
|
151
|
-
|
|
152
|
-
# reduce 6 omitted
|
|
153
|
-
|
|
154
|
-
def _reduce_7(val, _values)
|
|
155
|
-
Group.new(val[1])
|
|
156
|
-
end
|
|
157
|
-
|
|
158
|
-
def _reduce_8(val, _values)
|
|
159
|
-
Or.new([val.first, val.last])
|
|
160
|
-
end
|
|
161
|
-
|
|
162
|
-
def _reduce_9(val, _values)
|
|
163
|
-
Or.new([val.first, val.last])
|
|
164
|
-
end
|
|
165
|
-
|
|
166
|
-
def _reduce_10(val, _values)
|
|
167
|
-
Star.new(Symbol.new(val.last, Symbol::GREEDY_EXP))
|
|
7
|
+
module Journey # :nodoc:
|
|
8
|
+
class Parser # :nodoc:
|
|
9
|
+
include Journey::Nodes
|
|
10
|
+
|
|
11
|
+
def self.parse(string)
|
|
12
|
+
new.parse string
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def initialize
|
|
16
|
+
@scanner = Scanner.new
|
|
17
|
+
@next_token = nil
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def parse(string)
|
|
21
|
+
@scanner.scan_setup(string)
|
|
22
|
+
advance_token
|
|
23
|
+
do_parse
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
private
|
|
27
|
+
def advance_token
|
|
28
|
+
@next_token = @scanner.next_token
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def do_parse
|
|
32
|
+
parse_expressions
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def parse_expressions
|
|
36
|
+
node = parse_expression
|
|
37
|
+
|
|
38
|
+
while @next_token
|
|
39
|
+
case @next_token
|
|
40
|
+
when :RPAREN
|
|
41
|
+
break
|
|
42
|
+
when :OR
|
|
43
|
+
node = parse_or(node)
|
|
44
|
+
else
|
|
45
|
+
node = Cat.new(node, parse_expressions)
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
node
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def parse_or(lhs)
|
|
53
|
+
advance_token
|
|
54
|
+
node = parse_expression
|
|
55
|
+
Or.new([lhs, node])
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def parse_expression
|
|
59
|
+
if @next_token == :STAR
|
|
60
|
+
parse_star
|
|
61
|
+
elsif @next_token == :LPAREN
|
|
62
|
+
parse_group
|
|
63
|
+
else
|
|
64
|
+
parse_terminal
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def parse_star
|
|
69
|
+
node = Star.new(Symbol.new(@scanner.last_string, Symbol::GREEDY_EXP))
|
|
70
|
+
advance_token
|
|
71
|
+
node
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def parse_group
|
|
75
|
+
advance_token
|
|
76
|
+
node = parse_expressions
|
|
77
|
+
if @next_token == :RPAREN
|
|
78
|
+
node = Group.new(node)
|
|
79
|
+
advance_token
|
|
80
|
+
node
|
|
81
|
+
else
|
|
82
|
+
raise ArgumentError, "missing right parenthesis."
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def parse_terminal
|
|
87
|
+
node = case @next_token
|
|
88
|
+
when :SYMBOL
|
|
89
|
+
Symbol.new(@scanner.last_string)
|
|
90
|
+
when :LITERAL
|
|
91
|
+
Literal.new(@scanner.last_literal)
|
|
92
|
+
when :SLASH
|
|
93
|
+
Slash.new("/")
|
|
94
|
+
when :DOT
|
|
95
|
+
Dot.new(".")
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
advance_token
|
|
99
|
+
node
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
end
|
|
168
103
|
end
|
|
169
|
-
|
|
170
|
-
# reduce 11 omitted
|
|
171
|
-
|
|
172
|
-
# reduce 12 omitted
|
|
173
|
-
|
|
174
|
-
# reduce 13 omitted
|
|
175
|
-
|
|
176
|
-
# reduce 14 omitted
|
|
177
|
-
|
|
178
|
-
def _reduce_15(val, _values)
|
|
179
|
-
Slash.new(val.first)
|
|
180
|
-
end
|
|
181
|
-
|
|
182
|
-
def _reduce_16(val, _values)
|
|
183
|
-
Symbol.new(val.first)
|
|
184
|
-
end
|
|
185
|
-
|
|
186
|
-
def _reduce_17(val, _values)
|
|
187
|
-
Literal.new(val.first)
|
|
188
|
-
end
|
|
189
|
-
|
|
190
|
-
def _reduce_18(val, _values)
|
|
191
|
-
Dot.new(val.first)
|
|
192
|
-
end
|
|
193
|
-
|
|
194
|
-
def _reduce_none(val, _values)
|
|
195
|
-
val[0]
|
|
196
|
-
end
|
|
197
|
-
|
|
198
|
-
end # class Parser
|
|
199
|
-
end # module Journey
|
|
200
|
-
end # module ActionDispatch
|
|
@@ -38,29 +38,50 @@ module ActionDispatch
|
|
|
38
38
|
def self.verb; ""; end
|
|
39
39
|
end
|
|
40
40
|
|
|
41
|
+
class Or
|
|
42
|
+
attr_reader :verb
|
|
43
|
+
|
|
44
|
+
def initialize(verbs)
|
|
45
|
+
@verbs = verbs
|
|
46
|
+
@verb = @verbs.map(&:verb).join("|")
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def call(req)
|
|
50
|
+
@verbs.any? { |v| v.call req }
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
41
54
|
VERB_TO_CLASS = VERBS.each_with_object(all: All) do |verb, hash|
|
|
42
55
|
klass = const_get verb
|
|
43
56
|
hash[verb] = klass
|
|
44
57
|
hash[verb.downcase] = klass
|
|
45
58
|
hash[verb.downcase.to_sym] = klass
|
|
46
59
|
end
|
|
47
|
-
end
|
|
48
60
|
|
|
49
|
-
|
|
50
|
-
VerbMatchers::VERB_TO_CLASS.fetch(verb) do
|
|
61
|
+
VERB_TO_CLASS.default_proc = proc do |_, verb|
|
|
51
62
|
VerbMatchers::Unknown.new verb.to_s.dasherize.upcase
|
|
52
63
|
end
|
|
64
|
+
|
|
65
|
+
def self.for(verbs)
|
|
66
|
+
if verbs.any? { |v| VERB_TO_CLASS[v] == All }
|
|
67
|
+
All
|
|
68
|
+
elsif verbs.one?
|
|
69
|
+
VERB_TO_CLASS[verbs.first]
|
|
70
|
+
else
|
|
71
|
+
Or.new(verbs.map { |v| VERB_TO_CLASS[v] })
|
|
72
|
+
end
|
|
73
|
+
end
|
|
53
74
|
end
|
|
54
75
|
|
|
55
76
|
##
|
|
56
77
|
# +path+ is a path constraint.
|
|
57
78
|
# `constraints` is a hash of constraints to be applied to this route.
|
|
58
|
-
def initialize(name:, app: nil, path:, constraints: {}, required_defaults: [], defaults: {},
|
|
79
|
+
def initialize(name:, app: nil, path:, constraints: {}, required_defaults: [], defaults: {}, via: nil, precedence: 0, scope_options: {}, internal: false, source_location: nil)
|
|
59
80
|
@name = name
|
|
60
81
|
@app = app
|
|
61
82
|
@path = path
|
|
62
83
|
|
|
63
|
-
@request_method_match =
|
|
84
|
+
@request_method_match = via && VerbMatchers.for(via)
|
|
64
85
|
@constraints = constraints
|
|
65
86
|
@defaults = defaults
|
|
66
87
|
@required_defaults = nil
|
|
@@ -146,21 +167,23 @@ module ActionDispatch
|
|
|
146
167
|
end
|
|
147
168
|
|
|
148
169
|
def matches?(request)
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
170
|
+
@request_method_match.call(request) && (
|
|
171
|
+
constraints.empty? ||
|
|
172
|
+
constraints.all? { |method, value|
|
|
173
|
+
case value
|
|
174
|
+
when Regexp, String
|
|
175
|
+
value === request.send(method).to_s
|
|
176
|
+
when Array
|
|
177
|
+
value.include?(request.send(method))
|
|
178
|
+
when TrueClass
|
|
179
|
+
request.send(method).present?
|
|
180
|
+
when FalseClass
|
|
181
|
+
request.send(method).blank?
|
|
182
|
+
else
|
|
183
|
+
value === request.send(method)
|
|
184
|
+
end
|
|
185
|
+
}
|
|
186
|
+
)
|
|
164
187
|
end
|
|
165
188
|
|
|
166
189
|
def ip
|
|
@@ -168,21 +191,12 @@ module ActionDispatch
|
|
|
168
191
|
end
|
|
169
192
|
|
|
170
193
|
def requires_matching_verb?
|
|
171
|
-
|
|
194
|
+
@request_method_match != VerbMatchers::All
|
|
172
195
|
end
|
|
173
196
|
|
|
174
197
|
def verb
|
|
175
|
-
|
|
198
|
+
@request_method_match.verb
|
|
176
199
|
end
|
|
177
|
-
|
|
178
|
-
private
|
|
179
|
-
def verbs
|
|
180
|
-
@request_method_match.map(&:verb)
|
|
181
|
-
end
|
|
182
|
-
|
|
183
|
-
def match_verb(request)
|
|
184
|
-
@request_method_match.any? { |m| m.call request }
|
|
185
|
-
end
|
|
186
200
|
end
|
|
187
201
|
end
|
|
188
202
|
# :startdoc:
|
|
@@ -17,7 +17,14 @@ module ActionDispatch
|
|
|
17
17
|
# normalize_path("") # => "/"
|
|
18
18
|
# normalize_path("/%ab") # => "/%AB"
|
|
19
19
|
def self.normalize_path(path)
|
|
20
|
-
|
|
20
|
+
return "/".dup unless path
|
|
21
|
+
|
|
22
|
+
# Fast path for the overwhelming majority of paths that don't need to be normalized
|
|
23
|
+
if path == "/" || (path.start_with?("/") && !path.end_with?("/") && !path.match?(%r{%|//}))
|
|
24
|
+
return path.dup
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# Slow path
|
|
21
28
|
encoding = path.encoding
|
|
22
29
|
path = +"/#{path}"
|
|
23
30
|
path.squeeze!("/")
|
|
@@ -61,11 +68,6 @@ module ActionDispatch
|
|
|
61
68
|
escape(segment, SEGMENT)
|
|
62
69
|
end
|
|
63
70
|
|
|
64
|
-
def unescape_uri(uri)
|
|
65
|
-
encoding = uri.encoding == US_ASCII ? UTF_8 : uri.encoding
|
|
66
|
-
uri.gsub(ESCAPED) { |match| [match[1, 2].hex].pack("C") }.force_encoding(encoding)
|
|
67
|
-
end
|
|
68
|
-
|
|
69
71
|
private
|
|
70
72
|
def escape(component, pattern)
|
|
71
73
|
component.gsub(pattern) { |unsafe| percent_encode(unsafe) }.force_encoding(US_ASCII)
|
|
@@ -91,14 +93,6 @@ module ActionDispatch
|
|
|
91
93
|
def self.escape_fragment(fragment)
|
|
92
94
|
ENCODER.escape_fragment(fragment.to_s)
|
|
93
95
|
end
|
|
94
|
-
|
|
95
|
-
# Replaces any escaped sequences with their unescaped representations.
|
|
96
|
-
#
|
|
97
|
-
# uri = "/topics?title=Ruby%20on%20Rails"
|
|
98
|
-
# unescape_uri(uri) #=> "/topics?title=Ruby on Rails"
|
|
99
|
-
def self.unescape_uri(uri)
|
|
100
|
-
ENCODER.unescape_uri(uri)
|
|
101
|
-
end
|
|
102
96
|
end
|
|
103
97
|
end
|
|
104
98
|
end
|