actionpack 5.1.7 → 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 +282 -362
- data/MIT-LICENSE +1 -1
- data/README.rdoc +5 -5
- data/lib/abstract_controller.rb +3 -0
- data/lib/abstract_controller/asset_paths.rb +2 -0
- data/lib/abstract_controller/base.rb +10 -2
- data/lib/abstract_controller/caching.rb +3 -2
- data/lib/abstract_controller/caching/fragments.rb +30 -7
- data/lib/abstract_controller/callbacks.rb +25 -3
- data/lib/abstract_controller/collector.rb +2 -0
- data/lib/abstract_controller/error.rb +2 -0
- data/lib/abstract_controller/helpers.rb +4 -5
- data/lib/abstract_controller/logger.rb +2 -0
- data/lib/abstract_controller/railties/routes_helpers.rb +2 -0
- data/lib/abstract_controller/rendering.rb +9 -16
- data/lib/abstract_controller/translation.rb +2 -0
- data/lib/abstract_controller/url_for.rb +2 -0
- data/lib/action_controller.rb +3 -0
- data/lib/action_controller/api.rb +2 -0
- data/lib/action_controller/api/api_rendering.rb +2 -0
- data/lib/action_controller/base.rb +3 -0
- data/lib/action_controller/caching.rb +2 -0
- data/lib/action_controller/form_builder.rb +2 -0
- data/lib/action_controller/log_subscriber.rb +5 -3
- data/lib/action_controller/metal.rb +13 -14
- data/lib/action_controller/metal/basic_implicit_render.rb +2 -0
- data/lib/action_controller/metal/conditional_get.rb +4 -3
- data/lib/action_controller/metal/content_security_policy.rb +52 -0
- data/lib/action_controller/metal/cookies.rb +2 -0
- data/lib/action_controller/metal/data_streaming.rb +7 -5
- data/lib/action_controller/metal/etag_with_flash.rb +2 -0
- data/lib/action_controller/metal/etag_with_template_digest.rb +3 -2
- data/lib/action_controller/metal/exceptions.rb +2 -3
- data/lib/action_controller/metal/flash.rb +3 -2
- data/lib/action_controller/metal/force_ssl.rb +4 -2
- data/lib/action_controller/metal/head.rb +2 -0
- data/lib/action_controller/metal/helpers.rb +4 -3
- data/lib/action_controller/metal/http_authentication.rb +8 -9
- data/lib/action_controller/metal/implicit_render.rb +2 -0
- data/lib/action_controller/metal/instrumentation.rb +4 -6
- data/lib/action_controller/metal/live.rb +3 -1
- data/lib/action_controller/metal/mime_responds.rb +3 -1
- data/lib/action_controller/metal/parameter_encoding.rb +2 -0
- data/lib/action_controller/metal/params_wrapper.rb +14 -10
- data/lib/action_controller/metal/redirecting.rb +22 -11
- data/lib/action_controller/metal/renderers.rb +4 -3
- data/lib/action_controller/metal/rendering.rb +2 -2
- data/lib/action_controller/metal/request_forgery_protection.rb +62 -10
- data/lib/action_controller/metal/rescue.rb +5 -3
- data/lib/action_controller/metal/streaming.rb +3 -1
- data/lib/action_controller/metal/strong_parameters.rb +36 -25
- data/lib/action_controller/metal/testing.rb +2 -6
- data/lib/action_controller/metal/url_for.rb +2 -0
- data/lib/action_controller/railtie.rb +16 -4
- data/lib/action_controller/railties/helpers.rb +2 -0
- data/lib/action_controller/renderer.rb +2 -0
- data/lib/action_controller/template_assertions.rb +2 -0
- data/lib/action_controller/test_case.rb +16 -10
- data/lib/action_dispatch.rb +9 -5
- data/lib/action_dispatch/http/cache.rb +22 -14
- data/lib/action_dispatch/http/content_security_policy.rb +272 -0
- data/lib/action_dispatch/http/filter_parameters.rb +4 -2
- data/lib/action_dispatch/http/filter_redirect.rb +2 -0
- data/lib/action_dispatch/http/headers.rb +2 -0
- data/lib/action_dispatch/http/mime_negotiation.rb +4 -8
- data/lib/action_dispatch/http/mime_type.rb +15 -13
- data/lib/action_dispatch/http/mime_types.rb +17 -2
- data/lib/action_dispatch/http/parameter_filter.rb +2 -0
- data/lib/action_dispatch/http/parameters.rb +6 -9
- data/lib/action_dispatch/http/rack_cache.rb +2 -0
- data/lib/action_dispatch/http/request.rb +36 -16
- data/lib/action_dispatch/http/response.rb +11 -9
- data/lib/action_dispatch/http/upload.rb +2 -0
- data/lib/action_dispatch/http/url.rb +5 -6
- data/lib/action_dispatch/journey.rb +2 -0
- data/lib/action_dispatch/journey/formatter.rb +4 -2
- data/lib/action_dispatch/journey/gtg/builder.rb +2 -0
- data/lib/action_dispatch/journey/gtg/simulator.rb +2 -8
- data/lib/action_dispatch/journey/gtg/transition_table.rb +3 -2
- data/lib/action_dispatch/journey/nfa/builder.rb +2 -0
- data/lib/action_dispatch/journey/nfa/dot.rb +12 -10
- data/lib/action_dispatch/journey/nfa/simulator.rb +2 -0
- data/lib/action_dispatch/journey/nfa/transition_table.rb +2 -0
- data/lib/action_dispatch/journey/nodes/node.rb +2 -0
- data/lib/action_dispatch/journey/parser_extras.rb +2 -0
- data/lib/action_dispatch/journey/path/pattern.rb +4 -1
- data/lib/action_dispatch/journey/route.rb +15 -6
- data/lib/action_dispatch/journey/router.rb +3 -1
- data/lib/action_dispatch/journey/router/utils.rb +14 -7
- data/lib/action_dispatch/journey/routes.rb +3 -1
- data/lib/action_dispatch/journey/scanner.rb +1 -0
- data/lib/action_dispatch/journey/visitors.rb +5 -3
- data/lib/action_dispatch/middleware/callbacks.rb +2 -0
- data/lib/action_dispatch/middleware/cookies.rb +148 -91
- data/lib/action_dispatch/middleware/debug_exceptions.rb +4 -2
- data/lib/action_dispatch/middleware/debug_locks.rb +9 -7
- data/lib/action_dispatch/middleware/exception_wrapper.rb +5 -6
- data/lib/action_dispatch/middleware/executor.rb +2 -0
- data/lib/action_dispatch/middleware/flash.rb +4 -2
- data/lib/action_dispatch/middleware/public_exceptions.rb +6 -4
- data/lib/action_dispatch/middleware/reloader.rb +2 -0
- data/lib/action_dispatch/middleware/remote_ip.rb +7 -5
- data/lib/action_dispatch/middleware/request_id.rb +3 -1
- data/lib/action_dispatch/middleware/session/abstract_store.rb +17 -1
- data/lib/action_dispatch/middleware/session/cache_store.rb +13 -6
- data/lib/action_dispatch/middleware/session/cookie_store.rb +31 -32
- data/lib/action_dispatch/middleware/session/mem_cache_store.rb +2 -0
- data/lib/action_dispatch/middleware/show_exceptions.rb +3 -1
- data/lib/action_dispatch/middleware/ssl.rb +44 -38
- data/lib/action_dispatch/middleware/stack.rb +4 -2
- data/lib/action_dispatch/middleware/static.rb +14 -12
- 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/routes/_table.html.erb +6 -2
- data/lib/action_dispatch/railtie.rb +11 -1
- data/lib/action_dispatch/request/session.rb +16 -5
- data/lib/action_dispatch/request/utils.rb +6 -4
- data/lib/action_dispatch/routing.rb +3 -1
- data/lib/action_dispatch/routing/endpoint.rb +9 -2
- data/lib/action_dispatch/routing/inspector.rb +6 -4
- data/lib/action_dispatch/routing/mapper.rb +64 -52
- data/lib/action_dispatch/routing/polymorphic_routes.rb +2 -0
- data/lib/action_dispatch/routing/redirection.rb +7 -5
- data/lib/action_dispatch/routing/route_set.rb +29 -24
- data/lib/action_dispatch/routing/routes_proxy.rb +5 -2
- data/lib/action_dispatch/routing/url_for.rb +25 -5
- data/lib/action_dispatch/system_test_case.rb +22 -6
- data/lib/action_dispatch/system_testing/browser.rb +49 -0
- data/lib/action_dispatch/system_testing/driver.rb +9 -3
- data/lib/action_dispatch/system_testing/server.rb +2 -16
- data/lib/action_dispatch/system_testing/test_helpers/screenshot_helper.rb +12 -14
- data/lib/action_dispatch/system_testing/test_helpers/setup_and_teardown.rb +8 -2
- data/lib/action_dispatch/system_testing/test_helpers/undef_methods.rb +26 -0
- data/lib/action_dispatch/testing/assertion_response.rb +2 -0
- data/lib/action_dispatch/testing/assertions.rb +2 -0
- data/lib/action_dispatch/testing/assertions/response.rb +4 -2
- data/lib/action_dispatch/testing/assertions/routing.rb +5 -5
- data/lib/action_dispatch/testing/integration.rb +24 -21
- data/lib/action_dispatch/testing/request_encoder.rb +3 -1
- data/lib/action_dispatch/testing/test_process.rb +2 -0
- data/lib/action_dispatch/testing/test_request.rb +3 -1
- data/lib/action_dispatch/testing/test_response.rb +23 -3
- data/lib/action_pack.rb +3 -1
- data/lib/action_pack/gem_version.rb +5 -3
- data/lib/action_pack/version.rb +2 -0
- metadata +23 -11
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "active_support/inflector/methods"
|
2
4
|
require "active_support/dependencies"
|
3
5
|
|
@@ -95,8 +97,8 @@ module ActionDispatch
|
|
95
97
|
middlewares.push(build_middleware(klass, args, block))
|
96
98
|
end
|
97
99
|
|
98
|
-
def build(app =
|
99
|
-
middlewares.freeze.reverse.inject(app) { |a, e| e.build(a) }
|
100
|
+
def build(app = nil, &block)
|
101
|
+
middlewares.freeze.reverse.inject(app || block) { |a, e| e.build(a) }
|
100
102
|
end
|
101
103
|
|
102
104
|
private
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "rack/utils"
|
2
4
|
require "active_support/core_ext/uri"
|
3
5
|
|
@@ -6,15 +8,15 @@ module ActionDispatch
|
|
6
8
|
# When initialized, it can accept optional HTTP headers, which will be set
|
7
9
|
# when a response containing a file's contents is delivered.
|
8
10
|
#
|
9
|
-
# This middleware will render the file specified in
|
11
|
+
# This middleware will render the file specified in <tt>env["PATH_INFO"]</tt>
|
10
12
|
# where the base path is in the +root+ directory. For example, if the +root+
|
11
|
-
# is set to
|
12
|
-
#
|
13
|
-
# located at
|
13
|
+
# is set to +public/+, then a request with <tt>env["PATH_INFO"]</tt> of
|
14
|
+
# +assets/application.js+ will return a response with the contents of a file
|
15
|
+
# located at +public/assets/application.js+ if the file exists. If the file
|
14
16
|
# does not exist, a 404 "File not Found" response will be returned.
|
15
17
|
class FileHandler
|
16
18
|
def initialize(root, index: "index", headers: {})
|
17
|
-
@root = root.chomp("/")
|
19
|
+
@root = root.chomp("/").b
|
18
20
|
@file_server = ::Rack::File.new(@root, headers)
|
19
21
|
@index = index
|
20
22
|
end
|
@@ -23,8 +25,8 @@ module ActionDispatch
|
|
23
25
|
# correct read permissions, the return value is a URI-escaped string
|
24
26
|
# representing the filename. Otherwise, false is returned.
|
25
27
|
#
|
26
|
-
# Used by the
|
27
|
-
# in the server's
|
28
|
+
# Used by the +Static+ class to check the existence of a valid file
|
29
|
+
# in the server's +public/+ directory (see Static#call).
|
28
30
|
def match?(path)
|
29
31
|
path = ::Rack::Utils.unescape_path path
|
30
32
|
return false unless ::Rack::Utils.valid_path? path
|
@@ -33,7 +35,7 @@ module ActionDispatch
|
|
33
35
|
paths = [path, "#{path}#{ext}", "#{path}/#{@index}#{ext}"]
|
34
36
|
|
35
37
|
if match = paths.detect { |p|
|
36
|
-
path = File.join(@root, p.
|
38
|
+
path = File.join(@root, p.b)
|
37
39
|
begin
|
38
40
|
File.file?(path) && File.readable?(path)
|
39
41
|
rescue SystemCallError
|
@@ -41,7 +43,7 @@ module ActionDispatch
|
|
41
43
|
end
|
42
44
|
|
43
45
|
}
|
44
|
-
return ::Rack::Utils.escape_path(match)
|
46
|
+
return ::Rack::Utils.escape_path(match).b
|
45
47
|
end
|
46
48
|
end
|
47
49
|
|
@@ -88,8 +90,8 @@ module ActionDispatch
|
|
88
90
|
def gzip_file_path(path)
|
89
91
|
can_gzip_mime = content_type(path) =~ /\A(?:text\/|application\/javascript)/
|
90
92
|
gzip_path = "#{path}.gz"
|
91
|
-
if can_gzip_mime && File.exist?(File.join(@root, ::Rack::Utils.unescape_path(gzip_path)))
|
92
|
-
gzip_path
|
93
|
+
if can_gzip_mime && File.exist?(File.join(@root, ::Rack::Utils.unescape_path(gzip_path).b))
|
94
|
+
gzip_path.b
|
93
95
|
else
|
94
96
|
false
|
95
97
|
end
|
@@ -99,7 +101,7 @@ module ActionDispatch
|
|
99
101
|
# This middleware will attempt to return the contents of a file's body from
|
100
102
|
# disk in the response. If a file is not found on disk, the request will be
|
101
103
|
# delegated to the application stack. This middleware is commonly initialized
|
102
|
-
# to serve assets from a server's
|
104
|
+
# to serve assets from a server's +public/+ directory.
|
103
105
|
#
|
104
106
|
# This middleware verifies the path to ensure that only files
|
105
107
|
# living in the root directory can be rendered. A request cannot
|
@@ -0,0 +1,21 @@
|
|
1
|
+
<header>
|
2
|
+
<h1>
|
3
|
+
<%= @exception.class.to_s %>
|
4
|
+
<% if @request.parameters['controller'] %>
|
5
|
+
in <%= @request.parameters['controller'].camelize %>Controller<% if @request.parameters['action'] %>#<%= @request.parameters['action'] %><% end %>
|
6
|
+
<% end %>
|
7
|
+
</h1>
|
8
|
+
</header>
|
9
|
+
|
10
|
+
<div id="container">
|
11
|
+
<h2>
|
12
|
+
<%= h @exception.message %>
|
13
|
+
<% if %r{#{ActiveStorage::Blob.table_name}|#{ActiveStorage::Attachment.table_name}}.match?(@exception.message) %>
|
14
|
+
<br />To resolve this issue run: bin/rails active_storage:install
|
15
|
+
<% end %>
|
16
|
+
</h2>
|
17
|
+
|
18
|
+
<%= render template: "rescues/_source" %>
|
19
|
+
<%= render template: "rescues/_trace" %>
|
20
|
+
<%= render template: "rescues/_request_and_response" %>
|
21
|
+
</div>
|
@@ -0,0 +1,13 @@
|
|
1
|
+
<%= @exception.class.to_s %><%
|
2
|
+
if @request.parameters['controller']
|
3
|
+
%> in <%= @request.parameters['controller'].camelize %>Controller<% if @request.parameters['action'] %>#<%= @request.parameters['action'] %><% end %>
|
4
|
+
<% end %>
|
5
|
+
|
6
|
+
<%= @exception.message %>
|
7
|
+
<% if %r{#{ActiveStorage::Blob.table_name}|#{ActiveStorage::Attachment.table_name}}.match?(@exception.message) %>
|
8
|
+
To resolve this issue run: bin/rails active_storage:install
|
9
|
+
<% end %>
|
10
|
+
|
11
|
+
<%= render template: "rescues/_source" %>
|
12
|
+
<%= render template: "rescues/_trace" %>
|
13
|
+
<%= render template: "rescues/_request_and_response" %>
|
@@ -17,6 +17,10 @@
|
|
17
17
|
line-height: 15px;
|
18
18
|
}
|
19
19
|
|
20
|
+
#route_table thead tr.bottom th input#search {
|
21
|
+
-webkit-appearance: textfield;
|
22
|
+
}
|
23
|
+
|
20
24
|
#route_table tbody tr {
|
21
25
|
border-bottom: 1px solid #ddd;
|
22
26
|
}
|
@@ -60,7 +64,7 @@
|
|
60
64
|
<%= link_to "Path", "#", 'data-route-helper' => '_path',
|
61
65
|
title: "Returns a relative path (without the http or domain)" %> /
|
62
66
|
<%= link_to "Url", "#", 'data-route-helper' => '_url',
|
63
|
-
title: "Returns an absolute
|
67
|
+
title: "Returns an absolute URL (with the http and domain)" %>
|
64
68
|
</th>
|
65
69
|
<th><%# HTTP Verb %>
|
66
70
|
</th>
|
@@ -93,7 +97,7 @@
|
|
93
97
|
}
|
94
98
|
}
|
95
99
|
|
96
|
-
// get JSON from
|
100
|
+
// get JSON from URL and invoke callback with result
|
97
101
|
function getJSON(url, success) {
|
98
102
|
var xhr = new XMLHttpRequest();
|
99
103
|
xhr.open('GET', url);
|
@@ -1,4 +1,7 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "action_dispatch"
|
4
|
+
require "active_support/messages/rotation_configuration"
|
2
5
|
|
3
6
|
module ActionDispatch
|
4
7
|
class Railtie < Rails::Railtie # :nodoc:
|
@@ -16,14 +19,21 @@ module ActionDispatch
|
|
16
19
|
config.action_dispatch.signed_cookie_salt = "signed cookie"
|
17
20
|
config.action_dispatch.encrypted_cookie_salt = "encrypted cookie"
|
18
21
|
config.action_dispatch.encrypted_signed_cookie_salt = "signed encrypted cookie"
|
22
|
+
config.action_dispatch.authenticated_encrypted_cookie_salt = "authenticated encrypted cookie"
|
23
|
+
config.action_dispatch.use_authenticated_cookie_encryption = false
|
19
24
|
config.action_dispatch.perform_deep_munge = true
|
20
25
|
|
21
26
|
config.action_dispatch.default_headers = {
|
22
27
|
"X-Frame-Options" => "SAMEORIGIN",
|
23
28
|
"X-XSS-Protection" => "1; mode=block",
|
24
|
-
"X-Content-Type-Options" => "nosniff"
|
29
|
+
"X-Content-Type-Options" => "nosniff",
|
30
|
+
"X-Download-Options" => "noopen",
|
31
|
+
"X-Permitted-Cross-Domain-Policies" => "none",
|
32
|
+
"Referrer-Policy" => "strict-origin-when-cross-origin"
|
25
33
|
}
|
26
34
|
|
35
|
+
config.action_dispatch.cookies_rotations = ActiveSupport::Messages::RotationConfiguration.new
|
36
|
+
|
27
37
|
config.eager_load_namespaces << ActionDispatch
|
28
38
|
|
29
39
|
initializer "action_dispatch.configure" do |app|
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "rack/session/abstract/id"
|
2
4
|
|
3
5
|
module ActionDispatch
|
@@ -7,10 +9,10 @@ module ActionDispatch
|
|
7
9
|
ENV_SESSION_KEY = Rack::RACK_SESSION # :nodoc:
|
8
10
|
ENV_SESSION_OPTIONS_KEY = Rack::RACK_SESSION_OPTIONS # :nodoc:
|
9
11
|
|
10
|
-
# Singleton object used to determine if an optional param wasn't specified
|
12
|
+
# Singleton object used to determine if an optional param wasn't specified.
|
11
13
|
Unspecified = Object.new
|
12
14
|
|
13
|
-
# Creates a session hash, merging the properties of the previous session if any
|
15
|
+
# Creates a session hash, merging the properties of the previous session if any.
|
14
16
|
def self.create(store, req, default_options)
|
15
17
|
session_was = find req
|
16
18
|
session = Request::Session.new(store, req)
|
@@ -63,7 +65,7 @@ module ActionDispatch
|
|
63
65
|
@req = req
|
64
66
|
@delegate = {}
|
65
67
|
@loaded = false
|
66
|
-
@exists = nil #
|
68
|
+
@exists = nil # We haven't checked yet.
|
67
69
|
end
|
68
70
|
|
69
71
|
def id
|
@@ -79,7 +81,7 @@ module ActionDispatch
|
|
79
81
|
options = self.options || {}
|
80
82
|
@by.send(:delete_session, @req, options.id(@req), options)
|
81
83
|
|
82
|
-
# Load the new sid to be written with the response
|
84
|
+
# Load the new sid to be written with the response.
|
83
85
|
@loaded = false
|
84
86
|
load_for_write!
|
85
87
|
end
|
@@ -88,7 +90,13 @@ module ActionDispatch
|
|
88
90
|
# +nil+ if the given key is not found in the session.
|
89
91
|
def [](key)
|
90
92
|
load_for_read!
|
91
|
-
|
93
|
+
key = key.to_s
|
94
|
+
|
95
|
+
if key == "session_id"
|
96
|
+
id&.public_id
|
97
|
+
else
|
98
|
+
@delegate[key]
|
99
|
+
end
|
92
100
|
end
|
93
101
|
|
94
102
|
# Returns true if the session has the given key or false.
|
@@ -101,11 +109,13 @@ module ActionDispatch
|
|
101
109
|
|
102
110
|
# Returns keys of the session as Array.
|
103
111
|
def keys
|
112
|
+
load_for_read!
|
104
113
|
@delegate.keys
|
105
114
|
end
|
106
115
|
|
107
116
|
# Returns values of the session as Array.
|
108
117
|
def values
|
118
|
+
load_for_read!
|
109
119
|
@delegate.values
|
110
120
|
end
|
111
121
|
|
@@ -126,6 +136,7 @@ module ActionDispatch
|
|
126
136
|
load_for_read!
|
127
137
|
@delegate.dup.delete_if { |_, v| v.nil? }
|
128
138
|
end
|
139
|
+
alias :to_h :to_hash
|
129
140
|
|
130
141
|
# Updates the session with given Hash.
|
131
142
|
#
|
@@ -1,8 +1,11 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_support/core_ext/hash/indifferent_access"
|
4
|
+
|
1
5
|
module ActionDispatch
|
2
6
|
class Request
|
3
7
|
class Utils # :nodoc:
|
4
|
-
mattr_accessor :perform_deep_munge
|
5
|
-
self.perform_deep_munge = true
|
8
|
+
mattr_accessor :perform_deep_munge, default: true
|
6
9
|
|
7
10
|
def self.each_param_value(params, &block)
|
8
11
|
case params
|
@@ -40,7 +43,6 @@ module ActionDispatch
|
|
40
43
|
|
41
44
|
class ParamEncoder # :nodoc:
|
42
45
|
# Convert nested Hash to HashWithIndifferentAccess.
|
43
|
-
#
|
44
46
|
def self.normalize_encode_params(params)
|
45
47
|
case params
|
46
48
|
when Array
|
@@ -63,7 +65,7 @@ module ActionDispatch
|
|
63
65
|
end
|
64
66
|
end
|
65
67
|
|
66
|
-
# Remove nils from the params hash
|
68
|
+
# Remove nils from the params hash.
|
67
69
|
class NoNilParamEncoder < ParamEncoder # :nodoc:
|
68
70
|
def self.handle_array(params)
|
69
71
|
list = super
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "active_support/core_ext/string/filters"
|
2
4
|
|
3
5
|
module ActionDispatch
|
@@ -120,7 +122,7 @@ module ActionDispatch
|
|
120
122
|
# controller :blog do
|
121
123
|
# get 'blog/show' => :list
|
122
124
|
# get 'blog/delete' => :delete
|
123
|
-
# get 'blog/edit'
|
125
|
+
# get 'blog/edit' => :edit
|
124
126
|
# end
|
125
127
|
#
|
126
128
|
# # provides named routes for show, delete, and edit
|
@@ -1,10 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ActionDispatch
|
2
4
|
module Routing
|
3
5
|
class Endpoint # :nodoc:
|
4
6
|
def dispatcher?; false; end
|
5
7
|
def redirect?; false; end
|
6
|
-
def matches?(req);
|
7
|
-
def app;
|
8
|
+
def matches?(req); true; end
|
9
|
+
def app; self; end
|
10
|
+
def rack_app; app; end
|
11
|
+
|
12
|
+
def engine?
|
13
|
+
rack_app.is_a?(Class) && rack_app < Rails::Engine
|
14
|
+
end
|
8
15
|
end
|
9
16
|
end
|
10
17
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "delegate"
|
2
4
|
require "active_support/core_ext/string/strip"
|
3
5
|
|
@@ -13,7 +15,7 @@ module ActionDispatch
|
|
13
15
|
end
|
14
16
|
|
15
17
|
def rack_app
|
16
|
-
app.
|
18
|
+
app.rack_app
|
17
19
|
end
|
18
20
|
|
19
21
|
def path
|
@@ -45,7 +47,7 @@ module ActionDispatch
|
|
45
47
|
end
|
46
48
|
|
47
49
|
def engine?
|
48
|
-
|
50
|
+
app.engine?
|
49
51
|
end
|
50
52
|
end
|
51
53
|
|
@@ -82,7 +84,7 @@ module ActionDispatch
|
|
82
84
|
|
83
85
|
def normalize_filter(filter)
|
84
86
|
if filter.is_a?(Hash) && filter[:controller]
|
85
|
-
{ controller: /#{filter[:controller].
|
87
|
+
{ controller: /#{filter[:controller].underscore.sub(/_?controller\z/, "")}/ }
|
86
88
|
elsif filter
|
87
89
|
{ controller: /#{filter}/, action: /#{filter}/, verb: /#{filter}/, name: /#{filter}/, path: /#{filter}/ }
|
88
90
|
end
|
@@ -196,7 +198,7 @@ module ActionDispatch
|
|
196
198
|
@buffer << @view.render(partial: "routes/route", collection: routes)
|
197
199
|
end
|
198
200
|
|
199
|
-
#
|
201
|
+
# The header is part of the HTML page, so we don't construct it here.
|
200
202
|
def header(routes)
|
201
203
|
end
|
202
204
|
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "active_support/core_ext/hash/slice"
|
2
4
|
require "active_support/core_ext/enumerable"
|
3
5
|
require "active_support/core_ext/array/extract_options"
|
@@ -17,9 +19,9 @@ module ActionDispatch
|
|
17
19
|
CALL = ->(app, req) { app.call req.env }
|
18
20
|
|
19
21
|
def initialize(app, constraints, strategy)
|
20
|
-
# Unwrap Constraints objects.
|
22
|
+
# Unwrap Constraints objects. I don't actually think it's possible
|
21
23
|
# to pass a Constraints object to this constructor, but there were
|
22
|
-
# multiple places that kept testing children of this object.
|
24
|
+
# multiple places that kept testing children of this object. I
|
23
25
|
# *think* they were just being defensive, but I have no idea.
|
24
26
|
if app.is_a?(self.class)
|
25
27
|
constraints += app.constraints
|
@@ -219,7 +221,7 @@ module ActionDispatch
|
|
219
221
|
private
|
220
222
|
def add_wildcard_options(options, formatted, path_ast)
|
221
223
|
# Add a constraint for wildcard route to make it non-greedy and match the
|
222
|
-
# optional format part of the route by default
|
224
|
+
# optional format part of the route by default.
|
223
225
|
if formatted != false
|
224
226
|
path_ast.grep(Journey::Nodes::Star).each_with_object({}) { |node, hash|
|
225
227
|
hash[node.name.to_sym] ||= /.+?/
|
@@ -306,7 +308,7 @@ module ActionDispatch
|
|
306
308
|
def check_controller_and_action(path_params, controller, action)
|
307
309
|
hash = check_part(:controller, controller, path_params, {}) do |part|
|
308
310
|
translate_controller(part) {
|
309
|
-
message = "'#{part}' is not a supported controller name. This can lead to potential routing problems."
|
311
|
+
message = "'#{part}' is not a supported controller name. This can lead to potential routing problems.".dup
|
310
312
|
message << " See http://guides.rubyonrails.org/routing.html#specifying-a-controller-to-use"
|
311
313
|
|
312
314
|
raise ArgumentError, message
|
@@ -388,7 +390,7 @@ module ActionDispatch
|
|
388
390
|
# for root cases, where the latter is the correct one.
|
389
391
|
def self.normalize_path(path)
|
390
392
|
path = Journey::Router::Utils.normalize_path(path)
|
391
|
-
path.gsub!(%r{/(\(+)/?}, '\1/') unless path =~ %r{
|
393
|
+
path.gsub!(%r{/(\(+)/?}, '\1/') unless path =~ %r{^/(\(+[^)]+\)){1,}$}
|
392
394
|
path
|
393
395
|
end
|
394
396
|
|
@@ -397,7 +399,7 @@ module ActionDispatch
|
|
397
399
|
end
|
398
400
|
|
399
401
|
module Base
|
400
|
-
# Matches a
|
402
|
+
# Matches a URL pattern to one or more routes.
|
401
403
|
#
|
402
404
|
# You should not use the +match+ method in your router
|
403
405
|
# without specifying an HTTP method.
|
@@ -407,7 +409,7 @@ module ActionDispatch
|
|
407
409
|
# # sets :controller, :action and :id in params
|
408
410
|
# match ':controller/:action/:id', via: [:get, :post]
|
409
411
|
#
|
410
|
-
# Note that +:controller+, +:action+ and +:id+ are interpreted as
|
412
|
+
# Note that +:controller+, +:action+ and +:id+ are interpreted as URL
|
411
413
|
# query parameters and thus available through +params+ in an action.
|
412
414
|
#
|
413
415
|
# If you want to expose your action to GET, use +get+ in the router:
|
@@ -456,7 +458,7 @@ module ActionDispatch
|
|
456
458
|
#
|
457
459
|
# === Options
|
458
460
|
#
|
459
|
-
# Any options not seen here are passed on as params with the
|
461
|
+
# Any options not seen here are passed on as params with the URL.
|
460
462
|
#
|
461
463
|
# [:controller]
|
462
464
|
# The route's controller.
|
@@ -471,7 +473,17 @@ module ActionDispatch
|
|
471
473
|
# <tt>params[<:param>]</tt>.
|
472
474
|
# In your router:
|
473
475
|
#
|
474
|
-
# resources :
|
476
|
+
# resources :users, param: :name
|
477
|
+
#
|
478
|
+
# The +users+ resource here will have the following routes generated for it:
|
479
|
+
#
|
480
|
+
# GET /users(.:format)
|
481
|
+
# POST /users(.:format)
|
482
|
+
# GET /users/new(.:format)
|
483
|
+
# GET /users/:name/edit(.:format)
|
484
|
+
# GET /users/:name(.:format)
|
485
|
+
# PATCH/PUT /users/:name(.:format)
|
486
|
+
# DELETE /users/:name(.:format)
|
475
487
|
#
|
476
488
|
# You can override <tt>ActiveRecord::Base#to_param</tt> of a related
|
477
489
|
# model to construct a URL:
|
@@ -482,8 +494,8 @@ module ActionDispatch
|
|
482
494
|
# end
|
483
495
|
# end
|
484
496
|
#
|
485
|
-
#
|
486
|
-
#
|
497
|
+
# user = User.find_by(name: 'Phusion')
|
498
|
+
# user_path(user) # => "/users/Phusion"
|
487
499
|
#
|
488
500
|
# [:path]
|
489
501
|
# The path prefix for the routes.
|
@@ -1252,7 +1264,7 @@ module ActionDispatch
|
|
1252
1264
|
#
|
1253
1265
|
# resource :profile
|
1254
1266
|
#
|
1255
|
-
# creates six different routes in your application, all mapping to
|
1267
|
+
# This creates six different routes in your application, all mapping to
|
1256
1268
|
# the +Profiles+ controller (note that the controller is named after
|
1257
1269
|
# the plural):
|
1258
1270
|
#
|
@@ -1264,7 +1276,7 @@ module ActionDispatch
|
|
1264
1276
|
# POST /profile
|
1265
1277
|
#
|
1266
1278
|
# === Options
|
1267
|
-
# Takes same options as
|
1279
|
+
# Takes same options as resources[rdoc-ref:#resources]
|
1268
1280
|
def resource(*resources, &block)
|
1269
1281
|
options = resources.extract_options!.dup
|
1270
1282
|
|
@@ -1329,7 +1341,7 @@ module ActionDispatch
|
|
1329
1341
|
# DELETE /photos/:photo_id/comments/:id
|
1330
1342
|
#
|
1331
1343
|
# === Options
|
1332
|
-
# Takes same options as
|
1344
|
+
# Takes same options as match[rdoc-ref:Base#match] as well as:
|
1333
1345
|
#
|
1334
1346
|
# [:path_names]
|
1335
1347
|
# Allows you to change the segment component of the +edit+ and +new+ actions.
|
@@ -1337,14 +1349,14 @@ module ActionDispatch
|
|
1337
1349
|
#
|
1338
1350
|
# resources :posts, path_names: { new: "brand_new" }
|
1339
1351
|
#
|
1340
|
-
# The above example will now change /posts/new to /posts/brand_new
|
1352
|
+
# The above example will now change /posts/new to /posts/brand_new.
|
1341
1353
|
#
|
1342
1354
|
# [:path]
|
1343
1355
|
# Allows you to change the path prefix for the resource.
|
1344
1356
|
#
|
1345
1357
|
# resources :posts, path: 'postings'
|
1346
1358
|
#
|
1347
|
-
# The resource and all segments will now route to /postings instead of /posts
|
1359
|
+
# The resource and all segments will now route to /postings instead of /posts.
|
1348
1360
|
#
|
1349
1361
|
# [:only]
|
1350
1362
|
# Only generate routes for the given actions.
|
@@ -1539,7 +1551,7 @@ module ActionDispatch
|
|
1539
1551
|
end
|
1540
1552
|
end
|
1541
1553
|
|
1542
|
-
# See ActionDispatch::Routing::Mapper::Scoping#namespace
|
1554
|
+
# See ActionDispatch::Routing::Mapper::Scoping#namespace.
|
1543
1555
|
def namespace(path, options = {})
|
1544
1556
|
if resource_scope?
|
1545
1557
|
nested { super }
|
@@ -1559,10 +1571,10 @@ module ActionDispatch
|
|
1559
1571
|
!parent_resource.singleton? && @scope[:shallow]
|
1560
1572
|
end
|
1561
1573
|
|
1562
|
-
# Matches a
|
1574
|
+
# Matches a URL pattern to one or more routes.
|
1563
1575
|
# For more information, see match[rdoc-ref:Base#match].
|
1564
1576
|
#
|
1565
|
-
# match 'path' => 'controller#action', via: patch
|
1577
|
+
# match 'path' => 'controller#action', via: :patch
|
1566
1578
|
# match 'path', to: 'controller#action', via: :post
|
1567
1579
|
# match 'path', 'otherpath', on: :member, via: :get
|
1568
1580
|
def match(path, *rest, &block)
|
@@ -1850,7 +1862,7 @@ module ActionDispatch
|
|
1850
1862
|
path_types.fetch(String, []).each do |_path|
|
1851
1863
|
route_options = options.dup
|
1852
1864
|
if _path && option_path
|
1853
|
-
raise ArgumentError, "
|
1865
|
+
raise ArgumentError, "Ambiguous route definition. Both :path and the route path were specified as strings."
|
1854
1866
|
end
|
1855
1867
|
to = get_to_from_path(_path, to, route_options[:action])
|
1856
1868
|
decomposed_match(_path, controller, route_options, _path, to, via, formatted, anchor, options_constraints)
|
@@ -2017,7 +2029,7 @@ module ActionDispatch
|
|
2017
2029
|
# concerns :commentable
|
2018
2030
|
# end
|
2019
2031
|
#
|
2020
|
-
#
|
2032
|
+
# Concerns also work in any routes helper that you want to use:
|
2021
2033
|
#
|
2022
2034
|
# namespace :posts do
|
2023
2035
|
# concerns :commentable
|
@@ -2035,7 +2047,7 @@ module ActionDispatch
|
|
2035
2047
|
end
|
2036
2048
|
|
2037
2049
|
module CustomUrls
|
2038
|
-
# Define custom
|
2050
|
+
# Define custom URL helpers that will be added to the application's
|
2039
2051
|
# routes. This allows you to override and/or replace the default behavior
|
2040
2052
|
# of routing helpers, e.g:
|
2041
2053
|
#
|
@@ -2051,37 +2063,37 @@ module ActionDispatch
|
|
2051
2063
|
# { controller: "pages", action: "index", subdomain: "www" }
|
2052
2064
|
# end
|
2053
2065
|
#
|
2054
|
-
# The return value from the block passed to
|
2055
|
-
# arguments for
|
2066
|
+
# The return value from the block passed to +direct+ must be a valid set of
|
2067
|
+
# arguments for +url_for+ which will actually build the URL string. This can
|
2056
2068
|
# be one of the following:
|
2057
2069
|
#
|
2058
|
-
#
|
2059
|
-
#
|
2060
|
-
#
|
2061
|
-
#
|
2062
|
-
#
|
2070
|
+
# * A string, which is treated as a generated URL
|
2071
|
+
# * A hash, e.g. <tt>{ controller: "pages", action: "index" }</tt>
|
2072
|
+
# * An array, which is passed to +polymorphic_url+
|
2073
|
+
# * An Active Model instance
|
2074
|
+
# * An Active Model class
|
2063
2075
|
#
|
2064
|
-
# NOTE: Other
|
2065
|
-
# your custom
|
2076
|
+
# NOTE: Other URL helpers can be called in the block but be careful not to invoke
|
2077
|
+
# your custom URL helper again otherwise it will result in a stack overflow error.
|
2066
2078
|
#
|
2067
2079
|
# You can also specify default options that will be passed through to
|
2068
|
-
# your
|
2080
|
+
# your URL helper definition, e.g:
|
2069
2081
|
#
|
2070
2082
|
# direct :browse, page: 1, size: 10 do |options|
|
2071
2083
|
# [ :products, options.merge(params.permit(:page, :size).to_h.symbolize_keys) ]
|
2072
2084
|
# end
|
2073
2085
|
#
|
2074
|
-
# In this instance the
|
2075
|
-
# block is executed, e.g. generating a
|
2076
|
-
# If the block is executed where there isn't a params object such as this:
|
2086
|
+
# In this instance the +params+ object comes from the context in which the
|
2087
|
+
# block is executed, e.g. generating a URL inside a controller action or a view.
|
2088
|
+
# If the block is executed where there isn't a +params+ object such as this:
|
2077
2089
|
#
|
2078
2090
|
# Rails.application.routes.url_helpers.browse_path
|
2079
2091
|
#
|
2080
|
-
# then it will raise a
|
2081
|
-
# context in which you will use your custom
|
2092
|
+
# then it will raise a +NameError+. Because of this you need to be aware of the
|
2093
|
+
# context in which you will use your custom URL helper when defining it.
|
2082
2094
|
#
|
2083
|
-
# NOTE: The
|
2084
|
-
#
|
2095
|
+
# NOTE: The +direct+ method can't be used inside of a scope block such as
|
2096
|
+
# +namespace+ or +scope+ and will raise an error if it detects that it is.
|
2085
2097
|
def direct(name, options = {}, &block)
|
2086
2098
|
unless @scope.root?
|
2087
2099
|
raise RuntimeError, "The direct method can't be used inside a routes scope block"
|
@@ -2090,9 +2102,9 @@ module ActionDispatch
|
|
2090
2102
|
@set.add_url_helper(name, options, &block)
|
2091
2103
|
end
|
2092
2104
|
|
2093
|
-
# Define custom polymorphic mappings of models to
|
2094
|
-
# behavior of
|
2095
|
-
#
|
2105
|
+
# Define custom polymorphic mappings of models to URLs. This alters the
|
2106
|
+
# behavior of +polymorphic_url+ and consequently the behavior of
|
2107
|
+
# +link_to+ and +form_for+ when passed a model instance, e.g:
|
2096
2108
|
#
|
2097
2109
|
# resource :basket
|
2098
2110
|
#
|
@@ -2100,10 +2112,10 @@ module ActionDispatch
|
|
2100
2112
|
# [:basket]
|
2101
2113
|
# end
|
2102
2114
|
#
|
2103
|
-
# This will now generate "/basket" when a
|
2104
|
-
#
|
2115
|
+
# This will now generate "/basket" when a +Basket+ instance is passed to
|
2116
|
+
# +link_to+ or +form_for+ instead of the standard "/baskets/:id".
|
2105
2117
|
#
|
2106
|
-
# NOTE: This custom behavior only applies to simple polymorphic
|
2118
|
+
# NOTE: This custom behavior only applies to simple polymorphic URLs where
|
2107
2119
|
# a single model instance is passed and not more complicated forms, e.g:
|
2108
2120
|
#
|
2109
2121
|
# # config/routes.rb
|
@@ -2118,8 +2130,8 @@ module ActionDispatch
|
|
2118
2130
|
# link_to "Profile", @current_user
|
2119
2131
|
# link_to "Profile", [:admin, @current_user]
|
2120
2132
|
#
|
2121
|
-
# The first
|
2122
|
-
# the standard polymorphic
|
2133
|
+
# The first +link_to+ will generate "/profile" but the second will generate
|
2134
|
+
# the standard polymorphic URL of "/admin/users/1".
|
2123
2135
|
#
|
2124
2136
|
# You can pass options to a polymorphic mapping - the arity for the block
|
2125
2137
|
# needs to be two as the instance is passed as the first argument, e.g:
|
@@ -2128,12 +2140,12 @@ module ActionDispatch
|
|
2128
2140
|
# [:basket, options]
|
2129
2141
|
# end
|
2130
2142
|
#
|
2131
|
-
# This generates the
|
2132
|
-
# array passed to
|
2133
|
-
# to the
|
2143
|
+
# This generates the URL "/basket#items" because when the last item in an
|
2144
|
+
# array passed to +polymorphic_url+ is a hash then it's treated as options
|
2145
|
+
# to the URL helper that gets called.
|
2134
2146
|
#
|
2135
|
-
# NOTE: The
|
2136
|
-
#
|
2147
|
+
# NOTE: The +resolve+ method can't be used inside of a scope block such as
|
2148
|
+
# +namespace+ or +scope+ and will raise an error if it detects that it is.
|
2137
2149
|
def resolve(*args, &block)
|
2138
2150
|
unless @scope.root?
|
2139
2151
|
raise RuntimeError, "The resolve method can't be used inside a routes scope block"
|