actionpack 7.0.8.7 → 7.1.5.1
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 +423 -342
- data/MIT-LICENSE +1 -1
- data/README.rdoc +2 -2
- data/lib/abstract_controller/base.rb +20 -11
- data/lib/abstract_controller/caching/fragments.rb +2 -0
- data/lib/abstract_controller/callbacks.rb +31 -6
- data/lib/abstract_controller/deprecator.rb +7 -0
- data/lib/abstract_controller/helpers.rb +61 -18
- data/lib/abstract_controller/railties/routes_helpers.rb +1 -16
- data/lib/abstract_controller/rendering.rb +3 -3
- data/lib/abstract_controller/translation.rb +7 -24
- data/lib/abstract_controller/url_for.rb +2 -0
- data/lib/abstract_controller.rb +6 -0
- data/lib/action_controller/api.rb +5 -3
- data/lib/action_controller/base.rb +3 -17
- data/lib/action_controller/caching.rb +2 -0
- data/lib/action_controller/deprecator.rb +7 -0
- data/lib/action_controller/form_builder.rb +2 -0
- data/lib/action_controller/log_subscriber.rb +16 -4
- data/lib/action_controller/metal/content_security_policy.rb +1 -1
- data/lib/action_controller/metal/data_streaming.rb +2 -0
- data/lib/action_controller/metal/default_headers.rb +2 -0
- data/lib/action_controller/metal/etag_with_flash.rb +2 -0
- data/lib/action_controller/metal/etag_with_template_digest.rb +2 -0
- data/lib/action_controller/metal/exceptions.rb +8 -0
- data/lib/action_controller/metal/head.rb +8 -6
- data/lib/action_controller/metal/helpers.rb +3 -14
- data/lib/action_controller/metal/http_authentication.rb +13 -8
- data/lib/action_controller/metal/implicit_render.rb +5 -3
- data/lib/action_controller/metal/instrumentation.rb +8 -1
- data/lib/action_controller/metal/live.rb +24 -0
- data/lib/action_controller/metal/mime_responds.rb +2 -2
- data/lib/action_controller/metal/params_wrapper.rb +4 -2
- data/lib/action_controller/metal/permissions_policy.rb +1 -1
- data/lib/action_controller/metal/redirecting.rb +7 -7
- data/lib/action_controller/metal/renderers.rb +2 -2
- data/lib/action_controller/metal/rendering.rb +0 -7
- data/lib/action_controller/metal/request_forgery_protection.rb +139 -50
- data/lib/action_controller/metal/rescue.rb +2 -0
- data/lib/action_controller/metal/streaming.rb +70 -30
- data/lib/action_controller/metal/strong_parameters.rb +174 -54
- data/lib/action_controller/metal/url_for.rb +7 -0
- data/lib/action_controller/metal.rb +79 -21
- data/lib/action_controller/railtie.rb +22 -9
- data/lib/action_controller/renderer.rb +98 -65
- data/lib/action_controller/test_case.rb +18 -8
- data/lib/action_controller.rb +13 -3
- data/lib/action_dispatch/constants.rb +32 -0
- data/lib/action_dispatch/deprecator.rb +7 -0
- data/lib/action_dispatch/http/cache.rb +1 -3
- data/lib/action_dispatch/http/content_security_policy.rb +9 -8
- data/lib/action_dispatch/http/filter_parameters.rb +11 -5
- data/lib/action_dispatch/http/headers.rb +2 -0
- data/lib/action_dispatch/http/mime_negotiation.rb +22 -22
- data/lib/action_dispatch/http/mime_type.rb +37 -11
- data/lib/action_dispatch/http/mime_types.rb +3 -1
- data/lib/action_dispatch/http/parameters.rb +1 -1
- data/lib/action_dispatch/http/permissions_policy.rb +38 -16
- data/lib/action_dispatch/http/rack_cache.rb +2 -0
- data/lib/action_dispatch/http/request.rb +70 -16
- data/lib/action_dispatch/http/response.rb +80 -59
- data/lib/action_dispatch/http/upload.rb +2 -0
- data/lib/action_dispatch/journey/formatter.rb +8 -2
- data/lib/action_dispatch/journey/path/pattern.rb +14 -14
- data/lib/action_dispatch/journey/route.rb +3 -2
- data/lib/action_dispatch/journey/router.rb +9 -8
- data/lib/action_dispatch/journey/routes.rb +2 -2
- data/lib/action_dispatch/log_subscriber.rb +23 -0
- data/lib/action_dispatch/middleware/actionable_exceptions.rb +5 -6
- data/lib/action_dispatch/middleware/assume_ssl.rb +24 -0
- data/lib/action_dispatch/middleware/callbacks.rb +2 -0
- data/lib/action_dispatch/middleware/cookies.rb +81 -98
- data/lib/action_dispatch/middleware/debug_exceptions.rb +26 -25
- data/lib/action_dispatch/middleware/debug_locks.rb +4 -1
- data/lib/action_dispatch/middleware/debug_view.rb +7 -2
- data/lib/action_dispatch/middleware/exception_wrapper.rb +186 -27
- data/lib/action_dispatch/middleware/executor.rb +7 -1
- data/lib/action_dispatch/middleware/flash.rb +7 -0
- data/lib/action_dispatch/middleware/host_authorization.rb +6 -3
- data/lib/action_dispatch/middleware/public_exceptions.rb +5 -3
- data/lib/action_dispatch/middleware/reloader.rb +7 -5
- data/lib/action_dispatch/middleware/remote_ip.rb +17 -16
- data/lib/action_dispatch/middleware/request_id.rb +2 -0
- data/lib/action_dispatch/middleware/server_timing.rb +4 -4
- data/lib/action_dispatch/middleware/session/abstract_store.rb +5 -0
- data/lib/action_dispatch/middleware/session/cache_store.rb +2 -0
- data/lib/action_dispatch/middleware/session/cookie_store.rb +11 -5
- data/lib/action_dispatch/middleware/session/mem_cache_store.rb +3 -1
- data/lib/action_dispatch/middleware/show_exceptions.rb +33 -19
- data/lib/action_dispatch/middleware/ssl.rb +18 -6
- data/lib/action_dispatch/middleware/stack.rb +7 -2
- data/lib/action_dispatch/middleware/static.rb +12 -8
- data/lib/action_dispatch/middleware/templates/rescues/_actions.html.erb +2 -2
- data/lib/action_dispatch/middleware/templates/rescues/_message_and_suggestions.html.erb +4 -4
- data/lib/action_dispatch/middleware/templates/rescues/_source.html.erb +8 -1
- data/lib/action_dispatch/middleware/templates/rescues/diagnostics.html.erb +7 -7
- data/lib/action_dispatch/middleware/templates/rescues/diagnostics.text.erb +2 -2
- data/lib/action_dispatch/middleware/templates/rescues/layout.erb +17 -0
- data/lib/action_dispatch/middleware/templates/rescues/missing_exact_template.html.erb +16 -12
- data/lib/action_dispatch/middleware/templates/rescues/missing_template.html.erb +1 -1
- data/lib/action_dispatch/middleware/templates/rescues/routing_error.html.erb +3 -3
- data/lib/action_dispatch/middleware/templates/rescues/template_error.html.erb +4 -4
- data/lib/action_dispatch/middleware/templates/rescues/unknown_action.html.erb +1 -1
- data/lib/action_dispatch/middleware/templates/rescues/unknown_action.text.erb +1 -1
- data/lib/action_dispatch/middleware/templates/routes/_route.html.erb +3 -0
- data/lib/action_dispatch/middleware/templates/routes/_table.html.erb +46 -37
- data/lib/action_dispatch/railtie.rb +13 -4
- data/lib/action_dispatch/request/session.rb +16 -6
- data/lib/action_dispatch/request/utils.rb +8 -3
- data/lib/action_dispatch/routing/inspector.rb +54 -6
- data/lib/action_dispatch/routing/mapper.rb +74 -26
- data/lib/action_dispatch/routing/polymorphic_routes.rb +2 -0
- data/lib/action_dispatch/routing/redirection.rb +15 -6
- data/lib/action_dispatch/routing/route_set.rb +53 -23
- data/lib/action_dispatch/routing/routes_proxy.rb +10 -15
- data/lib/action_dispatch/routing/url_for.rb +5 -1
- data/lib/action_dispatch/routing.rb +7 -7
- data/lib/action_dispatch/system_test_case.rb +3 -3
- data/lib/action_dispatch/system_testing/browser.rb +25 -19
- data/lib/action_dispatch/system_testing/driver.rb +14 -22
- data/lib/action_dispatch/system_testing/test_helpers/screenshot_helper.rb +27 -16
- data/lib/action_dispatch/testing/assertion_response.rb +1 -1
- data/lib/action_dispatch/testing/assertions/response.rb +13 -6
- data/lib/action_dispatch/testing/assertions/routing.rb +67 -28
- data/lib/action_dispatch/testing/assertions.rb +3 -1
- data/lib/action_dispatch/testing/integration.rb +27 -17
- data/lib/action_dispatch/testing/request_encoder.rb +4 -1
- data/lib/action_dispatch/testing/test_process.rb +4 -3
- data/lib/action_dispatch/testing/test_request.rb +1 -1
- data/lib/action_dispatch/testing/test_response.rb +23 -9
- data/lib/action_dispatch.rb +41 -4
- data/lib/action_pack/gem_version.rb +4 -4
- data/lib/action_pack/version.rb +1 -1
- data/lib/action_pack.rb +1 -1
- metadata +62 -26
@@ -1,24 +1,45 @@
|
|
1
1
|
<% content_for :style do %>
|
2
|
+
h2, p {
|
3
|
+
padding-left: 30px;
|
4
|
+
}
|
5
|
+
|
2
6
|
#route_table {
|
3
7
|
margin: 0;
|
4
8
|
border-collapse: collapse;
|
9
|
+
word-wrap:break-word;
|
10
|
+
table-layout: fixed;
|
11
|
+
width:100%;
|
5
12
|
}
|
6
13
|
|
7
14
|
#route_table thead tr {
|
8
15
|
border-bottom: 2px solid #ddd;
|
9
16
|
}
|
10
17
|
|
18
|
+
#route_table th {
|
19
|
+
padding-left: 30px;
|
20
|
+
text-align: left;
|
21
|
+
}
|
22
|
+
|
11
23
|
#route_table thead tr.bottom {
|
12
24
|
border-bottom: none;
|
13
25
|
}
|
14
26
|
|
15
27
|
#route_table thead tr.bottom th {
|
16
|
-
padding: 10px
|
28
|
+
padding: 10px 30px;
|
17
29
|
line-height: 15px;
|
18
30
|
}
|
19
31
|
|
20
|
-
#route_table
|
32
|
+
#route_table #search_container {
|
33
|
+
padding: 7px 30px;
|
34
|
+
}
|
35
|
+
|
36
|
+
#route_table thead tr th input#search {
|
21
37
|
-webkit-appearance: textfield;
|
38
|
+
width:100%;
|
39
|
+
}
|
40
|
+
|
41
|
+
#route_table thead th.http-verb {
|
42
|
+
width: 10%;
|
22
43
|
}
|
23
44
|
|
24
45
|
#route_table tbody tr {
|
@@ -45,11 +66,6 @@
|
|
45
66
|
padding: 4px 30px;
|
46
67
|
}
|
47
68
|
|
48
|
-
#path_search {
|
49
|
-
width: 80%;
|
50
|
-
font-size: inherit;
|
51
|
-
}
|
52
|
-
|
53
69
|
@media (prefers-color-scheme: dark) {
|
54
70
|
#route_table tbody tr:nth-child(odd) {
|
55
71
|
background: #282828;
|
@@ -62,28 +78,22 @@
|
|
62
78
|
}
|
63
79
|
<% end %>
|
64
80
|
|
65
|
-
<table id='route_table'
|
81
|
+
<table id='route_table'>
|
66
82
|
<thead>
|
67
83
|
<tr>
|
68
|
-
<th>Helper
|
69
|
-
|
70
|
-
<th>Path</th>
|
71
|
-
<th>Controller#Action</th>
|
72
|
-
</tr>
|
73
|
-
<tr class='bottom'>
|
74
|
-
<th><%# Helper %>
|
75
|
-
<%= link_to "Path", "#", 'data-route-helper' => '_path',
|
84
|
+
<th>Helper
|
85
|
+
(<%= link_to "Path", "#", 'data-route-helper' => '_path',
|
76
86
|
title: "Returns a relative path (without the http or domain)" %> /
|
77
87
|
<%= link_to "Url", "#", 'data-route-helper' => '_url',
|
78
|
-
title: "Returns an absolute URL (with the http and domain)" %>
|
79
|
-
</th>
|
80
|
-
<th><%# HTTP Verb %>
|
81
|
-
</th>
|
82
|
-
<th><%# Path %>
|
83
|
-
<%= search_field(:path, nil, id: 'search', placeholder: "Path Match") %>
|
84
|
-
</th>
|
85
|
-
<th><%# Controller#action %>
|
88
|
+
title: "Returns an absolute URL (with the http and domain)" %>)
|
86
89
|
</th>
|
90
|
+
<th class="http-verb">HTTP Verb</th>
|
91
|
+
<th>Path</th>
|
92
|
+
<th>Controller#Action</th>
|
93
|
+
<th>Source Location</th>
|
94
|
+
</tr>
|
95
|
+
<tr>
|
96
|
+
<th colspan="5" id="search_container"><%= search_field(:query, nil, id: 'search', placeholder: "Search") %></th>
|
87
97
|
</tr>
|
88
98
|
</thead>
|
89
99
|
<tbody class='exact_matches' id='exact_matches'>
|
@@ -99,8 +109,8 @@
|
|
99
109
|
// support forEach iterator on NodeList
|
100
110
|
NodeList.prototype.forEach = Array.prototype.forEach;
|
101
111
|
|
102
|
-
// Enables
|
103
|
-
function
|
112
|
+
// Enables query search functionality
|
113
|
+
function setupMatchingRoutes() {
|
104
114
|
// Check if there are any matched results in a section
|
105
115
|
function checkNoMatch(section, trElement) {
|
106
116
|
if (section.children.length <= 1) {
|
@@ -128,8 +138,8 @@
|
|
128
138
|
}
|
129
139
|
|
130
140
|
// remove params or fragments
|
131
|
-
function
|
132
|
-
return
|
141
|
+
function sanitizeQuery(query) {
|
142
|
+
return query.replace(/[#?].*/, '');
|
133
143
|
}
|
134
144
|
|
135
145
|
var pathElements = document.querySelectorAll('#route_table [data-route-path]'),
|
@@ -156,16 +166,16 @@
|
|
156
166
|
|
157
167
|
// On key press perform a search for matching paths
|
158
168
|
delayedKeyup(searchElem, function() {
|
159
|
-
var
|
160
|
-
defaultExactMatch = buildTr(
|
161
|
-
defaultFuzzyMatch = buildTr(
|
162
|
-
noExactMatch = buildTr('No
|
163
|
-
noFuzzyMatch = buildTr('No
|
169
|
+
var query = sanitizeQuery(searchElem.value),
|
170
|
+
defaultExactMatch = buildTr("Routes matching '" + query + "':"),
|
171
|
+
defaultFuzzyMatch = buildTr("Routes containing '" + query + "':"),
|
172
|
+
noExactMatch = buildTr('No exact matches found'),
|
173
|
+
noFuzzyMatch = buildTr('No fuzzy matches found');
|
164
174
|
|
165
|
-
if (!
|
175
|
+
if (!query)
|
166
176
|
return searchElem.onblur();
|
167
177
|
|
168
|
-
getJSON('/rails/info/routes?
|
178
|
+
getJSON('/rails/info/routes?query=' + query, function(matches){
|
169
179
|
// Clear out results section
|
170
180
|
exactSection.replaceChildren(defaultExactMatch);
|
171
181
|
fuzzySection.replaceChildren(defaultFuzzyMatch);
|
@@ -173,7 +183,6 @@
|
|
173
183
|
// Display exact matches and fuzzy matches
|
174
184
|
pathElements.forEach(function(elem) {
|
175
185
|
var elemPath = elem.getAttribute('data-route-path');
|
176
|
-
|
177
186
|
if (matches['exact'].indexOf(elemPath) != -1)
|
178
187
|
exactSection.appendChild(elem.parentNode.cloneNode(true));
|
179
188
|
|
@@ -215,7 +224,7 @@
|
|
215
224
|
});
|
216
225
|
}
|
217
226
|
|
218
|
-
|
227
|
+
setupMatchingRoutes();
|
219
228
|
setupRouteToggleHelperLinks();
|
220
229
|
|
221
230
|
// Focus the search input after page has loaded
|
@@ -1,6 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require "action_dispatch"
|
4
|
+
require "action_dispatch/log_subscriber"
|
4
5
|
require "active_support/messages/rotation_configuration"
|
5
6
|
|
6
7
|
module ActionDispatch
|
@@ -8,7 +9,7 @@ module ActionDispatch
|
|
8
9
|
config.action_dispatch = ActiveSupport::OrderedOptions.new
|
9
10
|
config.action_dispatch.x_sendfile_header = nil
|
10
11
|
config.action_dispatch.ip_spoofing_check = true
|
11
|
-
config.action_dispatch.show_exceptions =
|
12
|
+
config.action_dispatch.show_exceptions = :all
|
12
13
|
config.action_dispatch.tld_length = 1
|
13
14
|
config.action_dispatch.ignore_accept_header = false
|
14
15
|
config.action_dispatch.rescue_templates = {}
|
@@ -23,9 +24,9 @@ module ActionDispatch
|
|
23
24
|
config.action_dispatch.use_authenticated_cookie_encryption = false
|
24
25
|
config.action_dispatch.use_cookies_with_metadata = false
|
25
26
|
config.action_dispatch.perform_deep_munge = true
|
26
|
-
config.action_dispatch.request_id_header =
|
27
|
-
config.action_dispatch.return_only_request_media_type_on_content_type = true
|
27
|
+
config.action_dispatch.request_id_header = ActionDispatch::Constants::X_REQUEST_ID
|
28
28
|
config.action_dispatch.log_rescued_responses = true
|
29
|
+
config.action_dispatch.debug_exception_log_level = :fatal
|
29
30
|
|
30
31
|
config.action_dispatch.default_headers = {
|
31
32
|
"X-Frame-Options" => "SAMEORIGIN",
|
@@ -40,13 +41,19 @@ module ActionDispatch
|
|
40
41
|
|
41
42
|
config.eager_load_namespaces << ActionDispatch
|
42
43
|
|
44
|
+
initializer "action_dispatch.deprecator", before: :load_environment_config do |app|
|
45
|
+
app.deprecators[:action_dispatch] = ActionDispatch.deprecator
|
46
|
+
end
|
47
|
+
|
43
48
|
initializer "action_dispatch.configure" do |app|
|
44
49
|
ActionDispatch::Http::URL.secure_protocol = app.config.force_ssl
|
45
50
|
ActionDispatch::Http::URL.tld_length = app.config.action_dispatch.tld_length
|
46
51
|
|
47
52
|
ActiveSupport.on_load(:action_dispatch_request) do
|
48
53
|
self.ignore_accept_header = app.config.action_dispatch.ignore_accept_header
|
49
|
-
|
54
|
+
unless app.config.action_dispatch.respond_to?(:return_only_request_media_type_on_content_type)
|
55
|
+
self.return_only_media_type_on_content_type = app.config.action_dispatch.return_only_request_media_type_on_content_type
|
56
|
+
end
|
50
57
|
ActionDispatch::Request::Utils.perform_deep_munge = app.config.action_dispatch.perform_deep_munge
|
51
58
|
end
|
52
59
|
|
@@ -61,6 +68,8 @@ module ActionDispatch
|
|
61
68
|
config.action_dispatch.always_write_cookie = Rails.env.development? if config.action_dispatch.always_write_cookie.nil?
|
62
69
|
ActionDispatch::Cookies::CookieJar.always_write_cookie = config.action_dispatch.always_write_cookie
|
63
70
|
|
71
|
+
ActionDispatch::Routing::Mapper.route_source_locations = Rails.env.development?
|
72
|
+
|
64
73
|
ActionDispatch.test_app = app
|
65
74
|
end
|
66
75
|
end
|
@@ -78,6 +78,8 @@ module ActionDispatch
|
|
78
78
|
@loaded = false
|
79
79
|
@exists = nil # We haven't checked yet.
|
80
80
|
@enabled = enabled
|
81
|
+
@id_was = nil
|
82
|
+
@id_was_initialized = false
|
81
83
|
end
|
82
84
|
|
83
85
|
def id
|
@@ -176,9 +178,14 @@ module ActionDispatch
|
|
176
178
|
# session.to_hash
|
177
179
|
# # => {"session_id"=>"e29b9ea315edf98aad94cc78c34cc9b2", "foo" => "bar"}
|
178
180
|
def update(hash)
|
181
|
+
unless hash.respond_to?(:to_hash)
|
182
|
+
raise TypeError, "no implicit conversion of #{hash.class.name} into Hash"
|
183
|
+
end
|
184
|
+
|
179
185
|
load_for_write!
|
180
|
-
@delegate.update hash.stringify_keys
|
186
|
+
@delegate.update hash.to_hash.stringify_keys
|
181
187
|
end
|
188
|
+
alias :merge! :update
|
182
189
|
|
183
190
|
# Deletes given key from the session.
|
184
191
|
def delete(key)
|
@@ -232,15 +239,15 @@ module ActionDispatch
|
|
232
239
|
@delegate.empty?
|
233
240
|
end
|
234
241
|
|
235
|
-
def merge!(other)
|
236
|
-
load_for_write!
|
237
|
-
@delegate.merge!(other)
|
238
|
-
end
|
239
|
-
|
240
242
|
def each(&block)
|
241
243
|
to_hash.each(&block)
|
242
244
|
end
|
243
245
|
|
246
|
+
def id_was
|
247
|
+
load_for_read!
|
248
|
+
@id_was
|
249
|
+
end
|
250
|
+
|
244
251
|
private
|
245
252
|
def load_for_read!
|
246
253
|
load! if !loaded? && exists?
|
@@ -260,10 +267,13 @@ module ActionDispatch
|
|
260
267
|
|
261
268
|
def load!
|
262
269
|
if enabled?
|
270
|
+
@id_was_initialized = true unless exists?
|
263
271
|
id, session = @by.load_session @req
|
264
272
|
options[:id] = id
|
265
273
|
@delegate.replace(session.stringify_keys)
|
274
|
+
@id_was = id unless @id_was_initialized
|
266
275
|
end
|
276
|
+
@id_was_initialized = true
|
267
277
|
@loaded = true
|
268
278
|
end
|
269
279
|
end
|
@@ -55,9 +55,11 @@ module ActionDispatch
|
|
55
55
|
if params.has_key?(:tempfile)
|
56
56
|
ActionDispatch::Http::UploadedFile.new(params)
|
57
57
|
else
|
58
|
-
|
59
|
-
|
60
|
-
|
58
|
+
hwia = ActiveSupport::HashWithIndifferentAccess.new
|
59
|
+
params.each_pair do |key, val|
|
60
|
+
hwia[key] = normalize_encode_params(val)
|
61
|
+
end
|
62
|
+
hwia
|
61
63
|
end
|
62
64
|
else
|
63
65
|
params
|
@@ -83,6 +85,9 @@ module ActionDispatch
|
|
83
85
|
return params unless controller && controller.valid_encoding? && encoding_template = action_encoding_template(request, controller, action)
|
84
86
|
params.except(:controller, :action).each do |key, value|
|
85
87
|
ActionDispatch::Request::Utils.each_param_value(value) do |param|
|
88
|
+
# If `param` is frozen, it comes from the router defaults
|
89
|
+
next if param.frozen?
|
90
|
+
|
86
91
|
if encoding_template[key.to_s]
|
87
92
|
param.force_encoding(encoding_template[key.to_s])
|
88
93
|
end
|
@@ -6,8 +6,21 @@ require "io/console/size"
|
|
6
6
|
module ActionDispatch
|
7
7
|
module Routing
|
8
8
|
class RouteWrapper < SimpleDelegator # :nodoc:
|
9
|
+
def matches_filter?(filter, value)
|
10
|
+
return __getobj__.path.match(value) if filter == :exact_path_match
|
11
|
+
|
12
|
+
value.match?(public_send(filter))
|
13
|
+
end
|
14
|
+
|
9
15
|
def endpoint
|
10
|
-
|
16
|
+
case
|
17
|
+
when app.dispatcher?
|
18
|
+
"#{controller}##{action}"
|
19
|
+
when rack_app.is_a?(Proc)
|
20
|
+
"Inline handler (Proc/Lambda)"
|
21
|
+
else
|
22
|
+
rack_app.inspect
|
23
|
+
end
|
11
24
|
end
|
12
25
|
|
13
26
|
def constraints
|
@@ -85,8 +98,18 @@ module ActionDispatch
|
|
85
98
|
if filter[:controller]
|
86
99
|
{ controller: /#{filter[:controller].underscore.sub(/_?controller\z/, "")}/ }
|
87
100
|
elsif filter[:grep]
|
88
|
-
|
89
|
-
|
101
|
+
grep_pattern = Regexp.new(filter[:grep])
|
102
|
+
path = RFC2396_PARSER.escape(filter[:grep])
|
103
|
+
normalized_path = ("/" + path).squeeze("/")
|
104
|
+
|
105
|
+
{
|
106
|
+
controller: grep_pattern,
|
107
|
+
action: grep_pattern,
|
108
|
+
verb: grep_pattern,
|
109
|
+
name: grep_pattern,
|
110
|
+
path: grep_pattern,
|
111
|
+
exact_path_match: normalized_path,
|
112
|
+
}
|
90
113
|
end
|
91
114
|
end
|
92
115
|
|
@@ -94,7 +117,7 @@ module ActionDispatch
|
|
94
117
|
if filter
|
95
118
|
@routes.select do |route|
|
96
119
|
route_wrapper = RouteWrapper.new(route)
|
97
|
-
filter.any? { |
|
120
|
+
filter.any? { |filter_type, value| route_wrapper.matches_filter?(filter_type, value) }
|
98
121
|
end
|
99
122
|
else
|
100
123
|
@routes
|
@@ -110,7 +133,8 @@ module ActionDispatch
|
|
110
133
|
{ name: route.name,
|
111
134
|
verb: route.verb,
|
112
135
|
path: route.path,
|
113
|
-
reqs: route.reqs
|
136
|
+
reqs: route.reqs,
|
137
|
+
source_location: route.source_location }
|
114
138
|
end
|
115
139
|
end
|
116
140
|
|
@@ -216,13 +240,16 @@ module ActionDispatch
|
|
216
240
|
private
|
217
241
|
def draw_expanded_section(routes)
|
218
242
|
routes.map.each_with_index do |r, i|
|
219
|
-
<<~MESSAGE.chomp
|
243
|
+
route_rows = <<~MESSAGE.chomp
|
220
244
|
#{route_header(index: i + 1)}
|
221
245
|
Prefix | #{r[:name]}
|
222
246
|
Verb | #{r[:verb]}
|
223
247
|
URI | #{r[:path]}
|
224
248
|
Controller#Action | #{r[:reqs]}
|
225
249
|
MESSAGE
|
250
|
+
source_location = "\nSource Location | #{r[:source_location]}"
|
251
|
+
route_rows += source_location if r[:source_location].present?
|
252
|
+
route_rows
|
226
253
|
end
|
227
254
|
end
|
228
255
|
|
@@ -230,6 +257,27 @@ module ActionDispatch
|
|
230
257
|
"--[ Route #{index} ]".ljust(@width, "-")
|
231
258
|
end
|
232
259
|
end
|
260
|
+
|
261
|
+
class Unused < Sheet
|
262
|
+
def header(routes)
|
263
|
+
@buffer << <<~MSG
|
264
|
+
Found #{routes.count} unused #{"route".pluralize(routes.count)}:
|
265
|
+
MSG
|
266
|
+
|
267
|
+
super
|
268
|
+
end
|
269
|
+
|
270
|
+
def no_routes(routes, filter)
|
271
|
+
@buffer <<
|
272
|
+
if filter.none?
|
273
|
+
"No unused routes found."
|
274
|
+
elsif filter.key?(:controller)
|
275
|
+
"No unused routes found for this controller."
|
276
|
+
elsif filter.key?(:grep)
|
277
|
+
"No unused routes found for this grep pattern."
|
278
|
+
end
|
279
|
+
end
|
280
|
+
end
|
233
281
|
end
|
234
282
|
|
235
283
|
class HtmlTableFormatter
|
@@ -10,8 +10,20 @@ require "action_dispatch/routing/endpoint"
|
|
10
10
|
module ActionDispatch
|
11
11
|
module Routing
|
12
12
|
class Mapper
|
13
|
+
class BacktraceCleaner < ActiveSupport::BacktraceCleaner # :nodoc:
|
14
|
+
def initialize
|
15
|
+
super
|
16
|
+
remove_silencers!
|
17
|
+
add_core_silencer
|
18
|
+
add_stdlib_silencer
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
13
22
|
URL_OPTIONS = [:protocol, :subdomain, :domain, :host, :port]
|
14
23
|
|
24
|
+
cattr_accessor :route_source_locations, instance_accessor: false, default: false
|
25
|
+
cattr_accessor :backtrace_cleaner, instance_accessor: false, default: BacktraceCleaner.new
|
26
|
+
|
15
27
|
class Constraints < Routing::Endpoint # :nodoc:
|
16
28
|
attr_reader :app, :constraints
|
17
29
|
|
@@ -43,7 +55,7 @@ module ActionDispatch
|
|
43
55
|
end
|
44
56
|
|
45
57
|
def serve(req)
|
46
|
-
return [ 404, {
|
58
|
+
return [ 404, { Constants::X_CASCADE => "pass" }, [] ] unless matches?(req)
|
47
59
|
|
48
60
|
@strategy.call @app, req
|
49
61
|
end
|
@@ -170,7 +182,7 @@ module ActionDispatch
|
|
170
182
|
Journey::Route.new(name: name, app: application, path: path, constraints: conditions,
|
171
183
|
required_defaults: required_defaults, defaults: defaults,
|
172
184
|
request_method_match: request_method, precedence: precedence,
|
173
|
-
scope_options: scope_options, internal: @internal)
|
185
|
+
scope_options: scope_options, internal: @internal, source_location: route_source_location)
|
174
186
|
end
|
175
187
|
|
176
188
|
def application
|
@@ -214,9 +226,21 @@ module ActionDispatch
|
|
214
226
|
if to.respond_to?(:action) || to.respond_to?(:call)
|
215
227
|
options
|
216
228
|
else
|
217
|
-
|
218
|
-
|
219
|
-
|
229
|
+
if to.nil?
|
230
|
+
controller = default_controller
|
231
|
+
action = default_action
|
232
|
+
elsif to.is_a?(String)
|
233
|
+
if to.include?("#")
|
234
|
+
to_endpoint = to.split("#").map!(&:-@)
|
235
|
+
controller = to_endpoint[0]
|
236
|
+
action = to_endpoint[1]
|
237
|
+
else
|
238
|
+
controller = default_controller
|
239
|
+
action = to
|
240
|
+
end
|
241
|
+
else
|
242
|
+
raise ArgumentError, ":to must respond to `action` or `call`, or it must be a String that includes '#', or the controller should be implicit"
|
243
|
+
end
|
220
244
|
|
221
245
|
controller = add_controller_module(controller, modyoule)
|
222
246
|
|
@@ -305,14 +329,6 @@ module ActionDispatch
|
|
305
329
|
hash
|
306
330
|
end
|
307
331
|
|
308
|
-
def split_to(to)
|
309
|
-
if /#/.match?(to)
|
310
|
-
to.split("#").map!(&:-@)
|
311
|
-
else
|
312
|
-
[]
|
313
|
-
end
|
314
|
-
end
|
315
|
-
|
316
332
|
def add_controller_module(controller, modyoule)
|
317
333
|
if modyoule && !controller.is_a?(Regexp)
|
318
334
|
if controller&.start_with?("/")
|
@@ -356,6 +372,38 @@ module ActionDispatch
|
|
356
372
|
def dispatcher(raise_on_name_error)
|
357
373
|
Routing::RouteSet::Dispatcher.new raise_on_name_error
|
358
374
|
end
|
375
|
+
|
376
|
+
if Thread.respond_to?(:each_caller_location)
|
377
|
+
def route_source_location
|
378
|
+
if Mapper.route_source_locations
|
379
|
+
action_dispatch_dir = File.expand_path("..", __dir__)
|
380
|
+
Thread.each_caller_location do |location|
|
381
|
+
next if location.path.start_with?(action_dispatch_dir)
|
382
|
+
|
383
|
+
cleaned_path = Mapper.backtrace_cleaner.clean_frame(location.path)
|
384
|
+
next if cleaned_path.nil?
|
385
|
+
|
386
|
+
return "#{cleaned_path}:#{location.lineno}"
|
387
|
+
end
|
388
|
+
nil
|
389
|
+
end
|
390
|
+
end
|
391
|
+
else
|
392
|
+
def route_source_location
|
393
|
+
if Mapper.route_source_locations
|
394
|
+
action_dispatch_dir = File.expand_path("..", __dir__)
|
395
|
+
caller_locations.each do |location|
|
396
|
+
next if location.path.start_with?(action_dispatch_dir)
|
397
|
+
|
398
|
+
cleaned_path = Mapper.backtrace_cleaner.clean_frame(location.path)
|
399
|
+
next if cleaned_path.nil?
|
400
|
+
|
401
|
+
return "#{cleaned_path}:#{location.lineno}"
|
402
|
+
end
|
403
|
+
nil
|
404
|
+
end
|
405
|
+
end
|
406
|
+
end
|
359
407
|
end
|
360
408
|
|
361
409
|
# Invokes Journey::Router::Utils.normalize_path, then ensures that
|
@@ -652,7 +700,7 @@ module ActionDispatch
|
|
652
700
|
|
653
701
|
script_namer = ->(options) do
|
654
702
|
prefix_options = options.slice(*_route.segment_keys)
|
655
|
-
prefix_options[:
|
703
|
+
prefix_options[:script_name] = "" if options[:original_script_name]
|
656
704
|
|
657
705
|
if options[:_recall]
|
658
706
|
prefix_options.reverse_merge!(options[:_recall].slice(*_route.segment_keys))
|
@@ -669,7 +717,7 @@ module ActionDispatch
|
|
669
717
|
def optimize_routes_generation?; false; end
|
670
718
|
|
671
719
|
define_method :find_script_name do |options|
|
672
|
-
if options.key? :script_name
|
720
|
+
if options.key?(:script_name) && options[:script_name].present?
|
673
721
|
super(options)
|
674
722
|
else
|
675
723
|
script_namer.call(options)
|
@@ -748,7 +796,7 @@ module ActionDispatch
|
|
748
796
|
# end
|
749
797
|
#
|
750
798
|
# This will create a number of routes for each of the posts and comments
|
751
|
-
# controller. For
|
799
|
+
# controller. For +Admin::PostsController+, \Rails will create:
|
752
800
|
#
|
753
801
|
# GET /admin/posts
|
754
802
|
# GET /admin/posts/new
|
@@ -759,7 +807,7 @@ module ActionDispatch
|
|
759
807
|
# DELETE /admin/posts/1
|
760
808
|
#
|
761
809
|
# If you want to route /posts (without the prefix /admin) to
|
762
|
-
#
|
810
|
+
# +Admin::PostsController+, you could use
|
763
811
|
#
|
764
812
|
# scope module: "admin" do
|
765
813
|
# resources :posts
|
@@ -808,7 +856,7 @@ module ActionDispatch
|
|
808
856
|
#
|
809
857
|
# Takes same options as <tt>Base#match</tt> and <tt>Resources#resources</tt>.
|
810
858
|
#
|
811
|
-
# # route /posts (without the prefix /admin) to
|
859
|
+
# # route /posts (without the prefix /admin) to +Admin::PostsController+
|
812
860
|
# scope module: "admin" do
|
813
861
|
# resources :posts
|
814
862
|
# end
|
@@ -917,7 +965,7 @@ module ActionDispatch
|
|
917
965
|
# resources :posts
|
918
966
|
# end
|
919
967
|
#
|
920
|
-
# # maps to
|
968
|
+
# # maps to +Sekret::PostsController+ rather than +Admin::PostsController+
|
921
969
|
# namespace :admin, module: "sekret" do
|
922
970
|
# resources :posts
|
923
971
|
# end
|
@@ -1318,7 +1366,7 @@ module ActionDispatch
|
|
1318
1366
|
self
|
1319
1367
|
end
|
1320
1368
|
|
1321
|
-
# In Rails, a resourceful route provides a mapping between HTTP verbs
|
1369
|
+
# In \Rails, a resourceful route provides a mapping between HTTP verbs
|
1322
1370
|
# and URLs and controller actions. By convention, each action also maps
|
1323
1371
|
# to particular CRUD operations in a database. A single entry in the
|
1324
1372
|
# routing file, such as
|
@@ -1450,7 +1498,7 @@ module ActionDispatch
|
|
1450
1498
|
#
|
1451
1499
|
# === Examples
|
1452
1500
|
#
|
1453
|
-
# # routes call
|
1501
|
+
# # routes call +Admin::PostsController+
|
1454
1502
|
# resources :posts, module: "admin"
|
1455
1503
|
#
|
1456
1504
|
# # resource actions are at /admin/posts.
|
@@ -1493,7 +1541,7 @@ module ActionDispatch
|
|
1493
1541
|
# end
|
1494
1542
|
# end
|
1495
1543
|
#
|
1496
|
-
# This will enable Rails to recognize paths such as <tt>/photos/search</tt>
|
1544
|
+
# This will enable \Rails to recognize paths such as <tt>/photos/search</tt>
|
1497
1545
|
# with GET, and route to the search action of +PhotosController+. It will also
|
1498
1546
|
# create the <tt>search_photos_url</tt> and <tt>search_photos_path</tt>
|
1499
1547
|
# route helpers.
|
@@ -1640,7 +1688,7 @@ module ActionDispatch
|
|
1640
1688
|
when Symbol
|
1641
1689
|
options[:action] = to
|
1642
1690
|
when String
|
1643
|
-
if
|
1691
|
+
if to.include?("#")
|
1644
1692
|
options[:to] = to
|
1645
1693
|
else
|
1646
1694
|
options[:controller] = to
|
@@ -1663,7 +1711,7 @@ module ActionDispatch
|
|
1663
1711
|
end
|
1664
1712
|
end
|
1665
1713
|
|
1666
|
-
# You can specify what Rails should route "/" to with the root method:
|
1714
|
+
# You can specify what \Rails should route "/" to with the root method:
|
1667
1715
|
#
|
1668
1716
|
# root to: 'pages#main'
|
1669
1717
|
#
|
@@ -1675,7 +1723,7 @@ module ActionDispatch
|
|
1675
1723
|
#
|
1676
1724
|
# You should put the root route at the top of <tt>config/routes.rb</tt>,
|
1677
1725
|
# because this means it will be matched first. As this is the most popular route
|
1678
|
-
# of most Rails applications, this is beneficial.
|
1726
|
+
# of most \Rails applications, this is beneficial.
|
1679
1727
|
def root(path, options = {})
|
1680
1728
|
if path.is_a?(String)
|
1681
1729
|
options[:to] = path
|
@@ -1978,7 +2026,7 @@ module ActionDispatch
|
|
1978
2026
|
name_for_action(options.delete(:as), action)
|
1979
2027
|
end
|
1980
2028
|
|
1981
|
-
path = Mapping.normalize_path
|
2029
|
+
path = Mapping.normalize_path RFC2396_PARSER.escape(path), formatted
|
1982
2030
|
ast = Journey::Parser.parse path
|
1983
2031
|
|
1984
2032
|
mapping = Mapping.build(@scope, @set, ast, controller, default_action, to, via, formatted, options_constraints, anchor, options)
|
@@ -2,6 +2,8 @@
|
|
2
2
|
|
3
3
|
module ActionDispatch
|
4
4
|
module Routing
|
5
|
+
# = Action Dispatch Routing \PolymorphicRoutes
|
6
|
+
#
|
5
7
|
# Polymorphic URL helpers are methods for smart resolution to a named route call when
|
6
8
|
# given an Active Record model instance. They are to be used in combination with
|
7
9
|
# ActionController::Resources.
|