actionpack 4.2.11.1 → 5.2.4.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +287 -488
- data/MIT-LICENSE +1 -1
- data/README.rdoc +6 -7
- data/lib/abstract_controller/asset_paths.rb +2 -0
- data/lib/abstract_controller/base.rb +45 -49
- data/lib/{action_controller → abstract_controller}/caching/fragments.rb +78 -15
- data/lib/abstract_controller/caching.rb +66 -0
- data/lib/abstract_controller/callbacks.rb +47 -31
- data/lib/abstract_controller/collector.rb +8 -11
- data/lib/abstract_controller/error.rb +6 -0
- data/lib/abstract_controller/helpers.rb +25 -25
- data/lib/abstract_controller/logger.rb +2 -0
- data/lib/abstract_controller/railties/routes_helpers.rb +4 -2
- data/lib/abstract_controller/rendering.rb +42 -41
- data/lib/abstract_controller/translation.rb +10 -7
- data/lib/abstract_controller/url_for.rb +2 -0
- data/lib/abstract_controller.rb +12 -5
- data/lib/action_controller/api/api_rendering.rb +16 -0
- data/lib/action_controller/api.rb +149 -0
- data/lib/action_controller/base.rb +27 -19
- data/lib/action_controller/caching.rb +14 -57
- data/lib/action_controller/form_builder.rb +50 -0
- data/lib/action_controller/log_subscriber.rb +10 -15
- data/lib/action_controller/metal/basic_implicit_render.rb +13 -0
- data/lib/action_controller/metal/conditional_get.rb +118 -44
- data/lib/action_controller/metal/content_security_policy.rb +52 -0
- data/lib/action_controller/metal/cookies.rb +3 -3
- data/lib/action_controller/metal/data_streaming.rb +27 -46
- data/lib/action_controller/metal/etag_with_flash.rb +18 -0
- data/lib/action_controller/metal/etag_with_template_digest.rb +20 -13
- data/lib/action_controller/metal/exceptions.rb +8 -14
- data/lib/action_controller/metal/flash.rb +4 -3
- data/lib/action_controller/metal/force_ssl.rb +23 -21
- data/lib/action_controller/metal/head.rb +21 -19
- data/lib/action_controller/metal/helpers.rb +24 -14
- data/lib/action_controller/metal/http_authentication.rb +64 -57
- data/lib/action_controller/metal/implicit_render.rb +62 -8
- data/lib/action_controller/metal/instrumentation.rb +19 -21
- data/lib/action_controller/metal/live.rb +90 -106
- data/lib/action_controller/metal/mime_responds.rb +33 -46
- data/lib/action_controller/metal/parameter_encoding.rb +51 -0
- data/lib/action_controller/metal/params_wrapper.rb +61 -53
- data/lib/action_controller/metal/redirecting.rb +49 -28
- data/lib/action_controller/metal/renderers.rb +87 -44
- data/lib/action_controller/metal/rendering.rb +72 -50
- data/lib/action_controller/metal/request_forgery_protection.rb +229 -93
- data/lib/action_controller/metal/rescue.rb +9 -16
- data/lib/action_controller/metal/streaming.rb +12 -10
- data/lib/action_controller/metal/strong_parameters.rb +583 -164
- data/lib/action_controller/metal/testing.rb +2 -17
- data/lib/action_controller/metal/url_for.rb +19 -10
- data/lib/action_controller/metal.rb +98 -83
- data/lib/action_controller/railtie.rb +28 -10
- data/lib/action_controller/railties/helpers.rb +2 -0
- data/lib/action_controller/renderer.rb +117 -0
- data/lib/action_controller/template_assertions.rb +11 -0
- data/lib/action_controller/test_case.rb +280 -411
- data/lib/action_controller.rb +29 -21
- data/lib/action_dispatch/http/cache.rb +93 -47
- data/lib/action_dispatch/http/content_security_policy.rb +272 -0
- data/lib/action_dispatch/http/filter_parameters.rb +26 -20
- data/lib/action_dispatch/http/filter_redirect.rb +10 -11
- data/lib/action_dispatch/http/headers.rb +55 -22
- data/lib/action_dispatch/http/mime_negotiation.rb +56 -41
- data/lib/action_dispatch/http/mime_type.rb +134 -121
- data/lib/action_dispatch/http/mime_types.rb +20 -6
- data/lib/action_dispatch/http/parameter_filter.rb +25 -11
- data/lib/action_dispatch/http/parameters.rb +98 -39
- data/lib/action_dispatch/http/rack_cache.rb +2 -0
- data/lib/action_dispatch/http/request.rb +200 -118
- data/lib/action_dispatch/http/response.rb +225 -110
- data/lib/action_dispatch/http/upload.rb +12 -6
- data/lib/action_dispatch/http/url.rb +110 -28
- data/lib/action_dispatch/journey/formatter.rb +55 -32
- data/lib/action_dispatch/journey/gtg/builder.rb +7 -5
- data/lib/action_dispatch/journey/gtg/simulator.rb +3 -9
- data/lib/action_dispatch/journey/gtg/transition_table.rb +17 -16
- data/lib/action_dispatch/journey/nfa/builder.rb +5 -3
- data/lib/action_dispatch/journey/nfa/dot.rb +13 -13
- data/lib/action_dispatch/journey/nfa/simulator.rb +3 -1
- data/lib/action_dispatch/journey/nfa/transition_table.rb +5 -48
- data/lib/action_dispatch/journey/nodes/node.rb +18 -6
- data/lib/action_dispatch/journey/parser.rb +23 -22
- data/lib/action_dispatch/journey/parser.y +3 -2
- data/lib/action_dispatch/journey/parser_extras.rb +12 -4
- data/lib/action_dispatch/journey/path/pattern.rb +50 -44
- data/lib/action_dispatch/journey/route.rb +106 -28
- data/lib/action_dispatch/journey/router/utils.rb +20 -11
- data/lib/action_dispatch/journey/router.rb +35 -23
- data/lib/action_dispatch/journey/routes.rb +18 -16
- data/lib/action_dispatch/journey/scanner.rb +18 -15
- data/lib/action_dispatch/journey/visitors.rb +99 -52
- data/lib/action_dispatch/journey.rb +7 -5
- data/lib/action_dispatch/middleware/callbacks.rb +1 -2
- data/lib/action_dispatch/middleware/cookies.rb +304 -193
- data/lib/action_dispatch/middleware/debug_exceptions.rb +152 -57
- data/lib/action_dispatch/middleware/debug_locks.rb +124 -0
- data/lib/action_dispatch/middleware/exception_wrapper.rb +68 -69
- data/lib/action_dispatch/middleware/executor.rb +21 -0
- data/lib/action_dispatch/middleware/flash.rb +78 -54
- data/lib/action_dispatch/middleware/public_exceptions.rb +27 -25
- data/lib/action_dispatch/middleware/reloader.rb +5 -91
- data/lib/action_dispatch/middleware/remote_ip.rb +41 -31
- data/lib/action_dispatch/middleware/request_id.rb +17 -9
- data/lib/action_dispatch/middleware/session/abstract_store.rb +41 -25
- data/lib/action_dispatch/middleware/session/cache_store.rb +24 -14
- data/lib/action_dispatch/middleware/session/cookie_store.rb +72 -67
- data/lib/action_dispatch/middleware/session/mem_cache_store.rb +8 -2
- data/lib/action_dispatch/middleware/show_exceptions.rb +26 -22
- data/lib/action_dispatch/middleware/ssl.rb +114 -36
- data/lib/action_dispatch/middleware/stack.rb +31 -44
- data/lib/action_dispatch/middleware/static.rb +57 -50
- data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.html.erb +2 -14
- data/lib/action_dispatch/middleware/templates/rescues/{_source.erb → _source.html.erb} +0 -0
- data/lib/action_dispatch/middleware/templates/rescues/_source.text.erb +8 -0
- data/lib/action_dispatch/middleware/templates/rescues/invalid_statement.html.erb +21 -0
- data/lib/action_dispatch/middleware/templates/rescues/invalid_statement.text.erb +13 -0
- data/lib/action_dispatch/middleware/templates/rescues/layout.erb +1 -0
- data/lib/action_dispatch/middleware/templates/rescues/template_error.html.erb +1 -1
- data/lib/action_dispatch/middleware/templates/rescues/template_error.text.erb +1 -1
- data/lib/action_dispatch/middleware/templates/routes/_route.html.erb +4 -4
- data/lib/action_dispatch/middleware/templates/routes/_table.html.erb +64 -64
- data/lib/action_dispatch/railtie.rb +19 -11
- data/lib/action_dispatch/request/session.rb +106 -59
- data/lib/action_dispatch/request/utils.rb +67 -24
- data/lib/action_dispatch/routing/endpoint.rb +9 -2
- data/lib/action_dispatch/routing/inspector.rb +58 -67
- data/lib/action_dispatch/routing/mapper.rb +733 -447
- data/lib/action_dispatch/routing/polymorphic_routes.rb +161 -139
- data/lib/action_dispatch/routing/redirection.rb +36 -26
- data/lib/action_dispatch/routing/route_set.rb +321 -291
- data/lib/action_dispatch/routing/routes_proxy.rb +32 -5
- data/lib/action_dispatch/routing/url_for.rb +65 -25
- data/lib/action_dispatch/routing.rb +17 -18
- data/lib/action_dispatch/system_test_case.rb +147 -0
- data/lib/action_dispatch/system_testing/browser.rb +49 -0
- data/lib/action_dispatch/system_testing/driver.rb +59 -0
- data/lib/action_dispatch/system_testing/server.rb +31 -0
- data/lib/action_dispatch/system_testing/test_helpers/screenshot_helper.rb +96 -0
- data/lib/action_dispatch/system_testing/test_helpers/setup_and_teardown.rb +31 -0
- data/lib/action_dispatch/system_testing/test_helpers/undef_methods.rb +26 -0
- data/lib/action_dispatch/testing/assertion_response.rb +47 -0
- data/lib/action_dispatch/testing/assertions/response.rb +45 -20
- data/lib/action_dispatch/testing/assertions/routing.rb +30 -26
- data/lib/action_dispatch/testing/assertions.rb +6 -4
- data/lib/action_dispatch/testing/integration.rb +347 -209
- data/lib/action_dispatch/testing/request_encoder.rb +55 -0
- data/lib/action_dispatch/testing/test_process.rb +28 -22
- data/lib/action_dispatch/testing/test_request.rb +27 -34
- data/lib/action_dispatch/testing/test_response.rb +35 -7
- data/lib/action_dispatch.rb +27 -19
- data/lib/action_pack/gem_version.rb +5 -3
- data/lib/action_pack/version.rb +3 -1
- data/lib/action_pack.rb +4 -2
- metadata +56 -38
- 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/journey/backwards.rb +0 -5
- data/lib/action_dispatch/journey/router/strexp.rb +0 -27
- data/lib/action_dispatch/middleware/params_parser.rb +0 -60
- 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,6 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "action_dispatch/journey/nfa/dot"
|
2
4
|
|
3
5
|
module ActionDispatch
|
4
6
|
module Journey # :nodoc:
|
@@ -10,7 +12,7 @@ module ActionDispatch
|
|
10
12
|
attr_reader :memos
|
11
13
|
|
12
14
|
def initialize
|
13
|
-
@table = Hash.new { |h,f| h[f] = {} }
|
15
|
+
@table = Hash.new { |h, f| h[f] = {} }
|
14
16
|
@memos = {}
|
15
17
|
@accepting = nil
|
16
18
|
@inverted = nil
|
@@ -45,51 +47,6 @@ module ActionDispatch
|
|
45
47
|
(@table.keys + @table.values.flat_map(&:keys)).uniq
|
46
48
|
end
|
47
49
|
|
48
|
-
# Returns a generalized transition graph with reduced states. The states
|
49
|
-
# are reduced like a DFA, but the table must be simulated like an NFA.
|
50
|
-
#
|
51
|
-
# Edges of the GTG are regular expressions.
|
52
|
-
def generalized_table
|
53
|
-
gt = GTG::TransitionTable.new
|
54
|
-
marked = {}
|
55
|
-
state_id = Hash.new { |h,k| h[k] = h.length }
|
56
|
-
alphabet = self.alphabet
|
57
|
-
|
58
|
-
stack = [eclosure(0)]
|
59
|
-
|
60
|
-
until stack.empty?
|
61
|
-
state = stack.pop
|
62
|
-
next if marked[state] || state.empty?
|
63
|
-
|
64
|
-
marked[state] = true
|
65
|
-
|
66
|
-
alphabet.each do |alpha|
|
67
|
-
next_state = eclosure(following_states(state, alpha))
|
68
|
-
next if next_state.empty?
|
69
|
-
|
70
|
-
gt[state_id[state], state_id[next_state]] = alpha
|
71
|
-
stack << next_state
|
72
|
-
end
|
73
|
-
end
|
74
|
-
|
75
|
-
final_groups = state_id.keys.find_all { |s|
|
76
|
-
s.sort.last == accepting
|
77
|
-
}
|
78
|
-
|
79
|
-
final_groups.each do |states|
|
80
|
-
id = state_id[states]
|
81
|
-
|
82
|
-
gt.add_accepting(id)
|
83
|
-
save = states.find { |s|
|
84
|
-
@memos.key?(s) && eclosure(s).sort.last == accepting
|
85
|
-
}
|
86
|
-
|
87
|
-
gt.add_memo(id, memo(save))
|
88
|
-
end
|
89
|
-
|
90
|
-
gt
|
91
|
-
end
|
92
|
-
|
93
50
|
# Returns set of NFA states to which there is a transition on ast symbol
|
94
51
|
# +a+ from some state +s+ in +t+.
|
95
52
|
def following_states(t, a)
|
@@ -107,7 +64,7 @@ module ActionDispatch
|
|
107
64
|
end
|
108
65
|
|
109
66
|
def alphabet
|
110
|
-
inverted.values.flat_map(&:keys).compact.uniq.sort_by
|
67
|
+
inverted.values.flat_map(&:keys).compact.uniq.sort_by(&:to_s)
|
111
68
|
end
|
112
69
|
|
113
70
|
# Returns a set of NFA states reachable from some NFA state +s+ in set
|
@@ -1,4 +1,6 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "action_dispatch/journey/visitors"
|
2
4
|
|
3
5
|
module ActionDispatch
|
4
6
|
module Journey # :nodoc:
|
@@ -14,15 +16,15 @@ module ActionDispatch
|
|
14
16
|
end
|
15
17
|
|
16
18
|
def each(&block)
|
17
|
-
Visitors::Each.
|
19
|
+
Visitors::Each::INSTANCE.accept(self, block)
|
18
20
|
end
|
19
21
|
|
20
22
|
def to_s
|
21
|
-
Visitors::String.
|
23
|
+
Visitors::String::INSTANCE.accept(self, "")
|
22
24
|
end
|
23
25
|
|
24
26
|
def to_dot
|
25
|
-
Visitors::Dot.
|
27
|
+
Visitors::Dot::INSTANCE.accept(self)
|
26
28
|
end
|
27
29
|
|
28
30
|
def to_sym
|
@@ -30,7 +32,7 @@ module ActionDispatch
|
|
30
32
|
end
|
31
33
|
|
32
34
|
def name
|
33
|
-
left.tr
|
35
|
+
left.tr "*:".freeze, "".freeze
|
34
36
|
end
|
35
37
|
|
36
38
|
def type
|
@@ -39,10 +41,15 @@ module ActionDispatch
|
|
39
41
|
|
40
42
|
def symbol?; false; end
|
41
43
|
def literal?; false; end
|
44
|
+
def terminal?; false; end
|
45
|
+
def star?; false; end
|
46
|
+
def cat?; false; end
|
47
|
+
def group?; false; end
|
42
48
|
end
|
43
49
|
|
44
50
|
class Terminal < Node # :nodoc:
|
45
51
|
alias :symbol :left
|
52
|
+
def terminal?; true; end
|
46
53
|
end
|
47
54
|
|
48
55
|
class Literal < Terminal # :nodoc:
|
@@ -69,11 +76,13 @@ module ActionDispatch
|
|
69
76
|
class Symbol < Terminal # :nodoc:
|
70
77
|
attr_accessor :regexp
|
71
78
|
alias :symbol :regexp
|
79
|
+
attr_reader :name
|
72
80
|
|
73
81
|
DEFAULT_EXP = /[^\.\/\?]+/
|
74
82
|
def initialize(left)
|
75
83
|
super
|
76
84
|
@regexp = DEFAULT_EXP
|
85
|
+
@name = left.tr "*:".freeze, "".freeze
|
77
86
|
end
|
78
87
|
|
79
88
|
def default_regexp?
|
@@ -89,13 +98,15 @@ module ActionDispatch
|
|
89
98
|
|
90
99
|
class Group < Unary # :nodoc:
|
91
100
|
def type; :GROUP; end
|
101
|
+
def group?; true; end
|
92
102
|
end
|
93
103
|
|
94
104
|
class Star < Unary # :nodoc:
|
105
|
+
def star?; true; end
|
95
106
|
def type; :STAR; end
|
96
107
|
|
97
108
|
def name
|
98
|
-
left.name.tr
|
109
|
+
left.name.tr "*:", ""
|
99
110
|
end
|
100
111
|
end
|
101
112
|
|
@@ -111,6 +122,7 @@ module ActionDispatch
|
|
111
122
|
end
|
112
123
|
|
113
124
|
class Cat < Binary # :nodoc:
|
125
|
+
def cat?; true; end
|
114
126
|
def type; :CAT; end
|
115
127
|
end
|
116
128
|
|
@@ -1,32 +1,33 @@
|
|
1
1
|
#
|
2
2
|
# DO NOT MODIFY!!!!
|
3
|
-
# This file is automatically generated by Racc 1.4.
|
4
|
-
# from Racc
|
3
|
+
# This file is automatically generated by Racc 1.4.14
|
4
|
+
# from Racc grammar file "".
|
5
5
|
#
|
6
6
|
|
7
7
|
require 'racc/parser.rb'
|
8
8
|
|
9
|
+
# :stopdoc:
|
9
10
|
|
10
|
-
require
|
11
|
+
require "action_dispatch/journey/parser_extras"
|
11
12
|
module ActionDispatch
|
12
13
|
module Journey
|
13
14
|
class Parser < Racc::Parser
|
14
15
|
##### State transition tables begin ###
|
15
16
|
|
16
17
|
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,
|
18
|
+
13, 15, 14, 7, 19, 16, 8, 19, 13, 15,
|
19
|
+
14, 7, 17, 16, 8, 13, 15, 14, 7, 21,
|
20
|
+
16, 8, 13, 15, 14, 7, 24, 16, 8 ]
|
20
21
|
|
21
22
|
racc_action_check = [
|
22
|
-
2, 2, 2, 2,
|
23
|
-
|
24
|
-
|
23
|
+
2, 2, 2, 2, 22, 2, 2, 2, 19, 19,
|
24
|
+
19, 19, 1, 19, 19, 7, 7, 7, 7, 17,
|
25
|
+
7, 7, 0, 0, 0, 0, 20, 0, 0 ]
|
25
26
|
|
26
27
|
racc_action_pointer = [
|
27
|
-
|
28
|
-
nil, nil, nil, nil, nil, nil, nil,
|
29
|
-
|
28
|
+
20, 12, -2, nil, nil, nil, nil, 13, nil, nil,
|
29
|
+
nil, nil, nil, nil, nil, nil, nil, 19, nil, 6,
|
30
|
+
20, nil, -5, nil, nil ]
|
30
31
|
|
31
32
|
racc_action_default = [
|
32
33
|
-19, -19, -2, -3, -4, -5, -6, -19, -10, -11,
|
@@ -134,11 +135,11 @@ Racc_debug_parser = false
|
|
134
135
|
# reduce 0 omitted
|
135
136
|
|
136
137
|
def _reduce_1(val, _values)
|
137
|
-
Cat.new(val.first, val.last)
|
138
|
+
Cat.new(val.first, val.last)
|
138
139
|
end
|
139
140
|
|
140
141
|
def _reduce_2(val, _values)
|
141
|
-
val.first
|
142
|
+
val.first
|
142
143
|
end
|
143
144
|
|
144
145
|
# reduce 3 omitted
|
@@ -150,19 +151,19 @@ end
|
|
150
151
|
# reduce 6 omitted
|
151
152
|
|
152
153
|
def _reduce_7(val, _values)
|
153
|
-
Group.new(val[1])
|
154
|
+
Group.new(val[1])
|
154
155
|
end
|
155
156
|
|
156
157
|
def _reduce_8(val, _values)
|
157
|
-
Or.new([val.first, val.last])
|
158
|
+
Or.new([val.first, val.last])
|
158
159
|
end
|
159
160
|
|
160
161
|
def _reduce_9(val, _values)
|
161
|
-
Or.new([val.first, val.last])
|
162
|
+
Or.new([val.first, val.last])
|
162
163
|
end
|
163
164
|
|
164
165
|
def _reduce_10(val, _values)
|
165
|
-
Star.new(Symbol.new(val.last))
|
166
|
+
Star.new(Symbol.new(val.last))
|
166
167
|
end
|
167
168
|
|
168
169
|
# reduce 11 omitted
|
@@ -174,19 +175,19 @@ end
|
|
174
175
|
# reduce 14 omitted
|
175
176
|
|
176
177
|
def _reduce_15(val, _values)
|
177
|
-
Slash.new(
|
178
|
+
Slash.new(val.first)
|
178
179
|
end
|
179
180
|
|
180
181
|
def _reduce_16(val, _values)
|
181
|
-
Symbol.new(val.first)
|
182
|
+
Symbol.new(val.first)
|
182
183
|
end
|
183
184
|
|
184
185
|
def _reduce_17(val, _values)
|
185
|
-
Literal.new(val.first)
|
186
|
+
Literal.new(val.first)
|
186
187
|
end
|
187
188
|
|
188
189
|
def _reduce_18(val, _values)
|
189
|
-
Dot.new(val.first)
|
190
|
+
Dot.new(val.first)
|
190
191
|
end
|
191
192
|
|
192
193
|
def _reduce_none(val, _values)
|
@@ -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,18 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "action_dispatch/journey/scanner"
|
4
|
+
require "action_dispatch/journey/nodes/node"
|
3
5
|
|
4
6
|
module ActionDispatch
|
5
|
-
|
6
|
-
|
7
|
+
# :stopdoc:
|
8
|
+
module Journey
|
9
|
+
class Parser < Racc::Parser
|
7
10
|
include Journey::Nodes
|
8
11
|
|
12
|
+
def self.parse(string)
|
13
|
+
new.parse string
|
14
|
+
end
|
15
|
+
|
9
16
|
def initialize
|
10
17
|
@scanner = Scanner.new
|
11
18
|
end
|
@@ -20,4 +27,5 @@ module ActionDispatch
|
|
20
27
|
end
|
21
28
|
end
|
22
29
|
end
|
30
|
+
# :startdoc:
|
23
31
|
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module ActionDispatch
|
4
4
|
module Journey # :nodoc:
|
@@ -6,15 +6,21 @@ module ActionDispatch
|
|
6
6
|
class Pattern # :nodoc:
|
7
7
|
attr_reader :spec, :requirements, :anchored
|
8
8
|
|
9
|
-
def self.from_string
|
10
|
-
|
9
|
+
def self.from_string(string)
|
10
|
+
build(string, {}, "/.?", true)
|
11
11
|
end
|
12
12
|
|
13
|
-
def
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
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
|
18
24
|
|
19
25
|
@names = nil
|
20
26
|
@optional_names = nil
|
@@ -27,13 +33,20 @@ module ActionDispatch
|
|
27
33
|
Visitors::FormatBuilder.new.accept(spec)
|
28
34
|
end
|
29
35
|
|
36
|
+
def eager_load!
|
37
|
+
required_names
|
38
|
+
offsets
|
39
|
+
to_regexp
|
40
|
+
nil
|
41
|
+
end
|
42
|
+
|
30
43
|
def ast
|
31
|
-
@spec.
|
44
|
+
@spec.find_all(&:symbol?).each do |node|
|
32
45
|
re = @requirements[node.to_sym]
|
33
46
|
node.regexp = re if re
|
34
47
|
end
|
35
48
|
|
36
|
-
@spec.
|
49
|
+
@spec.find_all(&:star?).each do |node|
|
37
50
|
node = node.left
|
38
51
|
node.regexp = @requirements[node.to_sym] || /(.+)/
|
39
52
|
end
|
@@ -42,7 +55,7 @@ module ActionDispatch
|
|
42
55
|
end
|
43
56
|
|
44
57
|
def names
|
45
|
-
@names ||= spec.
|
58
|
+
@names ||= spec.find_all(&:symbol?).map(&:name)
|
46
59
|
end
|
47
60
|
|
48
61
|
def required_names
|
@@ -50,34 +63,9 @@ module ActionDispatch
|
|
50
63
|
end
|
51
64
|
|
52
65
|
def optional_names
|
53
|
-
@optional_names ||= spec.
|
54
|
-
group.
|
55
|
-
}.map
|
56
|
-
end
|
57
|
-
|
58
|
-
class RegexpOffsets < Journey::Visitors::Visitor # :nodoc:
|
59
|
-
attr_reader :offsets
|
60
|
-
|
61
|
-
def initialize(matchers)
|
62
|
-
@matchers = matchers
|
63
|
-
@capture_count = [0]
|
64
|
-
end
|
65
|
-
|
66
|
-
def visit(node)
|
67
|
-
super
|
68
|
-
@capture_count
|
69
|
-
end
|
70
|
-
|
71
|
-
def visit_SYMBOL(node)
|
72
|
-
node = node.to_sym
|
73
|
-
|
74
|
-
if @matchers.key?(node)
|
75
|
-
re = /#{@matchers[node]}|/
|
76
|
-
@capture_count.push((re.match('').length - 1) + (@capture_count.last || 0))
|
77
|
-
else
|
78
|
-
@capture_count << (@capture_count.last || 0)
|
79
|
-
end
|
80
|
-
end
|
66
|
+
@optional_names ||= spec.find_all(&:group?).flat_map { |group|
|
67
|
+
group.find_all(&:symbol?)
|
68
|
+
}.map(&:name).uniq
|
81
69
|
end
|
82
70
|
|
83
71
|
class AnchoredRegexp < Journey::Visitors::Visitor # :nodoc:
|
@@ -119,14 +107,20 @@ module ActionDispatch
|
|
119
107
|
end
|
120
108
|
|
121
109
|
def visit_STAR(node)
|
122
|
-
re = @matchers[node.left.to_sym] ||
|
110
|
+
re = @matchers[node.left.to_sym] || ".+"
|
123
111
|
"(#{re})"
|
124
112
|
end
|
113
|
+
|
114
|
+
def visit_OR(node)
|
115
|
+
children = node.children.map { |n| visit n }
|
116
|
+
"(?:#{children.join(?|)})"
|
117
|
+
end
|
125
118
|
end
|
126
119
|
|
127
120
|
class UnanchoredRegexp < AnchoredRegexp # :nodoc:
|
128
121
|
def accept(node)
|
129
|
-
|
122
|
+
path = visit node
|
123
|
+
path == "/" ? %r{\A/} : %r{\A#{path}(?:\b|\Z|/)}
|
130
124
|
end
|
131
125
|
end
|
132
126
|
|
@@ -140,7 +134,7 @@ module ActionDispatch
|
|
140
134
|
end
|
141
135
|
|
142
136
|
def captures
|
143
|
-
(length - 1)
|
137
|
+
Array.new(length - 1) { |i| self[i + 1] }
|
144
138
|
end
|
145
139
|
|
146
140
|
def [](x)
|
@@ -184,8 +178,20 @@ module ActionDispatch
|
|
184
178
|
def offsets
|
185
179
|
return @offsets if @offsets
|
186
180
|
|
187
|
-
|
188
|
-
|
181
|
+
@offsets = [0]
|
182
|
+
|
183
|
+
spec.find_all(&:symbol?).each do |node|
|
184
|
+
node = node.to_sym
|
185
|
+
|
186
|
+
if @requirements.key?(node)
|
187
|
+
re = /#{@requirements[node]}|/
|
188
|
+
@offsets.push((re.match("").length - 1) + @offsets.last)
|
189
|
+
else
|
190
|
+
@offsets << @offsets.last
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
194
|
+
@offsets
|
189
195
|
end
|
190
196
|
end
|
191
197
|
end
|
@@ -1,42 +1,106 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ActionDispatch
|
2
|
-
|
3
|
-
|
4
|
-
|
4
|
+
# :stopdoc:
|
5
|
+
module Journey
|
6
|
+
class Route
|
7
|
+
attr_reader :app, :path, :defaults, :name, :precedence
|
5
8
|
|
6
|
-
attr_reader :constraints
|
9
|
+
attr_reader :constraints, :internal
|
7
10
|
alias :conditions :constraints
|
8
11
|
|
9
|
-
|
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
|
10
56
|
|
11
57
|
##
|
12
58
|
# +path+ is a path constraint.
|
13
59
|
# +constraints+ is a hash of constraints to be applied to this route.
|
14
|
-
def initialize(name, app, path, constraints, defaults =
|
60
|
+
def initialize(name, app, path, constraints, required_defaults, defaults, request_method_match, precedence, internal = false)
|
15
61
|
@name = name
|
16
62
|
@app = app
|
17
63
|
@path = path
|
18
64
|
|
65
|
+
@request_method_match = request_method_match
|
19
66
|
@constraints = constraints
|
20
67
|
@defaults = defaults
|
21
68
|
@required_defaults = nil
|
69
|
+
@_required_defaults = required_defaults
|
22
70
|
@required_parts = nil
|
23
71
|
@parts = nil
|
24
72
|
@decorated_ast = nil
|
25
|
-
@precedence =
|
73
|
+
@precedence = precedence
|
26
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
|
27
84
|
end
|
28
85
|
|
29
86
|
def ast
|
30
87
|
@decorated_ast ||= begin
|
31
88
|
decorated_ast = path.ast
|
32
|
-
decorated_ast.
|
89
|
+
decorated_ast.find_all(&:terminal?).each { |n| n.memo = self }
|
33
90
|
decorated_ast
|
34
91
|
end
|
35
92
|
end
|
36
93
|
|
37
|
-
|
38
|
-
|
39
|
-
|
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|
|
40
104
|
/.+?/ == v
|
41
105
|
}
|
42
106
|
end
|
@@ -49,18 +113,23 @@ module ActionDispatch
|
|
49
113
|
required_parts + required_defaults.keys
|
50
114
|
end
|
51
115
|
|
52
|
-
def score(
|
116
|
+
def score(supplied_keys)
|
53
117
|
required_keys = path.required_names
|
54
|
-
supplied_keys = constraints.map { |k,v| v && k.to_s }.compact
|
55
118
|
|
56
|
-
|
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
|
57
127
|
|
58
|
-
score = (supplied_keys & path.names).length
|
59
128
|
score + (required_defaults.length * 2)
|
60
129
|
end
|
61
130
|
|
62
131
|
def parts
|
63
|
-
@parts ||= segments.map
|
132
|
+
@parts ||= segments.map(&:to_sym)
|
64
133
|
end
|
65
134
|
alias :segment_keys :parts
|
66
135
|
|
@@ -68,20 +137,16 @@ module ActionDispatch
|
|
68
137
|
@path_formatter.evaluate path_options
|
69
138
|
end
|
70
139
|
|
71
|
-
def optional_parts
|
72
|
-
path.optional_names.map { |n| n.to_sym }
|
73
|
-
end
|
74
|
-
|
75
140
|
def required_parts
|
76
|
-
@required_parts ||= path.required_names.map
|
141
|
+
@required_parts ||= path.required_names.map(&:to_sym)
|
77
142
|
end
|
78
143
|
|
79
144
|
def required_default?(key)
|
80
|
-
|
145
|
+
@_required_defaults.include?(key)
|
81
146
|
end
|
82
147
|
|
83
148
|
def required_defaults
|
84
|
-
@required_defaults ||= @defaults.dup.delete_if do |k,_|
|
149
|
+
@required_defaults ||= @defaults.dup.delete_if do |k, _|
|
85
150
|
parts.include?(k) || !required_default?(k)
|
86
151
|
end
|
87
152
|
end
|
@@ -95,9 +160,8 @@ module ActionDispatch
|
|
95
160
|
end
|
96
161
|
|
97
162
|
def matches?(request)
|
98
|
-
|
99
|
-
|
100
|
-
|
163
|
+
match_verb(request) &&
|
164
|
+
constraints.all? { |method, value|
|
101
165
|
case value
|
102
166
|
when Regexp, String
|
103
167
|
value === request.send(method).to_s
|
@@ -110,16 +174,30 @@ module ActionDispatch
|
|
110
174
|
else
|
111
175
|
value === request.send(method)
|
112
176
|
end
|
113
|
-
|
177
|
+
}
|
114
178
|
end
|
115
179
|
|
116
180
|
def ip
|
117
181
|
constraints[:ip] || //
|
118
182
|
end
|
119
183
|
|
184
|
+
def requires_matching_verb?
|
185
|
+
!@request_method_match.all? { |x| x == VerbMatchers::All }
|
186
|
+
end
|
187
|
+
|
120
188
|
def verb
|
121
|
-
|
189
|
+
verbs.join("|")
|
122
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
|
123
200
|
end
|
124
201
|
end
|
202
|
+
# :startdoc:
|
125
203
|
end
|