actionpack 7.0.7 → 7.1.3.4
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 +367 -331
- 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 -4
- 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 +17 -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 +132 -52
- 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 +15 -5
- data/lib/action_controller.rb +8 -1
- 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 +35 -12
- 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 -23
- data/lib/action_dispatch/http/rack_cache.rb +2 -0
- data/lib/action_dispatch/http/request.rb +48 -14
- 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 +1 -1
- data/lib/action_dispatch/middleware/flash.rb +7 -0
- data/lib/action_dispatch/middleware/host_authorization.rb +18 -8
- 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 +19 -15
- 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/blocked_host.html.erb +7 -3
- data/lib/action_dispatch/middleware/templates/rescues/blocked_host.text.erb +5 -3
- 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 +14 -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 +35 -24
- 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 +52 -22
- 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 +20 -19
- data/lib/action_dispatch/system_testing/driver.rb +13 -21
- 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 +37 -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 +64 -28
|
@@ -12,6 +12,9 @@ module ActionDispatch
|
|
|
12
12
|
class Mapper
|
|
13
13
|
URL_OPTIONS = [:protocol, :subdomain, :domain, :host, :port]
|
|
14
14
|
|
|
15
|
+
cattr_accessor :route_source_locations, instance_accessor: false, default: false
|
|
16
|
+
cattr_accessor :backtrace_cleaner, instance_accessor: false, default: ActiveSupport::BacktraceCleaner.new
|
|
17
|
+
|
|
15
18
|
class Constraints < Routing::Endpoint # :nodoc:
|
|
16
19
|
attr_reader :app, :constraints
|
|
17
20
|
|
|
@@ -43,7 +46,7 @@ module ActionDispatch
|
|
|
43
46
|
end
|
|
44
47
|
|
|
45
48
|
def serve(req)
|
|
46
|
-
return [ 404, {
|
|
49
|
+
return [ 404, { Constants::X_CASCADE => "pass" }, [] ] unless matches?(req)
|
|
47
50
|
|
|
48
51
|
@strategy.call @app, req
|
|
49
52
|
end
|
|
@@ -170,7 +173,7 @@ module ActionDispatch
|
|
|
170
173
|
Journey::Route.new(name: name, app: application, path: path, constraints: conditions,
|
|
171
174
|
required_defaults: required_defaults, defaults: defaults,
|
|
172
175
|
request_method_match: request_method, precedence: precedence,
|
|
173
|
-
scope_options: scope_options, internal: @internal)
|
|
176
|
+
scope_options: scope_options, internal: @internal, source_location: route_source_location)
|
|
174
177
|
end
|
|
175
178
|
|
|
176
179
|
def application
|
|
@@ -214,9 +217,16 @@ module ActionDispatch
|
|
|
214
217
|
if to.respond_to?(:action) || to.respond_to?(:call)
|
|
215
218
|
options
|
|
216
219
|
else
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
+
if to.nil?
|
|
221
|
+
controller = default_controller
|
|
222
|
+
action = default_action
|
|
223
|
+
elsif to.is_a?(String) && to.include?("#")
|
|
224
|
+
to_endpoint = to.split("#").map!(&:-@)
|
|
225
|
+
controller = to_endpoint[0]
|
|
226
|
+
action = to_endpoint[1]
|
|
227
|
+
else
|
|
228
|
+
raise ArgumentError, ":to must respond to `action` or `call`, or it must be a String that includes '#'"
|
|
229
|
+
end
|
|
220
230
|
|
|
221
231
|
controller = add_controller_module(controller, modyoule)
|
|
222
232
|
|
|
@@ -305,14 +315,6 @@ module ActionDispatch
|
|
|
305
315
|
hash
|
|
306
316
|
end
|
|
307
317
|
|
|
308
|
-
def split_to(to)
|
|
309
|
-
if /#/.match?(to)
|
|
310
|
-
to.split("#").map!(&:-@)
|
|
311
|
-
else
|
|
312
|
-
[]
|
|
313
|
-
end
|
|
314
|
-
end
|
|
315
|
-
|
|
316
318
|
def add_controller_module(controller, modyoule)
|
|
317
319
|
if modyoule && !controller.is_a?(Regexp)
|
|
318
320
|
if controller&.start_with?("/")
|
|
@@ -356,6 +358,15 @@ module ActionDispatch
|
|
|
356
358
|
def dispatcher(raise_on_name_error)
|
|
357
359
|
Routing::RouteSet::Dispatcher.new raise_on_name_error
|
|
358
360
|
end
|
|
361
|
+
|
|
362
|
+
def route_source_location
|
|
363
|
+
if Mapper.route_source_locations
|
|
364
|
+
action_dispatch_dir = File.expand_path("..", __dir__)
|
|
365
|
+
caller_location = caller_locations.find { |location| !location.path.include?(action_dispatch_dir) }
|
|
366
|
+
cleaned_path = Mapper.backtrace_cleaner.clean([caller_location.path]).first
|
|
367
|
+
"#{cleaned_path}:#{caller_location.lineno}" if cleaned_path
|
|
368
|
+
end
|
|
369
|
+
end
|
|
359
370
|
end
|
|
360
371
|
|
|
361
372
|
# Invokes Journey::Router::Utils.normalize_path, then ensures that
|
|
@@ -652,7 +663,7 @@ module ActionDispatch
|
|
|
652
663
|
|
|
653
664
|
script_namer = ->(options) do
|
|
654
665
|
prefix_options = options.slice(*_route.segment_keys)
|
|
655
|
-
prefix_options[:
|
|
666
|
+
prefix_options[:script_name] = "" if options[:original_script_name]
|
|
656
667
|
|
|
657
668
|
if options[:_recall]
|
|
658
669
|
prefix_options.reverse_merge!(options[:_recall].slice(*_route.segment_keys))
|
|
@@ -748,7 +759,7 @@ module ActionDispatch
|
|
|
748
759
|
# end
|
|
749
760
|
#
|
|
750
761
|
# This will create a number of routes for each of the posts and comments
|
|
751
|
-
# controller. For
|
|
762
|
+
# controller. For +Admin::PostsController+, \Rails will create:
|
|
752
763
|
#
|
|
753
764
|
# GET /admin/posts
|
|
754
765
|
# GET /admin/posts/new
|
|
@@ -759,7 +770,7 @@ module ActionDispatch
|
|
|
759
770
|
# DELETE /admin/posts/1
|
|
760
771
|
#
|
|
761
772
|
# If you want to route /posts (without the prefix /admin) to
|
|
762
|
-
#
|
|
773
|
+
# +Admin::PostsController+, you could use
|
|
763
774
|
#
|
|
764
775
|
# scope module: "admin" do
|
|
765
776
|
# resources :posts
|
|
@@ -808,7 +819,7 @@ module ActionDispatch
|
|
|
808
819
|
#
|
|
809
820
|
# Takes same options as <tt>Base#match</tt> and <tt>Resources#resources</tt>.
|
|
810
821
|
#
|
|
811
|
-
# # route /posts (without the prefix /admin) to
|
|
822
|
+
# # route /posts (without the prefix /admin) to +Admin::PostsController+
|
|
812
823
|
# scope module: "admin" do
|
|
813
824
|
# resources :posts
|
|
814
825
|
# end
|
|
@@ -917,7 +928,7 @@ module ActionDispatch
|
|
|
917
928
|
# resources :posts
|
|
918
929
|
# end
|
|
919
930
|
#
|
|
920
|
-
# # maps to
|
|
931
|
+
# # maps to +Sekret::PostsController+ rather than +Admin::PostsController+
|
|
921
932
|
# namespace :admin, module: "sekret" do
|
|
922
933
|
# resources :posts
|
|
923
934
|
# end
|
|
@@ -1318,7 +1329,7 @@ module ActionDispatch
|
|
|
1318
1329
|
self
|
|
1319
1330
|
end
|
|
1320
1331
|
|
|
1321
|
-
# In Rails, a resourceful route provides a mapping between HTTP verbs
|
|
1332
|
+
# In \Rails, a resourceful route provides a mapping between HTTP verbs
|
|
1322
1333
|
# and URLs and controller actions. By convention, each action also maps
|
|
1323
1334
|
# to particular CRUD operations in a database. A single entry in the
|
|
1324
1335
|
# routing file, such as
|
|
@@ -1450,7 +1461,7 @@ module ActionDispatch
|
|
|
1450
1461
|
#
|
|
1451
1462
|
# === Examples
|
|
1452
1463
|
#
|
|
1453
|
-
# # routes call
|
|
1464
|
+
# # routes call +Admin::PostsController+
|
|
1454
1465
|
# resources :posts, module: "admin"
|
|
1455
1466
|
#
|
|
1456
1467
|
# # resource actions are at /admin/posts.
|
|
@@ -1493,7 +1504,7 @@ module ActionDispatch
|
|
|
1493
1504
|
# end
|
|
1494
1505
|
# end
|
|
1495
1506
|
#
|
|
1496
|
-
# This will enable Rails to recognize paths such as <tt>/photos/search</tt>
|
|
1507
|
+
# This will enable \Rails to recognize paths such as <tt>/photos/search</tt>
|
|
1497
1508
|
# with GET, and route to the search action of +PhotosController+. It will also
|
|
1498
1509
|
# create the <tt>search_photos_url</tt> and <tt>search_photos_path</tt>
|
|
1499
1510
|
# route helpers.
|
|
@@ -1640,7 +1651,7 @@ module ActionDispatch
|
|
|
1640
1651
|
when Symbol
|
|
1641
1652
|
options[:action] = to
|
|
1642
1653
|
when String
|
|
1643
|
-
if
|
|
1654
|
+
if to.include?("#")
|
|
1644
1655
|
options[:to] = to
|
|
1645
1656
|
else
|
|
1646
1657
|
options[:controller] = to
|
|
@@ -1663,7 +1674,7 @@ module ActionDispatch
|
|
|
1663
1674
|
end
|
|
1664
1675
|
end
|
|
1665
1676
|
|
|
1666
|
-
# You can specify what Rails should route "/" to with the root method:
|
|
1677
|
+
# You can specify what \Rails should route "/" to with the root method:
|
|
1667
1678
|
#
|
|
1668
1679
|
# root to: 'pages#main'
|
|
1669
1680
|
#
|
|
@@ -1675,7 +1686,7 @@ module ActionDispatch
|
|
|
1675
1686
|
#
|
|
1676
1687
|
# You should put the root route at the top of <tt>config/routes.rb</tt>,
|
|
1677
1688
|
# because this means it will be matched first. As this is the most popular route
|
|
1678
|
-
# of most Rails applications, this is beneficial.
|
|
1689
|
+
# of most \Rails applications, this is beneficial.
|
|
1679
1690
|
def root(path, options = {})
|
|
1680
1691
|
if path.is_a?(String)
|
|
1681
1692
|
options[:to] = path
|
|
@@ -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.
|
|
@@ -18,10 +18,19 @@ module ActionDispatch
|
|
|
18
18
|
def redirect?; true; end
|
|
19
19
|
|
|
20
20
|
def call(env)
|
|
21
|
-
|
|
21
|
+
ActiveSupport::Notifications.instrument("redirect.action_dispatch") do |payload|
|
|
22
|
+
request = Request.new(env)
|
|
23
|
+
response = build_response(request)
|
|
24
|
+
|
|
25
|
+
payload[:status] = @status
|
|
26
|
+
payload[:location] = response.headers["Location"]
|
|
27
|
+
payload[:request] = request
|
|
28
|
+
|
|
29
|
+
response.to_a
|
|
30
|
+
end
|
|
22
31
|
end
|
|
23
32
|
|
|
24
|
-
def
|
|
33
|
+
def build_response(req)
|
|
25
34
|
uri = URI.parse(path(req.path_parameters, req))
|
|
26
35
|
|
|
27
36
|
unless uri.host
|
|
@@ -38,15 +47,15 @@ module ActionDispatch
|
|
|
38
47
|
|
|
39
48
|
req.commit_flash
|
|
40
49
|
|
|
41
|
-
body =
|
|
50
|
+
body = ""
|
|
42
51
|
|
|
43
52
|
headers = {
|
|
44
53
|
"Location" => uri.to_s,
|
|
45
|
-
"Content-Type" => "text/html",
|
|
54
|
+
"Content-Type" => "text/html; charset=#{ActionDispatch::Response.default_charset}",
|
|
46
55
|
"Content-Length" => body.length.to_s
|
|
47
56
|
}
|
|
48
57
|
|
|
49
|
-
|
|
58
|
+
ActionDispatch::Response.new(status, headers, body)
|
|
50
59
|
end
|
|
51
60
|
|
|
52
61
|
def path(params, request)
|
|
@@ -59,7 +68,7 @@ module ActionDispatch
|
|
|
59
68
|
|
|
60
69
|
private
|
|
61
70
|
def relative_path?(path)
|
|
62
|
-
path && !path.empty? && path
|
|
71
|
+
path && !path.empty? && !path.start_with?("/")
|
|
63
72
|
end
|
|
64
73
|
|
|
65
74
|
def escape(params)
|
|
@@ -34,20 +34,20 @@ module ActionDispatch
|
|
|
34
34
|
if @raise_on_name_error
|
|
35
35
|
raise
|
|
36
36
|
else
|
|
37
|
-
[404, {
|
|
37
|
+
[404, { Constants::X_CASCADE => "pass" }, []]
|
|
38
38
|
end
|
|
39
39
|
end
|
|
40
40
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
41
|
+
private
|
|
42
|
+
def controller(req)
|
|
43
|
+
req.controller_class
|
|
44
|
+
rescue NameError => e
|
|
45
|
+
raise ActionController::RoutingError, e.message, e.backtrace
|
|
46
|
+
end
|
|
47
47
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
48
|
+
def dispatch(controller, action, req, res)
|
|
49
|
+
controller.dispatch(action, req, res)
|
|
50
|
+
end
|
|
51
51
|
end
|
|
52
52
|
|
|
53
53
|
class StaticDispatcher < Dispatcher
|
|
@@ -282,7 +282,7 @@ module ActionDispatch
|
|
|
282
282
|
|
|
283
283
|
if args.size < path_params_size
|
|
284
284
|
path_params -= controller_options.keys
|
|
285
|
-
path_params -= result.keys
|
|
285
|
+
path_params -= (result[:path_params] || {}).merge(result).keys
|
|
286
286
|
else
|
|
287
287
|
path_params = path_params.dup
|
|
288
288
|
end
|
|
@@ -375,6 +375,7 @@ module ActionDispatch
|
|
|
375
375
|
@disable_clear_and_finalize = false
|
|
376
376
|
@finalized = false
|
|
377
377
|
@env_key = "ROUTES_#{object_id}_SCRIPT_NAME"
|
|
378
|
+
@default_env = nil
|
|
378
379
|
|
|
379
380
|
@set = Journey::Routes.new
|
|
380
381
|
@router = Journey::Router.new @set
|
|
@@ -405,6 +406,25 @@ module ActionDispatch
|
|
|
405
406
|
end
|
|
406
407
|
private :make_request
|
|
407
408
|
|
|
409
|
+
def default_env
|
|
410
|
+
if default_url_options != @default_env&.[]("action_dispatch.routes.default_url_options")
|
|
411
|
+
url_options = default_url_options.dup.freeze
|
|
412
|
+
uri = URI(ActionDispatch::Http::URL.full_url_for(host: "example.org", **url_options))
|
|
413
|
+
|
|
414
|
+
@default_env = {
|
|
415
|
+
"action_dispatch.routes" => self,
|
|
416
|
+
"action_dispatch.routes.default_url_options" => url_options,
|
|
417
|
+
"HTTPS" => uri.scheme == "https" ? "on" : "off",
|
|
418
|
+
"rack.url_scheme" => uri.scheme,
|
|
419
|
+
"HTTP_HOST" => uri.port == uri.default_port ? uri.host : "#{uri.host}:#{uri.port}",
|
|
420
|
+
"SCRIPT_NAME" => uri.path.chomp("/"),
|
|
421
|
+
"rack.input" => "",
|
|
422
|
+
}.freeze
|
|
423
|
+
end
|
|
424
|
+
|
|
425
|
+
@default_env
|
|
426
|
+
end
|
|
427
|
+
|
|
408
428
|
def draw(&block)
|
|
409
429
|
clear! unless @disable_clear_and_finalize
|
|
410
430
|
eval_block(block)
|
|
@@ -574,6 +594,20 @@ module ActionDispatch
|
|
|
574
594
|
end
|
|
575
595
|
|
|
576
596
|
private :_generate_paths_by_default
|
|
597
|
+
|
|
598
|
+
# If the module is included more than once (for example, in a subclass
|
|
599
|
+
# of an ancestor that includes the module), ensure that the `_routes`
|
|
600
|
+
# singleton and instance methods return the desired route set by
|
|
601
|
+
# including a new copy of the module (recursively if necessary). Note
|
|
602
|
+
# that this method is called for each inclusion, whereas the above
|
|
603
|
+
# `included` block is run only for the initial inclusion of each copy.
|
|
604
|
+
def self.included(base)
|
|
605
|
+
super
|
|
606
|
+
if base.respond_to?(:_routes) && !base._routes.equal?(@_proxy._routes)
|
|
607
|
+
@dup_for_reinclude ||= self.dup
|
|
608
|
+
base.include @dup_for_reinclude
|
|
609
|
+
end
|
|
610
|
+
end
|
|
577
611
|
end
|
|
578
612
|
end
|
|
579
613
|
|
|
@@ -596,16 +630,16 @@ module ActionDispatch
|
|
|
596
630
|
named_routes[name] = route if name
|
|
597
631
|
|
|
598
632
|
if route.segment_keys.include?(:controller)
|
|
599
|
-
|
|
633
|
+
ActionDispatch.deprecator.warn(<<-MSG.squish)
|
|
600
634
|
Using a dynamic :controller segment in a route is deprecated and
|
|
601
|
-
will be removed in Rails 7.
|
|
635
|
+
will be removed in Rails 7.2.
|
|
602
636
|
MSG
|
|
603
637
|
end
|
|
604
638
|
|
|
605
639
|
if route.segment_keys.include?(:action)
|
|
606
|
-
|
|
640
|
+
ActionDispatch.deprecator.warn(<<-MSG.squish)
|
|
607
641
|
Using a dynamic :action segment in a route is deprecated and
|
|
608
|
-
will be removed in Rails 7.
|
|
642
|
+
will be removed in Rails 7.2.
|
|
609
643
|
MSG
|
|
610
644
|
end
|
|
611
645
|
|
|
@@ -779,18 +813,14 @@ module ActionDispatch
|
|
|
779
813
|
|
|
780
814
|
RESERVED_OPTIONS = [:host, :protocol, :port, :subdomain, :domain, :tld_length,
|
|
781
815
|
:trailing_slash, :anchor, :params, :only_path, :script_name,
|
|
782
|
-
:original_script_name
|
|
816
|
+
:original_script_name]
|
|
783
817
|
|
|
784
818
|
def optimize_routes_generation?
|
|
785
819
|
default_url_options.empty?
|
|
786
820
|
end
|
|
787
821
|
|
|
788
822
|
def find_script_name(options)
|
|
789
|
-
options.delete(:script_name) ||
|
|
790
|
-
end
|
|
791
|
-
|
|
792
|
-
def find_relative_url_root(options)
|
|
793
|
-
options.delete(:relative_url_root) || relative_url_root
|
|
823
|
+
options.delete(:script_name) || relative_url_root || ""
|
|
794
824
|
end
|
|
795
825
|
|
|
796
826
|
def path_for(options, route_name = nil, reserved = RESERVED_OPTIONS)
|
|
@@ -854,7 +884,7 @@ module ActionDispatch
|
|
|
854
884
|
|
|
855
885
|
def recognize_path(path, environment = {})
|
|
856
886
|
method = (environment[:method] || "GET").to_s.upcase
|
|
857
|
-
path = Journey::Router::Utils.normalize_path(path) unless
|
|
887
|
+
path = Journey::Router::Utils.normalize_path(path) unless path&.include?("://")
|
|
858
888
|
extras = environment[:extras] || {}
|
|
859
889
|
|
|
860
890
|
begin
|
|
@@ -29,23 +29,18 @@ module ActionDispatch
|
|
|
29
29
|
|
|
30
30
|
def method_missing(method, *args)
|
|
31
31
|
if @helpers.respond_to?(method)
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
options = args.extract_options!
|
|
35
|
-
options = url_options.merge((options || {}).symbolize_keys)
|
|
32
|
+
options = args.extract_options!
|
|
33
|
+
options = url_options.merge((options || {}).symbolize_keys)
|
|
36
34
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
35
|
+
if @script_namer
|
|
36
|
+
options[:script_name] = merge_script_names(
|
|
37
|
+
options[:script_name],
|
|
38
|
+
@script_namer.call(options)
|
|
39
|
+
)
|
|
40
|
+
end
|
|
43
41
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
end
|
|
47
|
-
RUBY
|
|
48
|
-
public_send(method, *args)
|
|
42
|
+
args << options
|
|
43
|
+
@helpers.public_send(method, *args)
|
|
49
44
|
else
|
|
50
45
|
super
|
|
51
46
|
end
|
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
module ActionDispatch
|
|
4
4
|
module Routing
|
|
5
|
+
# = Action Dispatch Routing \UrlFor
|
|
6
|
+
#
|
|
5
7
|
# In <tt>config/routes.rb</tt> you define URL-to-controller mappings, but the reverse
|
|
6
8
|
# is also possible: a URL can be generated from one of your routing definitions.
|
|
7
9
|
# URL generation functionality is centralized in this module.
|
|
@@ -37,7 +39,7 @@ module ActionDispatch
|
|
|
37
39
|
# # => "/users/new?message=Welcome%21"
|
|
38
40
|
#
|
|
39
41
|
# Notice the <tt>only_path: true</tt> part. This is because UrlFor has no
|
|
40
|
-
# information about the website hostname that your Rails app is serving. So if you
|
|
42
|
+
# information about the website hostname that your \Rails app is serving. So if you
|
|
41
43
|
# want to include the hostname as well, then you must also pass the <tt>:host</tt>
|
|
42
44
|
# argument:
|
|
43
45
|
#
|
|
@@ -134,6 +136,8 @@ module ActionDispatch
|
|
|
134
136
|
# * <tt>:port</tt> - Optionally specify the port to connect to.
|
|
135
137
|
# * <tt>:anchor</tt> - An anchor name to be appended to the path.
|
|
136
138
|
# * <tt>:params</tt> - The query parameters to be appended to the path.
|
|
139
|
+
# * <tt>:path_params</tt> - The query parameters that will only be used
|
|
140
|
+
# for the named dynamic segments of path. If unused, they will be discarded.
|
|
137
141
|
# * <tt>:trailing_slash</tt> - If true, adds a trailing slash, as in <tt>"/archive/2009/"</tt>.
|
|
138
142
|
# * <tt>:script_name</tt> - Specifies application path relative to domain root. If provided, prepends application path.
|
|
139
143
|
#
|
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require "active_support/core_ext/string/filters"
|
|
4
|
-
|
|
5
3
|
module ActionDispatch
|
|
6
4
|
# The routing module provides URL rewriting in native Ruby. It's a way to
|
|
7
5
|
# redirect incoming requests to controllers and actions. This replaces
|
|
@@ -119,9 +117,9 @@ module ActionDispatch
|
|
|
119
117
|
#
|
|
120
118
|
# # In config/routes.rb
|
|
121
119
|
# controller :blog do
|
|
122
|
-
# get 'blog/show'
|
|
123
|
-
# get 'blog/delete'
|
|
124
|
-
# get 'blog/edit'
|
|
120
|
+
# get 'blog/show' => :list
|
|
121
|
+
# get 'blog/delete' => :delete
|
|
122
|
+
# get 'blog/edit' => :edit
|
|
125
123
|
# end
|
|
126
124
|
#
|
|
127
125
|
# # provides named routes for show, delete, and edit
|
|
@@ -240,7 +238,7 @@ module ActionDispatch
|
|
|
240
238
|
#
|
|
241
239
|
# == View a list of all your routes
|
|
242
240
|
#
|
|
243
|
-
# rails routes
|
|
241
|
+
# $ bin/rails routes
|
|
244
242
|
#
|
|
245
243
|
# Target a specific controller with <tt>-c</tt>, or grep routes
|
|
246
244
|
# using <tt>-g</tt>. Useful in conjunction with <tt>--expanded</tt>
|
|
@@ -250,7 +248,9 @@ module ActionDispatch
|
|
|
250
248
|
|
|
251
249
|
autoload :Mapper
|
|
252
250
|
autoload :RouteSet
|
|
253
|
-
|
|
251
|
+
eager_autoload do
|
|
252
|
+
autoload :RoutesProxy
|
|
253
|
+
end
|
|
254
254
|
autoload :UrlFor
|
|
255
255
|
autoload :PolymorphicRoutes
|
|
256
256
|
|
|
@@ -51,7 +51,7 @@ module ActionDispatch
|
|
|
51
51
|
# driven_by :selenium, using: :chrome, screen_size: [1400, 1400]
|
|
52
52
|
# end
|
|
53
53
|
#
|
|
54
|
-
# By default,
|
|
54
|
+
# By default, +ActionDispatch::SystemTestCase+ is driven by the
|
|
55
55
|
# Selenium driver, with the Chrome browser, and a browser size of 1400x1400.
|
|
56
56
|
#
|
|
57
57
|
# Changing the driver configuration options is easy. Let's say you want to use
|
|
@@ -106,8 +106,8 @@ module ActionDispatch
|
|
|
106
106
|
# end
|
|
107
107
|
# end
|
|
108
108
|
#
|
|
109
|
-
# Because
|
|
110
|
-
# and Rails, any driver that is supported by Capybara is supported by system
|
|
109
|
+
# Because +ActionDispatch::SystemTestCase+ is a shim between Capybara
|
|
110
|
+
# and \Rails, any driver that is supported by Capybara is supported by system
|
|
111
111
|
# tests as long as you include the required gems and files.
|
|
112
112
|
class SystemTestCase < ActiveSupport::TestCase
|
|
113
113
|
include Capybara::DSL
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
module ActionDispatch
|
|
4
4
|
module SystemTesting
|
|
5
5
|
class Browser # :nodoc:
|
|
6
|
-
attr_reader :name
|
|
6
|
+
attr_reader :name
|
|
7
7
|
|
|
8
8
|
def initialize(name)
|
|
9
9
|
@name = name
|
|
@@ -21,35 +21,32 @@ module ActionDispatch
|
|
|
21
21
|
end
|
|
22
22
|
end
|
|
23
23
|
|
|
24
|
+
def options
|
|
25
|
+
@options ||=
|
|
26
|
+
case type
|
|
27
|
+
when :chrome
|
|
28
|
+
::Selenium::WebDriver::Chrome::Options.new
|
|
29
|
+
when :firefox
|
|
30
|
+
::Selenium::WebDriver::Firefox::Options.new
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
24
34
|
def configure
|
|
25
|
-
|
|
26
|
-
yield options if block_given? && options
|
|
35
|
+
yield options if block_given?
|
|
27
36
|
end
|
|
28
37
|
|
|
29
|
-
# driver_path
|
|
30
|
-
#
|
|
31
|
-
# update the webdriver once and avoid race conditions when using
|
|
32
|
-
# parallel tests.
|
|
38
|
+
# driver_path is lazily initialized by default. Eagerly set it to
|
|
39
|
+
# avoid race conditions when using parallel tests.
|
|
33
40
|
def preload
|
|
34
41
|
case type
|
|
35
42
|
when :chrome
|
|
36
|
-
::Selenium::WebDriver::Chrome
|
|
43
|
+
resolve_driver_path(::Selenium::WebDriver::Chrome)
|
|
37
44
|
when :firefox
|
|
38
|
-
::Selenium::WebDriver::Firefox
|
|
45
|
+
resolve_driver_path(::Selenium::WebDriver::Firefox)
|
|
39
46
|
end
|
|
40
47
|
end
|
|
41
48
|
|
|
42
49
|
private
|
|
43
|
-
def initialize_options
|
|
44
|
-
@options ||=
|
|
45
|
-
case type
|
|
46
|
-
when :chrome
|
|
47
|
-
::Selenium::WebDriver::Chrome::Options.new
|
|
48
|
-
when :firefox
|
|
49
|
-
::Selenium::WebDriver::Firefox::Options.new
|
|
50
|
-
end
|
|
51
|
-
end
|
|
52
|
-
|
|
53
50
|
def set_default_options
|
|
54
51
|
case name
|
|
55
52
|
when :headless_chrome
|
|
@@ -71,6 +68,10 @@ module ActionDispatch
|
|
|
71
68
|
capabilities.add_argument("-headless")
|
|
72
69
|
end
|
|
73
70
|
end
|
|
71
|
+
|
|
72
|
+
def resolve_driver_path(namespace)
|
|
73
|
+
namespace::Service.driver_path = ::Selenium::WebDriver::DriverFinder.path(options, namespace::Service)
|
|
74
|
+
end
|
|
74
75
|
end
|
|
75
76
|
end
|
|
76
77
|
end
|
|
@@ -12,14 +12,6 @@ module ActionDispatch
|
|
|
12
12
|
@name = @options.delete(:name) || driver_type
|
|
13
13
|
@capabilities = capabilities
|
|
14
14
|
|
|
15
|
-
if [:poltergeist, :webkit].include?(driver_type)
|
|
16
|
-
ActiveSupport::Deprecation.warn <<~MSG.squish
|
|
17
|
-
Poltergeist and capybara-webkit are not maintained already.
|
|
18
|
-
Driver registration of :poltergeist or :webkit is deprecated and will be removed in Rails 7.1.
|
|
19
|
-
You can still use :selenium, and also :cuprite is available for alternative to Poltergeist.
|
|
20
|
-
MSG
|
|
21
|
-
end
|
|
22
|
-
|
|
23
15
|
if driver_type == :selenium
|
|
24
16
|
gem "selenium-webdriver", ">= 4.0.0"
|
|
25
17
|
require "selenium/webdriver"
|
|
@@ -38,7 +30,7 @@ module ActionDispatch
|
|
|
38
30
|
|
|
39
31
|
private
|
|
40
32
|
def registerable?
|
|
41
|
-
[:selenium, :
|
|
33
|
+
[:selenium, :cuprite, :rack_test, :playwright].include?(@driver_type)
|
|
42
34
|
end
|
|
43
35
|
|
|
44
36
|
def register
|
|
@@ -47,10 +39,9 @@ module ActionDispatch
|
|
|
47
39
|
Capybara.register_driver name do |app|
|
|
48
40
|
case @driver_type
|
|
49
41
|
when :selenium then register_selenium(app)
|
|
50
|
-
when :poltergeist then register_poltergeist(app)
|
|
51
|
-
when :webkit then register_webkit(app)
|
|
52
42
|
when :cuprite then register_cuprite(app)
|
|
53
43
|
when :rack_test then register_rack_test(app)
|
|
44
|
+
when :playwright then register_playwright(app)
|
|
54
45
|
end
|
|
55
46
|
end
|
|
56
47
|
end
|
|
@@ -65,16 +56,6 @@ module ActionDispatch
|
|
|
65
56
|
end
|
|
66
57
|
end
|
|
67
58
|
|
|
68
|
-
def register_poltergeist(app)
|
|
69
|
-
Capybara::Poltergeist::Driver.new(app, @options.merge(window_size: @screen_size))
|
|
70
|
-
end
|
|
71
|
-
|
|
72
|
-
def register_webkit(app)
|
|
73
|
-
Capybara::Webkit::Driver.new(app, Capybara::Webkit::Configuration.to_hash.merge(@options)).tap do |driver|
|
|
74
|
-
driver.resize_window_to(driver.current_window_handle, *@screen_size)
|
|
75
|
-
end
|
|
76
|
-
end
|
|
77
|
-
|
|
78
59
|
def register_cuprite(app)
|
|
79
60
|
Capybara::Cuprite::Driver.new(app, @options.merge(window_size: @screen_size))
|
|
80
61
|
end
|
|
@@ -83,6 +64,17 @@ module ActionDispatch
|
|
|
83
64
|
Capybara::RackTest::Driver.new(app, respect_data_method: true, **@options)
|
|
84
65
|
end
|
|
85
66
|
|
|
67
|
+
def register_playwright(app)
|
|
68
|
+
screen = { width: @screen_size[0], height: @screen_size[1] } if @screen_size
|
|
69
|
+
options = {
|
|
70
|
+
screen: screen,
|
|
71
|
+
viewport: screen,
|
|
72
|
+
**@options
|
|
73
|
+
}.compact
|
|
74
|
+
|
|
75
|
+
Capybara::Playwright::Driver.new(app, **options)
|
|
76
|
+
end
|
|
77
|
+
|
|
86
78
|
def setup
|
|
87
79
|
Capybara.current_driver = name
|
|
88
80
|
end
|